github.com/echohead/hub@v2.2.1+incompatible/git/git.go (about)

     1  package git
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/github/hub/cmd"
    11  )
    12  
    13  var GlobalFlags []string
    14  
    15  func Version() (string, error) {
    16  	output, err := gitOutput("version")
    17  	if err != nil {
    18  		return "", fmt.Errorf("Can't load git version")
    19  	}
    20  
    21  	return output[0], nil
    22  }
    23  
    24  func Dir() (string, error) {
    25  	output, err := gitOutput("rev-parse", "-q", "--git-dir")
    26  	if err != nil {
    27  		return "", fmt.Errorf("Not a git repository (or any of the parent directories): .git")
    28  	}
    29  
    30  	gitDir := output[0]
    31  	gitDir, err = filepath.Abs(gitDir)
    32  	if err != nil {
    33  		return "", err
    34  	}
    35  
    36  	return gitDir, nil
    37  }
    38  
    39  func HasFile(segments ...string) bool {
    40  	dir, err := Dir()
    41  	if err != nil {
    42  		return false
    43  	}
    44  
    45  	s := []string{dir}
    46  	s = append(s, segments...)
    47  	path := filepath.Join(s...)
    48  	if _, err := os.Stat(path); err == nil {
    49  		return true
    50  	}
    51  
    52  	return false
    53  }
    54  
    55  func BranchAtRef(paths ...string) (name string, err error) {
    56  	dir, err := Dir()
    57  	if err != nil {
    58  		return
    59  	}
    60  
    61  	segments := []string{dir}
    62  	segments = append(segments, paths...)
    63  	path := filepath.Join(segments...)
    64  	b, err := ioutil.ReadFile(path)
    65  	if err != nil {
    66  		return
    67  	}
    68  
    69  	n := string(b)
    70  	refPrefix := "ref: "
    71  	if strings.HasPrefix(n, refPrefix) {
    72  		name = strings.TrimPrefix(n, refPrefix)
    73  		name = strings.TrimSpace(name)
    74  	} else {
    75  		err = fmt.Errorf("No branch info in %s: %s", path, n)
    76  	}
    77  
    78  	return
    79  }
    80  
    81  func Editor() (string, error) {
    82  	output, err := gitOutput("var", "GIT_EDITOR")
    83  	if err != nil {
    84  		return "", fmt.Errorf("Can't load git var: GIT_EDITOR")
    85  	}
    86  
    87  	return output[0], nil
    88  }
    89  
    90  func Head() (string, error) {
    91  	return BranchAtRef("HEAD")
    92  }
    93  
    94  func SymbolicFullName(name string) (string, error) {
    95  	output, err := gitOutput("rev-parse", "--symbolic-full-name", name)
    96  	if err != nil {
    97  		return "", fmt.Errorf("Unknown revision or path not in the working tree: %s", name)
    98  	}
    99  
   100  	return output[0], nil
   101  }
   102  
   103  func Ref(ref string) (string, error) {
   104  	output, err := gitOutput("rev-parse", "-q", ref)
   105  	if err != nil {
   106  		return "", fmt.Errorf("Unknown revision or path not in the working tree: %s", ref)
   107  	}
   108  
   109  	return output[0], nil
   110  }
   111  
   112  func RefList(a, b string) ([]string, error) {
   113  	ref := fmt.Sprintf("%s...%s", a, b)
   114  	output, err := gitOutput("rev-list", "--cherry-pick", "--right-only", "--no-merges", ref)
   115  	if err != nil {
   116  		return []string{}, fmt.Errorf("Can't load rev-list for %s", ref)
   117  	}
   118  
   119  	return output, nil
   120  }
   121  
   122  func CommentChar() string {
   123  	char, err := Config("core.commentchar")
   124  	if err != nil {
   125  		char = "#"
   126  	}
   127  
   128  	return char
   129  }
   130  
   131  func Show(sha string) (string, error) {
   132  	cmd := cmd.New("git")
   133  	cmd.WithArg("show").WithArg("-s").WithArg("--format=%s%n%+b").WithArg(sha)
   134  
   135  	output, err := cmd.CombinedOutput()
   136  	output = strings.TrimSpace(output)
   137  
   138  	return output, err
   139  }
   140  
   141  func Log(sha1, sha2 string) (string, error) {
   142  	execCmd := cmd.New("git")
   143  	execCmd.WithArg("log").WithArg("--no-color")
   144  	execCmd.WithArg("--format=%h (%aN, %ar)%n%w(78,3,3)%s%n%+b")
   145  	execCmd.WithArg("--cherry")
   146  	shaRange := fmt.Sprintf("%s...%s", sha1, sha2)
   147  	execCmd.WithArg(shaRange)
   148  
   149  	outputs, err := execCmd.CombinedOutput()
   150  	if err != nil {
   151  		return "", fmt.Errorf("Can't load git log %s..%s", sha1, sha2)
   152  	}
   153  
   154  	return outputs, nil
   155  }
   156  
   157  func Remotes() ([]string, error) {
   158  	return gitOutput("remote", "-v")
   159  }
   160  
   161  func Config(name string) (string, error) {
   162  	return gitGetConfig(name)
   163  }
   164  
   165  func GlobalConfig(name string) (string, error) {
   166  	return gitGetConfig("--global", name)
   167  }
   168  
   169  func SetGlobalConfig(name, value string) error {
   170  	_, err := gitConfig("--global", name, value)
   171  	return err
   172  }
   173  
   174  func gitGetConfig(args ...string) (string, error) {
   175  	output, err := gitOutput(gitConfigCommand(args)...)
   176  	if err != nil {
   177  		return "", fmt.Errorf("Unknown config %s", args[len(args)-1])
   178  	}
   179  
   180  	if len(output) == 0 {
   181  		return "", nil
   182  	}
   183  
   184  	return output[0], nil
   185  }
   186  
   187  func gitConfig(args ...string) ([]string, error) {
   188  	return gitOutput(gitConfigCommand(args)...)
   189  }
   190  
   191  func gitConfigCommand(args []string) []string {
   192  	cmd := []string{"config"}
   193  	return append(cmd, args...)
   194  }
   195  
   196  func Alias(name string) (string, error) {
   197  	return Config(fmt.Sprintf("alias.%s", name))
   198  }
   199  
   200  func Run(command string, args ...string) error {
   201  	cmd := cmd.New("git")
   202  
   203  	for _, v := range GlobalFlags {
   204  		cmd.WithArg(v)
   205  	}
   206  
   207  	cmd.WithArg(command)
   208  
   209  	for _, a := range args {
   210  		cmd.WithArg(a)
   211  	}
   212  
   213  	return cmd.Run()
   214  }
   215  
   216  func gitOutput(input ...string) (outputs []string, err error) {
   217  	cmd := cmd.New("git")
   218  
   219  	for _, v := range GlobalFlags {
   220  		cmd.WithArg(v)
   221  	}
   222  
   223  	for _, i := range input {
   224  		cmd.WithArg(i)
   225  	}
   226  
   227  	out, err := cmd.CombinedOutput()
   228  	for _, line := range strings.Split(out, "\n") {
   229  		line = strings.TrimSpace(line)
   230  		if line != "" {
   231  			outputs = append(outputs, string(line))
   232  		}
   233  	}
   234  
   235  	return outputs, err
   236  }