{"thread":{"id":"27169","subject":"[PATCH 0/4] Fix diff-files output for unmerged paths","startedAt":"2011-04-24T20:51:25Z","lastAt":"2011-04-25T01:18:41Z","messageCount":8,"participants":["Junio C Hamano","Thiago Farina"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"166284","messageId":"1303678289-27627-1-git-send-email-gitster@pobox.com","threadId":"27169","inReplyTo":null,"subject":"[PATCH 0/4] Fix diff-files output for unmerged paths","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-24T20:51:25Z","receivedAt":"2011-04-24T20:51:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This is cleaned-up series of my previous attempts that were queued in 'pu'\nlate in the pre-1.7.5 cycle.\n\nJunio C Hamano (4):\n  test: use $_z40 from test-lib\n  diff.c: return filepair from diff_unmerge()\n  diff: remove often unused parameters from diff_unmerge()\n  diff-files: show unmerged entries correctly\n\n diff-lib.c                       |   15 +++++--\n diff.c                           |   12 +++---\n diff.h                           |    5 +--\n t/t1400-update-ref.sh            |    2 +-\n t/t1501-worktree.sh              |    7 +--\n t/t2011-checkout-invalid-head.sh |    2 +-\n t/t2201-add-update-typechange.sh |    2 -\n t/t3200-branch.sh                |    4 +-\n t/t3600-rm.sh                    |    3 +-\n t/t4002-diff-basic.sh            |    5 +--\n t/t4020-diff-external.sh         |    2 -\n t/t4027-diff-submodule.sh        |    1 -\n t/t4046-diff-unmerged.sh         |   87 ++++++++++++++++++++++++++++++++++++++\n t/t7011-skip-worktree-reading.sh |    4 +-\n t/t7012-skip-worktree-writing.sh |    2 +-\n t/test-lib.sh                    |    3 +\n 16 files changed, 120 insertions(+), 36 deletions(-)\n create mode 100755 t/t4046-diff-unmerged.sh\n\n-- \n1.7.5\n"},{"id":"166285","messageId":"1303678289-27627-2-git-send-email-gitster@pobox.com","threadId":"27169","inReplyTo":"1303678289-27627-1-git-send-email-gitster@pobox.com","subject":"[PATCH 1/4] test: use $_z40 from test-lib","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-24T20:51:26Z","receivedAt":"2011-04-24T20:51:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"There is no need to duplicate the definition of $_z40 and $_x40 that\ntest-lib.sh supplies the test scripts.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1400-update-ref.sh            |    2 +-\n t/t1501-worktree.sh              |    7 +++----\n t/t2011-checkout-invalid-head.sh |    2 +-\n t/t2201-add-update-typechange.sh |    2 --\n t/t3200-branch.sh                |    4 ++--\n t/t3600-rm.sh                    |    3 +--\n t/t4002-diff-basic.sh            |    5 +----\n t/t4020-diff-external.sh         |    2 --\n t/t4027-diff-submodule.sh        |    1 -\n t/t7011-skip-worktree-reading.sh |    4 ++--\n t/t7012-skip-worktree-writing.sh |    2 +-\n t/test-lib.sh                    |    3 +++\n 12 files changed, 15 insertions(+), 22 deletions(-)\n\ndiff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh\nindex 54ba3df..6b39915 100755\n--- a/t/t1400-update-ref.sh\n+++ b/t/t1400-update-ref.sh\n@@ -6,7 +6,7 @@\n test_description='Test git update-ref and basic ref logging'\n . ./test-lib.sh\n \n-Z=0000000000000000000000000000000000000000\n+Z=$_z40\n \n test_expect_success setup '\n \ndiff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh\nindex 2c8f01f..dc7c992 100755\n--- a/t/t1501-worktree.sh\n+++ b/t/t1501-worktree.sh\n@@ -7,7 +7,6 @@ test_expect_success 'setup' '\n \tEMPTY_TREE=$(git write-tree) &&\n \tEMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&\n \tCHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&\n-\tZEROES=0000000000000000000000000000000000000000 &&\n \tEMPTY_BLOB7=$(echo $EMPTY_BLOB | sed \"s/\\(.......\\).*/\\1/\") &&\n \tCHANGED_BLOB7=$(echo $CHANGED_BLOB | sed \"s/\\(.......\\).*/\\1/\") &&\n \n@@ -239,10 +238,10 @@ test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '\n \n test_expect_success 'diff-index respects work tree under .git dir' '\n \tcat >diff-index-cached.expected <<-EOF &&\n-\t:000000 100644 $ZEROES $EMPTY_BLOB A\tsub/dir/tracked\n+\t:000000 100644 $_z40 $EMPTY_BLOB A\tsub/dir/tracked\n \tEOF\n \tcat >diff-index.expected <<-EOF &&\n-\t:000000 100644 $ZEROES $ZEROES A\tsub/dir/tracked\n+\t:000000 100644 $_z40 $_z40 A\tsub/dir/tracked\n \tEOF\n \n \t(\n@@ -258,7 +257,7 @@ test_expect_success 'diff-index respects work tree under .git dir' '\n \n test_expect_success 'diff-files respects work tree under .git dir' '\n \tcat >diff-files.expected <<-EOF &&\n-\t:100644 100644 $EMPTY_BLOB $ZEROES M\tsub/dir/tracked\n+\t:100644 100644 $EMPTY_BLOB $_z40 M\tsub/dir/tracked\n \tEOF\n \n \t(\ndiff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh\nindex 15ebdc2..300f8bf 100755\n--- a/t/t2011-checkout-invalid-head.sh\n+++ b/t/t2011-checkout-invalid-head.sh\n@@ -15,7 +15,7 @@ test_expect_success 'checkout should not start branch from a tree' '\n '\n \n test_expect_success 'checkout master from invalid HEAD' '\n-\techo 0000000000000000000000000000000000000000 >.git/HEAD &&\n+\techo $_z40 >.git/HEAD &&\n \tgit checkout master --\n '\n \ndiff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh\nindex 2e8f702..954fc51 100755\n--- a/t/t2201-add-update-typechange.sh\n+++ b/t/t2201-add-update-typechange.sh\n@@ -4,8 +4,6 @@ test_description='more git add -u'\n \n . ./test-lib.sh\n \n-_z40=0000000000000000000000000000000000000000\n-\n test_expect_success setup '\n \t>xyzzy &&\n \t_empty=$(git hash-object --stdin <xyzzy) &&\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex f54a533..4c4cff1 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -35,7 +35,7 @@ test_expect_success \\\n     'git branch a/b/c && test -f .git/refs/heads/a/b/c'\n \n cat >expect <<EOF\n-0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000\tbranch: Created from master\n+$_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000\tbranch: Created from master\n EOF\n test_expect_success \\\n     'git branch -l d/e/f should create a branch and a log' \\\n@@ -214,7 +214,7 @@ test_expect_success \\\n \n # Keep this test last, as it changes the current branch\n cat >expect <<EOF\n-0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000\tbranch: Created from master\n+$_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000\tbranch: Created from master\n EOF\n test_expect_success \\\n     'git checkout -b g/h/i -l should create a branch and a log' \\\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex b26cabd..66523bd 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -240,11 +240,10 @@ test_expect_success 'refresh index before checking if it is up-to-date' '\n \n test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \tgit reset -q --hard &&\n-\tH=0000000000000000000000000000000000000000 &&\n \ti=0 &&\n \twhile test $i -lt 12000\n \tdo\n-\t    echo \"100644 $H 0\tsome-file-$i\"\n+\t    echo \"100644 $_z40 0\tsome-file-$i\"\n \t    i=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n \tgit rm -n \"some-file-*\" | :;\ndiff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh\nindex 73441a5..66e1a52 100755\n--- a/t/t4002-diff-basic.sh\n+++ b/t/t4002-diff-basic.sh\n@@ -126,15 +126,12 @@ cat >.test-recursive-AB <<\\EOF\n :100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M\tZ/NM\n EOF\n \n-x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'\n-x40=\"$x40$x40$x40$x40$x40$x40$x40$x40\"\n-z40='0000000000000000000000000000000000000000'\n cmp_diff_files_output () {\n     # diff-files never reports additions.  Also it does not fill in the\n     # object ID for the changed files because it wants you to look at the\n     # filesystem.\n     sed <\"$2\" >.test-tmp \\\n-\t-e '/^:000000 /d;s/'$x40'\\( [MCRNDU][0-9]*\\)\t/'$z40'\\1\t/' &&\n+\t-e '/^:000000 /d;s/'$_x40'\\( [MCRNDU][0-9]*\\)\t/'$_z40'\\1\t/' &&\n     test_cmp \"$1\" .test-tmp\n }\n \ndiff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh\nindex a7602cf..083f62d 100755\n--- a/t/t4020-diff-external.sh\n+++ b/t/t4020-diff-external.sh\n@@ -4,8 +4,6 @@ test_description='external diff interface test'\n \n . ./test-lib.sh\n \n-_z40=0000000000000000000000000000000000000000\n-\n test_expect_success setup '\n \n \ttest_tick &&\ndiff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh\nindex d99814a..fbe44a3 100755\n--- a/t/t4027-diff-submodule.sh\n+++ b/t/t4027-diff-submodule.sh\n@@ -5,7 +5,6 @@ test_description='difference in submodules'\n . ./test-lib.sh\n . \"$TEST_DIRECTORY\"/diff-lib.sh\n \n-_z40=0000000000000000000000000000000000000000\n test_expect_success setup '\n \ttest_tick &&\n \ttest_create_repo sub &&\ndiff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh\nindex bb4066f..8f3b54d 100755\n--- a/t/t7011-skip-worktree-reading.sh\n+++ b/t/t7011-skip-worktree-reading.sh\n@@ -24,7 +24,7 @@ H sub/2\n EOF\n \n NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n-ZERO_SHA0=0000000000000000000000000000000000000000\n+\n setup_absent() {\n \ttest -f 1 && rm 1\n \tgit update-index --remove 1 &&\n@@ -120,7 +120,7 @@ test_expect_success 'grep with skip-worktree file' '\n \ttest \"$(git grep --no-ext-grep test)\" = \"1:test\"\n '\n \n-echo \":000000 100644 $ZERO_SHA0 $NULL_SHA1 A\t1\" > expected\n+echo \":000000 100644 $_z40 $NULL_SHA1 A\t1\" > expected\n test_expect_success 'diff-index does not examine skip-worktree absent entries' '\n \tsetup_absent &&\n \tgit diff-index HEAD -- 1 > result &&\ndiff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh\nindex 582d0b5..d70fe2f 100755\n--- a/t/t7012-skip-worktree-writing.sh\n+++ b/t/t7012-skip-worktree-writing.sh\n@@ -54,7 +54,7 @@ test_expect_success 'read-tree removes worktree, dirty case' '\n '\n \n NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\n-ZERO_SHA0=0000000000000000000000000000000000000000\n+\n setup_absent() {\n \ttest -f 1 && rm 1\n \tgit update-index --remove 1 &&\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 830e5e7..7afa25f 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -97,6 +97,9 @@ esac\n _x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'\n _x40=\"$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05\"\n \n+# Zero SHA-1\n+_z40=0000000000000000000000000000000000000000\n+\n # Each test should start with something like this, after copyright notices:\n #\n # test_description='Description of this test...\n-- \n1.7.5\n"},{"id":"166286","messageId":"1303678289-27627-3-git-send-email-gitster@pobox.com","threadId":"27169","inReplyTo":"1303678289-27627-1-git-send-email-gitster@pobox.com","subject":"[PATCH 2/4] diff.c: return filepair from diff_unmerge()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-24T20:51:27Z","receivedAt":"2011-04-24T20:51:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The underlying diff_queue() returns diff_filepair so that the caller can\nfurther add information to it, and the helper function diff_unmerge()\nutilizes the feature itself, but does not expose it to its callers, which\nwas kind of selfish.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff.c |   13 ++++++++-----\n diff.h |    2 +-\n 2 files changed, 9 insertions(+), 6 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 9a5c77c..4c34c64 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4308,20 +4308,23 @@ void diff_change(struct diff_options *options,\n \t\tDIFF_OPT_SET(options, HAS_CHANGES);\n }\n \n-void diff_unmerge(struct diff_options *options,\n-\t\t  const char *path,\n-\t\t  unsigned mode, const unsigned char *sha1)\n+struct diff_filepair *diff_unmerge(struct diff_options *options,\n+\t\t\t\t   const char *path,\n+\t\t\t\t   unsigned mode, const unsigned char *sha1)\n {\n+\tstruct diff_filepair *pair;\n \tstruct diff_filespec *one, *two;\n \n \tif (options->prefix &&\n \t    strncmp(path, options->prefix, options->prefix_length))\n-\t\treturn;\n+\t\treturn NULL;\n \n \tone = alloc_filespec(path);\n \ttwo = alloc_filespec(path);\n \tfill_filespec(one, sha1, mode);\n-\tdiff_queue(&diff_queued_diff, one, two)->is_unmerged = 1;\n+\tpair = diff_queue(&diff_queued_diff, one, two);\n+\tpair->is_unmerged = 1;\n+\treturn pair;\n }\n \n static char *run_textconv(const char *pgm, struct diff_filespec *spec,\ndiff --git a/diff.h b/diff.h\nindex bf2f44d..f51a8ee 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -209,7 +209,7 @@ extern void diff_change(struct diff_options *,\n \t\t\tconst char *fullpath,\n \t\t\tunsigned dirty_submodule1, unsigned dirty_submodule2);\n \n-extern void diff_unmerge(struct diff_options *,\n+extern struct diff_filepair *diff_unmerge(struct diff_options *,\n \t\t\t const char *path,\n \t\t\t unsigned mode,\n \t\t\t const unsigned char *sha1);\n-- \n1.7.5\n"},{"id":"166288","messageId":"1303678289-27627-4-git-send-email-gitster@pobox.com","threadId":"27169","inReplyTo":"1303678289-27627-1-git-send-email-gitster@pobox.com","subject":"[PATCH 3/4] diff: remove often unused parameters from diff_unmerge()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-24T20:51:28Z","receivedAt":"2011-04-24T20:51:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"e9c8409 (diff-index --cached --raw: show tree entry on the LHS for\nunmerged entries., 2007-01-05) added a <mode, object name> pair as\nparameters to this function, to store them in the pre-image side of an\nunmerged file pair.  Now the function is fixed to return the filepair it\nqueued, we can make the caller on the special case codepath to do so.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff-lib.c |    7 ++++---\n diff.c     |    5 +----\n diff.h     |    5 +----\n 3 files changed, 6 insertions(+), 11 deletions(-)\n\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 392ce2b..a983855 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -183,7 +183,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t * Show the diff for the 'ce' if we found the one\n \t\t\t * from the desired stage.\n \t\t\t */\n-\t\t\tdiff_unmerge(&revs->diffopt, ce->name, 0, null_sha1);\n+\t\t\tdiff_unmerge(&revs->diffopt, ce->name);\n \t\t\tif (ce_stage(ce) != diff_unmerged_stage)\n \t\t\t\tcontinue;\n \t\t}\n@@ -372,8 +372,9 @@ static void do_oneway_diff(struct unpack_trees_options *o,\n \tmatch_missing = !revs->ignore_merges;\n \n \tif (cached && idx && ce_stage(idx)) {\n-\t\tdiff_unmerge(&revs->diffopt, idx->name, idx->ce_mode,\n-\t\t\t     idx->sha1);\n+\t\tstruct diff_filepair *pair;\n+\t\tpair = diff_unmerge(&revs->diffopt, idx->name);\n+\t\tfill_filespec(pair->one, idx->sha1, idx->ce_mode);\n \t\treturn;\n \t}\n \ndiff --git a/diff.c b/diff.c\nindex 4c34c64..d2c5c56 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -4308,9 +4308,7 @@ void diff_change(struct diff_options *options,\n \t\tDIFF_OPT_SET(options, HAS_CHANGES);\n }\n \n-struct diff_filepair *diff_unmerge(struct diff_options *options,\n-\t\t\t\t   const char *path,\n-\t\t\t\t   unsigned mode, const unsigned char *sha1)\n+struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path)\n {\n \tstruct diff_filepair *pair;\n \tstruct diff_filespec *one, *two;\n@@ -4321,7 +4319,6 @@ struct diff_filepair *diff_unmerge(struct diff_options *options,\n \n \tone = alloc_filespec(path);\n \ttwo = alloc_filespec(path);\n-\tfill_filespec(one, sha1, mode);\n \tpair = diff_queue(&diff_queued_diff, one, two);\n \tpair->is_unmerged = 1;\n \treturn pair;\ndiff --git a/diff.h b/diff.h\nindex f51a8ee..3edb705 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -209,10 +209,7 @@ extern void diff_change(struct diff_options *,\n \t\t\tconst char *fullpath,\n \t\t\tunsigned dirty_submodule1, unsigned dirty_submodule2);\n \n-extern struct diff_filepair *diff_unmerge(struct diff_options *,\n-\t\t\t const char *path,\n-\t\t\t unsigned mode,\n-\t\t\t const unsigned char *sha1);\n+extern struct diff_filepair *diff_unmerge(struct diff_options *, const char *path);\n \n #define DIFF_SETUP_REVERSE      \t1\n #define DIFF_SETUP_USE_CACHE\t\t2\n-- \n1.7.5\n"},{"id":"166287","messageId":"1303678289-27627-5-git-send-email-gitster@pobox.com","threadId":"27169","inReplyTo":"1303678289-27627-1-git-send-email-gitster@pobox.com","subject":"[PATCH 4/4] diff-files: show unmerged entries correctly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-24T20:51:29Z","receivedAt":"2011-04-24T20:51:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Earlier, e9c8409 (diff-index --cached --raw: show tree entry on the LHS\nfor unmerged entries., 2007-01-05) taught the command to show the object\nname and the mode from the entry coming from the tree side when comparing\na tree with an unmerged index.\n\nThis is a belated companion patch that teaches diff-files to show the mode\nfrom the entry coming from the working tree side, when comparing an\nunmerged index and the working tree.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n diff-lib.c               |   10 ++++-\n t/t4046-diff-unmerged.sh |   87 ++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 95 insertions(+), 2 deletions(-)\n create mode 100755 t/t4046-diff-unmerged.sh\n\ndiff --git a/diff-lib.c b/diff-lib.c\nindex a983855..b782476 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -111,6 +111,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)\n \n \t\tif (ce_stage(ce)) {\n \t\t\tstruct combine_diff_path *dpath;\n+\t\t\tstruct diff_filepair *pair;\n+\t\t\tunsigned int wt_mode = 0;\n \t\t\tint num_compare_stages = 0;\n \t\t\tsize_t path_len;\n \n@@ -129,7 +131,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)\n \n \t\t\tchanged = check_removed(ce, &st);\n \t\t\tif (!changed)\n-\t\t\t\tdpath->mode = ce_mode_from_stat(ce, st.st_mode);\n+\t\t\t\twt_mode = ce_mode_from_stat(ce, st.st_mode);\n \t\t\telse {\n \t\t\t\tif (changed < 0) {\n \t\t\t\t\tperror(ce->name);\n@@ -137,7 +139,9 @@ int run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t\t}\n \t\t\t\tif (silent_on_removed)\n \t\t\t\t\tcontinue;\n+\t\t\t\twt_mode = 0;\n \t\t\t}\n+\t\t\tdpath->mode = wt_mode;\n \n \t\t\twhile (i < entries) {\n \t\t\t\tstruct cache_entry *nce = active_cache[i];\n@@ -183,7 +187,9 @@ int run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t * Show the diff for the 'ce' if we found the one\n \t\t\t * from the desired stage.\n \t\t\t */\n-\t\t\tdiff_unmerge(&revs->diffopt, ce->name);\n+\t\t\tpair = diff_unmerge(&revs->diffopt, ce->name);\n+\t\t\tif (wt_mode)\n+\t\t\t\tpair->two->mode = wt_mode;\n \t\t\tif (ce_stage(ce) != diff_unmerged_stage)\n \t\t\t\tcontinue;\n \t\t}\ndiff --git a/t/t4046-diff-unmerged.sh b/t/t4046-diff-unmerged.sh\nnew file mode 100755\nindex 0000000..25d50a6\n--- /dev/null\n+++ b/t/t4046-diff-unmerged.sh\n@@ -0,0 +1,87 @@\n+#!/bin/sh\n+\n+test_description='diff with unmerged index entries'\n+. ./test-lib.sh\n+\n+test_expect_success setup '\n+\tfor i in 0 1 2 3\n+\tdo\n+\t\tblob=$(echo $i | git hash-object --stdin) &&\n+\t\teval \"blob$i=$blob\" &&\n+\t\teval \"m$i=\\\"100644 \\$blob$i $i\\\"\" || break\n+\tdone &&\n+\tpaths= &&\n+\tfor b in o x\n+\tdo\n+\t\tfor o in o x\n+\t\tdo\n+\t\t\tfor t in o x\n+\t\t\tdo\n+\t\t\t\tpath=\"$b$o$t\" &&\n+\t\t\t\tcase \"$path\" in ooo) continue ;; esac\n+\t\t\t\tpaths=\"$paths$path \" &&\n+\t\t\t\tp=\"\t$path\" &&\n+\t\t\t\tcase \"$b\" in x) echo \"$m1$p\" ;; esac &&\n+\t\t\t\tcase \"$o\" in x) echo \"$m2$p\" ;; esac &&\n+\t\t\t\tcase \"$t\" in x) echo \"$m3$p\" ;; esac ||\n+\t\t\t\tbreak\n+\t\t\tdone || break\n+\t\tdone || break\n+\tdone >ls-files-s.expect &&\n+\tgit update-index --index-info <ls-files-s.expect &&\n+\tgit ls-files -s >ls-files-s.actual &&\n+\ttest_cmp ls-files-s.expect ls-files-s.actual\n+'\n+\n+test_expect_success 'diff-files -0' '\n+\tfor path in $paths\n+\tdo\n+\t\t>\"$path\" &&\n+\t\techo \":000000 100644 $_z40 $_z40 U\t$path\"\n+\tdone >diff-files-0.expect &&\n+\tgit diff-files -0 >diff-files-0.actual &&\n+\ttest_cmp diff-files-0.expect diff-files-0.actual\n+'\n+\n+test_expect_success 'diff-files -1' '\n+\tfor path in $paths\n+\tdo\n+\t\t>\"$path\" &&\n+\t\techo \":000000 100644 $_z40 $_z40 U\t$path\" &&\n+\t\tcase \"$path\" in\n+\t\tx??) echo \":100644 100644 $blob1 $_z40 M\t$path\"\n+\t\tesac\n+\tdone >diff-files-1.expect &&\n+\tgit diff-files -1 >diff-files-1.actual &&\n+\ttest_cmp diff-files-1.expect diff-files-1.actual\n+'\n+\n+test_expect_success 'diff-files -2' '\n+\tfor path in $paths\n+\tdo\n+\t\t>\"$path\" &&\n+\t\techo \":000000 100644 $_z40 $_z40 U\t$path\" &&\n+\t\tcase \"$path\" in\n+\t\t?x?) echo \":100644 100644 $blob2 $_z40 M\t$path\"\n+\t\tesac\n+\tdone >diff-files-2.expect &&\n+\tgit diff-files -2 >diff-files-2.actual &&\n+\ttest_cmp diff-files-2.expect diff-files-2.actual &&\n+\tgit diff-files >diff-files-default-2.actual &&\n+\ttest_cmp diff-files-2.expect diff-files-default-2.actual\n+'\n+\n+test_expect_success 'diff-files -3' '\n+\tfor path in $paths\n+\tdo\n+\t\t>\"$path\" &&\n+\t\techo \":000000 100644 $_z40 $_z40 U\t$path\" &&\n+\t\tcase \"$path\" in\n+\t\t??x) echo \":100644 100644 $blob3 $_z40 M\t$path\"\n+\t\tesac\n+\tdone >diff-files-3.expect &&\n+\tgit diff-files -3 >diff-files-3.actual &&\n+\ttest_cmp diff-files-3.expect diff-files-3.actual\n+'\n+\n+test_done\n-- \n1.7.5\n"},{"id":"166289","messageId":"7vy62zl6am.fsf@alter.siamese.dyndns.org","threadId":"27169","inReplyTo":"1303678289-27627-1-git-send-email-gitster@pobox.com","subject":"[PATCH] Fix \"add -u\" that sometimes fails to resolve unmerged paths","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-24T20:53:53Z","receivedAt":"2011-04-24T20:53:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git add -u\" updates the index with the updated contents from the working\ntree by internally running \"diff-files\" to grab the set of paths that are\ndifferent from the index. Then it updates the index entries for the paths\nthat are modified in the working tree, and deletes the index entries for\nthe paths that are deleted in the working tree.\n\nIt ignored the output from the diff-files that indicated that a path is\nunmerged.  For these paths, it instead relied on the fact that an unmerged\npath is followed by the result of comparison between stage #2 (ours) and\nthe working tree, and used that to update or delete such a path when it is\nused to record the resolution of a conflict.\n\nAs the result, when a path did not have stage #2 (e.g. \"we deleted while\nthe other side added\"), these unmerged stages were left behind, instead of\nrecording what the user resolved in the working tree.\n\nSince we recently fixed \"diff-files\" to indicate if the corresponding path\nexists on the working tree for an unmerged path, we do not have to rely on\nthe comparison with stage #2 anymore. We can instead tell the diff-files\nnot to compare with higher stages, and use the unmerged output to update\nthe index to reflect the state of the working tree.\n\nThe changes to the test vector in t2200 illustrates the nature of the bug\nand the fix.  The test expected stage #1 and #3 entries be left behind,\nbut it was codifying the buggy behaviour.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * This comes on top of the 4-patch series to fix \"diff-files\" output for\n   unmerged paths.\n\n builtin/add.c         |   45 +++++++++++++++++++++++----------------------\n t/t2200-add-update.sh |   24 +++++++-----------------\n 2 files changed, 30 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin/add.c b/builtin/add.c\nindex 56a4e0a..027ca3b 100644\n--- a/builtin/add.c\n+++ b/builtin/add.c\n@@ -27,6 +27,27 @@ struct update_callback_data\n \tint add_errors;\n };\n \n+static int fix_unmerged_status(struct diff_filepair *p,\n+\t\t\t       struct update_callback_data *data)\n+{\n+\tif (p->status != DIFF_STATUS_UNMERGED)\n+\t\treturn p->status;\n+\tif (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)\n+\t\t/*\n+\t\t * This is not an explicit add request, and the\n+\t\t * path is missing from the working tree (deleted)\n+\t\t */\n+\t\treturn DIFF_STATUS_DELETED;\n+\telse\n+\t\t/*\n+\t\t * Either an explicit add request, or path exists\n+\t\t * in the working tree.  An attempt to explicitly\n+\t\t * add a path that does not exist in the working tree\n+\t\t * will be caught as an error by the caller immediately.\n+\t\t */\n+\t\treturn DIFF_STATUS_MODIFIED;\n+}\n+\n static void update_callback(struct diff_queue_struct *q,\n \t\t\t    struct diff_options *opt, void *cbdata)\n {\n@@ -36,30 +57,9 @@ static void update_callback(struct diff_queue_struct *q,\n \tfor (i = 0; i < q->nr; i++) {\n \t\tstruct diff_filepair *p = q->queue[i];\n \t\tconst char *path = p->one->path;\n-\t\tswitch (p->status) {\n+\t\tswitch (fix_unmerged_status(p, data)) {\n \t\tdefault:\n \t\t\tdie(\"unexpected diff status %c\", p->status);\n-\t\tcase DIFF_STATUS_UNMERGED:\n-\t\t\t/*\n-\t\t\t * ADD_CACHE_IGNORE_REMOVAL is unset if \"git\n-\t\t\t * add -u\" is calling us, In such a case, a\n-\t\t\t * missing work tree file needs to be removed\n-\t\t\t * if there is an unmerged entry at stage #2,\n-\t\t\t * but such a diff record is followed by\n-\t\t\t * another with DIFF_STATUS_DELETED (and if\n-\t\t\t * there is no stage #2, we won't see DELETED\n-\t\t\t * nor MODIFIED).  We can simply continue\n-\t\t\t * either way.\n-\t\t\t */\n-\t\t\tif (!(data->flags & ADD_CACHE_IGNORE_REMOVAL))\n-\t\t\t\tcontinue;\n-\t\t\t/*\n-\t\t\t * Otherwise, it is \"git add path\" is asking\n-\t\t\t * to explicitly add it; we fall through.  A\n-\t\t\t * missing work tree file is an error and is\n-\t\t\t * caught by add_file_to_index() in such a\n-\t\t\t * case.\n-\t\t\t */\n \t\tcase DIFF_STATUS_MODIFIED:\n \t\tcase DIFF_STATUS_TYPE_CHANGED:\n \t\t\tif (add_file_to_index(&the_index, path, data->flags)) {\n@@ -92,6 +92,7 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags)\n \tdata.flags = flags;\n \tdata.add_errors = 0;\n \trev.diffopt.format_callback_data = &data;\n+\trev.max_count = 0; /* do not compare unmerged paths with stage #2 */\n \trun_diff_files(&rev, DIFF_RACY_IS_MODIFIED);\n \treturn !!data.add_errors;\n }\ndiff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh\nindex 2ad2819..d3bb9fa 100755\n--- a/t/t2200-add-update.sh\n+++ b/t/t2200-add-update.sh\n@@ -149,31 +149,21 @@ test_expect_success 'add -u resolves unmerged paths' '\n \techo 3 >path1 &&\n \techo 2 >path3 &&\n \techo 2 >path5 &&\n-\tgit add -u &&\n-\tgit ls-files -s path1 path2 path3 path4 path5 path6 >actual &&\n-\t{\n-\t\techo \"100644 $three 0\tpath1\"\n-\t\techo \"100644 $one 1\tpath3\"\n-\t\techo \"100644 $one 1\tpath4\"\n-\t\techo \"100644 $one 3\tpath5\"\n-\t\techo \"100644 $one 3\tpath6\"\n-\t} >expect &&\n-\ttest_cmp expect actual &&\n \n-\t# Bonus tests.  Explicit resolving\n-\tgit add path3 path5 &&\n+\t# Explicit resolving by adding removed paths should fail\n \ttest_must_fail git add path4 &&\n \ttest_must_fail git add path6 &&\n-\tgit rm path4 &&\n-\tgit rm path6 &&\n \n-\tgit ls-files -s \"path?\" >actual &&\n+\t# \"add -u\" should notice removals no matter what stages\n+\t# the index entries are in.\n+\tgit add -u &&\n+\tgit ls-files -s path1 path2 path3 path4 path5 path6 >actual &&\n \t{\n \t\techo \"100644 $three 0\tpath1\"\n \t\techo \"100644 $two 0\tpath3\"\n \t\techo \"100644 $two 0\tpath5\"\n-\t} >expect\n-\n+\t} >expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success '\"add -u non-existent\" should fail' '\n-- \n1.7.5\n"},{"id":"166291","messageId":"BANLkTi=fnzRVc8Lx_Wba4yqa7u8t3xGAtQ@mail.gmail.com","threadId":"27169","inReplyTo":"1303678289-27627-3-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 2/4] diff.c: return filepair from diff_unmerge()","fromName":"Thiago Farina","fromEmail":"tfransosi@gmail.com","sentAt":"2011-04-24T22:18:35Z","receivedAt":"2011-04-24T22:18:35Z","isPatch":true,"sender":{"key":"tfransosi@gmail.com","avatar":"https://avatars.githubusercontent.com/u/970071?v=4"},"body":"Some unrelated style comments below.\n\nOn Sun, Apr 24, 2011 at 5:51 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> The underlying diff_queue() returns diff_filepair so that the caller can\n> further add information to it, and the helper function diff_unmerge()\n> utilizes the feature itself, but does not expose it to its callers, which\n> was kind of selfish.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  diff.c |   13 ++++++++-----\n>  diff.h |    2 +-\n>  2 files changed, 9 insertions(+), 6 deletions(-)\n>\n> diff --git a/diff.c b/diff.c\n> index 9a5c77c..4c34c64 100644\n> --- a/diff.c\n> +++ b/diff.c\n> @@ -4308,20 +4308,23 @@ void diff_change(struct diff_options *options,\n>                DIFF_OPT_SET(options, HAS_CHANGES);\n>  }\n>\n> -void diff_unmerge(struct diff_options *options,\n> -                 const char *path,\n> -                 unsigned mode, const unsigned char *sha1)\n> +struct diff_filepair *diff_unmerge(struct diff_options *options,\n> +                                  const char *path,\n> +                                  unsigned mode, const unsigned char *sha1)\n>  {\n\nWhile you are here, why not write one arg per line?\n\n> +       struct diff_filepair *pair;\n>        struct diff_filespec *one, *two;\n>\n>        if (options->prefix &&\n>            strncmp(path, options->prefix, options->prefix_length))\n> -               return;\n> +               return NULL;\n>\n>        one = alloc_filespec(path);\n>        two = alloc_filespec(path);\n>        fill_filespec(one, sha1, mode);\n> -       diff_queue(&diff_queued_diff, one, two)->is_unmerged = 1;\n> +       pair = diff_queue(&diff_queued_diff, one, two);\n> +       pair->is_unmerged = 1;\n> +       return pair;\n>  }\n>\n>  static char *run_textconv(const char *pgm, struct diff_filespec *spec,\n> diff --git a/diff.h b/diff.h\n> index bf2f44d..f51a8ee 100644\n> --- a/diff.h\n> +++ b/diff.h\n> @@ -209,7 +209,7 @@ extern void diff_change(struct diff_options *,\n>                        const char *fullpath,\n>                        unsigned dirty_submodule1, unsigned dirty_submodule2);\n>\n> -extern void diff_unmerge(struct diff_options *,\n> +extern struct diff_filepair *diff_unmerge(struct diff_options *,\n\nWhile you are here, why not add the argument name |options| here too?\n\n>                         const char *path,\n>                         unsigned mode,\n>                         const unsigned char *sha1);\n"},{"id":"166296","messageId":"7vtydnku1a.fsf@alter.siamese.dyndns.org","threadId":"27169","inReplyTo":"BANLkTi=fnzRVc8Lx_Wba4yqa7u8t3xGAtQ@mail.gmail.com","subject":"Re: [PATCH 2/4] diff.c: return filepair from diff_unmerge()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-25T01:18:41Z","receivedAt":"2011-04-25T01:18:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thiago Farina <tfransosi@gmail.com> writes:\n\n> Some unrelated style comments below.\n> ...\n>> -void diff_unmerge(struct diff_options *options,\n>> -                 const char *path,\n>> -                 unsigned mode, const unsigned char *sha1)\n>> +struct diff_filepair *diff_unmerge(struct diff_options *options,\n>> +                                  const char *path,\n>> +                                  unsigned mode, const unsigned char *sha1)\n>>  {\n>\n> While you are here, why not write one arg per line?\n\nNo, actually I reindented the two lines by accident; I didn't mean to.\n\n>> diff --git a/diff.h b/diff.h\n>> index bf2f44d..f51a8ee 100644\n>> --- a/diff.h\n>> +++ b/diff.h\n>> @@ -209,7 +209,7 @@ extern void diff_change(struct diff_options *,\n>>                        const char *fullpath,\n>>                        unsigned dirty_submodule1, unsigned dirty_submodule2);\n>>\n>> -extern void diff_unmerge(struct diff_options *,\n>> +extern struct diff_filepair *diff_unmerge(struct diff_options *,\n>\n> While you are here, why not add the argument name |options| here too?\n>\n>>                         const char *path,\n>>                         unsigned mode,\n>>                         const unsigned char *sha1);\n\nThe patch was meant to be minimum to begin with.  Besides, there is no\nrisk of confusion from not naming the option in this case, so even if we\nwere shooting for clean-up, we wouldn't be adding such noise here.  The\nother parameters do benefit from descriptive names, so there is no need to\nremove the names either.\n\nIn other case, your \"why not\" is totally unwarranted for this hunk.\n"}]}