From ce6744512e81ac2e291fea247d55fb0bf8e703e2 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sun, 16 Dec 2018 16:18:06 +0100 Subject: pkg/vcs: fix fetching of commits on non master branch Fixes #728 --- pkg/vcs/git.go | 12 +++- pkg/vcs/git_repo_test.go | 163 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 pkg/vcs/git_repo_test.go (limited to 'pkg/vcs') diff --git a/pkg/vcs/git.go b/pkg/vcs/git.go index bc0e05373..f73c47c58 100644 --- a/pkg/vcs/git.go +++ b/pkg/vcs/git.go @@ -16,6 +16,7 @@ import ( "strings" "time" + "github.com/google/syzkaller/pkg/hash" "github.com/google/syzkaller/pkg/osutil" ) @@ -87,13 +88,20 @@ func (git *git) CheckoutCommit(repo, commit string) (*Commit, error) { return nil, err } } - _, err := runSandboxed(dir, "git", "fetch", repo) - if err != nil { + if err := git.fetchRemote(repo); err != nil { return nil, err } return git.SwitchCommit(commit) } +func (git *git) fetchRemote(repo string) error { + repoHash := hash.String([]byte(repo)) + // Ignore error as we can double add the same remote and that will fail. + runSandboxed(git.dir, "git", "remote", "add", repoHash, repo) + _, err := runSandboxed(git.dir, "git", "fetch", repoHash) + return err +} + func (git *git) SwitchCommit(commit string) (*Commit, error) { dir := git.dir if _, err := runSandboxed(dir, "git", "checkout", commit); err != nil { diff --git a/pkg/vcs/git_repo_test.go b/pkg/vcs/git_repo_test.go new file mode 100644 index 000000000..e6f94c117 --- /dev/null +++ b/pkg/vcs/git_repo_test.go @@ -0,0 +1,163 @@ +// 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 vcs + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/syzkaller/pkg/osutil" +) + +func TestGitRepo(t *testing.T) { + baseDir, err := ioutil.TempDir("", "syz-git-test") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(baseDir) + repo1 := createTestRepo(t, baseDir, "repo1") + repo2 := createTestRepo(t, baseDir, "repo2") + repo := newGit(filepath.Join(baseDir, "repo")) + { + com, err := repo.Poll(repo1.dir, "master") + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(com, repo1.commits["master"]["1"]); diff != "" { + t.Fatal(diff) + } + } + { + com, err := repo.CheckoutBranch(repo1.dir, "branch1") + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(com, repo1.commits["branch1"]["1"]); diff != "" { + t.Fatal(diff) + } + } + { + want := repo1.commits["branch1"]["0"] + com, err := repo.CheckoutCommit(repo1.dir, want.Hash) + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(com, want); diff != "" { + t.Fatal(diff) + } + } + { + commits, err := repo.ListRecentCommits(repo1.commits["branch1"]["1"].Hash) + if err != nil { + t.Fatal(err) + } + want := []string{"repo1-branch1-1", "repo1-branch1-0", "repo1-master-0"} + if diff := cmp.Diff(commits, want); diff != "" { + t.Fatal(diff) + } + } + { + want := repo2.commits["branch1"]["0"] + com, err := repo.CheckoutCommit(repo2.dir, want.Hash) + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(com, want); diff != "" { + t.Fatal(diff) + } + } + { + want := repo2.commits["branch1"]["1"] + com, err := repo.CheckoutCommit(repo2.dir, want.Hash) + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(com, want); diff != "" { + t.Fatal(diff) + } + } + { + com, err := repo.CheckoutBranch(repo2.dir, "branch2") + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(com, repo2.commits["branch2"]["1"]); diff != "" { + t.Fatal(diff) + } + } + { + want := repo2.commits["branch2"]["0"] + com, err := repo.SwitchCommit(want.Hash) + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(com, want); diff != "" { + t.Fatal(diff) + } + } +} + +func createTestRepo(t *testing.T, baseDir, name string) *testRepo { + repo := makeTestRepo(t, filepath.Join(baseDir, name)) + repo.git("checkout", "-b", "master") + repo.commitFileChange("master", "0") + for _, branch := range []string{"branch1", "branch2"} { + repo.git("checkout", "-b", branch, "master") + repo.commitFileChange(branch, "0") + repo.commitFileChange(branch, "1") + } + repo.git("checkout", "master") + repo.commitFileChange("master", "1") + return repo +} + +type testRepo struct { + t *testing.T + dir string + name string + commits map[string]map[string]*Commit +} + +func makeTestRepo(t *testing.T, dir string) *testRepo { + if err := osutil.MkdirAll(dir); err != nil { + t.Fatal(err) + } + repo := &testRepo{ + t: t, + dir: dir, + name: filepath.Base(dir), + commits: make(map[string]map[string]*Commit), + } + repo.git("init") + return repo +} + +func (repo *testRepo) git(args ...string) { + if _, err := osutil.RunCmd(time.Minute, repo.dir, "git", args...); err != nil { + repo.t.Fatal(err) + } +} + +func (repo *testRepo) commitFileChange(branch, change string) { + id := fmt.Sprintf("%v-%v-%v", repo.name, branch, change) + file := filepath.Join(repo.dir, "file") + if err := osutil.WriteFile(file, []byte(id)); err != nil { + repo.t.Fatal(err) + } + repo.git("add", file) + repo.git("commit", "-m", id) + if repo.commits[branch] == nil { + repo.commits[branch] = make(map[string]*Commit) + } + com, err := newGit(repo.dir).HeadCommit() + if err != nil { + repo.t.Fatal(err) + } + repo.commits[branch][change] = com +} -- cgit mrf-deployment