我在程序中使用go-git
,并试图测试我的功能。为了测试一个功能,我想先创建一个内存中的存储库,向其中提交一个文件,然后让我的函数使用它。
因此,在我的测试中,我编写了一个可以在内存文件系统中创建新的内存回购(init)并返回它的助手。
但是当我尝试在调用函数中使用仓库时,我什么也没得到。
下面是重现该问题的示例:
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
函数无法列出来自存储库的任何提交或克隆它。
我在做什么错了?
答案 0 :(得分:1)
问题出在clone
方法中。
URL选项必须指向git存储库,但是fs
仅包含README.md文件(尝试查看fs.ReadDir("/")
的输出),因此fs.Root()
是无效的URL选项。
fs
没有.git
(请参阅comment),并且所有git内容都在存储设备中。