aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2024-01-15 17:07:26 +0100
committerAleksandr Nogikh <nogikh@google.com>2024-01-17 09:28:36 +0000
commitf3c9957806e53e07de6c36da01736aa5bbbca2bf (patch)
treee0e47ce0cb3ac17bc6df398bd7261984d1162f83
parent974181fc9058dafde8c999ec3d450f684c375c34 (diff)
pkg/vcs: make git fetch calls more specific
This should make syzkaller only fetch the commits relevant for further processing. Also, specifying the exact commit/branch name to fetch allows us to access commits from custom refs. Test the new behaviour and double-check that remote tags fetch was not broken.
-rw-r--r--pkg/vcs/git.go10
-rw-r--r--pkg/vcs/git_test.go55
-rw-r--r--pkg/vcs/linux.go2
3 files changed, 63 insertions, 4 deletions
diff --git a/pkg/vcs/git.go b/pkg/vcs/git.go
index 71fcac97a..0bd72d9a6 100644
--- a/pkg/vcs/git.go
+++ b/pkg/vcs/git.go
@@ -134,17 +134,21 @@ func (git *git) CheckoutCommit(repo, commit string) (*Commit, error) {
if err := git.repair(); err != nil {
return nil, err
}
- if err := git.fetchRemote(repo); err != nil {
+ if err := git.fetchRemote(repo, commit); err != nil {
return nil, err
}
return git.SwitchCommit(commit)
}
-func (git *git) fetchRemote(repo string) error {
+func (git *git) 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)
- _, err := git.git("fetch", "--force", "--tags", repoHash)
+ fetchArgs := []string{"fetch", "--force", "--tags", repoHash}
+ if commit != "" {
+ fetchArgs = append(fetchArgs, commit)
+ }
+ _, err := git.git(fetchArgs...)
if err != nil {
var verbose *osutil.VerboseError
if errors.As(err, &verbose) &&
diff --git a/pkg/vcs/git_test.go b/pkg/vcs/git_test.go
index 264cb54d8..5e9d30fa7 100644
--- a/pkg/vcs/git_test.go
+++ b/pkg/vcs/git_test.go
@@ -6,10 +6,12 @@ package vcs
import (
"os"
"reflect"
+ "sort"
"testing"
"time"
"github.com/google/go-cmp/cmp"
+ "github.com/stretchr/testify/assert"
)
func TestGitParseCommit(t *testing.T) {
@@ -371,3 +373,56 @@ func TestMergeBase(t *testing.T) {
t.Fatalf("expected base commit, got %v", mergeCommits)
}
}
+
+func TestGitCustomRefs(t *testing.T) {
+ remoteRepoDir := t.TempDir()
+ remote := MakeTestRepo(t, remoteRepoDir)
+ remote.Git("commit", "--no-edit", "--allow-empty", "-m", "base commit")
+ remote.Git("checkout", "-b", "base_branch")
+ remote.Git("tag", "base_tag")
+
+ // Create a commit non reachable from any branch or tag.
+ remote.Git("checkout", "base_branch")
+ remote.Git("checkout", "-b", "temp_branch")
+ remote.Git("commit", "--no-edit", "--allow-empty", "-m", "detached commit")
+ // Add a ref to prevent the commit from getting garbage collected.
+ remote.Git("update-ref", "refs/custom/test", "temp_branch")
+ refCommit, _ := remote.repo.HeadCommit()
+
+ // Remove the branch, let the commit stay only in refs.
+ remote.Git("checkout", "base_branch")
+ remote.Git("branch", "-D", "temp_branch")
+
+ // Create a local repo.
+ localRepoDir := t.TempDir()
+ local := newGit(localRepoDir, nil, nil)
+
+ // Fetch the commit from the custom ref.
+ _, err := local.CheckoutCommit(remoteRepoDir, refCommit.Hash)
+ assert.NoError(t, err)
+}
+
+func TestGitRemoteTags(t *testing.T) {
+ remoteRepoDir := t.TempDir()
+ remote := MakeTestRepo(t, remoteRepoDir)
+ remote.Git("commit", "--no-edit", "--allow-empty", "-m", "base commit")
+ remote.Git("checkout", "-b", "base_branch")
+ remote.Git("tag", "v1.0")
+
+ // Diverge sub_branch and add a tag.
+ remote.Git("commit", "--no-edit", "--allow-empty", "-m", "sub-branch")
+ remote.Git("checkout", "-b", "sub_branch")
+ remote.Git("tag", "v2.0")
+
+ // Create a local repo.
+ localRepoDir := t.TempDir()
+ local := newGit(localRepoDir, nil, nil)
+
+ // Ensure all tags were fetched.
+ commit, err := local.CheckoutCommit(remoteRepoDir, "sub_branch")
+ assert.NoError(t, err)
+ tags, err := local.previousReleaseTags(commit.Hash, true, false, false)
+ assert.NoError(t, err)
+ sort.Strings(tags)
+ assert.Equal(t, []string{"v1.0", "v2.0"}, tags)
+}
diff --git a/pkg/vcs/linux.go b/pkg/vcs/linux.go
index 62319096d..98ae07cda 100644
--- a/pkg/vcs/linux.go
+++ b/pkg/vcs/linux.go
@@ -195,7 +195,7 @@ func (ctx *linux) PrepareBisect() error {
if ctx.vmType != "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.git.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)
}