git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 04/10] unpack-trees: fix sparse checkout's "unable to match directories" fault

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Nov 15, 2010, 10:36 UTC
Message-ID
<1289817410-32470-5-git-send-email-pclouds@gmail.com>
In-Reply-To
<1289817410-32470-1-git-send-email-pclouds@gmail.com>

excluded_from_list() is designed to be work with a directory structure, where there are files and directories. Index however is a list of files, no directories, not really fit in excluded_from_list() design.

Commit c84de70 (excluded_1(): support exclude files in index - 2009-08-20) helped make it work somewhat. Although the lack of proper dtype means pattern "blah" won't match entries "blah/..." in the index.

clear_ce_flags() is now used to match the index against sparse patterns. It does generate directories for excluded_from_list() so the "blah" case should now work.

Also revert c84de70 because it is no longer needed.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-read-tree.txt      |    7 -------
 dir.c                                |    6 ------
 t/t1011-read-tree-sparse-checkout.sh |   14 +++++++++++---
 unpack-trees.c                       |   33 ++++++++++++++++++---------------
 4 files changed, 29 insertions(+), 31 deletions(-)
diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt
index e88e9c2..634423a 100644
--- a/Documentation/git-read-tree.txt
+++ b/Documentation/git-read-tree.txt
@@ -416,13 +416,6 @@ turn `core.sparseCheckout` on in order to have sparse checkout
 support.
 
 
-BUGS
-----
-In order to match a directory with $GIT_DIR/info/sparse-checkout,
-trailing slash must be used. The form without trailing slash, while
-works with .gitignore, does not work with sparse checkout.
-
-
 SEE ALSO
 --------
 linkgit:git-write-tree[1]; linkgit:git-ls-files[1];
