Skip to content

Commit 1a9cd37

Browse files
committed
Fixed an issue where sparse checkout settings were not preserved when switching branches.
1 parent f3c7b60 commit 1a9cd37

File tree

3 files changed

+69
-16
lines changed

3 files changed

+69
-16
lines changed

git/gogit/client.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,16 @@ const ClientName = "go-git"
6969
// Client implements repository.Client.
7070
type Client struct {
7171
*repository.DiscardCloser
72-
path string
73-
repository *extgogit.Repository
74-
authOpts *git.AuthOptions
75-
storer storage.Storer
76-
worktreeFS billy.Filesystem
77-
credentialsOverHTTP bool
78-
useDefaultKnownHosts bool
79-
singleBranch bool
80-
proxy transport.ProxyOptions
72+
path string
73+
repository *extgogit.Repository
74+
authOpts *git.AuthOptions
75+
storer storage.Storer
76+
worktreeFS billy.Filesystem
77+
credentialsOverHTTP bool
78+
useDefaultKnownHosts bool
79+
singleBranch bool
80+
proxy transport.ProxyOptions
81+
sparseCheckoutDirectories []string
8182
}
8283

8384
var _ repository.Client = &Client{}
@@ -503,8 +504,9 @@ func (g *Client) SwitchBranch(ctx context.Context, branchName string) error {
503504
}
504505

505506
err = wt.Checkout(&extgogit.CheckoutOptions{
506-
Branch: refName,
507-
Create: create,
507+
Branch: refName,
508+
Create: create,
509+
SparseCheckoutDirectories: g.sparseCheckoutDirectories,
508510
})
509511
if err != nil {
510512
return fmt.Errorf("could not checkout to branch '%s': %w", branchName, err)

git/gogit/client_test.go

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -394,11 +394,14 @@ func TestForcePush(t *testing.T) {
394394

395395
func TestSwitchBranch(t *testing.T) {
396396
tests := []struct {
397-
name string
398-
setupFunc func(g *WithT, path string) string
399-
changeRepo func(g *WithT, c *Client) string
400-
branch string
401-
singleBranch bool
397+
name string
398+
setupFunc func(g *WithT, path string) string
399+
changeRepo func(g *WithT, c *Client) string
400+
branch string
401+
singleBranch bool
402+
sparseCheckoutDirectories []string
403+
expectedFiles []string
404+
expectedNoFiles []string
402405
}{
403406
{
404407
name: "switch to a branch ahead of the current branch",
@@ -537,6 +540,37 @@ func TestSwitchBranch(t *testing.T) {
537540
setupFunc: nil,
538541
branch: "new",
539542
},
543+
{
544+
name: "switch branch preserves sparse checkout directories",
545+
setupFunc: func(g *WithT, repoURL string) string {
546+
tmp := t.TempDir()
547+
repo, err := extgogit.PlainClone(tmp, false, &extgogit.CloneOptions{
548+
URL: repoURL,
549+
ReferenceName: plumbing.NewBranchReferenceName(git.DefaultBranch),
550+
RemoteName: git.DefaultRemote,
551+
})
552+
g.Expect(err).ToNot(HaveOccurred())
553+
554+
err = createBranch(repo, "sparse-branch")
555+
g.Expect(err).ToNot(HaveOccurred())
556+
557+
// Create files in different directories
558+
_, err = commitFile(repo, "dir1/file1", "content in dir1", time.Now())
559+
g.Expect(err).ToNot(HaveOccurred())
560+
cc, err := commitFile(repo, "dir2/file2", "content in dir2", time.Now())
561+
g.Expect(err).ToNot(HaveOccurred())
562+
563+
err = repo.Push(&extgogit.PushOptions{
564+
RemoteName: git.DefaultRemote,
565+
})
566+
g.Expect(err).ToNot(HaveOccurred())
567+
return cc.String()
568+
},
569+
branch: "sparse-branch",
570+
sparseCheckoutDirectories: []string{"dir1"},
571+
expectedFiles: []string{"dir1/file1"},
572+
expectedNoFiles: []string{"dir2/file2"},
573+
},
540574
}
541575

542576
for _, tt := range tests {
@@ -571,6 +605,7 @@ func TestSwitchBranch(t *testing.T) {
571605
ggc, err := NewClient(tmp, nil)
572606
g.Expect(err).ToNot(HaveOccurred())
573607
ggc.repository = repo
608+
ggc.sparseCheckoutDirectories = tt.sparseCheckoutDirectories
574609

575610
if tt.changeRepo != nil {
576611
expectedHash = tt.changeRepo(g, ggc)
@@ -583,6 +618,18 @@ func TestSwitchBranch(t *testing.T) {
583618
g.Expect(err).ToNot(HaveOccurred())
584619
g.Expect(ref.Name().Short()).To(Equal(tt.branch))
585620
g.Expect(ref.Hash().String()).To(Equal(expectedHash))
621+
622+
// Verify sparse checkout: included files should exist
623+
for _, file := range tt.expectedFiles {
624+
_, err := os.Stat(filepath.Join(tmp, file))
625+
g.Expect(err).ToNot(HaveOccurred(), "file %s should exist with sparse checkout", file)
626+
}
627+
628+
// Verify sparse checkout: excluded files should not exist
629+
for _, noFile := range tt.expectedNoFiles {
630+
_, err := os.Stat(filepath.Join(tmp, noFile))
631+
g.Expect(os.IsNotExist(err)).To(BeTrue(), "file %s should not exist with sparse checkout", noFile)
632+
}
586633
})
587634
}
588635
}

git/gogit/clone.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ func (g *Client) cloneBranch(ctx context.Context, url, branch string, opts repos
135135
return nil, fmt.Errorf("unable to resolve commit object for HEAD '%s': %w", head.Hash(), err)
136136
}
137137
g.repository = repo
138+
g.sparseCheckoutDirectories = opts.SparseCheckoutDirectories
138139
return buildCommitWithRef(cc, nil, ref)
139140
}
140141

@@ -234,6 +235,7 @@ func (g *Client) cloneTag(ctx context.Context, url, tag string, opts repository.
234235
}
235236

236237
g.repository = repo
238+
g.sparseCheckoutDirectories = opts.SparseCheckoutDirectories
237239
return buildCommitWithRef(cc, tagObj, ref)
238240
}
239241

@@ -302,6 +304,7 @@ func (g *Client) cloneCommit(ctx context.Context, url, commit string, opts repos
302304
}
303305

304306
g.repository = repo
307+
g.sparseCheckoutDirectories = opts.SparseCheckoutDirectories
305308
return buildCommitWithRef(cc, nil, cloneOpts.ReferenceName)
306309
}
307310

@@ -435,6 +438,7 @@ func (g *Client) cloneSemVer(ctx context.Context, url, semverTag string, opts re
435438
}
436439

437440
g.repository = repo
441+
g.sparseCheckoutDirectories = opts.SparseCheckoutDirectories
438442
return buildCommitWithRef(cc, tagObj, tagRef.Name())
439443
}
440444

0 commit comments

Comments
 (0)