代码之家  ›  专栏  ›  技术社区  ›  fiskeben

从函数返回时,内存存储库将消失

  •  0
  • fiskeben  · 技术社区  · 6 年前

    我在用 go-git 在一个程序中尝试测试我的功能。要测试一个函数,我想首先创建一个内存存储库,向它提交一个文件,然后让我的函数使用它。

    但当我试图在调用函数中使用repo时,我什么也得不到。

    下面是一个重现问题的例子:

    package main
    
    import (
        "fmt"
        "os"
        "time"
    
        "gopkg.in/src-d/go-billy.v4"
    
        "gopkg.in/src-d/go-git.v4/config"
        "gopkg.in/src-d/go-git.v4/plumbing/object"
    
        "gopkg.in/src-d/go-billy.v4/memfs"
        "gopkg.in/src-d/go-git.v4"
        "gopkg.in/src-d/go-git.v4/storage/memory"
    )
    
    func makeTempRepo() (*git.Repository, billy.Filesystem, error) {
        s := memory.NewStorage()
        f := memfs.New()
        r, err := git.Init(s, f)
        if err != nil {
            return nil, nil, fmt.Errorf("failed to create in-memory repo: %v", err)
        }
    
        readme, err := f.Create("/README.md")
        if err != nil {
            return nil, nil, fmt.Errorf("failed to create a file in repository: %v", err)
        }
        readme.Write([]byte("Hello world"))
    
        w, _ := r.Worktree()
        _, err = w.Add("/README.md")
        if err != nil {
            return nil, nil, fmt.Errorf("failed to add file to repository: %v", err)
        }
        commit, err := w.Commit("test commit", &git.CommitOptions{
            Author: &object.Signature{
                Name:  "John Doe",
                Email: "john@does.com",
                When:  time.Now(),
            },
        })
        if err != nil {
            return nil, nil, fmt.Errorf("failed to commit file to repository: %v", err)
        }
    
        obj, err := r.CommitObject(commit)
        if err != nil {
            return nil, nil, fmt.Errorf("failed to get commit: %v", err)
        }
        if obj == nil {
            return nil, nil, fmt.Errorf("commit object is nil")
        }
    
        fmt.Printf("%v\n", obj)
    
        return r, f, nil
    }
    
    func clone(URL, tagPrefix string, fs billy.Filesystem) (*git.Repository, error) {
        r, err := git.Clone(memory.NewStorage(), fs, &git.CloneOptions{
            URL: URL,
        })
        if err != nil {
            return nil, fmt.Errorf("failed to clone repo '%s': %v", URL, err)
        }
    
        err = r.Fetch(&git.FetchOptions{
            Force: true,
            RefSpecs: []config.RefSpec{
                config.RefSpec("refs/*:refs/*"),
                config.RefSpec("HEAD:refs/heads/HEAD"),
            },
        })
        if err != nil {
            return nil, fmt.Errorf("failed to fetch repo '%s': %v", URL, err)
        }
        return r, nil
    }
    
    func main() {
        repo, fs, err := makeTempRepo()
        if err != nil {
            fmt.Printf("could not create temp repo: %v", err)
            os.Exit(1)
        }
        commits, err := repo.CommitObjects()
        if err != nil {
            fmt.Printf("unable to get commits: %v", err)
            os.Exit(1)
        }
        fmt.Println("commits:")
        for c, err := commits.Next(); err != nil; {
            fmt.Printf("a commit: %v\n", c)
            os.Exit(1)
        }
    
        res, err := clone(fs.Root(), "foo", fs)
        if err != nil {
            fmt.Printf("unexpected error: %v", err)
            os.Exit(1)
        }
    
        h, err := res.Head()
        if err != nil {
            fmt.Printf("error getting HEAD: %v", err)
            os.Exit(1)
        }
        if h == nil {
            fmt.Println("missing HEAD commit")
            os.Exit(1)
        }
    
        fmt.Printf("HEAD: %v", h)
    }
    

    $ go run main.go 
    commit 936fa4014b70e008bf01338d1c0916e1365f77a6
    Author: John Doe <john@does.com>
    Date:   Fri Dec 07 12:17:39 2018 +0100
    
        test commit
    
    commits:
    unexpected error: failed to clone repo '/': repository not foundexit status 1
    

    所以 main 函数既不能列出来自repo的任何提交,也不能克隆它。

    我做错什么了?

    1 回复  |  直到 6 年前
        1
  •  1
  •   bayrinat    6 年前

    问题出在 clone 方法。

    fs 仅包含README.md文件(尝试查看 fs.ReadDir("/") fs.Root() 不是有效的URL选项。

    四季酒店 没有 .git (见 comment