diff --git a/dir.c b/dir.c
index d1e5e5e..2b38f94 100644
--- a/dir.c
+++ b/dir.c
@@ -359,12 +359,6 @@ int excluded_from_list(const char *pathname,
 			int to_exclude = x->to_exclude;
 
 			if (x->flags & EXC_FLAG_MUSTBEDIR) {
-				if (!dtype) {
-					if (!prefixcmp(pathname, exclude))
-						return to_exclude;
-					else
-						continue;
-				}
 				if (*dtype == DT_UNKNOWN)
 					*dtype = get_dtype(NULL, pathname, pathlen);
 				if (*dtype != DT_DIR)
diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh
index 9a07de1..50f7dfe 100755
--- a/t/t1011-read-tree-sparse-checkout.sh
+++ b/t/t1011-read-tree-sparse-checkout.sh
@@ -91,12 +91,20 @@ test_expect_success 'match directories with trailing slash' '
 	test -f sub/added
 '
 
-test_expect_failure 'match directories without trailing slash' '
-	echo init.t >.git/info/sparse-checkout &&
+test_expect_success 'match directories without trailing slash' '
 	echo sub >>.git/info/sparse-checkout &&
 	git read-tree -m -u HEAD &&
 	git ls-files -t >result &&
-	test_cmp expected.swt result &&
+	test_cmp expected.swt-noinit result &&
+	test ! -f init.t &&
+	test -f sub/added
+'
+
+test_expect_success 'match directory pattern' '
+	echo "s?b" >>.git/info/sparse-checkout &&
+	git read-tree -m -u HEAD &&
+	git ls-files -t >result &&
+	test_cmp expected.swt-noinit result &&
 	test ! -f init.t &&
 	test -f sub/added
 '
diff --git a/unpack-trees.c b/unpack-trees.c
index 6c266ef..f005454 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -245,15 +245,6 @@ static int check_updates(struct unpack_trees_options *o)
 static int verify_uptodate_sparse(struct cache_entry *ce, struct unpack_trees_options *o);
 static int verify_absent_sparse(struct cache_entry *ce, enum unpack_trees_error_types, struct unpack_trees_options *o);
 
-static int will_have_skip_worktree(const struct cache_entry *ce, struct unpack_trees_options *o)
-{
-	const char *basename;
-
-	basename = strrchr(ce->name, '/');
-	basename = basename ? basename+1 : ce->name;
-	return excluded_from_list(ce->name, ce_namelen(ce), basename, NULL, o->el) <= 0;
-}
-
 static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_options *o)
 {
 	int was_skip_worktree = ce_skip_worktree(ce);
@@ -926,14 +917,19 @@ static void set_new_skip_worktree_1(struct unpack_trees_options *o)
 {
 	int i;
 
+	/* Mark everything out (except staged entries) */
 	for (i = 0;i < o->src_index->cache_nr;i++) {
 		struct cache_entry *ce = o->src_index->cache[i];
 		ce->ce_flags &= ~CE_ADDED;
-		if (!ce_stage(ce) && will_have_skip_worktree(ce, o))
+		if (!ce_stage(ce))
 			ce->ce_flags |= CE_NEW_SKIP_WORKTREE;
 		else
 			ce->ce_flags &= ~CE_NEW_SKIP_WORKTREE;
 	}
+
+	/* Then mark some of them in again according to o->el */
+	clear_ce_flags(o->src_index->cache, o->src_index->cache_nr,
+		       0, CE_NEW_SKIP_WORKTREE, o);
 }
 
 static int verify_absent(struct cache_entry *, enum unpack_trees_error_types, struct unpack_trees_options *);
@@ -943,19 +939,26 @@ static int set_new_skip_worktree_2(struct unpack_trees_options *o)
 
 	/*
 	 * CE_ADDED marks new index entries. These have not been processed
-	 * by set_new_skip_worktree_1() so we do it here.
+	 * by set_new_skip_worktree_1() so we do it here. Mark every new
+	 * entries out.
 	 */
 	for (i = 0;i < o->result.cache_nr;i++) {
 		struct cache_entry *ce = o->result.cache[i];
+		if (ce->ce_flags & CE_ADDED)
+			ce->ce_flags |= CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE;
+	}
+
+	/* Then mark some of them in again */
+	clear_ce_flags(o->result.cache, o->result.cache_nr, CE_ADDED,
+		       CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE, o);
+
+	for (i = 0;i < o->result.cache_nr;i++) {
+		struct cache_entry *ce = o->result.cache[i];
 
 		if (!(ce->ce_flags & CE_ADDED))
 			continue;
 
 		ce->ce_flags &= ~CE_ADDED;
-		if (!ce_stage(ce) && will_have_skip_worktree(ce, o))
-			ce->ce_flags |= CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE;
-		else
-			ce->ce_flags &= ~(CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);
 
 		/* Left-over checks from merged_entry when old == NULL */
 		if (verify_absent(ce, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o))
-- 
1.7.3.2.210.g045198
Previous: Jonathan NiederNext: Jonathan Nieder
Message 16 of 34 in “Sparse checkout fixes and improvements”
  1. 00/10 Sparse checkout fixes and improvementsNguyễn Thái Ngọc Duy, Nov 15, 2010
  2. 01/10 add: do not rely on dtype being NULL behaviorNguyễn Thái Ngọc Duy, Nov 15, 2010
  3. Jonathan NiederNov 15, 2010
  4. Nguyen Thai Ngoc DuyNov 16, 2010
  5. Jonathan NiederNov 16, 2010
  6. Junio C HamanoNov 16, 2010
  7. Nguyen Thai Ngoc DuyNov 17, 2010
  8. 02/10 unpack-trees: move all skip-worktree check back to unpack_trees()Nguyễn Thái Ngọc Duy, Nov 15, 2010
  9. Thiago FarinaNov 15, 2010
  10. Nguyen Thai Ngoc DuyNov 16, 2010
  11. Jonathan NiederNov 15, 2010
  12. Nguyen Thai Ngoc DuyNov 16, 2010
  13. 03/10 unpack-trees: add function to update ce_flags based on sparse patternsNguyễn Thái Ngọc Duy, Nov 15, 2010
  14. Jonathan NiederNov 15, 2010
  15. Jonathan NiederNov 15, 2010
  16. 04/10 unpack-trees: fix sparse checkout's "unable to match directories" faultNguyễn Thái Ngọc Duy, Nov 15, 2010
  17. Jonathan NiederNov 15, 2010
  18. Nguyen Thai Ngoc DuyNov 16, 2010
  19. 05/10 unpack-trees: optimize full checkout caseNguyễn Thái Ngọc Duy, Nov 15, 2010
  20. Jonathan NiederNov 15, 2010
  21. 06/10 templates: add info/sparse-checkoutNguyễn Thái Ngọc Duy, Nov 15, 2010
  22. 07/10 checkout: add -S to update sparse checkoutNguyễn Thái Ngọc Duy, Nov 15, 2010
  23. Jonathan NiederNov 15, 2010
  24. Miles BaderNov 15, 2010
  25. Nguyen Thai Ngoc DuyNov 17, 2010
  26. Nguyen Thai Ngoc DuyNov 16, 2010
  27. 08/10 checkout: add --full to fully populate working directoryNguyễn Thái Ngọc Duy, Nov 15, 2010
  28. Jonathan NiederNov 15, 2010
  29. Nguyen Thai Ngoc DuyNov 16, 2010
  30. 09/10 git-checkout.txt: mention of sparse checkoutNguyễn Thái Ngọc Duy, Nov 15, 2010
  31. 10/10 clean: support cleaning sparse checkout with -SNguyễn Thái Ngọc Duy, Nov 15, 2010
  32. Jonathan NiederNov 15, 2010
  33. Nguyen Thai Ngoc DuyNov 16, 2010
  34. Jonathan NiederNov 16, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.