Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions reposerver/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -2685,8 +2685,8 @@ func (s *Service) checkoutRevision(gitClient git.Client, revision string, submod

// fetch is a convenience function to fetch revisions
// We assumed that the caller has already initialized the git repo, i.e. gitClient.Init() has been called
func (s *Service) fetch(gitClient git.Client, targetRevisions []string) error {
err := fetch(gitClient, targetRevisions)
func (s *Service) fetch(gitClient git.Client, targetRevisions []string, depth int64) error {
err := fetch(gitClient, targetRevisions, depth)
if err != nil {
for _, revision := range targetRevisions {
s.metricsServer.IncGitFetchFail(gitClient.Root(), revision)
Expand All @@ -2695,7 +2695,7 @@ func (s *Service) fetch(gitClient git.Client, targetRevisions []string) error {
return err
}

func fetch(gitClient git.Client, targetRevisions []string) error {
func fetch(gitClient git.Client, targetRevisions []string, depth int64) error {
revisionPresent := true
for _, revision := range targetRevisions {
revisionPresent = gitClient.IsRevisionPresent(revision)
Expand All @@ -2707,6 +2707,16 @@ func fetch(gitClient git.Client, targetRevisions []string) error {
if revisionPresent {
return nil
}
if depth > 0 {
for _, revision := range targetRevisions {
if !gitClient.IsRevisionPresent(revision) {
if err := gitClient.Fetch(revision, depth); err != nil {
return status.Errorf(codes.Internal, "Failed to fetch revision %s: %v", revision, err)
}
}
}
return nil
}
// Fetching with no revision first. Fetching with an explicit version can cause repo bloat. https://github.com/argoproj/argo-cd/issues/8845
err := gitClient.Fetch("", 0)
if err != nil {
Expand Down Expand Up @@ -3081,14 +3091,14 @@ func (s *Service) UpdateRevisionForPaths(_ context.Context, request *apiclient.U
defer s.metricsServer.DecPendingRepoRequest(repo.Repo)

closer, err := s.repoLock.Lock(gitClient.Root(), revision, true, func() (goio.Closer, error) {
return s.checkoutRevision(gitClient, revision, false, 0)
return s.checkoutRevision(gitClient, revision, false, repo.Depth)
})
if err != nil {
return nil, status.Errorf(codes.Internal, "unable to checkout git repo %s with revision %s: %v", repo.Repo, revision, err)
}
defer utilio.Close(closer)

if err := s.fetch(gitClient, []string{syncedRevision}); err != nil {
if err := s.fetch(gitClient, []string{syncedRevision}, repo.Depth); err != nil {
return nil, status.Errorf(codes.Internal, "unable to fetch git repo %s with syncedRevisions %s: %v", repo.Repo, syncedRevision, err)
}

Expand Down
43 changes: 40 additions & 3 deletions reposerver/repository/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3218,10 +3218,47 @@ func TestFetch(t *testing.T) {
gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(true)
gitClient.EXPECT().IsRevisionPresent(revision2).Once().Return(true)

err := fetch(gitClient, []string{revision1, revision2})
err := fetch(gitClient, []string{revision1, revision2}, 0)
require.NoError(t, err)
}

func TestFetchWithDepth(t *testing.T) {
revision1 := "0123456789012345678901234567890123456789"
revision2 := "abcdefabcdefabcdefabcdefabcdefabcdefabcd"

t.Run("skips fetch when all revisions present", func(t *testing.T) {
gitClient := &gitmocks.Client{}
gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(true)
gitClient.EXPECT().IsRevisionPresent(revision2).Once().Return(true)

err := fetch(gitClient, []string{revision1, revision2}, 1)
require.NoError(t, err)
})

t.Run("fetches only missing revisions with depth", func(t *testing.T) {
gitClient := &gitmocks.Client{}
gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(true)
gitClient.EXPECT().IsRevisionPresent(revision2).Once().Return(false)
// After the initial check finds a missing revision, the per-revision loop runs
gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(true)
gitClient.EXPECT().IsRevisionPresent(revision2).Once().Return(false)
gitClient.EXPECT().Fetch(revision2, int64(1)).Return(nil)

err := fetch(gitClient, []string{revision1, revision2}, 1)
require.NoError(t, err)
})

t.Run("returns error on fetch failure", func(t *testing.T) {
gitClient := &gitmocks.Client{}
gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(false)
gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(false)
gitClient.EXPECT().Fetch(revision1, int64(1)).Return(errors.New("fetch failed"))

err := fetch(gitClient, []string{revision1, revision2}, 1)
require.Error(t, err)
})
}

// TestFetchRevisionCanGetNonstandardRefs shows that we can fetch a revision that points to a non-standard ref. In
func TestFetchRevisionCanGetNonstandardRefs(t *testing.T) {
rootPath := t.TempDir()
Expand Down Expand Up @@ -3254,10 +3291,10 @@ func TestFetchRevisionCanGetNonstandardRefs(t *testing.T) {
pullSha, err := gitClient.LsRemote("refs/pull/123/head")
require.NoError(t, err)

err = fetch(gitClient, []string{"does-not-exist"})
err = fetch(gitClient, []string{"does-not-exist"}, 0)
require.Error(t, err)

err = fetch(gitClient, []string{pullSha})
err = fetch(gitClient, []string{pullSha}, 0)
require.NoError(t, err)
}

Expand Down
Loading