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

标签 git go go-git

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

因此,在我的测试中,我编写了一个帮助程序,它可以在内存文件系统中创建一个新的内存存储库 (init) 并将其返回。

但是当我尝试在调用函数中使用 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 函数无法列出来自存储库的任何提交,也无法克隆它。

我做错了什么?

最佳答案

问题出在clone 方法中。

URL 选项必须指向 git 存储库,但是 fs 只包含 README.md 文件(尝试查看 fs.ReadDir("/") 的输出),所以fs.Root() 不是有效的 URL 选项。

fs 没有 .git(请参阅 comment )并且所有 git 内容都在您的 Storer 中。

关于git - 从函数返回时,内存存储库消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53668567/

相关文章:

go - 如何使用[] byte作为Registry.GetValue中的缓冲区?

go - 如何在golang中切割uuid?

git - 可以指示 git fetch pack 获取单个树对象吗?

git - 仅分支/ fork 父存储库的一部分

android - 使用 Ant 获取存储库提交消息以更新使用 VSTS 或 Bitrise 构建的 Crashlytics Beta 发行说明

go - 从结构迭代中排除空字段

git - 使用 go-git 从 GitHub Enterprise 克隆存储库

go - 使用 go-git 获取文件的平面列表

git - 哪个用户在 Windows 机器上执行接收后 Hook ?

由于未 merge 文件而导致 Github merge 失败