6
0
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:
Grzegorz Dlugoszewski
2020-05-19 14:12:38 +02:00
parent a0f09ef74d
commit dfc8437408
5 changed files with 130 additions and 32 deletions

View File

@@ -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

View File

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

View File

@@ -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
View 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")
}

View File

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