hub/git/git.go

267 строки
5.2 KiB
Go
Исходник Обычный вид История

2013-05-29 22:58:46 +04:00
package git
2013-04-22 07:36:21 +04:00
import (
2013-04-29 00:41:45 +04:00
"fmt"
"io/ioutil"
"os"
2013-04-24 14:00:45 +04:00
"path/filepath"
2013-04-22 07:36:21 +04:00
"strings"
2014-02-10 20:22:36 +04:00
"github.com/github/hub/cmd"
2013-04-22 07:36:21 +04:00
)
var GlobalFlags []string
2013-05-29 22:58:46 +04:00
func Version() (string, error) {
2015-01-13 09:13:23 +03:00
output, err := gitOutput("version")
2013-05-28 22:05:10 +04:00
if err != nil {
2013-12-11 01:10:49 +04:00
return "", fmt.Errorf("Can't load git version")
2013-05-28 22:05:10 +04:00
}
2013-05-28 21:52:27 +04:00
2013-05-29 00:14:40 +04:00
return output[0], nil
2013-05-28 21:52:27 +04:00
}
2013-05-29 22:58:46 +04:00
func Dir() (string, error) {
2015-01-13 09:13:23 +03:00
output, err := gitOutput("rev-parse", "-q", "--git-dir")
2013-04-24 14:00:45 +04:00
if err != nil {
2013-12-11 01:10:49 +04:00
return "", fmt.Errorf("Not a git repository (or any of the parent directories): .git")
2013-04-24 14:00:45 +04:00
}
var chdir string
for i, flag := range GlobalFlags {
if (flag == "-C") {
dir := GlobalFlags[i+1]
if (filepath.IsAbs(dir)) {
chdir = dir
} else {
chdir = filepath.Join(chdir, dir)
}
}
}
2013-05-24 09:41:06 +04:00
gitDir := output[0]
if (!filepath.IsAbs(gitDir)) {
if (chdir != "") {
gitDir = filepath.Join(chdir, gitDir)
}
gitDir, err = filepath.Abs(gitDir)
if err != nil {
return "", err
}
gitDir = filepath.Clean(gitDir)
2013-05-24 09:41:06 +04:00
}
return gitDir, nil
2013-04-22 07:36:21 +04:00
}
func HasFile(segments ...string) bool {
// The blessed way to resolve paths within git dir since Git 2.5.0
output, err := gitOutput("rev-parse", "-q", "--git-path", filepath.Join(segments...))
if err == nil && output[0] != "--git-path" {
if _, err := os.Stat(output[0]); err == nil {
return true
}
}
// Fallback for older git versions
dir, err := Dir()
if err != nil {
return false
}
s := []string{dir}
s = append(s, segments...)
path := filepath.Join(s...)
if _, err := os.Stat(path); err == nil {
return true
}
return false
}
2013-12-28 13:49:59 +04:00
func BranchAtRef(paths ...string) (name string, err error) {
dir, err := Dir()
if err != nil {
return
}
segments := []string{dir}
2013-12-28 13:49:59 +04:00
segments = append(segments, paths...)
path := filepath.Join(segments...)
b, err := ioutil.ReadFile(path)
if err != nil {
return
}
n := string(b)
2013-12-28 13:49:59 +04:00
refPrefix := "ref: "
if strings.HasPrefix(n, refPrefix) {
name = strings.TrimPrefix(n, refPrefix)
name = strings.TrimSpace(name)
} else {
err = fmt.Errorf("No branch info in %s: %s", path, n)
}
return
}
2013-05-29 22:58:46 +04:00
func Editor() (string, error) {
2015-01-13 09:13:23 +03:00
output, err := gitOutput("var", "GIT_EDITOR")
2013-05-24 09:41:06 +04:00
if err != nil {
2013-12-11 01:10:49 +04:00
return "", fmt.Errorf("Can't load git var: GIT_EDITOR")
2013-05-24 09:41:06 +04:00
}
return output[0], nil
2013-04-22 07:36:21 +04:00
}
func Head() (string, error) {
return BranchAtRef("HEAD")
}
func SymbolicFullName(name string) (string, error) {
2015-01-13 09:13:23 +03:00
output, err := gitOutput("rev-parse", "--symbolic-full-name", name)
if err != nil {
2013-12-11 01:10:49 +04:00
return "", fmt.Errorf("Unknown revision or path not in the working tree: %s", name)
}
return output[0], nil
2013-04-22 07:36:21 +04:00
}
2013-05-29 22:58:46 +04:00
func Ref(ref string) (string, error) {
2015-01-13 09:13:23 +03:00
output, err := gitOutput("rev-parse", "-q", ref)
2013-05-29 21:15:43 +04:00
if err != nil {
2013-12-11 01:10:49 +04:00
return "", fmt.Errorf("Unknown revision or path not in the working tree: %s", ref)
2013-05-29 21:15:43 +04:00
}
return output[0], nil
}
2013-12-02 20:28:47 +04:00
func RefList(a, b string) ([]string, error) {
ref := fmt.Sprintf("%s...%s", a, b)
2015-01-13 09:13:23 +03:00
output, err := gitOutput("rev-list", "--cherry-pick", "--right-only", "--no-merges", ref)
2013-12-02 20:28:47 +04:00
if err != nil {
return []string{}, fmt.Errorf("Can't load rev-list for %s", ref)
2013-12-02 20:28:47 +04:00
}
return output, nil
}
2014-07-16 02:44:48 +04:00
func CommentChar() string {
char, err := Config("core.commentchar")
if err != nil {
char = "#"
}
return char
}
func Show(sha string) (string, error) {
cmd := cmd.New("git")
2014-07-16 02:44:48 +04:00
cmd.WithArg("show").WithArg("-s").WithArg("--format=%s%n%+b").WithArg(sha)
output, err := cmd.CombinedOutput()
output = strings.TrimSpace(output)
return output, err
}
2013-05-29 22:58:46 +04:00
func Log(sha1, sha2 string) (string, error) {
execCmd := cmd.New("git")
2013-04-29 00:41:45 +04:00
execCmd.WithArg("log").WithArg("--no-color")
execCmd.WithArg("--format=%h (%aN, %ar)%n%w(78,3,3)%s%n%+b")
execCmd.WithArg("--cherry")
shaRange := fmt.Sprintf("%s...%s", sha1, sha2)
execCmd.WithArg(shaRange)
outputs, err := execCmd.CombinedOutput()
2013-04-29 00:41:45 +04:00
if err != nil {
2013-12-11 01:10:49 +04:00
return "", fmt.Errorf("Can't load git log %s..%s", sha1, sha2)
2013-04-29 00:41:45 +04:00
}
2013-05-24 09:41:06 +04:00
return outputs, nil
2013-04-29 00:41:45 +04:00
}
func Remotes() ([]string, error) {
2015-01-13 09:13:23 +03:00
return gitOutput("remote", "-v")
}
2013-06-29 02:15:41 +04:00
func Config(name string) (string, error) {
return gitGetConfig(name)
}
func GlobalConfig(name string) (string, error) {
return gitGetConfig("--global", name)
}
func SetGlobalConfig(name, value string) error {
_, err := gitConfig("--global", name, value)
return err
}
func gitGetConfig(args ...string) (string, error) {
2015-01-13 09:13:23 +03:00
output, err := gitOutput(gitConfigCommand(args)...)
2013-06-29 02:15:41 +04:00
if err != nil {
return "", fmt.Errorf("Unknown config %s", args[len(args)-1])
2013-06-29 02:15:41 +04:00
}
if len(output) == 0 {
return "", nil
}
2013-06-29 02:15:41 +04:00
return output[0], nil
}
func gitConfig(args ...string) ([]string, error) {
2015-01-13 09:13:23 +03:00
return gitOutput(gitConfigCommand(args)...)
}
func gitConfigCommand(args []string) []string {
cmd := []string{"config"}
return append(cmd, args...)
}
func Alias(name string) (string, error) {
return Config(fmt.Sprintf("alias.%s", name))
}
func Run(command string, args ...string) error {
2013-06-22 05:02:29 +04:00
cmd := cmd.New("git")
for _, v := range GlobalFlags {
cmd.WithArg(v)
}
2013-06-25 01:40:05 +04:00
cmd.WithArg(command)
2013-06-22 05:02:29 +04:00
for _, a := range args {
cmd.WithArg(a)
}
return cmd.Run()
2013-06-22 05:02:29 +04:00
}
2015-01-13 09:13:23 +03:00
func gitOutput(input ...string) (outputs []string, err error) {
2013-05-29 22:58:46 +04:00
cmd := cmd.New("git")
for _, v := range GlobalFlags {
cmd.WithArg(v)
}
2013-04-30 06:45:57 +04:00
for _, i := range input {
cmd.WithArg(i)
}
2013-04-22 07:36:21 +04:00
out, err := cmd.CombinedOutput()
2013-04-30 06:45:57 +04:00
for _, line := range strings.Split(out, "\n") {
line = strings.TrimSpace(line)
if line != "" {
outputs = append(outputs, string(line))
}
2013-04-22 07:36:21 +04:00
}
2013-06-25 00:43:59 +04:00
return outputs, err
2013-04-22 07:36:21 +04:00
}