簡體   English   中英

如何簽出特定的單個文件以使用 go-git 檢查它?

[英]How to checkout a specific single file to inspect it using go-git?

我想克隆一個特定的存儲庫,獲取所有標簽並遍歷它們。 對於每個標簽,我想檢查根目錄中的特定文件( package.json )。 如果沒有文件存在,它應該繼續,否則它應該傳遞它以便我可以檢查它。

我從以下代碼開始(我的第一個 Go 應用程序...)

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)
}

有人知道如何嘗試通過給定標簽檢查循環內的文件嗎?

如果您想要的只是文件內容,則無需“簽出”任何內容; 您可以直接從存儲庫中提取它。 但首先,需要注意的是:我既不是經驗豐富的 Go 程序員,也不是以前使用過go-git人,所以可能有更優化的方法來做這件事。

從標簽開始,您可以:

  1. 獲取標簽指向的提交
  2. 獲取提交指向的樹
  3. 遍歷樹尋找package.json
  4. 如果找到它,請提取相應的 blob。 現在你有你的內容了!

上述步驟可能如下所示:

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
}

上面的 function 將在給定提交參考的情況下,在存儲庫的頂層查找filename (因為它不會遍歷子目錄)。 您需要在main function 中修改tagsIterator.ForEach循環來執行以下操作:

    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 package 很有趣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM