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  }