diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-06-01 12:01:51 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-06-01 12:01:51 +0200 |
| commit | 4d6cb372add889a16f38d09803d0643d961b8dc0 (patch) | |
| tree | b0eaee8583f014d243500a70d33172c38a1ec896 /pkg | |
| parent | de6eb51045aeb6509b6087d5a4ed37a79496d15b (diff) | |
pkg/git: add new package
Move few helper git-related functions from syz-gce
to a separate pkg/git package.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/git/git.go | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/pkg/git/git.go b/pkg/git/git.go new file mode 100644 index 000000000..773535cb7 --- /dev/null +++ b/pkg/git/git.go @@ -0,0 +1,86 @@ +// Copyright 2017 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// Package git provides helper functions for working with git repositories. +package git + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "time" +) + +// Poll checkouts the specified repository/branch in dir. +// This involves fetching/resetting/cloning as necessary to recover from all possible problems. +// Returns hash of the HEAD commit in the specified branch. +func Poll(dir, repo, branch string) (string, error) { + runCmd(dir, "git", "reset", "--hard") + if _, err := runCmd(dir, "git", "fetch", "--no-tags", "--depth=", "1"); err != nil { + if err := os.RemoveAll(dir); err != nil { + return "", fmt.Errorf("failed to remove repo dir: %v", err) + } + if err := os.MkdirAll(dir, 0700); err != nil { + return "", fmt.Errorf("failed to create repo dir: %v", err) + } + args := []string{ + "clone", + repo, + "--no-tags", + "--depth", "1", + "--single-branch", + "--branch", branch, + dir, + } + if _, err := runCmd("", "git", args...); err != nil { + return "", err + } + } + if _, err := runCmd(dir, "git", "checkout", branch); err != nil { + return "", err + } + return HeadCommit(dir) +} + +// HeadCommit returns hash of the HEAD commit of the current branch of git repository in dir. +func HeadCommit(dir string) (string, error) { + output, err := runCmd(dir, "git", "log", "--pretty=format:'%H'", "-n", "1") + if err != nil { + return "", err + } + if len(output) != 0 && output[len(output)-1] == '\n' { + output = output[:len(output)-1] + } + if len(output) != 0 && output[0] == '\'' && output[len(output)-1] == '\'' { + output = output[1 : len(output)-1] + } + if len(output) != 40 { + return "", fmt.Errorf("unexpected git log output, want commit hash: %q", output) + } + return string(output), nil +} + +func runCmd(dir, bin string, args ...string) ([]byte, error) { + output := new(bytes.Buffer) + cmd := exec.Command(bin, args...) + cmd.Dir = dir + cmd.Stdout = output + cmd.Stderr = output + if err := cmd.Start(); err != nil { + return nil, fmt.Errorf("failed to start %v %+v: %v", bin, args, err) + } + done := make(chan bool) + go func() { + select { + case <-time.After(time.Hour): + cmd.Process.Kill() + case <-done: + } + }() + defer close(done) + if err := cmd.Wait(); err != nil { + return nil, fmt.Errorf("failed to run %v %+v: %v\n%v", bin, args, err, output.String()) + } + return output.Bytes(), nil +} |
