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

[PATCH 2/5] unpack-trees: fix accidental loss of user changes

From
Elijah Newren via GitGitGadget <gitgitgadget@gmail.com>
Date
Jan 13, 2022, 16:43 UTC
Message-ID
<1e3958576e2a132180f8c5d20acc1315d3062119.1642092230.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1114.git.1642092230.gitgitgadget@gmail.com>
From: Elijah Newren <newren@gmail.com>

For sparse-checkouts, we don't want unpack-trees to error out on files that are missing from the worktree, so there has traditionally been logic to make it skip the verify_uptodate() check for these. Unfortunately, it was skipping the verify_uptodate() check for files that were expected to *become* SKIP_WORKTREE. For files that were not already SKIP_WORKTREE, that can cause us to later delete the file in apply_sparse_checkout(). Only skip the check for files that were already SKIP_WORKTREE as well to avoid lightly discarding important changes users may have made to files.

Note 1: unpack-trees.c is already a bit complex, and the logic around CE_SKIP_WORKTREE and CE_NEW_SKIP_WORKTREE in that file are no exception. I also tried just replacing CE_NEW_SKIP_WORKTREE with CE_SKIP_WORKTREE in the verify_uptodate() check instead of checking for both flags, and found that it also fixed this bug and passed all the tests. I also attempted to devise a few testcases that might trip either variant of my fix and was unable to find any problems. It may be that just checking CE_SKIP_WORKTREE is a better fix, but I'm not sure. I thought it was a bit safer to strictly reduce the number of cases where we skip the up-to-date check rather than just toggling which kind of cases skip it, and thus went with the current variant of the fix.

Note 2: I also wondered if verify_absent() might have a similar bug, but despite my attempts to try to devise a testcase that would trigger such a thing, I couldn't find any problematic testcases. Thus, this patch makes no attempt to apply similar changes to verify_absent() and verify_absent_if_directory().

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 t/t1011-read-tree-sparse-checkout.sh | 2 +-
 unpack-trees.c                       | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh
index 1b2395b8a82..4ed0885bf2f 100755
--- a/t/t1011-read-tree-sparse-checkout.sh
+++ b/t/t1011-read-tree-sparse-checkout.sh
@@ -197,7 +197,7 @@ test_expect_success 'read-tree will not throw away dirty changes, non-sparse' '
 	grep -q dirty init.t
 '
 
-test_expect_failure 'read-tree will not throw away dirty changes, sparse' '
+test_expect_success 'read-tree will not throw away dirty changes, sparse' '
 	echo "/*" >.git/info/sparse-checkout &&
 	read_tree_u_must_succeed -m -u HEAD &&
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 98e2f2e0e6f..6d9d89c662a 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -2059,7 +2059,9 @@ static int verify_uptodate_1(const struct cache_entry *ce,
 int verify_uptodate(const struct cache_entry *ce,
 		    struct unpack_trees_options *o)
 {
-	if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
+	if (!o->skip_sparse_checkout &&
+	    (ce->ce_flags & CE_SKIP_WORKTREE) &&
+	    (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
 		return 0;
 	return verify_uptodate_1(ce, o, ERROR_NOT_UPTODATE_FILE);
 }
-- 
gitgitgadget
Previous: Elijah Newren via GitGitGadgetNext: Elijah Newren via GitGitGadget
Message 3 of 30 in “Remove the present-despite-SKIP_WORKTREE class of bugs (for sparse-checkouts)”
  1. 0/5 Remove the present-despite-SKIP_WORKTREE class of bugs (for sparse-checkouts)Elijah Newren via GitGitGadget, Jan 13, 2022
  2. 1/5 t1011: add testcase demonstrating accidental loss of user modificationsElijah Newren via GitGitGadget, Jan 13, 2022
  3. 2/5 unpack-trees: fix accidental loss of user changesElijah Newren via GitGitGadget, Jan 13, 2022
  4. 3/5 repo_read_index: clear SKIP_WORKTREE bit from files present in worktreeElijah Newren via GitGitGadget, Jan 13, 2022
  5. 4/5 Update documentation related to sparsity and the skip-worktree bitElijah Newren via GitGitGadget, Jan 13, 2022
  6. 5/5 Accelerate clear_skip_worktree_from_present_files() by cachingElijah Newren via GitGitGadget, Jan 13, 2022
  7. Elijah NewrenJan 13, 2022
  8. 0/5 Remove the present-despite-SKIP_WORKTREE class of bugs (for sparse-checkouts)Elijah Newren via GitGitGadget, Jan 14, 2022
  9. 1/5 t1011: add testcase demonstrating accidental loss of user modificationsElijah Newren via GitGitGadget, Jan 14, 2022
  10. Ævar Arnfjörð BjarmasonFeb 16, 2022
  11. Elijah NewrenFeb 16, 2022
  12. 2/5 unpack-trees: fix accidental loss of user changesElijah Newren via GitGitGadget, Jan 14, 2022
  13. 3/5 repo_read_index: clear SKIP_WORKTREE bit from files present in worktreeElijah Newren via GitGitGadget, Jan 14, 2022
  14. Ævar Arnfjörð BjarmasonFeb 16, 2022
  15. Elijah NewrenFeb 16, 2022
  16. Jonathan NiederFeb 19, 2022
  17. Elijah NewrenFeb 19, 2022
  18. Jonathan NiederFeb 19, 2022
  19. Elijah NewrenFeb 20, 2022
  20. Derrick StoleeFeb 20, 2022
  21. Jonathan NiederFeb 22, 2022
  22. 4/5 Update documentation related to sparsity and the skip-worktree bitElijah Newren via GitGitGadget, Jan 14, 2022
  23. Ævar Arnfjörð BjarmasonFeb 16, 2022
  24. Elijah NewrenFeb 16, 2022
  25. 5/5 Accelerate clear_skip_worktree_from_present_files() by cachingElijah Newren via GitGitGadget, Jan 14, 2022
  26. Victoria DyeJan 15, 2022
  27. Ævar Arnfjörð BjarmasonFeb 16, 2022
  28. Elijah NewrenFeb 16, 2022
  29. Elijah NewrenFeb 17, 2022
  30. Victoria DyeJan 15, 2022

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.