mirror of
https://github.com/grdl/git-get.git
synced 2026-02-05 18:52:56 +00:00
Add checking what is the current branch and if HEAD is detached
This commit is contained in:
@@ -83,6 +83,19 @@ func newRepoWithClonedBranch(t *testing.T) *Repo {
|
|||||||
|
|
||||||
r := origin.clone(t)
|
r := origin.clone(t)
|
||||||
r.newBranch(t, "local")
|
r.newBranch(t, "local")
|
||||||
|
r.checkoutBranch(t, "local")
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRepoWithDetachedHead(t *testing.T) *Repo {
|
||||||
|
r := newRepoWithCommit(t)
|
||||||
|
|
||||||
|
r.writeFile(t, "new", "I'm a new file")
|
||||||
|
r.addFile(t, "new")
|
||||||
|
hash := r.newCommit(t, "new commit")
|
||||||
|
|
||||||
|
r.checkoutHash(t, hash)
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -144,7 +157,7 @@ func newTempDir(t *testing.T) string {
|
|||||||
|
|
||||||
func (r *Repo) writeFile(t *testing.T, name string, content string) {
|
func (r *Repo) writeFile(t *testing.T, name string, content string) {
|
||||||
wt, err := r.repo.Worktree()
|
wt, err := r.repo.Worktree()
|
||||||
checkFatal(t, errors.Wrap(err, "Failed getting workree"))
|
checkFatal(t, errors.Wrap(err, "Failed getting worktree"))
|
||||||
|
|
||||||
file, err := wt.Filesystem.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
file, err := wt.Filesystem.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
checkFatal(t, errors.Wrap(err, "Failed opening a file"))
|
checkFatal(t, errors.Wrap(err, "Failed opening a file"))
|
||||||
@@ -155,15 +168,15 @@ func (r *Repo) writeFile(t *testing.T, name string, content string) {
|
|||||||
|
|
||||||
func (r *Repo) addFile(t *testing.T, name string) {
|
func (r *Repo) addFile(t *testing.T, name string) {
|
||||||
wt, err := r.repo.Worktree()
|
wt, err := r.repo.Worktree()
|
||||||
checkFatal(t, errors.Wrap(err, "Failed getting workree"))
|
checkFatal(t, errors.Wrap(err, "Failed getting worktree"))
|
||||||
|
|
||||||
_, err = wt.Add(name)
|
_, err = wt.Add(name)
|
||||||
checkFatal(t, errors.Wrap(err, "Failed adding file to index"))
|
checkFatal(t, errors.Wrap(err, "Failed adding file to index"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repo) newCommit(t *testing.T, msg string) {
|
func (r *Repo) newCommit(t *testing.T, msg string) plumbing.Hash {
|
||||||
wt, err := r.repo.Worktree()
|
wt, err := r.repo.Worktree()
|
||||||
checkFatal(t, errors.Wrap(err, "Failed getting workree"))
|
checkFatal(t, errors.Wrap(err, "Failed getting worktree"))
|
||||||
|
|
||||||
opts := &git.CommitOptions{
|
opts := &git.CommitOptions{
|
||||||
Author: &object.Signature{
|
Author: &object.Signature{
|
||||||
@@ -173,8 +186,9 @@ func (r *Repo) newCommit(t *testing.T, msg string) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = wt.Commit(msg, opts)
|
hash, err := wt.Commit(msg, opts)
|
||||||
checkFatal(t, errors.Wrap(err, "Failed creating commit"))
|
checkFatal(t, errors.Wrap(err, "Failed creating commit"))
|
||||||
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repo) newBranch(t *testing.T, name string) {
|
func (r *Repo) newBranch(t *testing.T, name string) {
|
||||||
@@ -203,6 +217,28 @@ func (r *Repo) fetch(t *testing.T) {
|
|||||||
checkFatal(t, err)
|
checkFatal(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Repo) checkoutBranch(t *testing.T, name string) {
|
||||||
|
wt, err := r.repo.Worktree()
|
||||||
|
checkFatal(t, errors.Wrap(err, "Failed getting worktree"))
|
||||||
|
|
||||||
|
opts := &git.CheckoutOptions{
|
||||||
|
Branch: plumbing.NewBranchReferenceName(name),
|
||||||
|
}
|
||||||
|
err = wt.Checkout(opts)
|
||||||
|
checkFatal(t, errors.Wrap(err, "Failed checking out branch"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Repo) checkoutHash(t *testing.T, hash plumbing.Hash) {
|
||||||
|
wt, err := r.repo.Worktree()
|
||||||
|
checkFatal(t, errors.Wrap(err, "Failed getting worktree"))
|
||||||
|
|
||||||
|
opts := &git.CheckoutOptions{
|
||||||
|
Hash: hash,
|
||||||
|
}
|
||||||
|
err = wt.Checkout(opts)
|
||||||
|
checkFatal(t, errors.Wrap(err, "Failed checking out hash"))
|
||||||
|
}
|
||||||
|
|
||||||
func checkFatal(t *testing.T, err error) {
|
func checkFatal(t *testing.T, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%+v", err)
|
t.Fatalf("%+v", err)
|
||||||
|
|||||||
@@ -140,12 +140,6 @@ const (
|
|||||||
ColorYellow = "\033[1;33m%s\033[0m"
|
ColorYellow = "\033[1;33m%s\033[0m"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
StatusOk = "ok"
|
|
||||||
StatusUncommitted = "uncommitted"
|
|
||||||
StatusUntracked = "untracked"
|
|
||||||
)
|
|
||||||
|
|
||||||
func PrintRepoStatus(repo *Repo) string {
|
func PrintRepoStatus(repo *Repo) string {
|
||||||
status := fmt.Sprintf(ColorGreen, StatusOk)
|
status := fmt.Sprintf(ColorGreen, StatusOk)
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,18 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusUnknown = "unknown"
|
||||||
|
StatusDetached = "detached HEAD"
|
||||||
|
StatusOk = "ok"
|
||||||
|
StatusUncommitted = "uncommitted"
|
||||||
|
StatusUntracked = "untracked"
|
||||||
|
)
|
||||||
|
|
||||||
type RepoStatus struct {
|
type RepoStatus struct {
|
||||||
HasUntrackedFiles bool
|
HasUntrackedFiles bool
|
||||||
HasUncommittedChanges bool
|
HasUncommittedChanges bool
|
||||||
|
Current string
|
||||||
Branches []*BranchStatus
|
Branches []*BranchStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +63,7 @@ func (r *Repo) LoadStatus() error {
|
|||||||
|
|
||||||
r.Status.HasUncommittedChanges = hasUncommitted(status)
|
r.Status.HasUncommittedChanges = hasUncommitted(status)
|
||||||
r.Status.HasUntrackedFiles = hasUntracked(status)
|
r.Status.HasUntrackedFiles = hasUntracked(status)
|
||||||
|
r.Status.Current = currentBranch(r)
|
||||||
|
|
||||||
err = r.loadBranchesStatus()
|
err = r.loadBranchesStatus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -91,6 +101,19 @@ func hasUncommitted(status git.Status) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func currentBranch(r *Repo) string {
|
||||||
|
head, err := r.repo.Head()
|
||||||
|
if err != nil {
|
||||||
|
return StatusUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
if head.Name().Short() == plumbing.HEAD.String() {
|
||||||
|
return StatusDetached
|
||||||
|
}
|
||||||
|
|
||||||
|
return head.Name().Short()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Repo) loadBranchesStatus() error {
|
func (r *Repo) loadBranchesStatus() error {
|
||||||
iter, err := r.repo.Branches()
|
iter, err := r.repo.Branches()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -13,21 +13,25 @@ func TestStatus(t *testing.T) {
|
|||||||
{newRepoEmpty, &RepoStatus{
|
{newRepoEmpty, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: StatusUnknown,
|
||||||
Branches: nil,
|
Branches: nil,
|
||||||
}},
|
}},
|
||||||
{newRepoWithUntracked, &RepoStatus{
|
{newRepoWithUntracked, &RepoStatus{
|
||||||
HasUntrackedFiles: true,
|
HasUntrackedFiles: true,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: StatusUnknown,
|
||||||
Branches: nil,
|
Branches: nil,
|
||||||
}},
|
}},
|
||||||
{newRepoWithStaged, &RepoStatus{
|
{newRepoWithStaged, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: true,
|
HasUncommittedChanges: true,
|
||||||
|
Current: StatusUnknown,
|
||||||
Branches: nil,
|
Branches: nil,
|
||||||
}},
|
}},
|
||||||
{newRepoWithCommit, &RepoStatus{
|
{newRepoWithCommit, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: "master",
|
||||||
Branches: []*BranchStatus{
|
Branches: []*BranchStatus{
|
||||||
{
|
{
|
||||||
Name: "master",
|
Name: "master",
|
||||||
@@ -40,6 +44,7 @@ func TestStatus(t *testing.T) {
|
|||||||
{newRepoWithModified, &RepoStatus{
|
{newRepoWithModified, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: true,
|
HasUncommittedChanges: true,
|
||||||
|
Current: "master",
|
||||||
Branches: []*BranchStatus{
|
Branches: []*BranchStatus{
|
||||||
{
|
{
|
||||||
Name: "master",
|
Name: "master",
|
||||||
@@ -52,6 +57,7 @@ func TestStatus(t *testing.T) {
|
|||||||
{newRepoWithIgnored, &RepoStatus{
|
{newRepoWithIgnored, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: "master",
|
||||||
Branches: []*BranchStatus{
|
Branches: []*BranchStatus{
|
||||||
{
|
{
|
||||||
Name: "master",
|
Name: "master",
|
||||||
@@ -64,6 +70,7 @@ func TestStatus(t *testing.T) {
|
|||||||
{newRepoWithLocalBranch, &RepoStatus{
|
{newRepoWithLocalBranch, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: "master",
|
||||||
Branches: []*BranchStatus{
|
Branches: []*BranchStatus{
|
||||||
{
|
{
|
||||||
Name: "local",
|
Name: "local",
|
||||||
@@ -81,6 +88,7 @@ func TestStatus(t *testing.T) {
|
|||||||
{newRepoWithClonedBranch, &RepoStatus{
|
{newRepoWithClonedBranch, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: "local",
|
||||||
Branches: []*BranchStatus{
|
Branches: []*BranchStatus{
|
||||||
{
|
{
|
||||||
Name: "local",
|
Name: "local",
|
||||||
@@ -95,9 +103,23 @@ func TestStatus(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
|
{newRepoWithDetachedHead, &RepoStatus{
|
||||||
|
HasUntrackedFiles: false,
|
||||||
|
HasUncommittedChanges: false,
|
||||||
|
Current: StatusDetached,
|
||||||
|
Branches: []*BranchStatus{
|
||||||
|
{
|
||||||
|
Name: "master",
|
||||||
|
Upstream: "",
|
||||||
|
NeedsPull: false,
|
||||||
|
NeedsPush: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
{newRepoWithBranchAhead, &RepoStatus{
|
{newRepoWithBranchAhead, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: "master",
|
||||||
Branches: []*BranchStatus{
|
Branches: []*BranchStatus{
|
||||||
{
|
{
|
||||||
Name: "master",
|
Name: "master",
|
||||||
@@ -110,6 +132,7 @@ func TestStatus(t *testing.T) {
|
|||||||
{newRepoWithBranchBehind, &RepoStatus{
|
{newRepoWithBranchBehind, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: "master",
|
||||||
Branches: []*BranchStatus{
|
Branches: []*BranchStatus{
|
||||||
{
|
{
|
||||||
Name: "master",
|
Name: "master",
|
||||||
@@ -122,6 +145,7 @@ func TestStatus(t *testing.T) {
|
|||||||
{newRepoWithBranchAheadAndBehind, &RepoStatus{
|
{newRepoWithBranchAheadAndBehind, &RepoStatus{
|
||||||
HasUntrackedFiles: false,
|
HasUntrackedFiles: false,
|
||||||
HasUncommittedChanges: false,
|
HasUncommittedChanges: false,
|
||||||
|
Current: "master",
|
||||||
Branches: []*BranchStatus{
|
Branches: []*BranchStatus{
|
||||||
{
|
{
|
||||||
Name: "master",
|
Name: "master",
|
||||||
|
|||||||
Reference in New Issue
Block a user