diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-06-01 12:03:48 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-06-01 12:03:48 +0200 |
| commit | 7ac42b0295b4e88960fe9e81fc9bb630521923a9 (patch) | |
| tree | f322defe838dfe5047e774658c1f53ccc03bc03a | |
| parent | 4c777a22999258c9f0edb7cb3ca1914f64f6d082 (diff) | |
| parent | 4d6cb372add889a16f38d09803d0643d961b8dc0 (diff) | |
Merge pull request #213 from google/dvyukov-git
pkg/git: add new package
| -rw-r--r-- | pkg/git/git.go | 86 | ||||
| -rw-r--r-- | syz-gce/syz-gce.go | 49 |
2 files changed, 90 insertions, 45 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 +} diff --git a/syz-gce/syz-gce.go b/syz-gce/syz-gce.go index 9bdedbe5b..ddc410536 100644 --- a/syz-gce/syz-gce.go +++ b/syz-gce/syz-gce.go @@ -42,6 +42,7 @@ import ( "github.com/google/syzkaller/gce" . "github.com/google/syzkaller/log" pkgconfig "github.com/google/syzkaller/pkg/config" + "github.com/google/syzkaller/pkg/git" "github.com/google/syzkaller/syz-manager/config" "golang.org/x/net/context" ) @@ -302,7 +303,7 @@ func (a *SyzkallerAction) Poll() (string, error) { if _, err := runCmd("", "go", "get", "-u", "-d", "github.com/google/syzkaller/syz-manager"); err != nil { return "", err } - return gitRevision("gopath/src/github.com/google/syzkaller") + return git.HeadCommit("gopath/src/github.com/google/syzkaller") } func (a *SyzkallerAction) Build() error { @@ -346,32 +347,7 @@ func (a *LocalBuildAction) Name() string { func (a *LocalBuildAction) Poll() (string, error) { dir := filepath.Join(a.Dir, "linux") - runCmd(dir, "git", "reset", "--hard") - if _, err := runCmd(dir, "git", "pull"); 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) - } - cloneArgs := []string{"clone", a.Repo, "--single-branch", "--depth", "1"} - if a.Branch != "" { - cloneArgs = append(cloneArgs, "--branch", a.Branch) - } - cloneArgs = append(cloneArgs, dir) - if _, err := runCmd("", "git", cloneArgs...); err != nil { - return "", err - } - if _, err := runCmd(dir, "git", "pull"); err != nil { - return "", err - } - } - if a.Branch != "" { - if _, err := runCmd(dir, "git", "checkout", a.Branch); err != nil { - return "", err - } - } - rev, err := gitRevision(dir) + rev, err := git.Poll(dir, a.Repo, a.Branch) if err != nil { return "", err } @@ -383,7 +359,7 @@ func (a *LocalBuildAction) Poll() (string, error) { func (a *LocalBuildAction) Build() error { dir := filepath.Join(a.Dir, "linux") - hash, err := gitRevision(dir) + hash, err := git.HeadCommit(dir) if err != nil { return err } @@ -633,23 +609,6 @@ func uploadFile(localFile, gcsFile string) error { return nil } -func gitRevision(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 buildKernel(dir, ccompiler string) error { os.Remove(filepath.Join(dir, ".config")) if _, err := runCmd(dir, "make", "defconfig"); err != nil { |
