mirror of
https://github.com/grdl/git-get.git
synced 2026-02-04 17:24:49 +00:00
182 lines
3.7 KiB
Go
182 lines
3.7 KiB
Go
package git
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// Status contains human readable (and printable) representation of a git repository status.
|
|
type Status struct {
|
|
path string
|
|
current string
|
|
branches map[string]string // key: branch name, value: branch status
|
|
worktree string
|
|
remote string
|
|
errors []string // Slice of errors which occurred when loading the status.
|
|
}
|
|
|
|
// LoadStatus reads status of a repository.
|
|
// If fetch equals true, it first fetches from the remote repo before loading the status.
|
|
// If errors occur during loading, they are stored in Status.errors slice.
|
|
func (r *Repo) LoadStatus(fetch bool) *Status {
|
|
status := &Status{
|
|
path: r.path,
|
|
branches: make(map[string]string),
|
|
errors: make([]string, 0),
|
|
}
|
|
|
|
if fetch {
|
|
if err := r.Fetch(); err != nil {
|
|
status.errors = append(status.errors, err.Error())
|
|
}
|
|
}
|
|
|
|
var err error
|
|
|
|
status.current, err = r.CurrentBranch()
|
|
if err != nil {
|
|
status.errors = append(status.errors, err.Error())
|
|
}
|
|
|
|
var errs []error
|
|
|
|
status.branches, errs = r.loadBranches()
|
|
for _, err := range errs {
|
|
status.errors = append(status.errors, err.Error())
|
|
}
|
|
|
|
status.worktree, err = r.loadWorkTree()
|
|
if err != nil {
|
|
status.errors = append(status.errors, err.Error())
|
|
}
|
|
|
|
status.remote, err = r.Remote()
|
|
if err != nil {
|
|
status.errors = append(status.errors, err.Error())
|
|
}
|
|
|
|
return status
|
|
}
|
|
|
|
func (r *Repo) loadBranches() (map[string]string, []error) {
|
|
statuses := make(map[string]string)
|
|
errors := make([]error, 0)
|
|
|
|
branches, err := r.Branches()
|
|
if err != nil {
|
|
errors = append(errors, err)
|
|
return statuses, errors
|
|
}
|
|
|
|
for _, branch := range branches {
|
|
status, err := r.loadBranchStatus(branch)
|
|
statuses[branch] = status
|
|
|
|
if err != nil {
|
|
errors = append(errors, err)
|
|
}
|
|
}
|
|
|
|
return statuses, errors
|
|
}
|
|
|
|
func (r *Repo) loadBranchStatus(branch string) (string, error) {
|
|
upstream, err := r.Upstream(branch)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if upstream == "" {
|
|
return "no upstream", nil
|
|
}
|
|
|
|
ahead, behind, err := r.AheadBehind(branch, upstream)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if ahead == 0 && behind == 0 {
|
|
return "", nil
|
|
}
|
|
|
|
var res []string
|
|
if ahead != 0 {
|
|
res = append(res, fmt.Sprintf("%d ahead", ahead))
|
|
}
|
|
|
|
if behind != 0 {
|
|
res = append(res, fmt.Sprintf("%d behind", behind))
|
|
}
|
|
|
|
return strings.Join(res, " "), nil
|
|
}
|
|
|
|
func (r *Repo) loadWorkTree() (string, error) {
|
|
uncommitted, err := r.Uncommitted()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
untracked, err := r.Untracked()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if uncommitted == 0 && untracked == 0 {
|
|
return "", nil
|
|
}
|
|
|
|
var res []string
|
|
if uncommitted != 0 {
|
|
res = append(res, fmt.Sprintf("%d uncommitted", uncommitted))
|
|
}
|
|
|
|
if untracked != 0 {
|
|
res = append(res, fmt.Sprintf("%d untracked", untracked))
|
|
}
|
|
|
|
return strings.Join(res, " "), nil
|
|
}
|
|
|
|
// Path returns path to a repository.
|
|
func (s *Status) Path() string {
|
|
return s.path
|
|
}
|
|
|
|
// Current returns the name of currently checked out branch (or tag or detached HEAD).
|
|
func (s *Status) Current() string {
|
|
return s.current
|
|
}
|
|
|
|
// Branches returns a list of all branches names except the currently checked out one. Use Current() to get its name.
|
|
func (s *Status) Branches() []string {
|
|
var branches []string
|
|
for b := range s.branches {
|
|
if b != s.current {
|
|
branches = append(branches, b)
|
|
}
|
|
}
|
|
|
|
return branches
|
|
}
|
|
|
|
// BranchStatus returns status of a given branch.
|
|
func (s *Status) BranchStatus(branch string) string {
|
|
return s.branches[branch]
|
|
}
|
|
|
|
// WorkTreeStatus returns status of a worktree.
|
|
func (s *Status) WorkTreeStatus() string {
|
|
return s.worktree
|
|
}
|
|
|
|
// Remote returns URL to remote repository.
|
|
func (s *Status) Remote() string {
|
|
return s.remote
|
|
}
|
|
|
|
// Errors is a slice of errors that occurred when loading repo status.
|
|
func (s *Status) Errors() []string {
|
|
return s.errors
|
|
}
|