Chapters ▾ 2nd Edition

A2.4 Appendix B: Incorporando o Git nos seus Aplicativos - go-git

go-git

Caso queira integrar o Git a um serviço escrito em Golang, também há uma implementação de biblioteca inteiramente em Go. Essa implementação não possui dependências nativas e, portanto, não está sujeita a erros de gerenciamento manual de memória. Ela também pode ser analisada normalmente pelas ferramentas padrão de desempenho do Golang, como os profilers de CPU e memória e o detector de condições de corrida.

O go-git se concentra em extensibilidade e compatibilidade e oferece suporte à maioria das APIs de encanamento, conforme documentado em https://github.com/go-git/go-git/blob/master/COMPATIBILITY.md.

Eis um exemplo básico de uso das APIs Go:

import "github.com/go-git/go-git/v5"

r, err := git.PlainClone("/tmp/foo", false, &git.CloneOptions{
    URL:      "https://github.com/go-git/go-git",
    Progress: os.Stdout,
})

Assim que tiver uma instância de Repository, você poderá acessar informações e fazer alterações nela:

// retrieves the branch pointed by HEAD
ref, err := r.Head()

// get the commit object, pointed by ref
commit, err := r.CommitObject(ref.Hash())

// retrieves the commit history
history, err := commit.History()

// iterates over the commits and print each
for _, c := range history {
    fmt.Println(c)
}

Funcionalidades Avançadas

O go-git tem alguns recursos avançados dignos de nota; um deles é um sistema de armazenamento plugável, semelhante aos backends da Libgit2. A implementação padrão usa armazenamento em memória, que é muito rápido.

r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
    URL: "https://github.com/go-git/go-git",
})

O armazenamento plugável oferece muitas opções interessantes. Por exemplo, https://github.com/go-git/go-git/tree/master/_examples/storage permite armazenar referências, objetos e configurações em um banco de dados Aerospike.

Outro recurso é uma abstração flexível do sistema de arquivos. Com https://pkg.go.dev/github.com/go-git/go-billy/v5?tab=doc#Filesystem, é fácil armazenar todos os arquivos de maneiras diferentes; por exemplo, empacotando-os em um único arquivo no disco ou mantendo-os todos na memória.

Outro caso de uso avançado envolve um cliente HTTP altamente configurável, como o encontrado em https://github.com/go-git/go-git/blob/master/_examples/custom_http/main.go.

customClient := &http.Client{
    Transport: &http.Transport{ // accept any certificate (might be useful for testing)
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    },
    Timeout: 15 * time.Second,  // 15 second timeout
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
        return http.ErrUseLastResponse // don't follow redirect
    },
}

// Override http(s) default protocol to use our custom client
client.InstallProtocol("https", githttp.NewClient(customClient))

// Clone repository using the new client if the protocol is https://
r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{URL: url})

Leituras Adicionais

Uma abordagem completa dos recursos do go-git está fora do escopo deste livro. Se quiser mais informações sobre o go-git, há documentação da API em https://pkg.go.dev/github.com/go-git/go-git/v5 e um conjunto de exemplos de uso em https://github.com/go-git/go-git/tree/master/_examples.