227 lines
5.6 KiB
Go
227 lines
5.6 KiB
Go
package git
|
|
|
|
import "errors"
|
|
import "strings"
|
|
|
|
import git "github.com/go-git/go-git/v5"
|
|
import "github.com/go-git/go-git/v5/plumbing"
|
|
import "github.com/go-git/go-git/v5/plumbing/object"
|
|
import "github.com/go-git/go-git/v5/plumbing/storer"
|
|
|
|
func GetDefaultBranch(repoPath string) (string, error) {
|
|
var repo *git.Repository
|
|
var err error
|
|
var head *plumbing.Reference
|
|
var target plumbing.ReferenceName
|
|
var targetRef *plumbing.Reference
|
|
repo, err = git.PlainOpen(repoPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
_ = EnsureHead(repoPath)
|
|
head, err = repo.Reference(plumbing.HEAD, false)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if head.Type() == plumbing.SymbolicReference {
|
|
target = head.Target()
|
|
targetRef, err = repo.Reference(target, true)
|
|
if err != nil {
|
|
if errors.Is(err, plumbing.ErrReferenceNotFound) {
|
|
return "", nil
|
|
}
|
|
return "", err
|
|
}
|
|
if targetRef.Hash().IsZero() {
|
|
return "", nil
|
|
}
|
|
return target.Short(), nil
|
|
}
|
|
return head.Name().Short(), nil
|
|
}
|
|
|
|
type BranchInfo struct {
|
|
Name string `json:"name"`
|
|
LastHash string `json:"last_hash"`
|
|
LastAuthor string `json:"last_author"`
|
|
LastWhen string `json:"last_when"`
|
|
LastMessage string `json:"last_message"`
|
|
}
|
|
|
|
func ListBranchInfos(repoPath string) ([]BranchInfo, error) {
|
|
var repo *git.Repository
|
|
var err error
|
|
var iter storer.ReferenceIter
|
|
var branches []BranchInfo
|
|
var ref *plumbing.Reference
|
|
var commit *object.Commit
|
|
repo, err = git.PlainOpen(repoPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
iter, err = repo.Branches()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer iter.Close()
|
|
err = iter.ForEach(func(r *plumbing.Reference) error {
|
|
ref = r
|
|
if ref.Hash().IsZero() {
|
|
return nil
|
|
}
|
|
commit, err = repo.CommitObject(ref.Hash())
|
|
if err != nil {
|
|
branches = append(branches, BranchInfo{Name: ref.Name().Short()})
|
|
return nil
|
|
}
|
|
branches = append(branches, BranchInfo{
|
|
Name: ref.Name().Short(),
|
|
LastHash: commit.Hash.String(),
|
|
LastAuthor: commit.Author.Name,
|
|
LastWhen: commit.Author.When.UTC().Format(timeFormat),
|
|
LastMessage: strings.TrimSpace(commit.Message),
|
|
})
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return branches, nil
|
|
}
|
|
|
|
func SetDefaultBranch(repoPath string, branch string) error {
|
|
var repo *git.Repository
|
|
var err error
|
|
var refName plumbing.ReferenceName
|
|
repo, err = git.PlainOpen(repoPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
refName = plumbing.NewBranchReferenceName(branch)
|
|
_, err = repo.Reference(refName, true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = repo.Storer.SetReference(plumbing.NewSymbolicReference(plumbing.HEAD, refName))
|
|
return err
|
|
}
|
|
|
|
func CreateBranch(repoPath string, name string, from string) error {
|
|
var repo *git.Repository
|
|
var err error
|
|
var commit *object.Commit
|
|
var refName plumbing.ReferenceName
|
|
repo, err = git.PlainOpen(repoPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
refName = plumbing.NewBranchReferenceName(name)
|
|
_, err = repo.Reference(refName, true)
|
|
if err == nil {
|
|
return err
|
|
}
|
|
commit, err = resolveCommit(repo, from)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = repo.Storer.SetReference(plumbing.NewHashReference(refName, commit.Hash))
|
|
return err
|
|
}
|
|
|
|
func DeleteBranch(repoPath string, branch string) error {
|
|
var repo *git.Repository
|
|
var err error
|
|
var refName plumbing.ReferenceName
|
|
repo, err = git.PlainOpen(repoPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
refName = plumbing.NewBranchReferenceName(branch)
|
|
err = repo.Storer.RemoveReference(refName)
|
|
return err
|
|
}
|
|
|
|
func RenameBranch(repoPath string, from string, to string) error {
|
|
var repo *git.Repository
|
|
var err error
|
|
var fromRef *plumbing.Reference
|
|
var toRefName plumbing.ReferenceName
|
|
var fromRefName plumbing.ReferenceName
|
|
var head *plumbing.Reference
|
|
if from == to {
|
|
return nil
|
|
}
|
|
repo, err = git.PlainOpen(repoPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fromRefName = plumbing.NewBranchReferenceName(from)
|
|
toRefName = plumbing.NewBranchReferenceName(to)
|
|
fromRef, err = repo.Reference(fromRefName, true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = repo.Storer.SetReference(plumbing.NewHashReference(toRefName, fromRef.Hash()))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
head, err = repo.Reference(plumbing.HEAD, false)
|
|
if err == nil && head.Type() == plumbing.SymbolicReference && head.Target() == fromRefName {
|
|
_ = repo.Storer.SetReference(plumbing.NewSymbolicReference(plumbing.HEAD, toRefName))
|
|
}
|
|
err = repo.Storer.RemoveReference(fromRefName)
|
|
return err
|
|
}
|
|
|
|
func EnsureHead(repoPath string) error {
|
|
var repo *git.Repository
|
|
var err error
|
|
var head *plumbing.Reference
|
|
var target plumbing.ReferenceName
|
|
var refName plumbing.ReferenceName
|
|
var iter storer.ReferenceIter
|
|
var first *plumbing.Reference
|
|
repo, err = git.PlainOpen(repoPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
head, err = repo.Reference(plumbing.HEAD, false)
|
|
if err == nil {
|
|
if head.Type() == plumbing.SymbolicReference {
|
|
target = head.Target()
|
|
_, err = repo.Reference(target, true)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
refName = plumbing.NewBranchReferenceName("main")
|
|
_, err = repo.Reference(refName, true)
|
|
if err == nil {
|
|
return repo.Storer.SetReference(plumbing.NewSymbolicReference(plumbing.HEAD, refName))
|
|
}
|
|
refName = plumbing.NewBranchReferenceName("master")
|
|
_, err = repo.Reference(refName, true)
|
|
if err == nil {
|
|
return repo.Storer.SetReference(plumbing.NewSymbolicReference(plumbing.HEAD, refName))
|
|
}
|
|
iter, err = repo.Branches()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer iter.Close()
|
|
err = iter.ForEach(func(r *plumbing.Reference) error {
|
|
first = r
|
|
return storer.ErrStop
|
|
})
|
|
if err != nil && err != storer.ErrStop {
|
|
return err
|
|
}
|
|
if first == nil {
|
|
return nil
|
|
}
|
|
return repo.Storer.SetReference(plumbing.NewSymbolicReference(plumbing.HEAD, first.Name()))
|
|
}
|