aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkg/vcs/fuchsia.go4
-rw-r--r--pkg/vcs/git.go396
-rw-r--r--pkg/vcs/git_repo_test.go2
-rw-r--r--pkg/vcs/git_test.go6
-rw-r--r--pkg/vcs/git_test_util.go6
-rw-r--r--pkg/vcs/linux.go18
-rw-r--r--pkg/vcs/linux_patches.go6
-rw-r--r--pkg/vcs/testos.go6
-rw-r--r--pkg/vcs/vcs.go10
9 files changed, 245 insertions, 209 deletions
diff --git a/pkg/vcs/fuchsia.go b/pkg/vcs/fuchsia.go
index 4a119baeb..ff5f5cd57 100644
--- a/pkg/vcs/fuchsia.go
+++ b/pkg/vcs/fuchsia.go
@@ -16,7 +16,7 @@ import (
// rather than fuchsia.git.
type fuchsia struct {
dir string
- repo *git
+ repo *gitRepo
}
func newFuchsia(dir string, opts []RepoOpt) *fuchsia {
@@ -26,7 +26,7 @@ func newFuchsia(dir string, opts []RepoOpt) *fuchsia {
opts = append(opts, OptPrecious)
return &fuchsia{
dir: dir,
- repo: newGit(dir, nil, opts),
+ repo: newGitRepo(dir, nil, opts),
}
}
diff --git a/pkg/vcs/git.go b/pkg/vcs/git.go
index d8a4967ba..fd71b8d36 100644
--- a/pkg/vcs/git.go
+++ b/pkg/vcs/git.go
@@ -22,25 +22,25 @@ import (
"github.com/google/syzkaller/pkg/osutil"
)
-type git struct {
- dir string
- ignoreCC map[string]bool
- precious bool
- sandbox bool
+type gitRepo struct {
+ *Git
}
-func newGit(dir string, ignoreCC map[string]bool, opts []RepoOpt) *git {
- git := &git{
- dir: dir,
- ignoreCC: ignoreCC,
- sandbox: true,
+func newGitRepo(dir string, ignoreCC map[string]bool, opts []RepoOpt) *gitRepo {
+ git := &gitRepo{
+ Git: &Git{
+ Dir: dir,
+ Sandbox: true,
+ Env: filterEnv(),
+ ignoreCC: ignoreCC,
+ },
}
for _, opt := range opts {
switch opt {
case OptPrecious:
git.precious = true
case OptDontSandbox:
- git.sandbox = false
+ git.Sandbox = false
}
}
return git
@@ -66,9 +66,9 @@ func filterEnv() []string {
return env
}
-func (git *git) Poll(repo, branch string) (*Commit, error) {
- git.reset()
- origin, err := git.git("remote", "get-url", "origin")
+func (git *gitRepo) Poll(repo, branch string) (*Commit, error) {
+ git.Reset()
+ origin, err := git.Run("remote", "get-url", "origin")
if err != nil || strings.TrimSpace(string(origin)) != repo {
// The repo is here, but it has wrong origin (e.g. repo in config has changed), re-clone.
if err := git.clone(repo, branch); err != nil {
@@ -78,28 +78,28 @@ func (git *git) Poll(repo, branch string) (*Commit, error) {
// Use origin/branch for the case the branch was force-pushed,
// in such case branch is not the same is origin/branch and we will
// stuck with the local version forever (git checkout won't fail).
- if _, err := git.git("checkout", "origin/"+branch); err != nil {
+ if _, err := git.Run("checkout", "origin/"+branch); err != nil {
// No such branch (e.g. branch in config has changed), re-clone.
if err := git.clone(repo, branch); err != nil {
return nil, err
}
}
- if _, err := git.git("fetch", "--force"); err != nil {
+ if _, err := git.Run("fetch", "--force"); err != nil {
// Something else is wrong, re-clone.
if err := git.clone(repo, branch); err != nil {
return nil, err
}
}
- if _, err := git.git("checkout", "origin/"+branch); err != nil {
+ if _, err := git.Run("checkout", "origin/"+branch); err != nil {
return nil, err
}
- if _, err := git.git("submodule", "update", "--init"); err != nil {
+ if _, err := git.Run("submodule", "update", "--init"); err != nil {
return nil, err
}
return git.Commit(HEAD)
}
-func (git *git) CheckoutBranch(repo, branch string) (*Commit, error) {
+func (git *gitRepo) CheckoutBranch(repo, branch string) (*Commit, error) {
if err := git.repair(); err != nil {
return nil, err
}
@@ -108,17 +108,17 @@ func (git *git) CheckoutBranch(repo, branch string) (*Commit, error) {
// remote when initializing.
// This sets "origin" to be the current remote.
// Ignore errors as we can double add or remove the same remote and that will fail.
- git.git("remote", "rm", "origin")
- git.git("remote", "add", "origin", repo)
- git.git("remote", "add", repoHash, repo)
- _, err := git.git("fetch", "--force", repoHash, branch)
+ git.Run("remote", "rm", "origin")
+ git.Run("remote", "add", "origin", repo)
+ git.Run("remote", "add", repoHash, repo)
+ _, err := git.Run("fetch", "--force", repoHash, branch)
if err != nil {
return nil, err
}
- if _, err := git.git("checkout", "FETCH_HEAD", "--force"); err != nil {
+ if _, err := git.Run("checkout", "FETCH_HEAD", "--force"); err != nil {
return nil, err
}
- if _, err := git.git("submodule", "update", "--init"); err != nil {
+ if _, err := git.Run("submodule", "update", "--init"); err != nil {
return nil, err
}
// If the branch checkout had to be "forced" the directory may
@@ -130,7 +130,7 @@ func (git *git) CheckoutBranch(repo, branch string) (*Commit, error) {
return git.Commit(HEAD)
}
-func (git *git) CheckoutCommit(repo, commit string) (*Commit, error) {
+func (git *gitRepo) CheckoutCommit(repo, commit string) (*Commit, error) {
if err := git.repair(); err != nil {
return nil, err
}
@@ -140,16 +140,16 @@ func (git *git) CheckoutCommit(repo, commit string) (*Commit, error) {
return git.SwitchCommit(commit)
}
-func (git *git) fetchRemote(repo, commit string) error {
+func (git *gitRepo) fetchRemote(repo, commit string) error {
repoHash := hash.String([]byte(repo))
// Ignore error as we can double add the same remote and that will fail.
- git.git("remote", "add", repoHash, repo)
+ git.Run("remote", "add", repoHash, repo)
fetchArgs := []string{"fetch", "--force", "--tags", repoHash}
if commit != "" && gitFullHashRe.MatchString(commit) {
// This trick only works with full commit hashes.
fetchArgs = append(fetchArgs, commit)
}
- _, err := git.git(fetchArgs...)
+ _, err := git.Run(fetchArgs...)
if err != nil {
var verbose *osutil.VerboseError
if errors.As(err, &verbose) &&
@@ -159,110 +159,75 @@ func (git *git) fetchRemote(repo, commit string) error {
// Try to fetch more, but this time prune tags, it should help.
// The --prune-tags option will remove all tags that are not present
// in this remote repo, so don't do it always. Only when necessary.
- _, err = git.git("fetch", "--force", "--tags", "--prune", "--prune-tags", repoHash)
+ _, err = git.Run("fetch", "--force", "--tags", "--prune", "--prune-tags", repoHash)
}
}
return err
}
-func (git *git) SwitchCommit(commit string) (*Commit, error) {
+func (git *gitRepo) SwitchCommit(commit string) (*Commit, error) {
if !git.precious {
- git.git("reset", "--hard")
- git.git("clean", "-fdx")
+ git.Run("reset", "--hard")
+ git.Run("clean", "-fdx")
}
- if _, err := git.git("checkout", commit); err != nil {
+ if _, err := git.Run("checkout", commit); err != nil {
return nil, err
}
- if _, err := git.git("submodule", "update", "--init"); err != nil {
+ if _, err := git.Run("submodule", "update", "--init"); err != nil {
return nil, err
}
return git.Commit(HEAD)
}
-func (git *git) clone(repo, branch string) error {
+func (git *gitRepo) clone(repo, branch string) error {
if git.precious {
return fmt.Errorf("won't reinit precious repo")
}
if err := git.initRepo(nil); err != nil {
return err
}
- if _, err := git.git("remote", "add", "origin", repo); err != nil {
+ if _, err := git.Run("remote", "add", "origin", repo); err != nil {
return err
}
- if _, err := git.git("fetch", "origin", branch); err != nil {
+ if _, err := git.Run("fetch", "origin", branch); err != nil {
return err
}
return nil
}
-func (git *git) reset() error {
- // This function tries to reset git repo state to a known clean state.
- if git.precious {
- return nil
- }
- git.git("reset", "--hard", "--recurse-submodules")
- git.git("clean", "-xfdf")
- git.git("submodule", "foreach", "--recursive", "git", "clean", "-xfdf")
- git.git("bisect", "reset")
- _, err := git.git("reset", "--hard", "--recurse-submodules")
- return err
-}
-
-func (git *git) repair() error {
- if err := git.reset(); err != nil {
+func (git *gitRepo) repair() error {
+ if err := git.Reset(); err != nil {
return git.initRepo(err)
}
return nil
}
-func (git *git) initRepo(reason error) error {
+func (git *gitRepo) initRepo(reason error) error {
if reason != nil {
- log.Logf(1, "git: initializing repo at %v: %v", git.dir, reason)
+ log.Logf(1, "git: initializing repo at %v: %v", git.Dir, reason)
}
- if err := os.RemoveAll(git.dir); err != nil {
+ if err := os.RemoveAll(git.Dir); err != nil {
return fmt.Errorf("failed to remove repo dir: %w", err)
}
- if err := osutil.MkdirAll(git.dir); err != nil {
+ if err := osutil.MkdirAll(git.Dir); err != nil {
return fmt.Errorf("failed to create repo dir: %w", err)
}
- if git.sandbox {
- if err := osutil.SandboxChown(git.dir); err != nil {
+ if git.Sandbox {
+ if err := osutil.SandboxChown(git.Dir); err != nil {
return err
}
}
- if _, err := git.git("init"); err != nil {
+ if _, err := git.Run("init"); err != nil {
return err
}
return nil
}
-func (git *git) Contains(commit string) (bool, error) {
- _, err := git.git("merge-base", "--is-ancestor", commit, HEAD)
+func (git *gitRepo) Contains(commit string) (bool, error) {
+ _, err := git.Run("merge-base", "--is-ancestor", commit, HEAD)
return err == nil, nil
}
-func (git *git) Commit(com string) (*Commit, error) {
- const patchSeparator = "---===syzkaller-patch-separator===---"
- output, err := git.git("log", "--format=%H%n%s%n%ae%n%an%n%ad%n%P%n%cd%n%b"+patchSeparator,
- "-n", "1", "-p", "-U0", com)
- if err != nil {
- return nil, err
- }
- pos := bytes.Index(output, []byte(patchSeparator))
- if pos == -1 {
- return nil, fmt.Errorf("git log output does not contain patch separator")
- }
- commit, err := gitParseCommit(output[:pos], nil, nil, git.ignoreCC)
- if err != nil {
- return nil, err
- }
- commit.Patch = output[pos+len(patchSeparator):]
- for len(commit.Patch) != 0 && commit.Patch[0] == '\n' {
- commit.Patch = commit.Patch[1:]
- }
- return commit, nil
-}
-
func gitParseCommit(output, user, domain []byte, ignoreCC map[string]bool) (*Commit, error) {
lines := bytes.Split(output, []byte{'\n'})
if len(lines) < 8 || len(lines[0]) != 40 {
@@ -340,7 +305,7 @@ func gitParseCommit(output, user, domain []byte, ignoreCC map[string]bool) (*Com
return com, nil
}
-func (git *git) GetCommitByTitle(title string) (*Commit, error) {
+func (git *gitRepo) GetCommitByTitle(title string) (*Commit, error) {
commits, _, err := git.GetCommitsByTitles([]string{title})
if err != nil || len(commits) == 0 {
return nil, err
@@ -352,7 +317,7 @@ const (
fetchCommitsMaxAgeInYears = 5
)
-func (git *git) GetCommitsByTitles(titles []string) ([]*Commit, []string, error) {
+func (git *gitRepo) GetCommitsByTitles(titles []string) ([]*Commit, []string, error) {
var greps []string
m := make(map[string]string)
for _, title := range titles {
@@ -381,12 +346,12 @@ func (git *git) GetCommitsByTitles(titles []string) ([]*Commit, []string, error)
return results, missing, nil
}
-func (git *git) ListCommitHashes(baseCommit string, from time.Time) ([]string, error) {
+func (git *gitRepo) ListCommitHashes(baseCommit string, from time.Time) ([]string, error) {
args := []string{"log", "--pretty=format:%h"}
if !from.IsZero() {
args = append(args, "--since", from.Format(time.RFC3339))
}
- output, err := git.git(append(args, baseCommit)...)
+ output, err := git.Run(append(args, baseCommit)...)
if err != nil {
return nil, err
}
@@ -396,7 +361,7 @@ func (git *git) ListCommitHashes(baseCommit string, from time.Time) ([]string, e
return strings.Split(string(output), "\n"), nil
}
-func (git *git) ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit, error) {
+func (git *gitRepo) ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit, error) {
user, domain, err := splitEmail(email)
if err != nil {
return nil, fmt.Errorf("failed to parse email %q: %w", email, err)
@@ -406,76 +371,6 @@ func (git *git) ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit,
return git.fetchCommits(since, baseCommit, user, domain, []string{grep}, false)
}
-func (git *git) fetchCommits(since, base, user, domain string, greps []string, fixedStrings bool) ([]*Commit, error) {
- const commitSeparator = "---===syzkaller-commit-separator===---"
- args := []string{"log", "--since", since, "--format=%H%n%s%n%ae%n%an%n%ad%n%P%n%cd%n%b%n" + commitSeparator}
- if fixedStrings {
- args = append(args, "--fixed-strings")
- }
- for _, grep := range greps {
- args = append(args, "--grep", grep)
- }
- args = append(args, base)
- cmd := exec.Command("git", args...)
- cmd.Dir = git.dir
- cmd.Env = filterEnv()
- if git.sandbox {
- if err := osutil.Sandbox(cmd, true, false); err != nil {
- return nil, err
- }
- }
- stdout, err := cmd.StdoutPipe()
- if err != nil {
- return nil, err
- }
- if err := cmd.Start(); err != nil {
- return nil, err
- }
- defer cmd.Wait()
- defer cmd.Process.Kill()
- var (
- s = bufio.NewScanner(stdout)
- buf = new(bytes.Buffer)
- separator = []byte(commitSeparator)
- commits []*Commit
- userBytes []byte
- domainBytes []byte
- )
- if user != "" {
- userBytes = []byte(user + "+")
- domainBytes = []byte(domain)
- }
- for s.Scan() {
- ln := s.Bytes()
- if !bytes.Equal(ln, separator) {
- buf.Write(ln)
- buf.WriteByte('\n')
- continue
- }
- com, err := gitParseCommit(buf.Bytes(), userBytes, domainBytes, git.ignoreCC)
- if err != nil {
- return nil, err
- }
- if user == "" || len(com.Tags) != 0 {
- commits = append(commits, com)
- }
- buf.Reset()
- }
- return commits, s.Err()
-}
-
-func (git *git) git(args ...string) ([]byte, error) {
- cmd := osutil.Command("git", args...)
- cmd.Dir = git.dir
- cmd.Env = filterEnv()
- if git.sandbox {
- if err := osutil.Sandbox(cmd, true, false); err != nil {
- return nil, err
- }
- }
- return osutil.Run(3*time.Hour, cmd)
-}
-
func splitEmail(email string) (user, domain string, err error) {
addr, err := mail.ParseAddress(email)
if err != nil {
@@ -493,18 +388,18 @@ func splitEmail(email string) (user, domain string, err error) {
return
}
-func (git *git) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult,
+func (git *gitRepo) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult,
error)) ([]*Commit, error) {
- git.reset()
+ git.Reset()
firstBad, err := git.Commit(bad)
if err != nil {
return nil, err
}
- output, err := git.git("bisect", "start", bad, good)
+ output, err := git.Run("bisect", "start", bad, good)
if err != nil {
return nil, err
}
- defer git.reset()
+ defer git.Reset()
dt.Log("# git bisect start %v %v\n%s", bad, good, output)
current, err := git.Commit(HEAD)
if err != nil {
@@ -518,14 +413,14 @@ func (git *git) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func()
for {
res, err := pred()
// Linux EnvForCommit may cherry-pick some fixes, reset these before the next step.
- git.git("reset", "--hard")
+ git.Run("reset", "--hard")
if err != nil {
return nil, err
}
if res == BisectBad {
firstBad = current
}
- output, err = git.git("bisect", bisectTerms[res])
+ output, err = git.Run("bisect", bisectTerms[res])
dt.Log("# git bisect %v %v\n%s", bisectTerms[res], current.Hash, output)
if err != nil {
if bytes.Contains(output, []byte("There are only 'skip'ped commits left to test")) {
@@ -546,7 +441,7 @@ func (git *git) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func()
var gitFullHashRe = regexp.MustCompile("[a-f0-9]{40}")
-func (git *git) bisectInconclusive(output []byte) ([]*Commit, error) {
+func (git *gitRepo) bisectInconclusive(output []byte) ([]*Commit, error) {
// For inconclusive bisection git prints the following message:
//
// There are only 'skip'ped commits left to test.
@@ -570,7 +465,7 @@ func (git *git) bisectInconclusive(output []byte) ([]*Commit, error) {
return commits, nil
}
-func (git *git) ReleaseTag(commit string) (string, error) {
+func (git *gitRepo) ReleaseTag(commit string) (string, error) {
tags, err := git.previousReleaseTags(commit, true, true, true)
if err != nil {
return "", err
@@ -581,10 +476,10 @@ func (git *git) ReleaseTag(commit string) (string, error) {
return tags[0], nil
}
-func (git *git) previousReleaseTags(commit string, self, onlyTop, includeRC bool) ([]string, error) {
+func (git *gitRepo) previousReleaseTags(commit string, self, onlyTop, includeRC bool) ([]string, error) {
var tags []string
if self {
- output, err := git.git("tag", "--list", "--points-at", commit, "--merged", commit, "v*.*")
+ output, err := git.Run("tag", "--list", "--points-at", commit, "--merged", commit, "v*.*")
if err != nil {
return nil, err
}
@@ -593,7 +488,7 @@ func (git *git) previousReleaseTags(commit string, self, onlyTop, includeRC bool
return tags, nil
}
}
- output, err := git.git("tag", "--no-contains", commit, "--merged", commit, "v*.*")
+ output, err := git.Run("tag", "--no-contains", commit, "--merged", commit, "v*.*")
if err != nil {
return nil, err
}
@@ -605,7 +500,7 @@ func (git *git) previousReleaseTags(commit string, self, onlyTop, includeRC bool
return tags, nil
}
-func (git *git) IsRelease(commit string) (bool, error) {
+func (git *gitRepo) IsRelease(commit string) (bool, error) {
tags1, err := git.previousReleaseTags(commit, true, false, false)
if err != nil {
return false, err
@@ -617,12 +512,12 @@ func (git *git) IsRelease(commit string) (bool, error) {
return len(tags1) != len(tags2), nil
}
-func (git *git) Object(name, commit string) ([]byte, error) {
- return git.git("show", fmt.Sprintf("%s:%s", commit, name))
+func (git *gitRepo) Object(name, commit string) ([]byte, error) {
+ return git.Run("show", fmt.Sprintf("%s:%s", commit, name))
}
-func (git *git) MergeBases(firstCommit, secondCommit string) ([]*Commit, error) {
- output, err := git.git("merge-base", firstCommit, secondCommit)
+func (git *gitRepo) MergeBases(firstCommit, secondCommit string) ([]*Commit, error) {
+ output, err := git.Run("merge-base", firstCommit, secondCommit)
if err != nil {
return nil, err
}
@@ -641,8 +536,8 @@ func (git *git) MergeBases(firstCommit, secondCommit string) ([]*Commit, error)
// If object exists its exit status is 0.
// If object doesn't exist its exit status is 1 (not documented).
// Otherwise, the exit status is 128 (not documented).
-func (git *git) CommitExists(commit string) (bool, error) {
- _, err := git.git("cat-file", "-e", commit)
+func (git *gitRepo) CommitExists(commit string) (bool, error) {
+ _, err := git.Run("cat-file", "-e", commit)
var vErr *osutil.VerboseError
if errors.As(err, &vErr) && vErr.ExitCode == 1 {
return false, nil
@@ -653,10 +548,10 @@ func (git *git) CommitExists(commit string) (bool, error) {
return true, nil
}
-func (git *git) PushCommit(repo, commit string) error {
+func (git *gitRepo) PushCommit(repo, commit string) error {
tagName := "tag-" + commit // assign tag to guarantee remote persistence
- git.git("tag", tagName) // ignore errors on re-tagging
- if _, err := git.git("push", repo, "tag", tagName); err != nil {
+ git.Run("tag", tagName) // ignore errors on re-tagging
+ if _, err := git.Run("push", repo, "tag", tagName); err != nil {
return fmt.Errorf("git push %s tag %s: %w", repo, tagName, err)
}
return nil
@@ -672,3 +567,144 @@ func ParseGitDiff(patch []byte) []string {
}
return files
}
+
+type Git struct {
+ Dir string
+ Sandbox bool
+ Env []string
+ precious bool
+ ignoreCC map[string]bool
+}
+
+func (git Git) Run(args ...string) ([]byte, error) {
+ cmd, err := git.command(args...)
+ if err != nil {
+ return nil, err
+ }
+ return osutil.Run(3*time.Hour, cmd)
+}
+
+func (git Git) command(args ...string) (*exec.Cmd, error) {
+ cmd := osutil.Command("git", args...)
+ cmd.Dir = git.Dir
+ cmd.Env = git.Env
+ if git.Sandbox {
+ if err := osutil.Sandbox(cmd, true, false); err != nil {
+ return nil, err
+ }
+ }
+ return cmd, nil
+}
+
+// Apply invokes git apply for a series of git patches.
+// It is different from Patch() in that it normally handles raw patch emails.
+func (git Git) Apply(patch []byte) error {
+ cmd, err := git.command("apply", "-")
+ if err != nil {
+ return err
+ }
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ return err
+ }
+ go func() {
+ stdin.Write(patch)
+ stdin.Close()
+ }()
+ _, err = osutil.Run(3*time.Hour, cmd)
+ return err
+}
+
+// Reset resets the git repo to a known clean state.
+func (git Git) Reset() error {
+ if git.precious {
+ return nil
+ }
+ git.Run("reset", "--hard", "--recurse-submodules")
+ git.Run("clean", "-xfdf")
+ git.Run("submodule", "foreach", "--recursive", "git", "clean", "-xfdf")
+ git.Run("bisect", "reset")
+ _, err := git.Run("reset", "--hard", "--recurse-submodules")
+ return err
+}
+
+// Commit extracts the information about the particular git commit.
+func (git Git) Commit(hash string) (*Commit, error) {
+ const patchSeparator = "---===syzkaller-patch-separator===---"
+ output, err := git.Run("log", "--format=%H%n%s%n%ae%n%an%n%ad%n%P%n%cd%n%b"+patchSeparator,
+ "-n", "1", "-p", "-U0", hash)
+ if err != nil {
+ return nil, err
+ }
+ pos := bytes.Index(output, []byte(patchSeparator))
+ if pos == -1 {
+ return nil, fmt.Errorf("git log output does not contain patch separator")
+ }
+ commit, err := gitParseCommit(output[:pos], nil, nil, git.ignoreCC)
+ if err != nil {
+ return nil, err
+ }
+ commit.Patch = output[pos+len(patchSeparator):]
+ for len(commit.Patch) != 0 && commit.Patch[0] == '\n' {
+ commit.Patch = commit.Patch[1:]
+ }
+ return commit, nil
+}
+
+func (git Git) fetchCommits(since, base, user, domain string, greps []string, fixedStrings bool) ([]*Commit, error) {
+ const commitSeparator = "---===syzkaller-commit-separator===---"
+ args := []string{"log", "--since", since, "--format=%H%n%s%n%ae%n%an%n%ad%n%P%n%cd%n%b%n" + commitSeparator}
+ if fixedStrings {
+ args = append(args, "--fixed-strings")
+ }
+ for _, grep := range greps {
+ args = append(args, "--grep", grep)
+ }
+ args = append(args, base)
+ cmd := exec.Command("git", args...)
+ cmd.Dir = git.Dir
+ cmd.Env = filterEnv()
+ if git.Sandbox {
+ if err := osutil.Sandbox(cmd, true, false); err != nil {
+ return nil, err
+ }
+ }
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ return nil, err
+ }
+ if err := cmd.Start(); err != nil {
+ return nil, err
+ }
+ defer cmd.Wait()
+ defer cmd.Process.Kill()
+ var (
+ s = bufio.NewScanner(stdout)
+ buf = new(bytes.Buffer)
+ separator = []byte(commitSeparator)
+ commits []*Commit
+ userBytes []byte
+ domainBytes []byte
+ )
+ if user != "" {
+ userBytes = []byte(user + "+")
+ domainBytes = []byte(domain)
+ }
+ for s.Scan() {
+ ln := s.Bytes()
+ if !bytes.Equal(ln, separator) {
+ buf.Write(ln)
+ buf.WriteByte('\n')
+ continue
+ }
+ com, err := gitParseCommit(buf.Bytes(), userBytes, domainBytes, git.ignoreCC)
+ if err != nil {
+ return nil, err
+ }
+ if user == "" || len(com.Tags) != 0 {
+ commits = append(commits, com)
+ }
+ buf.Reset()
+ }
+ return commits, s.Err()
+}
diff --git a/pkg/vcs/git_repo_test.go b/pkg/vcs/git_repo_test.go
index 6409b59cf..2db10bb91 100644
--- a/pkg/vcs/git_repo_test.go
+++ b/pkg/vcs/git_repo_test.go
@@ -24,7 +24,7 @@ func TestGitRepo(t *testing.T) {
baseDir := t.TempDir()
repo1 := CreateTestRepo(t, baseDir, "repo1")
repo2 := CreateTestRepo(t, baseDir, "repo2")
- repo := newGit(filepath.Join(baseDir, "repo"), nil, nil)
+ repo := newGitRepo(filepath.Join(baseDir, "repo"), nil, nil)
{
com, err := repo.Poll(repo1.Dir, "master")
if err != nil {
diff --git a/pkg/vcs/git_test.go b/pkg/vcs/git_test.go
index 76c34dbd3..1c1320364 100644
--- a/pkg/vcs/git_test.go
+++ b/pkg/vcs/git_test.go
@@ -412,7 +412,7 @@ func TestGitCustomRefs(t *testing.T) {
// Create a local repo.
localRepoDir := t.TempDir()
- local := newGit(localRepoDir, nil, nil)
+ local := newGitRepo(localRepoDir, nil, nil)
// Fetch the commit from the custom ref.
_, err := local.CheckoutCommit(remoteRepoDir, refCommit.Hash)
@@ -433,7 +433,7 @@ func TestGitRemoteTags(t *testing.T) {
// Create a local repo.
localRepoDir := t.TempDir()
- local := newGit(localRepoDir, nil, nil)
+ local := newGitRepo(localRepoDir, nil, nil)
// Ensure all tags were fetched.
commit, err := local.CheckoutCommit(remoteRepoDir, "sub_branch")
@@ -456,7 +456,7 @@ func TestGitFetchShortHash(t *testing.T) {
// Create a local repo.
localRepoDir := t.TempDir()
- local := newGit(localRepoDir, nil, nil)
+ local := newGitRepo(localRepoDir, nil, nil)
// Fetch the commit from the custom ref.
_, err := local.CheckoutCommit(remoteRepoDir, refCommit.Hash[:12])
diff --git a/pkg/vcs/git_test_util.go b/pkg/vcs/git_test_util.go
index 79b2d958a..0595dc533 100644
--- a/pkg/vcs/git_test_util.go
+++ b/pkg/vcs/git_test_util.go
@@ -24,7 +24,7 @@ type TestRepo struct {
Dir string
name string
Commits map[string]map[string]*Commit
- repo *git
+ repo *gitRepo
}
func (repo *TestRepo) Git(args ...string) {
@@ -50,7 +50,7 @@ func MakeTestRepo(t *testing.T, dir string) *TestRepo {
Dir: dir,
name: filepath.Base(dir),
Commits: make(map[string]map[string]*Commit),
- repo: newGit(dir, ignoreCC, []RepoOpt{OptPrecious, OptDontSandbox}),
+ repo: newGitRepo(dir, ignoreCC, []RepoOpt{OptPrecious, OptDontSandbox}),
}
repo.Git("init")
repo.Git("config", "--add", "user.email", userEmail)
@@ -124,7 +124,7 @@ func CloneTestRepo(t *testing.T, baseDir, name string, originRepo *TestRepo) *Te
Dir: dir,
name: filepath.Base(dir),
Commits: make(map[string]map[string]*Commit),
- repo: newGit(dir, ignoreCC, []RepoOpt{OptPrecious, OptDontSandbox}),
+ repo: newGitRepo(dir, ignoreCC, []RepoOpt{OptPrecious, OptDontSandbox}),
}
repo.Git("clone", originRepo.Dir, repo.Dir)
return repo
diff --git a/pkg/vcs/linux.go b/pkg/vcs/linux.go
index 41716e50c..d348dd71e 100644
--- a/pkg/vcs/linux.go
+++ b/pkg/vcs/linux.go
@@ -23,7 +23,7 @@ import (
)
type linux struct {
- *git
+ *gitRepo
vmType string
}
@@ -38,13 +38,13 @@ func newLinux(dir string, opts []RepoOpt, vmType string) *linux {
}
return &linux{
- git: newGit(dir, ignoreCC, opts),
- vmType: vmType,
+ gitRepo: newGitRepo(dir, ignoreCC, opts),
+ vmType: vmType,
}
}
func (ctx *linux) PreviousReleaseTags(commit, compilerType string) ([]string, error) {
- tags, err := ctx.git.previousReleaseTags(commit, false, false, false)
+ tags, err := ctx.gitRepo.previousReleaseTags(commit, false, false, false)
if err != nil {
return nil, err
}
@@ -153,7 +153,7 @@ func (ctx *linux) EnvForCommit(
Compiler: compiler,
KernelConfig: cf.Serialize(),
}
- err = linuxFixBackports(ctx.git, backports...)
+ err = linuxFixBackports(ctx.gitRepo, backports...)
if err != nil {
return nil, fmt.Errorf("failed to cherry pick fixes: %w", err)
}
@@ -196,7 +196,7 @@ func (ctx *linux) PrepareBisect() error {
if ctx.vmType != targets.GVisor {
// Some linux repos we fuzz don't import the upstream release git tags. We need tags
// to decide which compiler versions to use. Let's fetch upstream for its tags.
- err := ctx.git.fetchRemote("https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git", "")
+ err := ctx.gitRepo.fetchRemote("https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git", "")
if err != nil {
return fmt.Errorf("fetching upstream linux failed: %w", err)
}
@@ -206,7 +206,7 @@ func (ctx *linux) PrepareBisect() error {
func (ctx *linux) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult,
error)) ([]*Commit, error) {
- commits, err := ctx.git.Bisect(bad, good, dt, pred)
+ commits, err := ctx.gitRepo.Bisect(bad, good, dt, pred)
if len(commits) == 1 {
ctx.addMaintainers(commits[0])
}
@@ -233,7 +233,7 @@ func (ctx *linux) getMaintainers(hash string, blame bool) Recipients {
if blame {
args += " --git-blame"
}
- output, err := osutil.RunCmd(time.Minute, ctx.git.dir, "bash", "-c", args)
+ output, err := osutil.RunCmd(time.Minute, ctx.gitRepo.Dir, "bash", "-c", args)
if err != nil {
return nil
}
@@ -290,7 +290,7 @@ func (ctx *linux) Minimize(target *targets.Target, original, baseline []byte, ty
dt.Log("# configuration already minimized\n")
return original, nil
}
- kconf, err := kconfig.Parse(target, filepath.Join(ctx.git.dir, "Kconfig"))
+ kconf, err := kconfig.Parse(target, filepath.Join(ctx.gitRepo.Dir, "Kconfig"))
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrBadKconfig, err)
}
diff --git a/pkg/vcs/linux_patches.go b/pkg/vcs/linux_patches.go
index e1993d5c9..03b20e656 100644
--- a/pkg/vcs/linux_patches.go
+++ b/pkg/vcs/linux_patches.go
@@ -20,7 +20,7 @@ type BackportCommit struct {
}
// linuxFixBackports() cherry-picks the commits necessary to compile/run older Linux kernel releases.
-func linuxFixBackports(repo *git, extraCommits ...BackportCommit) error {
+func linuxFixBackports(repo *gitRepo, extraCommits ...BackportCommit) error {
return applyFixBackports(repo,
append(
append([]BackportCommit{}, pickLinuxCommits...),
@@ -29,7 +29,7 @@ func linuxFixBackports(repo *git, extraCommits ...BackportCommit) error {
)
}
-func applyFixBackports(repo *git, commits []BackportCommit) error {
+func applyFixBackports(repo *gitRepo, commits []BackportCommit) error {
for _, info := range commits {
if info.GuiltyHash != "" {
contains, err := repo.Contains(info.GuiltyHash)
@@ -49,7 +49,7 @@ func applyFixBackports(repo *git, commits []BackportCommit) error {
// The fix is already present.
continue
}
- _, err = repo.git("cherry-pick", "--no-commit", info.FixHash)
+ _, err = repo.Run("cherry-pick", "--no-commit", info.FixHash)
if err != nil {
return err
}
diff --git a/pkg/vcs/testos.go b/pkg/vcs/testos.go
index 68d9eeccd..2fd4dd151 100644
--- a/pkg/vcs/testos.go
+++ b/pkg/vcs/testos.go
@@ -12,19 +12,19 @@ import (
)
type testos struct {
- *git
+ *gitRepo
}
var _ ConfigMinimizer = new(testos)
func newTestos(dir string, opts []RepoOpt) *testos {
return &testos{
- git: newGit(dir, nil, opts),
+ gitRepo: newGitRepo(dir, nil, opts),
}
}
func (ctx *testos) PreviousReleaseTags(commit, compilerType string) ([]string, error) {
- return ctx.git.previousReleaseTags(commit, false, false, false)
+ return ctx.gitRepo.previousReleaseTags(commit, false, false, false)
}
func (ctx *testos) EnvForCommit(
diff --git a/pkg/vcs/vcs.go b/pkg/vcs/vcs.go
index 494e9a673..b0a2dc8eb 100644
--- a/pkg/vcs/vcs.go
+++ b/pkg/vcs/vcs.go
@@ -204,11 +204,11 @@ func NewRepo(os, vmType, dir string, opts ...RepoOpt) (Repo, error) {
case targets.Fuchsia:
return newFuchsia(dir, opts), nil
case targets.OpenBSD:
- return newGit(dir, nil, opts), nil
+ return newGitRepo(dir, nil, opts), nil
case targets.NetBSD:
- return newGit(dir, nil, opts), nil
+ return newGitRepo(dir, nil, opts), nil
case targets.FreeBSD:
- return newGit(dir, nil, opts), nil
+ return newGitRepo(dir, nil, opts), nil
case targets.TestOS:
return newTestos(dir, opts), nil
}
@@ -216,12 +216,12 @@ func NewRepo(os, vmType, dir string, opts ...RepoOpt) (Repo, error) {
}
func NewSyzkallerRepo(dir string, opts ...RepoOpt) Repo {
- git := newGit(dir, nil, append(opts, OptDontSandbox))
+ git := newGitRepo(dir, nil, append(opts, OptDontSandbox))
return git
}
func NewLKMLRepo(dir string) Repo {
- return newGit(dir, nil, []RepoOpt{OptDontSandbox})
+ return newGitRepo(dir, nil, []RepoOpt{OptDontSandbox})
}
func Patch(dir string, patch []byte) error {