diff --git a/README.md b/README.md index 7c99a09..dc8a2a8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # git-get +`git get` - a better way to clone and manage git repositories. + ## Build How to build with `libgit2` statically linked into a single executable without dependencies: diff --git a/branch.go b/branch.go index 178513d..88961f2 100644 --- a/branch.go +++ b/branch.go @@ -1,8 +1,6 @@ package main import ( - "fmt" - git "github.com/libgit2/git2go/v30" "github.com/pkg/errors" ) @@ -13,24 +11,58 @@ type BranchStatus struct { HasUpstream bool NeedsPull bool NeedsPush bool + Ahead int + Behind int } -func Branches(repo *git.Repository) ([]*git.Branch, error) { - it, err := repo.NewBranchIterator(git.BranchAll) +func Branches(repo *git.Repository) ([]BranchStatus, error) { + iter, err := repo.NewBranchIterator(git.BranchAll) if err != nil { return nil, errors.Wrap(err, "Failed creating branch iterator") } - it.ForEach(func(branch *git.Branch, branchType git.BranchType) error { - fmt.Print(branch.IsRemote()) - upstream, err := branch.Upstream() - if err != nil { - fmt.Println(err.Error()) - } else { - fmt.Println(upstream.Name()) - } + var branches []*git.Branch + err = iter.ForEach(func(branch *git.Branch, branchType git.BranchType) error { + branches = append(branches, branch) return nil }) - return nil, nil + if err != nil { + return nil, errors.Wrap(err, "Failed iterating over branches") + } + + var statuses []BranchStatus + for _, branch := range branches { + status, err := NewBranchStatus(branch) + if err != nil { + // TODO: handle error + continue + } + statuses = append(statuses, status) + } + + return statuses, nil +} + +func NewBranchStatus(branch *git.Branch) (BranchStatus, error) { + var status BranchStatus + + name, err := branch.Name() + if err != nil { + return status, errors.Wrap(err, "Failed getting branch name") + } + status.Name = name + + status.IsRemote = branch.IsRemote() + + _, err = branch.Upstream() + if err != nil { + if git.IsErrorCode(err, git.ErrNotFound) { + status.HasUpstream = false + } else { + return status, errors.Wrap(err, "Failed getting branch upstream") + } + } + + return status, nil } diff --git a/branch_test.go b/branch_test.go index 58b483f..15fffa5 100644 --- a/branch_test.go +++ b/branch_test.go @@ -1,18 +1,27 @@ package main import ( - "fmt" "testing" - git "github.com/libgit2/git2go/v30" + "github.com/pkg/errors" ) -func TestBranches(t *testing.T) { - repo, err := git.OpenRepository("/home/grdl/workspace/gitlab.com/grdl/git-get") - checkFatal(t, err) +func TestNewBranch(t *testing.T) { + repo := newTestRepo(t) - branches, err := Branches(repo) - checkFatal(t, err) + createFile(t, repo, "file") + stageFile(t, repo, "file") + createCommit(t, repo, "Initial commit") + branch := createBranch(t, repo, "branch") - fmt.Println(len(branches)) + status, err := NewBranchStatus(branch) + checkFatal(t, errors.Wrap(err, "Failed getting branch status")) + + if status.Name != "branch" { + t.Errorf("Wrong branch name, got %s; want %s", status.Name, "branch") + } + + if status.IsRemote != false { + t.Errorf("Branch should be local") + } } diff --git a/helpers_test.go b/helpers_test.go index b500eb5..5c4edd5 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -55,7 +55,7 @@ func stageFile(t *testing.T, repo *git.Repository, name string) { checkFatal(t, errors.Wrap(err, "Failed writing index")) } -func createCommit(t *testing.T, repo *git.Repository, message string) { +func createCommit(t *testing.T, repo *git.Repository, message string) *git.Commit { index, err := repo.Index() checkFatal(t, errors.Wrap(err, "Failed getting repo index")) @@ -74,6 +74,7 @@ func createCommit(t *testing.T, repo *git.Repository, message string) { empty, err := repo.IsEmpty() checkFatal(t, errors.Wrap(err, "Failed checking if repo is empty")) + var commitId *git.Oid if !empty { currentBranch, err := repo.Head() checkFatal(t, errors.Wrap(err, "Failed getting current branch")) @@ -81,10 +82,26 @@ func createCommit(t *testing.T, repo *git.Repository, message string) { currentTip, err := repo.LookupCommit(currentBranch.Target()) checkFatal(t, errors.Wrap(err, "Failed getting current tip")) - _, err = repo.CreateCommit("HEAD", signature, signature, message, tree, currentTip) + commitId, err = repo.CreateCommit("HEAD", signature, signature, message, tree, currentTip) } else { - _, err = repo.CreateCommit("HEAD", signature, signature, message, tree) + commitId, err = repo.CreateCommit("HEAD", signature, signature, message, tree) } - checkFatal(t, errors.Wrap(err, "Failed creating a commit")) + commit, err := repo.LookupCommit(commitId) + checkFatal(t, errors.Wrap(err, "Failed looking up a commit")) + + return commit +} + +func createBranch(t *testing.T, repo *git.Repository, name string) *git.Branch { + head, err := repo.Head() + checkFatal(t, errors.Wrap(err, "Failed getting repo head")) + + commit, err := repo.LookupCommit(head.Target()) + checkFatal(t, errors.Wrap(err, "Failed getting commit id from head")) + + branch, err := repo.CreateBranch(name, commit, false) + checkFatal(t, errors.Wrap(err, "Failed creating branch")) + + return branch }