github.com/cli/cli@v1.14.1-0.20210902173923-1af6a669e342/pkg/cmd/repo/sync/git.go (about)

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