{"thread":{"id":"24590","subject":"[PATCH 0/5] nd/fix-sparse-checkout v2","startedAt":"2010-07-31T06:14:24Z","lastAt":"2010-08-08T22:39:24Z","messageCount":10,"participants":["Nguyễn Thái Ngọc Duy","Junio C Hamano","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"146844","messageId":"1280556869-707-1-git-send-email-pclouds@gmail.com","threadId":"24590","inReplyTo":null,"subject":"[PATCH 0/5] nd/fix-sparse-checkout v2","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-31T06:14:24Z","receivedAt":"2010-07-31T06:14:24Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Discussion of patch 1/3 from the first series resulted in 2/5 in this\nseries. 2/3 and 3/3 from the former have commit messages revised,\ncode change remains the same.\n\nJonathan Nieder (1):\n  t1011 (sparse checkout): style nitpicks\n\nNguyễn Thái Ngọc Duy (4):\n  unpack-trees: only clear CE_UPDATE|CE_REMOVE when skip-worktree is always set\n  unpack-trees: let read-tree -u remove index entries outside sparse area\n  unpack-trees: do not check for conflict entries too early\n  unpack-trees: mark new entries skip-worktree appropriately\n\n cache.h                              |    3 +-\n t/t1011-read-tree-sparse-checkout.sh |  123 +++++++++++++++++++++-------------\n unpack-trees.c                       |   56 +++++++++-------\n 3 files changed, 108 insertions(+), 74 deletions(-)\n"},{"id":"146845","messageId":"1280556869-707-2-git-send-email-pclouds@gmail.com","threadId":"24590","inReplyTo":"1280556869-707-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 1/5] t1011 (sparse checkout): style nitpicks","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-31T06:14:25Z","receivedAt":"2010-07-31T06:14:25Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"From: Jonathan Nieder <jrnieder@gmail.com>\n\nTweak the rest of the script to more closely follow the test\nstyle guide.  Guarding setup commands with test_expect_success\nmakes it easy to see the scope in which some particular data is\nused; removal of whitespace after >redirection operators is just\nfor consistency.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n t/t1011-read-tree-sparse-checkout.sh |  102 ++++++++++++++++++----------------\n 1 files changed, 55 insertions(+), 47 deletions(-)\n\ndiff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh\nindex 62246db..9189de8 100755\n--- a/t/t1011-read-tree-sparse-checkout.sh\n+++ b/t/t1011-read-tree-sparse-checkout.sh\n@@ -1,16 +1,30 @@\n #!/bin/sh\n \n-test_description='sparse checkout tests'\n+test_description='sparse checkout tests\n+\n+* (tag: removed, master) removed\n+| D\tsub/added\n+* (HEAD, tag: top) modified and added\n+| M\tinit.t\n+| A\tsub/added\n+* (tag: init) init\n+  A\tinit.t\n+'\n \n . ./test-lib.sh\n \n-cat >expected <<EOF\n-100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0\tinit.t\n-100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tsub/added\n-EOF\n test_expect_success 'setup' '\n+\tcat >expected <<-\\EOF &&\n+\t100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0\tinit.t\n+\t100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0\tsub/added\n+\tEOF\n+\tcat >expected.swt <<-\\EOF &&\n+\tH init.t\n+\tH sub/added\n+\tEOF\n+\n \ttest_commit init &&\n-\techo modified >> init.t &&\n+\techo modified >>init.t &&\n \tmkdir sub &&\n \ttouch sub/added &&\n \tgit add init.t sub/added &&\n@@ -20,26 +34,22 @@ test_expect_success 'setup' '\n \tgit commit -m removed &&\n \tgit tag removed &&\n \tgit checkout top &&\n-\tgit ls-files --stage > result &&\n+\tgit ls-files --stage >result &&\n \ttest_cmp expected result\n '\n \n-cat >expected.swt <<EOF\n-H init.t\n-H sub/added\n-EOF\n test_expect_success 'read-tree without .git/info/sparse-checkout' '\n \tgit read-tree -m -u HEAD &&\n-\tgit ls-files --stage > result &&\n+\tgit ls-files --stage >result &&\n \ttest_cmp expected result &&\n-\tgit ls-files -t > result &&\n+\tgit ls-files -t >result &&\n \ttest_cmp expected.swt result\n '\n \n test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' '\n-\techo > .git/info/sparse-checkout\n+\techo >.git/info/sparse-checkout\n \tgit read-tree -m -u HEAD &&\n-\tgit ls-files -t > result &&\n+\tgit ls-files -t >result &&\n \ttest_cmp expected.swt result &&\n \ttest -f init.t &&\n \ttest -f sub/added\n@@ -47,9 +57,9 @@ test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' '\n \n test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled' '\n \tgit config core.sparsecheckout true &&\n-\techo > .git/info/sparse-checkout &&\n+\techo >.git/info/sparse-checkout &&\n \tgit read-tree --no-sparse-checkout -m -u HEAD &&\n-\tgit ls-files -t > result &&\n+\tgit ls-files -t >result &&\n \ttest_cmp expected.swt result &&\n \ttest -f init.t &&\n \ttest -f sub/added\n@@ -57,92 +67,90 @@ test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-\n \n test_expect_success 'read-tree with empty .git/info/sparse-checkout' '\n \tgit config core.sparsecheckout true &&\n-\techo > .git/info/sparse-checkout &&\n+\techo >.git/info/sparse-checkout &&\n \ttest_must_fail git read-tree -m -u HEAD &&\n-\tgit ls-files --stage > result &&\n+\tgit ls-files --stage >result &&\n \ttest_cmp expected result &&\n-\tgit ls-files -t > result &&\n+\tgit ls-files -t >result &&\n \ttest_cmp expected.swt result &&\n \ttest -f init.t &&\n \ttest -f sub/added\n '\n \n-cat >expected.swt <<EOF\n-S init.t\n-H sub/added\n-EOF\n test_expect_success 'match directories with trailing slash' '\n+\tcat >expected.swt-noinit <<-\\EOF &&\n+\tS init.t\n+\tH sub/added\n+\tEOF\n+\n \techo sub/ > .git/info/sparse-checkout &&\n \tgit read-tree -m -u HEAD &&\n \tgit ls-files -t > result &&\n-\ttest_cmp expected.swt result &&\n+\ttest_cmp expected.swt-noinit result &&\n \ttest ! -f init.t &&\n \ttest -f sub/added\n '\n \n-cat >expected.swt <<EOF\n-H init.t\n-H sub/added\n-EOF\n test_expect_failure 'match directories without trailing slash' '\n-\techo init.t > .git/info/sparse-checkout &&\n-\techo sub >> .git/info/sparse-checkout &&\n+\techo init.t >.git/info/sparse-checkout &&\n+\techo sub >>.git/info/sparse-checkout &&\n \tgit read-tree -m -u HEAD &&\n-\tgit ls-files -t > result &&\n+\tgit ls-files -t >result &&\n \ttest_cmp expected.swt result &&\n \ttest ! -f init.t &&\n \ttest -f sub/added\n '\n \n-cat >expected.swt <<EOF\n-H init.t\n-S sub/added\n-EOF\n test_expect_success 'checkout area changes' '\n-\techo init.t > .git/info/sparse-checkout &&\n+\tcat >expected.swt-nosub <<-\\EOF &&\n+\tH init.t\n+\tS sub/added\n+\tEOF\n+\n+\techo init.t >.git/info/sparse-checkout &&\n \tgit read-tree -m -u HEAD &&\n-\tgit ls-files -t > result &&\n-\ttest_cmp expected.swt result &&\n+\tgit ls-files -t >result &&\n+\ttest_cmp expected.swt-nosub result &&\n \ttest -f init.t &&\n \ttest ! -f sub/added\n '\n \n test_expect_success 'read-tree updates worktree, absent case' '\n-\techo sub/added > .git/info/sparse-checkout &&\n+\techo sub/added >.git/info/sparse-checkout &&\n \tgit checkout -f top &&\n \tgit read-tree -m -u HEAD^ &&\n \ttest ! -f init.t\n '\n \n test_expect_success 'read-tree updates worktree, dirty case' '\n-\techo sub/added > .git/info/sparse-checkout &&\n+\techo sub/added >.git/info/sparse-checkout &&\n \tgit checkout -f top &&\n-\techo dirty > init.t &&\n+\techo dirty >init.t &&\n \tgit read-tree -m -u HEAD^ &&\n \tgrep -q dirty init.t &&\n \trm init.t\n '\n \n test_expect_success 'read-tree removes worktree, dirty case' '\n-\techo init.t > .git/info/sparse-checkout &&\n+\techo init.t >.git/info/sparse-checkout &&\n \tgit checkout -f top &&\n-\techo dirty > added &&\n+\techo dirty >added &&\n \tgit read-tree -m -u HEAD^ &&\n \tgrep -q dirty added\n '\n \n test_expect_success 'read-tree adds to worktree, absent case' '\n-\techo init.t > .git/info/sparse-checkout &&\n+\techo init.t >.git/info/sparse-checkout &&\n \tgit checkout -f removed &&\n \tgit read-tree -u -m HEAD^ &&\n \ttest ! -f sub/added\n '\n \n test_expect_success 'read-tree adds to worktree, dirty case' '\n-\techo init.t > .git/info/sparse-checkout &&\n+\techo init.t >.git/info/sparse-checkout &&\n \tgit checkout -f removed &&\n \tmkdir sub &&\n-\techo dirty > sub/added &&\n+\techo dirty >sub/added &&\n \tgit read-tree -u -m HEAD^ &&\n \tgrep -q dirty sub/added\n '\n-- \n1.7.1.rc1.69.g24c2f7\n"},{"id":"146846","messageId":"1280556869-707-3-git-send-email-pclouds@gmail.com","threadId":"24590","inReplyTo":"1280556869-707-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 2/5] unpack-trees: only clear CE_UPDATE|CE_REMOVE when skip-worktree is always set","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-31T06:14:26Z","receivedAt":"2010-07-31T06:14:26Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The purpose of this clearing is, as explained in comment, because\nverify_*() may set those bits before apply_sparse_checkout() is\ncalled. By that time, it's not clear whether an entry will stay in\ncheckout area or out. After $GIT_DIR/info/sparse-checkout is applied,\nwe know what entries will be in finally. It's time to clean unwanted\nbits.\n\nThat works perfectly when checkout area remains unchanged. When\ncheckout area changes, apply_sparse_checkout() may set CE_UPDATE\nor CE_WT_REMOVE to widen/narrow checkout area. Doing the clearing\nafter apply_sparse_checkout() may clear those widening/narrowing\nbits unexpectedly.\n\nSo, only do that on entries that are not affected by checkout area\nchanges (i.e. skip-worktree bit does not change after\napply_sparse_checkout).\n\nThis code does not actually fix anything though, just\nfuture-proof. The removed code and the narrow/widen code inside\napply_sparse_checkout are currently independent (narrow code never\nsets CE_REMOVE, widen code sets CE_UPDATE, but ce_skip_worktree()\nwould be false).\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n t/t1011-read-tree-sparse-checkout.sh |   12 ++++++++++++\n unpack-trees.c                       |   26 ++++++++++++--------------\n 2 files changed, 24 insertions(+), 14 deletions(-)\n\ndiff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh\nindex 9189de8..2876daf 100755\n--- a/t/t1011-read-tree-sparse-checkout.sh\n+++ b/t/t1011-read-tree-sparse-checkout.sh\n@@ -155,4 +155,16 @@ test_expect_success 'read-tree adds to worktree, dirty case' '\n \tgrep -q dirty sub/added\n '\n \n+test_expect_success 'index removal and worktree narrowing at the same time' '\n+\t>empty &&\n+\techo init.t >.git/info/sparse-checkout &&\n+\techo sub/added >>.git/info/sparse-checkout &&\n+\tgit checkout -f top &&\n+\techo init.t >.git/info/sparse-checkout &&\n+\tgit checkout removed &&\n+\tgit ls-files sub/added >result\n+\ttest ! -f sub/added &&\n+\ttest_cmp empty result\n+'\n+\n test_done\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex e8f03f5..6d0df99 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -156,13 +156,18 @@ static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_opt\n \t\tce->ce_flags &= ~CE_SKIP_WORKTREE;\n \n \t/*\n-\t * We only care about files getting into the checkout area\n-\t * If merge strategies want to remove some, go ahead, this\n-\t * flag will be removed eventually in unpack_trees() if it's\n-\t * outside checkout area.\n+\t * if (!was_skip_worktree && !ce_skip_worktree()) {\n+\t *\tThis is perfectly normal. Move on;\n+\t * }\n \t */\n-\tif (ce->ce_flags & CE_REMOVE)\n-\t\treturn 0;\n+\n+\t/*\n+\t * Merge strategies may set CE_UPDATE|CE_REMOVE outside checkout\n+\t * area as a result of ce_skip_worktree() shortcuts in\n+\t * verify_absent() and verify_uptodate(). Clear them.\n+\t */\n+\tif (was_skip_worktree && ce_skip_worktree(ce))\n+\t\tce->ce_flags &= ~(CE_UPDATE | CE_REMOVE);\n \n \tif (!was_skip_worktree && ce_skip_worktree(ce)) {\n \t\t/*\n@@ -796,14 +801,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \t\t\t\tret = -1;\n \t\t\t\tgoto done;\n \t\t\t}\n-\t\t\t/*\n-\t\t\t * Merge strategies may set CE_UPDATE|CE_REMOVE outside checkout\n-\t\t\t * area as a result of ce_skip_worktree() shortcuts in\n-\t\t\t * verify_absent() and verify_uptodate(). Clear them.\n-\t\t\t */\n-\t\t\tif (ce_skip_worktree(ce))\n-\t\t\t\tce->ce_flags &= ~(CE_UPDATE | CE_REMOVE);\n-\t\t\telse\n+\t\t\tif (!ce_skip_worktree(ce))\n \t\t\t\tempty_worktree = 0;\n \n \t\t}\n-- \n1.7.1.rc1.69.g24c2f7\n"},{"id":"146847","messageId":"1280556869-707-4-git-send-email-pclouds@gmail.com","threadId":"24590","inReplyTo":"1280556869-707-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 3/5] unpack-trees: let read-tree -u remove index entries outside sparse area","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-31T06:14:27Z","receivedAt":"2010-07-31T06:14:27Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"To avoid touching the worktree outside a sparse checkout,\nwhen the update flag is enabled unpack_trees() clears the\nCE_UPDATE and CE_REMOVE flags on entries that do not match the\nsparse pattern before actually committing any updates to the\nindex file or worktree.\n\nThe effect on the index was unintentional; sparse checkout was\nnever meant to prevent index updates outside the area checked\nout.  And the result is very confusing: for example, after a\nfailed merge, currently \"git reset --hard\" does not reset the\nstate completely but an additional \"git reset --mixed\" will.\n\nSo stop clearing the CE_REMOVE flag.  Instead, maintain a\nCE_WT_REMOVE flag to separately track whether a particular\nfile removal should apply to the worktree in addition to the\nindex or not.\n\nThe CE_WT_REMOVE flag is used already to mark files that\nshould be removed because of a narrowing checkout area.  That\nusage will still apply; do not clear the CE_WT_REMOVE flag\nin that case (detectable because the CE_REMOVE flag is not\nset).\n\nThis bug masked some other bugs illustrated by the test\nsuite, which will be addressed by later patches.\n\nReported-by: Frédéric Brière <fbriere@fbriere.net>\nFixes: http://bugs.debian.org/583699\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h                              |    3 +--\n t/t1011-read-tree-sparse-checkout.sh |   11 ++++++++++-\n unpack-trees.c                       |   29 +++++++++++++++++++----------\n 3 files changed, 30 insertions(+), 13 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 0d101e4..4e7bb62 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -179,8 +179,7 @@ struct cache_entry {\n #define CE_UNHASHED  (0x200000)\n #define CE_CONFLICTED (0x800000)\n \n-/* Only remove in work directory, not index */\n-#define CE_WT_REMOVE (0x400000)\n+#define CE_WT_REMOVE (0x400000) /* remove in work directory */\n \n #define CE_UNPACKED  (0x1000000)\n \ndiff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh\nindex 2876daf..3e01c6e 100755\n--- a/t/t1011-read-tree-sparse-checkout.sh\n+++ b/t/t1011-read-tree-sparse-checkout.sh\n@@ -146,7 +146,7 @@ test_expect_success 'read-tree adds to worktree, absent case' '\n \ttest ! -f sub/added\n '\n \n-test_expect_success 'read-tree adds to worktree, dirty case' '\n+test_expect_failure 'read-tree adds to worktree, dirty case' '\n \techo init.t >.git/info/sparse-checkout &&\n \tgit checkout -f removed &&\n \tmkdir sub &&\n@@ -167,4 +167,13 @@ test_expect_success 'index removal and worktree narrowing at the same time' '\n \ttest_cmp empty result\n '\n \n+test_expect_success 'read-tree --reset removes outside worktree' '\n+\t>empty &&\n+\techo init.t >.git/info/sparse-checkout &&\n+\tgit checkout -f top &&\n+\tgit reset --hard removed &&\n+\tgit ls-files sub/added >result &&\n+\ttest_cmp empty result\n+'\n+\n test_done\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 6d0df99..1413872 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -53,6 +53,9 @@ static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,\n \n \tclear |= CE_HASHED | CE_UNHASHED;\n \n+\tif (set & CE_REMOVE)\n+\t\tset |= CE_WT_REMOVE;\n+\n \tmemcpy(new, ce, size);\n \tnew->next = NULL;\n \tnew->ce_flags = (new->ce_flags & ~clear) | set;\n@@ -84,7 +87,7 @@ static int check_updates(struct unpack_trees_options *o)\n \tif (o->update && o->verbose_update) {\n \t\tfor (total = cnt = 0; cnt < index->cache_nr; cnt++) {\n \t\t\tstruct cache_entry *ce = index->cache[cnt];\n-\t\t\tif (ce->ce_flags & (CE_UPDATE | CE_REMOVE | CE_WT_REMOVE))\n+\t\t\tif (ce->ce_flags & (CE_UPDATE | CE_WT_REMOVE))\n \t\t\t\ttotal++;\n \t\t}\n \n@@ -104,12 +107,6 @@ static int check_updates(struct unpack_trees_options *o)\n \t\t\t\tunlink_entry(ce);\n \t\t\tcontinue;\n \t\t}\n-\n-\t\tif (ce->ce_flags & CE_REMOVE) {\n-\t\t\tdisplay_progress(progress, ++cnt);\n-\t\t\tif (o->update)\n-\t\t\t\tunlink_entry(ce);\n-\t\t}\n \t}\n \tremove_marked_cache_entries(&o->result);\n \tremove_scheduled_dirs();\n@@ -164,10 +161,22 @@ static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_opt\n \t/*\n \t * Merge strategies may set CE_UPDATE|CE_REMOVE outside checkout\n \t * area as a result of ce_skip_worktree() shortcuts in\n-\t * verify_absent() and verify_uptodate(). Clear them.\n+\t * verify_absent() and verify_uptodate().\n+\t * Make sure they don't modify worktree if they are already\n+\t * outside checkout area\n \t */\n-\tif (was_skip_worktree && ce_skip_worktree(ce))\n-\t\tce->ce_flags &= ~(CE_UPDATE | CE_REMOVE);\n+\tif (was_skip_worktree && ce_skip_worktree(ce)) {\n+\t\tce->ce_flags &= ~CE_UPDATE;\n+\n+\t\t/*\n+\t\t * By default, when CE_REMOVE is on, CE_WT_REMOVE is also\n+\t\t * on to get that file removed from both index and worktree.\n+\t\t * If that file is already outside worktree area, don't\n+\t\t * bother remove it.\n+\t\t */\n+\t\tif (ce->ce_flags & CE_REMOVE)\n+\t\t\tce->ce_flags &= ~CE_WT_REMOVE;\n+\t}\n \n \tif (!was_skip_worktree && ce_skip_worktree(ce)) {\n \t\t/*\n-- \n1.7.1.rc1.69.g24c2f7\n"},{"id":"146848","messageId":"1280556869-707-5-git-send-email-pclouds@gmail.com","threadId":"24590","inReplyTo":"1280556869-707-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 4/5] unpack-trees: do not check for conflict entries too early","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-31T06:14:28Z","receivedAt":"2010-07-31T06:14:28Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The idea of sparse checkout is conflict entries should always stay\nin worktree, regardless $GIT_DIR/info/sparse-checkout. Therefore,\nce_stage(ce) usually means no CE_SKIP_WORKTREE. This is true when all\nentries have been merged into the index, and identical staged entries\ncollapsed.\n\nHowever, will_have_skip_worktree() since f1f523e (unpack-trees():\nignore worktree check outside checkout area) is also used earlier in\nverify_* functions, where entries have not been merged to index yet\nand ce_stage() is not zero. Checking ce_stage() then may provoke\nunnecessary verification on entries outside checkout area and error\nout.\n\nThis fixes part of test case \"read-tree adds to worktree, dirty case\".\nThe error\n\nerror: Untracked working tree file 'sub/added' would be overwritten by merge.\n\nis now gone and (unfortunately) replaced by another error, which will\nbe addressed in the next patch.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n unpack-trees.c |    5 +----\n 1 files changed, 1 insertions(+), 4 deletions(-)\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 1413872..b34ef46 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -135,9 +135,6 @@ static int will_have_skip_worktree(const struct cache_entry *ce, struct unpack_t\n {\n \tconst char *basename;\n \n-\tif (ce_stage(ce))\n-\t\treturn 0;\n-\n \tbasename = strrchr(ce->name, '/');\n \tbasename = basename ? basename+1 : ce->name;\n \treturn excluded_from_list(ce->name, ce_namelen(ce), basename, NULL, o->el) <= 0;\n@@ -147,7 +144,7 @@ static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_opt\n {\n \tint was_skip_worktree = ce_skip_worktree(ce);\n \n-\tif (will_have_skip_worktree(ce, o))\n+\tif (!ce_stage(ce) && will_have_skip_worktree(ce, o))\n \t\tce->ce_flags |= CE_SKIP_WORKTREE;\n \telse\n \t\tce->ce_flags &= ~CE_SKIP_WORKTREE;\n-- \n1.7.1.rc1.69.g24c2f7\n"},{"id":"146849","messageId":"1280556869-707-6-git-send-email-pclouds@gmail.com","threadId":"24590","inReplyTo":"1280556869-707-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 5/5] unpack-trees: mark new entries skip-worktree appropriately","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-31T06:14:29Z","receivedAt":"2010-07-31T06:14:29Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Sparse checkout narrows worktree down based on the skip-worktree bit\nbefore and after $GIT_DIR/info/sparse-checkout application. If it does\nnot have that bit before but does after, a narrow is detected and the\nfile will be removed from worktree.\n\nNew files added by merge, however, does not have skip-worktree bit. If\nthose files appear to be outside checkout area, the same rule applies:\nthe file gets removed from worktree even though they don't exist in\nworktree.\n\nJust pretend they have skip-worktree before in that case, so the rule\nis ignored.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n t/t1011-read-tree-sparse-checkout.sh |    2 +-\n unpack-trees.c                       |    2 ++\n 2 files changed, 3 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh\nindex 3e01c6e..04d4450 100755\n--- a/t/t1011-read-tree-sparse-checkout.sh\n+++ b/t/t1011-read-tree-sparse-checkout.sh\n@@ -146,7 +146,7 @@ test_expect_success 'read-tree adds to worktree, absent case' '\n \ttest ! -f sub/added\n '\n \n-test_expect_failure 'read-tree adds to worktree, dirty case' '\n+test_expect_success 'read-tree adds to worktree, dirty case' '\n \techo init.t >.git/info/sparse-checkout &&\n \tgit checkout -f removed &&\n \tmkdir sub &&\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex b34ef46..86e6409 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1096,6 +1096,8 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old,\n \tif (!old) {\n \t\tif (verify_absent(merge, \"overwritten\", o))\n \t\t\treturn -1;\n+\t\tif (!o->skip_sparse_checkout && will_have_skip_worktree(merge, o))\n+\t\t\tupdate |= CE_SKIP_WORKTREE;\n \t\tinvalidate_ce_path(merge, o);\n \t} else if (!(old->ce_flags & CE_CONFLICTED)) {\n \t\t/*\n-- \n1.7.1.rc1.69.g24c2f7\n"},{"id":"146959","messageId":"7vmxt5lyjh.fsf@alter.siamese.dyndns.org","threadId":"24590","inReplyTo":"1280556869-707-2-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 1/5] t1011 (sparse checkout): style nitpicks","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-02T17:22:42Z","receivedAt":"2010-08-02T17:22:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> From: Jonathan Nieder <jrnieder@gmail.com>\n>\n> Tweak the rest of the script to more closely follow the test\n> style guide.  Guarding setup commands with test_expect_success\n> makes it easy to see the scope in which some particular data is\n> used; removal of whitespace after >redirection operators is just\n> for consistency.\n>\n> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\nWhat happened to the 'test -z \"$(cmd)\" discards exit status from cmd' part\nof Jonathan's patch?\n"},{"id":"146960","messageId":"7viq3sncpy.fsf@alter.siamese.dyndns.org","threadId":"24590","inReplyTo":"7vmxt5lyjh.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 1/5] t1011 (sparse checkout): style nitpicks","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-02T17:31:05Z","receivedAt":"2010-08-02T17:31:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>> From: Jonathan Nieder <jrnieder@gmail.com>\n>>\n>> Tweak the rest of the script to more closely follow the test\n>> style guide.  Guarding setup commands with test_expect_success\n>> makes it easy to see the scope in which some particular data is\n>> used; removal of whitespace after >redirection operators is just\n>> for consistency.\n>>\n>> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>\n>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n>\n> What happened to the 'test -z \"$(cmd)\" discards exit status from cmd' part\n> of Jonathan's patch?\n\nSorry, I was confused.\n\nPlease disregard the above; it took me a while to realize that this\n5-patch series is a re-roll of what I queued, which in turn Jonathan's\nnitpick is based on, and you took the advice while redoing 2/5.\n\nThanks.\n"},{"id":"147073","messageId":"20100803211632.GA2645@burratino","threadId":"24590","inReplyTo":"1280556869-707-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 0/5] nd/fix-sparse-checkout v2","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-08-03T21:16:33Z","receivedAt":"2010-08-03T21:16:33Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Nguyễn Thái Ngọc Duy wrote:\n\n> Discussion of patch 1/3 from the first series resulted in 2/5 in this\n> series. 2/3 and 3/3 from the former have commit messages revised,\n> code change remains the same.\n> \n> Jonathan Nieder (1):\n>   t1011 (sparse checkout): style nitpicks\n> \n> Nguyễn Thái Ngọc Duy (4):\n>   unpack-trees: only clear CE_UPDATE|CE_REMOVE when skip-worktree is always set\n>   unpack-trees: let read-tree -u remove index entries outside sparse area\n>   unpack-trees: do not check for conflict entries too early\n>   unpack-trees: mark new entries skip-worktree appropriately\n\nReviewed-by: Jonathan Nieder <jrnieder@gmail.com>\n\nThanks for the explanations.\n"},{"id":"147470","messageId":"20100808223924.GA7946@burratino","threadId":"24590","inReplyTo":"1280556869-707-3-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 2/5] unpack-trees: only clear CE_UPDATE|CE_REMOVE when skip-worktree is always set","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-08-08T22:39:24Z","receivedAt":"2010-08-08T22:39:24Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi Duy,\n\nNguyễn Thái Ngọc Duy wrote:\n\n> +++ b/t/t1011-read-tree-sparse-checkout.sh\n> @@ -155,4 +155,16 @@ test_expect_success 'read-tree adds to worktree, dirty case' '\n>  \tgrep -q dirty sub/added\n>  '\n>  \n> +test_expect_success 'index removal and worktree narrowing at the same time' '\n> +\t>empty &&\n> +\techo init.t >.git/info/sparse-checkout &&\n> +\techo sub/added >>.git/info/sparse-checkout &&\n> +\tgit checkout -f top &&\n> +\techo init.t >.git/info/sparse-checkout &&\n> +\tgit checkout removed &&\n> +\tgit ls-files sub/added >result\n> +\ttest ! -f sub/added &&\n\nMissing “&&”.  Sorry to miss this before.\n\nPatch for squashing follows.\n\n-- 8< --\nSubject: t1011 (sparse checkout): fix &&-chaining\n\nMake sure errors from “git checkout” are detected.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n t/t1011-read-tree-sparse-checkout.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh\nindex 04d4450..9a07de1 100755\n--- a/t/t1011-read-tree-sparse-checkout.sh\n+++ b/t/t1011-read-tree-sparse-checkout.sh\n@@ -162,7 +162,7 @@ test_expect_success 'index removal and worktree narrowing at the same time' '\n \tgit checkout -f top &&\n \techo init.t >.git/info/sparse-checkout &&\n \tgit checkout removed &&\n-\tgit ls-files sub/added >result\n+\tgit ls-files sub/added >result &&\n \ttest ! -f sub/added &&\n \ttest_cmp empty result\n '\n-- \n1.7.2.1.544.ga752d.dirty\n"}]}