From 4f35ebab20f1034df1df943044903e7044e6cdf4 Mon Sep 17 00:00:00 2001 From: Paulo Gomes Date: Sun, 13 Apr 2025 16:48:21 +0100 Subject: [PATCH] Merge pull request #1484 from patricsss/patricsss/fix-1455 utils: fix diff so subpaths work for sparse checkouts, fixes 1455 --- utils/merkletrie/change.go | 2 +- utils/merkletrie/index/node.go | 10 ++++++++- utils/merkletrie/index/node_test.go | 34 +++++++++++++++++++++++++---- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/utils/merkletrie/change.go b/utils/merkletrie/change.go index 562ff8902..d32b5a7d4 100644 --- a/utils/merkletrie/change.go +++ b/utils/merkletrie/change.go @@ -150,7 +150,7 @@ func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error { } return err } - if current.IsDir() { + if current.IsDir() || current.Skip() { continue } l.Add(ctor(current)) diff --git a/utils/merkletrie/index/node.go b/utils/merkletrie/index/node.go index c1809f7ec..5bc63f8b2 100644 --- a/utils/merkletrie/index/node.go +++ b/utils/merkletrie/index/node.go @@ -36,7 +36,15 @@ func NewRootNode(idx *index.Index) noder.Noder { parent := fullpath fullpath = path.Join(fullpath, part) - if _, ok := m[fullpath]; ok { + // It's possible that the first occurrence of subdirectory is skipped. + // The parent node can be created with SkipWorktree set to true, but + // if any future children do not skip their subtree, the entire lineage + // of the tree needs to have this value set to false so that subdirectories + // are not ignored. + if parentNode, ok := m[fullpath]; ok { + if e.SkipWorktree == false { + parentNode.skip = false + } continue } diff --git a/utils/merkletrie/index/node_test.go b/utils/merkletrie/index/node_test.go index cc5600dcb..53f8a9f45 100644 --- a/utils/merkletrie/index/node_test.go +++ b/utils/merkletrie/index/node_test.go @@ -2,7 +2,7 @@ package index import ( "bytes" - "path/filepath" + "path" "testing" "github.com/go-git/go-git/v5/plumbing" @@ -46,14 +46,14 @@ func (s *NoderSuite) TestDiff(c *C) { func (s *NoderSuite) TestDiffChange(c *C) { indexA := &index.Index{ Entries: []*index.Entry{{ - Name: filepath.Join("bar", "baz", "bar"), + Name: path.Join("bar", "baz", "bar"), Hash: plumbing.NewHash("8ab686eafeb1f44702738c8b0f24f2567c36da6d"), }}, } indexB := &index.Index{ Entries: []*index.Entry{{ - Name: filepath.Join("bar", "baz", "foo"), + Name: path.Join("bar", "baz", "foo"), Hash: plumbing.NewHash("8ab686eafeb1f44702738c8b0f24f2567c36da6d"), }}, } @@ -63,6 +63,32 @@ func (s *NoderSuite) TestDiffChange(c *C) { c.Assert(ch, HasLen, 2) } +func (s *NoderSuite) TestDiffSkipIssue1455(c *C) { + indexA := &index.Index{ + Entries: []*index.Entry{ + { + Name: path.Join("bar", "baz", "bar"), + Hash: plumbing.NewHash("8ab686eafeb1f44702738c8b0f24f2567c36da6d"), + SkipWorktree: true, + }, + { + Name: path.Join("bar", "biz", "bat"), + Hash: plumbing.NewHash("8ab686eafeb1f44702738c8b0f24f2567c36da6d"), + SkipWorktree: false, + }, + }, + } + + indexB := &index.Index{} + + ch, err := merkletrie.DiffTree(NewRootNode(indexB), NewRootNode(indexA), isEquals) + c.Assert(err, IsNil) + c.Assert(ch, HasLen, 1) + a, err := ch[0].Action() + c.Assert(err, IsNil) + c.Assert(a, Equals, merkletrie.Insert) +} + func (s *NoderSuite) TestDiffDir(c *C) { indexA := &index.Index{ Entries: []*index.Entry{{ @@ -73,7 +99,7 @@ func (s *NoderSuite) TestDiffDir(c *C) { indexB := &index.Index{ Entries: []*index.Entry{{ - Name: filepath.Join("foo", "bar"), + Name: path.Join("foo", "bar"), Hash: plumbing.NewHash("8ab686eafeb1f44702738c8b0f24f2567c36da6d"), }}, }