github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/repo/sync/git.go (about) 1 package sync 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 8 "github.com/ungtb10d/cli/v2/git" 9 ) 10 11 type gitClient interface { 12 BranchRemote(string) (string, error) 13 CurrentBranch() (string, error) 14 UpdateBranch(string, string) error 15 CreateBranch(string, string, string) error 16 Fetch(string, string) error 17 HasLocalBranch(string) bool 18 IsAncestor(string, string) (bool, error) 19 IsDirty() (bool, error) 20 MergeFastForward(string) error 21 ResetHard(string) error 22 } 23 24 type gitExecuter struct { 25 client *git.Client 26 } 27 28 func (g *gitExecuter) BranchRemote(branch string) (string, error) { 29 args := []string{"rev-parse", "--symbolic-full-name", "--abbrev-ref", fmt.Sprintf("%s@{u}", branch)} 30 cmd, err := g.client.Command(context.Background(), args...) 31 if err != nil { 32 return "", err 33 } 34 out, err := cmd.Output() 35 if err != nil { 36 return "", err 37 } 38 parts := strings.SplitN(string(out), "/", 2) 39 return parts[0], nil 40 } 41 42 func (g *gitExecuter) UpdateBranch(branch, ref string) error { 43 cmd, err := g.client.Command(context.Background(), "update-ref", fmt.Sprintf("refs/heads/%s", branch), ref) 44 if err != nil { 45 return err 46 } 47 _, err = cmd.Output() 48 return err 49 } 50 51 func (g *gitExecuter) CreateBranch(branch, ref, upstream string) error { 52 ctx := context.Background() 53 cmd, err := g.client.Command(ctx, "branch", branch, ref) 54 if err != nil { 55 return err 56 } 57 if _, err := cmd.Output(); err != nil { 58 return err 59 } 60 cmd, err = g.client.Command(ctx, "branch", "--set-upstream-to", upstream, branch) 61 if err != nil { 62 return err 63 } 64 _, err = cmd.Output() 65 return err 66 } 67 68 func (g *gitExecuter) CurrentBranch() (string, error) { 69 return g.client.CurrentBranch(context.Background()) 70 } 71 72 func (g *gitExecuter) Fetch(remote, ref string) error { 73 args := []string{"fetch", "-q", remote, ref} 74 cmd, err := g.client.Command(context.Background(), args...) 75 if err != nil { 76 return err 77 } 78 return cmd.Run() 79 } 80 81 func (g *gitExecuter) HasLocalBranch(branch string) bool { 82 return g.client.HasLocalBranch(context.Background(), branch) 83 } 84 85 func (g *gitExecuter) IsAncestor(ancestor, progeny string) (bool, error) { 86 args := []string{"merge-base", "--is-ancestor", ancestor, progeny} 87 cmd, err := g.client.Command(context.Background(), args...) 88 if err != nil { 89 return false, err 90 } 91 _, err = cmd.Output() 92 return err == nil, nil 93 } 94 95 func (g *gitExecuter) IsDirty() (bool, error) { 96 changeCount, err := g.client.UncommittedChangeCount(context.Background()) 97 if err != nil { 98 return false, err 99 } 100 return changeCount != 0, nil 101 } 102 103 func (g *gitExecuter) MergeFastForward(ref string) error { 104 args := []string{"merge", "--ff-only", "--quiet", ref} 105 cmd, err := g.client.Command(context.Background(), args...) 106 if err != nil { 107 return err 108 } 109 _, err = cmd.Output() 110 return err 111 } 112 113 func (g *gitExecuter) ResetHard(ref string) error { 114 args := []string{"reset", "--hard", ref} 115 cmd, err := g.client.Command(context.Background(), args...) 116 if err != nil { 117 return err 118 } 119 _, err = cmd.Output() 120 return err 121 }