mirror of
https://github.com/grdl/git-get.git
synced 2026-02-04 17:24:49 +00:00
Add CloneRepo function and unit tests for cloned repos status
This commit is contained in:
45
branch.go
45
branch.go
@@ -15,7 +15,7 @@ type BranchStatus struct {
|
||||
Behind int
|
||||
}
|
||||
|
||||
func Branches(repo *git.Repository) ([]BranchStatus, error) {
|
||||
func Branches(repo *git.Repository) (map[string]BranchStatus, error) {
|
||||
iter, err := repo.NewBranchIterator(git.BranchAll)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed creating branch iterator")
|
||||
@@ -31,14 +31,14 @@ func Branches(repo *git.Repository) ([]BranchStatus, error) {
|
||||
return nil, errors.Wrap(err, "Failed iterating over branches")
|
||||
}
|
||||
|
||||
var statuses []BranchStatus
|
||||
statuses := make(map[string]BranchStatus)
|
||||
for _, branch := range branches {
|
||||
status, err := NewBranchStatus(repo, branch)
|
||||
if err != nil {
|
||||
// TODO: handle error
|
||||
// TODO: Handle error. We should tell user that we couldn't read status of that branch but probably shouldn't exit
|
||||
continue
|
||||
}
|
||||
statuses = append(statuses, status)
|
||||
statuses[status.Name] = status
|
||||
}
|
||||
|
||||
return statuses, nil
|
||||
@@ -53,31 +53,38 @@ func NewBranchStatus(repo *git.Repository, branch *git.Branch) (BranchStatus, er
|
||||
}
|
||||
status.Name = name
|
||||
|
||||
status.IsRemote = branch.IsRemote()
|
||||
// If branch is a remote one, return immediately. Upstream can only be found for local branches.
|
||||
if branch.IsRemote() {
|
||||
status.IsRemote = true
|
||||
return status, nil
|
||||
}
|
||||
|
||||
upstream, err := branch.Upstream()
|
||||
if err != nil && !git.IsErrorCode(err, git.ErrNotFound) {
|
||||
return status, errors.Wrap(err, "Failed getting branch upstream")
|
||||
}
|
||||
|
||||
if upstream != nil {
|
||||
status.HasUpstream = true
|
||||
// If there's no upstream, return immediately. Ahead/Behind can only be found when upstream exists.
|
||||
if upstream == nil {
|
||||
return status, nil
|
||||
}
|
||||
|
||||
ahead, behind, err := repo.AheadBehind(branch.Target(), upstream.Target())
|
||||
if err != nil {
|
||||
return status, errors.Wrap(err, "Failed getting ahead/behind information")
|
||||
}
|
||||
status.HasUpstream = true
|
||||
|
||||
status.Ahead = ahead
|
||||
status.Behind = behind
|
||||
ahead, behind, err := repo.AheadBehind(branch.Target(), upstream.Target())
|
||||
if err != nil {
|
||||
return status, errors.Wrap(err, "Failed getting ahead/behind information")
|
||||
}
|
||||
|
||||
if ahead > 0 {
|
||||
status.NeedsPush = true
|
||||
}
|
||||
status.Ahead = ahead
|
||||
status.Behind = behind
|
||||
|
||||
if behind > 0 {
|
||||
status.NeedsPull = true
|
||||
}
|
||||
if ahead > 0 {
|
||||
status.NeedsPush = true
|
||||
}
|
||||
|
||||
if behind > 0 {
|
||||
status.NeedsPull = true
|
||||
}
|
||||
|
||||
return status, nil
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -29,3 +30,49 @@ func TestNewLocalBranch(t *testing.T) {
|
||||
t.Errorf("Wrong branch status, got %+v; want %+v", status, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClonedBranches(t *testing.T) {
|
||||
origin := newTestRepo(t)
|
||||
createFile(t, origin, "file")
|
||||
stageFile(t, origin, "file")
|
||||
createCommit(t, origin, "Initial commit")
|
||||
|
||||
repo, err := CloneRepo(origin.Path(), newTempDir(t))
|
||||
checkFatal(t, err)
|
||||
|
||||
createBranch(t, repo, "branch")
|
||||
|
||||
branches, err := Branches(repo)
|
||||
checkFatal(t, err)
|
||||
|
||||
master := branches["master"]
|
||||
wantMaster := BranchStatus{
|
||||
Name: "master",
|
||||
IsRemote: false,
|
||||
HasUpstream: true,
|
||||
}
|
||||
|
||||
originMaster := branches["origin/master"]
|
||||
wantOriginMaster := BranchStatus{
|
||||
Name: "origin/master",
|
||||
IsRemote: true,
|
||||
HasUpstream: false,
|
||||
}
|
||||
|
||||
branch := branches["branch"]
|
||||
wantBranch := BranchStatus{
|
||||
Name: "branch",
|
||||
IsRemote: false,
|
||||
HasUpstream: false,
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(master, wantMaster) {
|
||||
t.Errorf("Wrong branch status, got %+v; want %+v", master, wantMaster)
|
||||
}
|
||||
if !reflect.DeepEqual(originMaster, wantOriginMaster) {
|
||||
t.Errorf("Wrong branch status, got %+v; want %+v", originMaster, wantOriginMaster)
|
||||
}
|
||||
if !reflect.DeepEqual(branch, wantBranch) {
|
||||
t.Errorf("Wrong branch status, got %+v; want %+v", branch, wantBranch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,24 +18,26 @@ func checkFatal(t *testing.T, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func cleanupRepo(t *testing.T, repo *git.Repository) {
|
||||
err := os.RemoveAll(repo.Workdir())
|
||||
if err != nil {
|
||||
t.Errorf("failed cleaning up repo")
|
||||
}
|
||||
}
|
||||
|
||||
func newTestRepo(t *testing.T) *git.Repository {
|
||||
dir, err := ioutil.TempDir("", "test-repo-")
|
||||
func newTempDir(t *testing.T) string {
|
||||
dir, err := ioutil.TempDir("", "git-get-repo-")
|
||||
checkFatal(t, errors.Wrap(err, "Failed creating test repo directory"))
|
||||
|
||||
repo, err := git.InitRepository(dir, false)
|
||||
checkFatal(t, errors.Wrap(err, "Failed initializing a temp repo"))
|
||||
|
||||
// Automatically remove repo when test is over
|
||||
t.Cleanup(func() {
|
||||
cleanupRepo(t, repo)
|
||||
err := os.RemoveAll(dir)
|
||||
if err != nil {
|
||||
t.Errorf("failed cleaning up repo")
|
||||
}
|
||||
})
|
||||
|
||||
return dir
|
||||
}
|
||||
|
||||
func newTestRepo(t *testing.T) *git.Repository {
|
||||
dir := newTempDir(t)
|
||||
repo, err := git.InitRepository(dir, false)
|
||||
checkFatal(t, errors.Wrap(err, "Failed initializing a temp repo"))
|
||||
|
||||
return repo
|
||||
}
|
||||
|
||||
|
||||
20
repo.go
Normal file
20
repo.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
git "github.com/libgit2/git2go/v30"
|
||||
)
|
||||
|
||||
func CloneRepo(url string, path string) (*git.Repository, error) {
|
||||
options := &git.CloneOptions{
|
||||
CheckoutOpts: nil,
|
||||
FetchOptions: nil,
|
||||
Bare: false,
|
||||
CheckoutBranch: "",
|
||||
RemoteCreateCallback: nil,
|
||||
}
|
||||
|
||||
repo, err := git.Clone(url, path, options)
|
||||
return repo, errors.Wrap(err, "Failed cloning repo")
|
||||
}
|
||||
@@ -140,6 +140,28 @@ func TestStatusWithMultipleCommits(t *testing.T) {
|
||||
if len(entries) != 0 {
|
||||
t.Errorf("Repo with no uncommitted files should have no status entries")
|
||||
}
|
||||
|
||||
status, err := NewRepoStatus(repo.Workdir())
|
||||
checkFatal(t, err)
|
||||
|
||||
want := RepoStatus{
|
||||
HasUntrackedFiles: false,
|
||||
HasUncommittedChanges: false,
|
||||
BranchStatuses: nil,
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(status, want) {
|
||||
t.Errorf("Wrong repo status, got %+v; want %+v", status, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusCloned(t *testing.T) {
|
||||
origin := newTestRepo(t)
|
||||
dir := newTempDir(t)
|
||||
|
||||
repo, err := CloneRepo(origin.Path(), dir)
|
||||
checkFatal(t, err)
|
||||
|
||||
status, err := NewRepoStatus(repo.Workdir())
|
||||
checkFatal(t, err)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user