首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用git签出特定的单个文件来检查它?

如何使用git签出特定的单个文件来检查它?
EN

Stack Overflow用户
提问于 2022-08-31 20:26:48
回答 1查看 31关注 0票数 0

我希望克隆一个特定的存储库,获取所有标记并遍历它们。对于每个标记,我想签出根目录中的特定文件( package.json )。如果没有文件存在,它应该继续,否则它应该通过它,以便我可以检查它。

我从以下代码开始(我的第一个Go应用程序.)

代码语言:javascript
复制
package main

import (
    "fmt"
    "github.com/go-git/go-billy/v5"
    "github.com/go-git/go-billy/v5/memfs"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
    "github.com/go-git/go-git/v5/storage/memory"
    "os"
)

func main() {
    authentication := &http.BasicAuth{
        Username: "me",
        Password: "my-key",
    }
    repositoryUrl := "my-repo-url"
    inMemoryStorage := memory.NewStorage()
    inMemoryFilesystem := memfs.New()

    repository, err := cloneRepository(repositoryUrl, authentication, inMemoryStorage, inMemoryFilesystem)

    if err != nil {
        handleError(err)
    }

    tagsIterator, err := repository.Tags()

    if err != nil {
        handleError(err)
    }

    err = tagsIterator.ForEach(func(tag *plumbing.Reference) error {
        fmt.Println(tag.Name().Short()) // for debugging purposes

        // checkout package.json file ( at root ) via tag

        return nil
    })

    if err != nil {
        handleError(err)
    }
}

func cloneRepository(repositoryUrl string, authentication *http.BasicAuth, inMemoryStorage *memory.Storage, inMemoryFilesystem billy.Filesystem) (*git.Repository, error) {
    return git.Clone(inMemoryStorage, inMemoryFilesystem, &git.CloneOptions{
        URL:  repositoryUrl,
        Auth: authentication,
    })
}

func handleError(err error) {
    fmt.Println(err)
    os.Exit(1)
}

有人知道如何尝试通过给定的标记签出循环中的文件吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-31 23:21:51

如果只需要文件内容,则不需要“签出”任何内容;您可以直接从存储库中提取该内容。但是首先要注意的是:我既不是一个经验丰富的围棋程序员,也从来没有使用过go-git,所以可能有一种更好的方法来做到这一点。

从标记开始,您可以:

package.json

  • If

  • 获取标记指向的提交,

  • 得到提交点

  • 遍历树的树,寻找找到的

,提取相应的blob。现在你有你的内容了!

以上步骤可能如下所示:

代码语言:javascript
复制
func getFileFromRef(repository *git.Repository, ref *plumbing.Hash, filename string) (bool, []byte, error) {
    // Get the commit object corresponding to ref
    commit, err := repository.CommitObject(*ref)
    if err != nil {
        return false, nil, err
    }

    // Get the tree object from the commit
    tree, err := repository.TreeObject(commit.TreeHash)
    if err != nil {
        return false, nil, err
    }

    // Iterate through tree entries
    for _, entry := range tree.Entries {
        // If we find the target file...
        if entry.Name == filename {
            // Get the blob object from the repository
            blob, err := repository.BlobObject(entry.Hash)
            if err != nil {
                return false, nil, err
            }

            // Ask for a Reader
            reader, err := blob.Reader()
            if err != nil {
                return false, nil, err
            }

            // Allocate a slice for the data...
            data := make([]byte, blob.Size)

            // ...and read it in.
            n, err := reader.Read(data)
            if err != nil {
                return false, nil, err
            }

            // Double check that we read as many bytes as
            // we expected
            if int64(n) != blob.Size {
                return true, nil, fmt.Errorf("wrong size")
            }
            return true, data, nil
        }
    }

    return false, nil, nil
}

给定一个提交引用,上面的函数将在存储库的顶层查找filename (因为它没有遍历子目录)。您需要修改tagsIterator.ForEach函数中的main循环来执行如下操作:

代码语言:javascript
复制
    err = tagsIterator.ForEach(func(tag *plumbing.Reference) error {
        // Get the commit to which the tag refers. We need this to
        // resolve annotated tags.
        ref, err := repository.ResolveRevision(plumbing.Revision(tag.Hash().String()))
        if err != nil {
            handleError(err)
        }

        found, content, err := getFileFromRef(repository, ref, "package.json")
        if found && err == nil {
            fmt.Printf("found \"package.json\" in tag %s\n", tag.Name().Short())
            fmt.Println(string(content))
        }

        return nil
    })

我不知道这是否是您要找的东西,但是关于go-git包的学习很有趣。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73561564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档