{"thread":{"id":"44844","subject":"[RFC/PATCH 0/4] working tree operations: support superprefix","startedAt":"2017-01-10T01:46:00Z","lastAt":"2017-01-13T17:50:54Z","messageCount":17,"participants":["Stefan Beller","Junio C Hamano","Brian J. Davis"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"309100","messageId":"20170110014542.19352-1-sbeller@google.com","threadId":"44844","inReplyTo":null,"subject":"[RFC/PATCH 0/4] working tree operations: support superprefix","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-10T01:45:38Z","receivedAt":"2017-01-10T01:46:00Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"As you may know, I am trying to implement \"git checkout --recurse-submodules\"\nwhich recurses into submodules and update the submodules to the recorded\nstate of the superproject. I realized that such a huge change is a big endeavor,\nand needs to be broken up into many series. \n\nCurrently I plan to send about 4 series:\n\n* This one; teaching the superprefix to working tree operations.\n\n* structured tests, i.e. enhancing lib-submodule-update.sh to have a function\n  to test for any corner case (File/Submodule conflict,\n  Directory/Submodule conflict; non-existence of submodule commit; and such)\n\n* the actual internal implementation, mostly touching unpack-trees.c,\n  entry.c and helper functions in submodule.c\n  \n* Enabling commands to take advantage of the infrastructure provided.\n  At that point we only need to add a --recurse-submodule flag in the\n  respective command and add a line to its respective test\n  \n  \"test_switch_submodule_recursing $cmd --recurse-submodule\"\n\n--\nThis patch series is the first of the four series.\n\nIt consists of 4 patches, the first 3 are refactoring to a modern style of Git,\nthe last patch is the actual patch that allows read-tree to be used with\nthe superprefix option. read-tree is already exposed there to make the\nsuper-prefix code tested.\n\nThe series is based on master.\n\nThanks,\nStefan\n\nStefan Beller (4):\n  read-tree: use OPT_BOOL instead of OPT_SET_INT\n  t1000: modernize style\n  t1001: modernize style\n  unpack-trees: support super-prefix option\n\n builtin/read-tree.c         |  36 +--\n git.c                       |   2 +-\n t/t1000-read-tree-m-3way.sh | 648 +++++++++++++++++++++----------------------\n t/t1001-read-tree-m-2way.sh | 650 ++++++++++++++++++++++----------------------\n unpack-trees.c              |  39 ++-\n 5 files changed, 699 insertions(+), 676 deletions(-)\n\n-- \n2.11.0.rc2.30.g7c4be45.dirty\n\n"},{"id":"309101","messageId":"20170110014542.19352-2-sbeller@google.com","threadId":"44844","inReplyTo":"20170110014542.19352-1-sbeller@google.com","subject":"[PATCH 1/4] read-tree: use OPT_BOOL instead of OPT_SET_INT","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-10T01:45:39Z","receivedAt":"2017-01-10T01:46:03Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"All occurrences of OPT_SET_INT were setting the value to 1;\ninternally OPT_BOOL is just that.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n builtin/read-tree.c | 36 ++++++++++++++++++------------------\n 1 file changed, 18 insertions(+), 18 deletions(-)\n\ndiff --git a/builtin/read-tree.c b/builtin/read-tree.c\nindex fa6edb35b2..8ba64bc785 100644\n--- a/builtin/read-tree.c\n+++ b/builtin/read-tree.c\n@@ -109,34 +109,34 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t\t{ OPTION_CALLBACK, 0, \"index-output\", NULL, N_(\"file\"),\n \t\t  N_(\"write resulting index to <file>\"),\n \t\t  PARSE_OPT_NONEG, index_output_cb },\n-\t\tOPT_SET_INT(0, \"empty\", &read_empty,\n-\t\t\t    N_(\"only empty the index\"), 1),\n+\t\tOPT_BOOL(0, \"empty\", &read_empty,\n+\t\t\t    N_(\"only empty the index\")),\n \t\tOPT__VERBOSE(&opts.verbose_update, N_(\"be verbose\")),\n \t\tOPT_GROUP(N_(\"Merging\")),\n-\t\tOPT_SET_INT('m', NULL, &opts.merge,\n-\t\t\t    N_(\"perform a merge in addition to a read\"), 1),\n-\t\tOPT_SET_INT(0, \"trivial\", &opts.trivial_merges_only,\n-\t\t\t    N_(\"3-way merge if no file level merging required\"), 1),\n-\t\tOPT_SET_INT(0, \"aggressive\", &opts.aggressive,\n-\t\t\t    N_(\"3-way merge in presence of adds and removes\"), 1),\n-\t\tOPT_SET_INT(0, \"reset\", &opts.reset,\n-\t\t\t    N_(\"same as -m, but discard unmerged entries\"), 1),\n+\t\tOPT_BOOL('m', NULL, &opts.merge,\n+\t\t\t N_(\"perform a merge in addition to a read\")),\n+\t\tOPT_BOOL(0, \"trivial\", &opts.trivial_merges_only,\n+\t\t\t N_(\"3-way merge if no file level merging required\")),\n+\t\tOPT_BOOL(0, \"aggressive\", &opts.aggressive,\n+\t\t\t N_(\"3-way merge in presence of adds and removes\")),\n+\t\tOPT_BOOL(0, \"reset\", &opts.reset,\n+\t\t\t N_(\"same as -m, but discard unmerged entries\")),\n \t\t{ OPTION_STRING, 0, \"prefix\", &opts.prefix, N_(\"<subdirectory>/\"),\n \t\t  N_(\"read the tree into the index under <subdirectory>/\"),\n \t\t  PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP },\n-\t\tOPT_SET_INT('u', NULL, &opts.update,\n-\t\t\t    N_(\"update working tree with merge result\"), 1),\n+\t\tOPT_BOOL('u', NULL, &opts.update,\n+\t\t\t N_(\"update working tree with merge result\")),\n \t\t{ OPTION_CALLBACK, 0, \"exclude-per-directory\", &opts,\n \t\t  N_(\"gitignore\"),\n \t\t  N_(\"allow explicitly ignored files to be overwritten\"),\n \t\t  PARSE_OPT_NONEG, exclude_per_directory_cb },\n-\t\tOPT_SET_INT('i', NULL, &opts.index_only,\n-\t\t\t    N_(\"don't check the working tree after merging\"), 1),\n+\t\tOPT_BOOL('i', NULL, &opts.index_only,\n+\t\t\t N_(\"don't check the working tree after merging\")),\n \t\tOPT__DRY_RUN(&opts.dry_run, N_(\"don't update the index or the work tree\")),\n-\t\tOPT_SET_INT(0, \"no-sparse-checkout\", &opts.skip_sparse_checkout,\n-\t\t\t    N_(\"skip applying sparse checkout filter\"), 1),\n-\t\tOPT_SET_INT(0, \"debug-unpack\", &opts.debug_unpack,\n-\t\t\t    N_(\"debug unpack-trees\"), 1),\n+\t\tOPT_BOOL(0, \"no-sparse-checkout\", &opts.skip_sparse_checkout,\n+\t\t\t N_(\"skip applying sparse checkout filter\")),\n+\t\tOPT_BOOL(0, \"debug-unpack\", &opts.debug_unpack,\n+\t\t\t N_(\"debug unpack-trees\")),\n \t\tOPT_END()\n \t};\n \n-- \n2.11.0.rc2.30.g7c4be45.dirty\n\n"},{"id":"309102","messageId":"20170110014542.19352-4-sbeller@google.com","threadId":"44844","inReplyTo":"20170110014542.19352-1-sbeller@google.com","subject":"[PATCH 3/4] t1001: modernize style","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-10T01:45:41Z","receivedAt":"2017-01-10T01:46:07Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"The preferred style in tests seems to be\n\ntest_expect_success 'short description, ended by 2 single quotes' '\n\there comes the test &&\n\tand chains over many lines &&\n \tended by a quote\n'\n\nOr going by the numbers:\n    $ git -C t/ grep \"' '$\" | wc -l\n    9796\n    $ git -C t/ grep test_expect_ |wc -l\n    11861\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n t/t1001-read-tree-m-2way.sh | 641 ++++++++++++++++++++++----------------------\n 1 file changed, 320 insertions(+), 321 deletions(-)\n\ndiff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh\nindex db1b6f5cf4..7b70089705 100755\n--- a/t/t1001-read-tree-m-2way.sh\n+++ b/t/t1001-read-tree-m-2way.sh\n@@ -14,10 +14,10 @@ all the combinations described in the two-tree merge \"carry forward\"\n rules, found in <Documentation/git read-tree.txt>.\n \n In the test, these paths are used:\n-        bozbar  - in H, stays in M, modified from bozbar to gnusto\n-        frotz   - not in H added in M\n-        nitfol  - in H, stays in M unmodified\n-        rezrov  - in H, deleted in M\n+\tbozbar  - in H, stays in M, modified from bozbar to gnusto\n+\tfrotz   - not in H added in M\n+\tnitfol  - in H, stays in M unmodified\n+\trezrov  - in H, deleted in M\n \tyomin   - not in H or M\n '\n . ./test-lib.sh\n@@ -60,336 +60,335 @@ EOF\n \n sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new\n \n-test_expect_success \\\n-    setup \\\n-    'echo frotz >frotz &&\n-     echo nitfol >nitfol &&\n-     cat bozbar-old >bozbar &&\n-     echo rezrov >rezrov &&\n-     echo yomin >yomin &&\n-     git update-index --add nitfol bozbar rezrov &&\n-     treeH=$(git write-tree) &&\n-     echo treeH $treeH &&\n-     git ls-tree $treeH &&\n-\n-     cat bozbar-new >bozbar &&\n-     git update-index --add frotz bozbar --force-remove rezrov &&\n-     git ls-files --stage >M.out &&\n-     treeM=$(git write-tree) &&\n-     echo treeM $treeM &&\n-     git ls-tree $treeM &&\n-     git diff-tree $treeH $treeM'\n-\n-test_expect_success \\\n-    '1, 2, 3 - no carry forward' \\\n-    'rm -f .git/index &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >1-3.out &&\n-     test_cmp M.out 1-3.out &&\n-     check_cache_at bozbar dirty &&\n-     check_cache_at frotz dirty &&\n-     check_cache_at nitfol dirty'\n+test_expect_success 'setup' '\n+\techo frotz >frotz &&\n+\techo nitfol >nitfol &&\n+\tcat bozbar-old >bozbar &&\n+\techo rezrov >rezrov &&\n+\techo yomin >yomin &&\n+\tgit update-index --add nitfol bozbar rezrov &&\n+\ttreeH=$(git write-tree) &&\n+\techo treeH $treeH &&\n+\tgit ls-tree $treeH &&\n+\n+\tcat bozbar-new >bozbar &&\n+\tgit update-index --add frotz bozbar --force-remove rezrov &&\n+\tgit ls-files --stage >M.out &&\n+\ttreeM=$(git write-tree) &&\n+\techo treeM $treeM &&\n+\tgit ls-tree $treeM &&\n+\tgit diff-tree $treeH $treeM\n+'\n \n+test_expect_success '1, 2, 3 - no carry forward' '\n+\trm -f .git/index &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >1-3.out &&\n+\ttest_cmp M.out 1-3.out &&\n+\tcheck_cache_at bozbar dirty &&\n+\tcheck_cache_at frotz dirty &&\n+\tcheck_cache_at nitfol dirty\n+'\n echo '+100644 X 0\tyomin' >expected\n \n-test_expect_success \\\n-    '4 - carry forward local addition.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     git update-index --add yomin &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >4.out &&\n-     test_must_fail git diff --no-index M.out 4.out >4diff.out &&\n-     compare_change 4diff.out expected &&\n-     check_cache_at yomin clean'\n-\n-test_expect_success \\\n-    '5 - carry forward local addition.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo yomin >yomin &&\n-     git update-index --add yomin &&\n-     echo yomin yomin >yomin &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >5.out &&\n-     test_must_fail git diff --no-index M.out 5.out >5diff.out &&\n-     compare_change 5diff.out expected &&\n-     check_cache_at yomin dirty'\n-\n-test_expect_success \\\n-    '6 - local addition already has the same.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     git update-index --add frotz &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >6.out &&\n-     test_cmp M.out 6.out &&\n-     check_cache_at frotz clean'\n-\n-test_expect_success \\\n-    '7 - local addition already has the same.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo frotz >frotz &&\n-     git update-index --add frotz &&\n-     echo frotz frotz >frotz &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >7.out &&\n-     test_cmp M.out 7.out &&\n-     check_cache_at frotz dirty'\n-\n-test_expect_success \\\n-    '8 - conflicting addition.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo frotz frotz >frotz &&\n-     git update-index --add frotz &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n-\n-test_expect_success \\\n-    '9 - conflicting addition.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo frotz frotz >frotz &&\n-     git update-index --add frotz &&\n-     echo frotz >frotz &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n-\n-test_expect_success \\\n-    '10 - path removed.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo rezrov >rezrov &&\n-     git update-index --add rezrov &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >10.out &&\n-     test_cmp M.out 10.out'\n-\n-test_expect_success \\\n-    '11 - dirty path removed.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo rezrov >rezrov &&\n-     git update-index --add rezrov &&\n-     echo rezrov rezrov >rezrov &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n-\n-test_expect_success \\\n-    '12 - unmatching local changes being removed.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo rezrov rezrov >rezrov &&\n-     git update-index --add rezrov &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n-\n-test_expect_success \\\n-    '13 - unmatching local changes being removed.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo rezrov rezrov >rezrov &&\n-     git update-index --add rezrov &&\n-     echo rezrov >rezrov &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n+test_expect_success '4 - carry forward local addition.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\tgit update-index --add yomin &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >4.out &&\n+\ttest_must_fail git diff --no-index M.out 4.out >4diff.out &&\n+\tcompare_change 4diff.out expected &&\n+\tcheck_cache_at yomin clean\n+'\n+\n+test_expect_success '5 - carry forward local addition.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo yomin >yomin &&\n+\tgit update-index --add yomin &&\n+\techo yomin yomin >yomin &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >5.out &&\n+\ttest_must_fail git diff --no-index M.out 5.out >5diff.out &&\n+\tcompare_change 5diff.out expected &&\n+\tcheck_cache_at yomin dirty\n+'\n+\n+test_expect_success '6 - local addition already has the same.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\tgit update-index --add frotz &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >6.out &&\n+\ttest_cmp M.out 6.out &&\n+\tcheck_cache_at frotz clean\n+'\n+\n+test_expect_success '7 - local addition already has the same.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo frotz >frotz &&\n+\tgit update-index --add frotz &&\n+\techo frotz frotz >frotz &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >7.out &&\n+\ttest_cmp M.out 7.out &&\n+\tcheck_cache_at frotz dirty\n+'\n+\n+test_expect_success '8 - conflicting addition.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo frotz frotz >frotz &&\n+\tgit update-index --add frotz &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n+\n+test_expect_success '9 - conflicting addition.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo frotz frotz >frotz &&\n+\tgit update-index --add frotz &&\n+\techo frotz >frotz &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n+\n+test_expect_success '10 - path removed.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo rezrov >rezrov &&\n+\tgit update-index --add rezrov &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >10.out &&\n+\ttest_cmp M.out 10.out\n+'\n+\n+test_expect_success '11 - dirty path removed.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo rezrov >rezrov &&\n+\tgit update-index --add rezrov &&\n+\techo rezrov rezrov >rezrov &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n+\n+test_expect_success '12 - unmatching local changes being removed.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo rezrov rezrov >rezrov &&\n+\tgit update-index --add rezrov &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n+\n+test_expect_success '13 - unmatching local changes being removed.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo rezrov rezrov >rezrov &&\n+\tgit update-index --add rezrov &&\n+\techo rezrov >rezrov &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n \n cat >expected <<EOF\n -100644 X 0\tnitfol\n +100644 X 0\tnitfol\n EOF\n \n-test_expect_success \\\n-    '14 - unchanged in two heads.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo nitfol nitfol >nitfol &&\n-     git update-index --add nitfol &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >14.out &&\n-     test_must_fail git diff --no-index M.out 14.out >14diff.out &&\n-     compare_change 14diff.out expected &&\n-     check_cache_at nitfol clean'\n-\n-test_expect_success \\\n-    '15 - unchanged in two heads.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo nitfol nitfol >nitfol &&\n-     git update-index --add nitfol &&\n-     echo nitfol nitfol nitfol >nitfol &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >15.out &&\n-     test_must_fail git diff --no-index M.out 15.out >15diff.out &&\n-     compare_change 15diff.out expected &&\n-     check_cache_at nitfol dirty'\n-\n-test_expect_success \\\n-    '16 - conflicting local change.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo bozbar bozbar >bozbar &&\n-     git update-index --add bozbar &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n-\n-test_expect_success \\\n-    '17 - conflicting local change.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     echo bozbar bozbar >bozbar &&\n-     git update-index --add bozbar &&\n-     echo bozbar bozbar bozbar >bozbar &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n-\n-test_expect_success \\\n-    '18 - local change already having a good result.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     cat bozbar-new >bozbar &&\n-     git update-index --add bozbar &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >18.out &&\n-     test_cmp M.out 18.out &&\n-     check_cache_at bozbar clean'\n-\n-test_expect_success \\\n-    '19 - local change already having a good result, further modified.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     cat bozbar-new >bozbar &&\n-     git update-index --add bozbar &&\n-     echo gnusto gnusto >bozbar &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >19.out &&\n-     test_cmp M.out 19.out &&\n-     check_cache_at bozbar dirty'\n-\n-test_expect_success \\\n-    '20 - no local change, use new tree.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     cat bozbar-old >bozbar &&\n-     git update-index --add bozbar &&\n-     read_tree_twoway $treeH $treeM &&\n-     git ls-files --stage >20.out &&\n-     test_cmp M.out 20.out &&\n-     check_cache_at bozbar dirty'\n-\n-test_expect_success \\\n-    '21 - no local change, dirty cache.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     cat bozbar-old >bozbar &&\n-     git update-index --add bozbar &&\n-     echo gnusto gnusto >bozbar &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n+test_expect_success '14 - unchanged in two heads.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo nitfol nitfol >nitfol &&\n+\tgit update-index --add nitfol &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >14.out &&\n+\ttest_must_fail git diff --no-index M.out 14.out >14diff.out &&\n+\tcompare_change 14diff.out expected &&\n+\tcheck_cache_at nitfol clean\n+'\n+\n+test_expect_success '15 - unchanged in two heads.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo nitfol nitfol >nitfol &&\n+\tgit update-index --add nitfol &&\n+\techo nitfol nitfol nitfol >nitfol &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >15.out &&\n+\ttest_must_fail git diff --no-index M.out 15.out >15diff.out &&\n+\tcompare_change 15diff.out expected &&\n+\tcheck_cache_at nitfol dirty\n+'\n+\n+test_expect_success '16 - conflicting local change.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo bozbar bozbar >bozbar &&\n+\tgit update-index --add bozbar &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n+\n+test_expect_success '17 - conflicting local change.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\techo bozbar bozbar >bozbar &&\n+\tgit update-index --add bozbar &&\n+\techo bozbar bozbar bozbar >bozbar &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n+\n+test_expect_success '18 - local change already having a good result.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\tcat bozbar-new >bozbar &&\n+\tgit update-index --add bozbar &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >18.out &&\n+\ttest_cmp M.out 18.out &&\n+\tcheck_cache_at bozbar clean\n+'\n+\n+test_expect_success '19 - local change already having a good result, further modified.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\tcat bozbar-new >bozbar &&\n+\tgit update-index --add bozbar &&\n+\techo gnusto gnusto >bozbar &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >19.out &&\n+\ttest_cmp M.out 19.out &&\n+\tcheck_cache_at bozbar dirty\n+'\n+\n+test_expect_success '20 - no local change, use new tree.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\tcat bozbar-old >bozbar &&\n+\tgit update-index --add bozbar &&\n+\tread_tree_twoway $treeH $treeM &&\n+\tgit ls-files --stage >20.out &&\n+\ttest_cmp M.out 20.out &&\n+\tcheck_cache_at bozbar dirty\n+'\n+\n+test_expect_success '21 - no local change, dirty cache.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\tcat bozbar-old >bozbar &&\n+\tgit update-index --add bozbar &&\n+\techo gnusto gnusto >bozbar &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n \n # This fails with straight two-way fast-forward.\n-test_expect_success \\\n-    '22 - local change cache updated.' \\\n-    'rm -f .git/index &&\n-     read_tree_must_succeed $treeH &&\n-     git checkout-index -u -f -q -a &&\n-     sed -e \"s/such as/SUCH AS/\" bozbar-old >bozbar &&\n-     git update-index --add bozbar &&\n-     if read_tree_twoway $treeH $treeM; then false; else :; fi'\n+test_expect_success '22 - local change cache updated.' '\n+\trm -f .git/index &&\n+\tread_tree_must_succeed $treeH &&\n+\tgit checkout-index -u -f -q -a &&\n+\tsed -e \"s/such as/SUCH AS/\" bozbar-old >bozbar &&\n+\tgit update-index --add bozbar &&\n+\tif read_tree_twoway $treeH $treeM; then false; else :; fi\n+'\n \n # Also make sure we did not break DF vs DF/DF case.\n-test_expect_success \\\n-    'DF vs DF/DF case setup.' \\\n-    'rm -f .git/index &&\n-     echo DF >DF &&\n-     git update-index --add DF &&\n-     treeDF=$(git write-tree) &&\n-     echo treeDF $treeDF &&\n-     git ls-tree $treeDF &&\n-\n-     rm -f DF &&\n-     mkdir DF &&\n-     echo DF/DF >DF/DF &&\n-     git update-index --add --remove DF DF/DF &&\n-     treeDFDF=$(git write-tree) &&\n-     echo treeDFDF $treeDFDF &&\n-     git ls-tree $treeDFDF &&\n-     git ls-files --stage >DFDF.out'\n-\n-test_expect_success \\\n-    'DF vs DF/DF case test.' \\\n-    'rm -f .git/index &&\n-     rm -fr DF &&\n-     echo DF >DF &&\n-     git update-index --add DF &&\n-     read_tree_twoway $treeDF $treeDFDF &&\n-     git ls-files --stage >DFDFcheck.out &&\n-     test_cmp DFDF.out DFDFcheck.out &&\n-     check_cache_at DF/DF dirty &&\n-     :'\n-\n-test_expect_success \\\n-    'a/b (untracked) vs a case setup.' \\\n-    'rm -f .git/index &&\n-     : >a &&\n-     git update-index --add a &&\n-     treeM=$(git write-tree) &&\n-     echo treeM $treeM &&\n-     git ls-tree $treeM &&\n-     git ls-files --stage >treeM.out &&\n-\n-     rm -f a &&\n-     git update-index --remove a &&\n-     mkdir a &&\n-     : >a/b &&\n-     treeH=$(git write-tree) &&\n-     echo treeH $treeH &&\n-     git ls-tree $treeH'\n-\n-test_expect_success \\\n-    'a/b (untracked) vs a, plus c/d case test.' \\\n-    'read_tree_u_must_fail -u -m \"$treeH\" \"$treeM\" &&\n-     git ls-files --stage &&\n-     test -f a/b'\n-\n-test_expect_success \\\n-    'a/b vs a, plus c/d case setup.' \\\n-    'rm -f .git/index &&\n-     rm -fr a &&\n-     : >a &&\n-     mkdir c &&\n-     : >c/d &&\n-     git update-index --add a c/d &&\n-     treeM=$(git write-tree) &&\n-     echo treeM $treeM &&\n-     git ls-tree $treeM &&\n-     git ls-files --stage >treeM.out &&\n-\n-     rm -f a &&\n-     mkdir a &&\n-     : >a/b &&\n-     git update-index --add --remove a a/b &&\n-     treeH=$(git write-tree) &&\n-     echo treeH $treeH &&\n-     git ls-tree $treeH'\n-\n-test_expect_success \\\n-    'a/b vs a, plus c/d case test.' \\\n-    'read_tree_u_must_succeed -u -m \"$treeH\" \"$treeM\" &&\n-     git ls-files --stage | tee >treeMcheck.out &&\n-     test_cmp treeM.out treeMcheck.out'\n+test_expect_success 'DF vs DF/DF case setup.' '\n+\trm -f .git/index &&\n+\techo DF >DF &&\n+\tgit update-index --add DF &&\n+\ttreeDF=$(git write-tree) &&\n+\techo treeDF $treeDF &&\n+\tgit ls-tree $treeDF &&\n+\n+\trm -f DF &&\n+\tmkdir DF &&\n+\techo DF/DF >DF/DF &&\n+\tgit update-index --add --remove DF DF/DF &&\n+\ttreeDFDF=$(git write-tree) &&\n+\techo treeDFDF $treeDFDF &&\n+\tgit ls-tree $treeDFDF &&\n+\tgit ls-files --stage >DFDF.out\n+'\n+\n+test_expect_success 'DF vs DF/DF case test.' '\n+\trm -f .git/index &&\n+\trm -fr DF &&\n+\techo DF >DF &&\n+\tgit update-index --add DF &&\n+\tread_tree_twoway $treeDF $treeDFDF &&\n+\tgit ls-files --stage >DFDFcheck.out &&\n+\ttest_cmp DFDF.out DFDFcheck.out &&\n+\tcheck_cache_at DF/DF dirty &&\n+\t:\n+'\n+\n+test_expect_success 'a/b (untracked) vs a case setup.' '\n+\trm -f .git/index &&\n+\t: >a &&\n+\tgit update-index --add a &&\n+\ttreeM=$(git write-tree) &&\n+\techo treeM $treeM &&\n+\tgit ls-tree $treeM &&\n+\tgit ls-files --stage >treeM.out &&\n+\n+\trm -f a &&\n+\tgit update-index --remove a &&\n+\tmkdir a &&\n+\t: >a/b &&\n+\ttreeH=$(git write-tree) &&\n+\techo treeH $treeH &&\n+\tgit ls-tree $treeH\n+'\n+\n+test_expect_success 'a/b (untracked) vs a, plus c/d case test.' '\n+\tread_tree_u_must_fail -u -m \"$treeH\" \"$treeM\" &&\n+\tgit ls-files --stage &&\n+\ttest -f a/b\n+'\n+\n+test_expect_success 'a/b vs a, plus c/d case setup.' '\n+\trm -f .git/index &&\n+\trm -fr a &&\n+\t: >a &&\n+\tmkdir c &&\n+\t: >c/d &&\n+\tgit update-index --add a c/d &&\n+\ttreeM=$(git write-tree) &&\n+\techo treeM $treeM &&\n+\tgit ls-tree $treeM &&\n+\tgit ls-files --stage >treeM.out &&\n+\n+\trm -f a &&\n+\tmkdir a &&\n+\t: >a/b &&\n+\tgit update-index --add --remove a a/b &&\n+\ttreeH=$(git write-tree) &&\n+\techo treeH $treeH &&\n+\tgit ls-tree $treeH\n+'\n+\n+test_expect_success 'a/b vs a, plus c/d case test.' '\n+\tread_tree_u_must_succeed -u -m \"$treeH\" \"$treeM\" &&\n+\tgit ls-files --stage | tee >treeMcheck.out &&\n+\ttest_cmp treeM.out treeMcheck.out\n+'\n \n test_expect_success '-m references the correct modified tree' '\n \techo >file-a &&\n-- \n2.11.0.rc2.30.g7c4be45.dirty\n\n"},{"id":"309103","messageId":"20170110014542.19352-3-sbeller@google.com","threadId":"44844","inReplyTo":"20170110014542.19352-1-sbeller@google.com","subject":"[PATCH 2/4] t1000: modernize style","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-10T01:45:40Z","receivedAt":"2017-01-10T01:46:11Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"The preferred style in tests seems to be\n\ntest_expect_success 'short description, ended by 2 single quotes' '\n\there comes the test &&\n\tand chains over many lines &&\n\tended by a quote\n'\n\nOr going by the numbers:\n    $ git -C t/ grep \"' '$\" | wc -l\n    9796\n    $ git -C t/ grep test_expect_ |wc -l\n    11861\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n t/t1000-read-tree-m-3way.sh | 648 +++++++++++++++++++++-----------------------\n 1 file changed, 315 insertions(+), 333 deletions(-)\n\ndiff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh\nindex a0b79b4839..3c4d2d6045 100755\n--- a/t/t1000-read-tree-m-3way.sh\n+++ b/t/t1000-read-tree-m-3way.sh\n@@ -128,29 +128,29 @@ cat >expected <<\\EOF\n EOF\n \n check_result () {\n-    git ls-files --stage | sed -e 's/ '\"$_x40\"' / X /' >current &&\n-    test_cmp expected current\n+\tgit ls-files --stage | sed -e 's/ '\"$_x40\"' / X /' >current &&\n+\ttest_cmp expected current\n }\n \n # This is done on an empty work directory, which is the normal\n # merge person behaviour.\n-test_expect_success \\\n-    '3-way merge with git read-tree -m, empty cache' \\\n-    \"rm -fr [NDMALTS][NDMALTSF] Z &&\n-     rm .git/index &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n+test_expect_success '3-way merge with git read-tree -m, empty cache' '\n+\trm -fr [NDMALTS][NDMALTSF] Z &&\n+\trm .git/index &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n \n # This starts out with the first head, which is the normal\n # patch submitter behaviour.\n-test_expect_success \\\n-    '3-way merge with git read-tree -m, match H' \\\n-    \"rm -fr [NDMALTS][NDMALTSF] Z &&\n-     rm .git/index &&\n-     read_tree_must_succeed $tree_A &&\n-     git checkout-index -f -u -a &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n+test_expect_success '3-way merge with git read-tree -m, match H' '\n+\trm -fr [NDMALTS][NDMALTSF] Z &&\n+\trm .git/index &&\n+\tread_tree_must_succeed $tree_A &&\n+\tgit checkout-index -f -u -a &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n \n : <<\\END_OF_CASE_TABLE\n \n@@ -208,322 +208,304 @@ DF (file) when tree B require DF to be a directory by having DF/DF\n \n END_OF_CASE_TABLE\n \n-test_expect_success '1 - must not have an entry not in A.' \"\n-     rm -f .git/index XX &&\n-     echo XX >XX &&\n-     git update-index --add XX &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '2 - must match B in !O && !A && B case.' \\\n-    \"rm -f .git/index NA &&\n-     cp .orig-B/NA NA &&\n-     git update-index --add NA &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B\"\n-\n-test_expect_success \\\n-    '2 - matching B alone is OK in !O && !A && B case.' \\\n-    \"rm -f .git/index NA &&\n-     cp .orig-B/NA NA &&\n-     git update-index --add NA &&\n-     echo extra >>NA &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B\"\n-\n-test_expect_success \\\n-    '3 - must match A in !O && A && !B case.' \\\n-    \"rm -f .git/index AN &&\n-     cp .orig-A/AN AN &&\n-     git update-index --add AN &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '3 - matching A alone is OK in !O && A && !B case.' \\\n-    \"rm -f .git/index AN &&\n-     cp .orig-A/AN AN &&\n-     git update-index --add AN &&\n-     echo extra >>AN &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B\"\n-\n-test_expect_success \\\n-    '3 (fail) - must match A in !O && A && !B case.' \"\n-     rm -f .git/index AN &&\n-     cp .orig-A/AN AN &&\n-     echo extra >>AN &&\n-     git update-index --add AN &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '4 - must match and be up-to-date in !O && A && B && A!=B case.' \\\n-    \"rm -f .git/index AA &&\n-     cp .orig-A/AA AA &&\n-     git update-index --add AA &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' \"\n-     rm -f .git/index AA &&\n-     cp .orig-A/AA AA &&\n-     git update-index --add AA &&\n-     echo extra >>AA &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' \"\n-     rm -f .git/index AA &&\n-     cp .orig-A/AA AA &&\n-     echo extra >>AA &&\n-     git update-index --add AA &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '5 - must match in !O && A && B && A==B case.' \\\n-    \"rm -f .git/index LL &&\n-     cp .orig-A/LL LL &&\n-     git update-index --add LL &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '5 - must match in !O && A && B && A==B case.' \\\n-    \"rm -f .git/index LL &&\n-     cp .orig-A/LL LL &&\n-     git update-index --add LL &&\n-     echo extra >>LL &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '5 (fail) - must match A in !O && A && B && A==B case.' \"\n-     rm -f .git/index LL &&\n-     cp .orig-A/LL LL &&\n-     echo extra >>LL &&\n-     git update-index --add LL &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '6 - must not exist in O && !A && !B case' \"\n-     rm -f .git/index DD &&\n-     echo DD >DD &&\n-     git update-index --add DD &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '7 - must not exist in O && !A && B && O!=B case' \"\n-     rm -f .git/index DM &&\n-     cp .orig-B/DM DM &&\n-     git update-index --add DM &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '8 - must not exist in O && !A && B && O==B case' \"\n-     rm -f .git/index DN &&\n-     cp .orig-B/DN DN &&\n-     git update-index --add DN &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '9 - must match and be up-to-date in O && A && !B && O!=A case' \\\n-    \"rm -f .git/index MD &&\n-     cp .orig-A/MD MD &&\n-     git update-index --add MD &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' \"\n-     rm -f .git/index MD &&\n-     cp .orig-A/MD MD &&\n-     git update-index --add MD &&\n-     echo extra >>MD &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' \"\n-     rm -f .git/index MD &&\n-     cp .orig-A/MD MD &&\n-     echo extra >>MD &&\n-     git update-index --add MD &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '10 - must match and be up-to-date in O && A && !B && O==A case' \\\n-    \"rm -f .git/index ND &&\n-     cp .orig-A/ND ND &&\n-     git update-index --add ND &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' \"\n-     rm -f .git/index ND &&\n-     cp .orig-A/ND ND &&\n-     git update-index --add ND &&\n-     echo extra >>ND &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' \"\n-     rm -f .git/index ND &&\n-     cp .orig-A/ND ND &&\n-     echo extra >>ND &&\n-     git update-index --add ND &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '11 - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \\\n-    \"rm -f .git/index MM &&\n-     cp .orig-A/MM MM &&\n-     git update-index --add MM &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \"\n-     rm -f .git/index MM &&\n-     cp .orig-A/MM MM &&\n-     git update-index --add MM &&\n-     echo extra >>MM &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \"\n-     rm -f .git/index MM &&\n-     cp .orig-A/MM MM &&\n-     echo extra >>MM &&\n-     git update-index --add MM &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '12 - must match A in O && A && B && O!=A && A==B case' \\\n-    \"rm -f .git/index SS &&\n-     cp .orig-A/SS SS &&\n-     git update-index --add SS &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '12 - must match A in O && A && B && O!=A && A==B case' \\\n-    \"rm -f .git/index SS &&\n-     cp .orig-A/SS SS &&\n-     git update-index --add SS &&\n-     echo extra >>SS &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '12 (fail) - must match A in O && A && B && O!=A && A==B case' \"\n-     rm -f .git/index SS &&\n-     cp .orig-A/SS SS &&\n-     echo extra >>SS &&\n-     git update-index --add SS &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '13 - must match A in O && A && B && O!=A && O==B case' \\\n-    \"rm -f .git/index MN &&\n-     cp .orig-A/MN MN &&\n-     git update-index --add MN &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '13 - must match A in O && A && B && O!=A && O==B case' \\\n-    \"rm -f .git/index MN &&\n-     cp .orig-A/MN MN &&\n-     git update-index --add MN &&\n-     echo extra >>MN &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '14 - must match and be up-to-date in O && A && B && O==A && O!=B case' \\\n-    \"rm -f .git/index NM &&\n-     cp .orig-A/NM NM &&\n-     git update-index --add NM &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '14 - may match B in O && A && B && O==A && O!=B case' \\\n-    \"rm -f .git/index NM &&\n-     cp .orig-B/NM NM &&\n-     git update-index --add NM &&\n-     echo extra >>NM &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' \"\n-     rm -f .git/index NM &&\n-     cp .orig-A/NM NM &&\n-     git update-index --add NM &&\n-     echo extra >>NM &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' \"\n-     rm -f .git/index NM &&\n-     cp .orig-A/NM NM &&\n-     echo extra >>NM &&\n-     git update-index --add NM &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-test_expect_success \\\n-    '15 - must match A in O && A && B && O==A && O==B case' \\\n-    \"rm -f .git/index NN &&\n-     cp .orig-A/NN NN &&\n-     git update-index --add NN &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '15 - must match A in O && A && B && O==A && O==B case' \\\n-    \"rm -f .git/index NN &&\n-     cp .orig-A/NN NN &&\n-     git update-index --add NN &&\n-     echo extra >>NN &&\n-     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n-     check_result\"\n-\n-test_expect_success \\\n-    '15 (fail) - must match A in O && A && B && O==A && O==B case' \"\n-     rm -f .git/index NN &&\n-     cp .orig-A/NN NN &&\n-     echo extra >>NN &&\n-     git update-index --add NN &&\n-     read_tree_must_fail -m $tree_O $tree_A $tree_B\n-\"\n-\n-# #16\n-test_expect_success \\\n-    '16 - A matches in one and B matches in another.' \\\n-    'rm -f .git/index F16 &&\n-    echo F16 >F16 &&\n-    git update-index --add F16 &&\n-    tree0=$(git write-tree) &&\n-    echo E16 >F16 &&\n-    git update-index F16 &&\n-    tree1=$(git write-tree) &&\n-    read_tree_must_succeed -m $tree0 $tree1 $tree1 $tree0 &&\n-    git ls-files --stage'\n+test_expect_success '1 - must not have an entry not in A.' '\n+\trm -f .git/index XX &&\n+\techo XX >XX &&\n+\tgit update-index --add XX &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '2 - must match B in !O && !A && B case.' '\n+\trm -f .git/index NA &&\n+\tcp .orig-B/NA NA &&\n+\tgit update-index --add NA &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '2 - matching B alone is OK in !O && !A && B case.' '\n+\trm -f .git/index NA &&\n+\tcp .orig-B/NA NA &&\n+\tgit update-index --add NA &&\n+\techo extra >>NA &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '3 - must match A in !O && A && !B case.' '\n+\trm -f .git/index AN &&\n+\tcp .orig-A/AN AN &&\n+\tgit update-index --add AN &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '3 - matching A alone is OK in !O && A && !B case.' '\n+\trm -f .git/index AN &&\n+\tcp .orig-A/AN AN &&\n+\tgit update-index --add AN &&\n+\techo extra >>AN &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '3 (fail) - must match A in !O && A && !B case.' '\n+\trm -f .git/index AN &&\n+\tcp .orig-A/AN AN &&\n+\techo extra >>AN &&\n+\tgit update-index --add AN &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '4 - must match and be up-to-date in !O && A && B && A!=B case.' '\n+\trm -f .git/index AA &&\n+\tcp .orig-A/AA AA &&\n+\tgit update-index --add AA &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' '\n+\trm -f .git/index AA &&\n+\tcp .orig-A/AA AA &&\n+\tgit update-index --add AA &&\n+\techo extra >>AA &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' '\n+\trm -f .git/index AA &&\n+\tcp .orig-A/AA AA &&\n+\techo extra >>AA &&\n+\tgit update-index --add AA &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '5 - must match in !O && A && B && A==B case.' '\n+\trm -f .git/index LL &&\n+\tcp .orig-A/LL LL &&\n+\tgit update-index --add LL &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '5 - must match in !O && A && B && A==B case.' '\n+\trm -f .git/index LL &&\n+\tcp .orig-A/LL LL &&\n+\tgit update-index --add LL &&\n+\techo extra >>LL &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '5 (fail) - must match A in !O && A && B && A==B case.' '\n+\trm -f .git/index LL &&\n+\tcp .orig-A/LL LL &&\n+\techo extra >>LL &&\n+\tgit update-index --add LL &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '6 - must not exist in O && !A && !B case' '\n+\trm -f .git/index DD &&\n+\techo DD >DD &&\n+\tgit update-index --add DD &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '7 - must not exist in O && !A && B && O!=B case' '\n+\trm -f .git/index DM &&\n+\tcp .orig-B/DM DM &&\n+\tgit update-index --add DM &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '8 - must not exist in O && !A && B && O==B case' '\n+\trm -f .git/index DN &&\n+\tcp .orig-B/DN DN &&\n+\tgit update-index --add DN &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '9 - must match and be up-to-date in O && A && !B && O!=A case' '\n+\trm -f .git/index MD &&\n+\tcp .orig-A/MD MD &&\n+\tgit update-index --add MD &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' '\n+\trm -f .git/index MD &&\n+\tcp .orig-A/MD MD &&\n+\tgit update-index --add MD &&\n+\techo extra >>MD &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' '\n+\trm -f .git/index MD &&\n+\tcp .orig-A/MD MD &&\n+\techo extra >>MD &&\n+\tgit update-index --add MD &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '10 - must match and be up-to-date in O && A && !B && O==A case' '\n+\trm -f .git/index ND &&\n+\tcp .orig-A/ND ND &&\n+\tgit update-index --add ND &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' '\n+\trm -f .git/index ND &&\n+\tcp .orig-A/ND ND &&\n+\tgit update-index --add ND &&\n+\techo extra >>ND &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' '\n+\trm -f .git/index ND &&\n+\tcp .orig-A/ND ND &&\n+\techo extra >>ND &&\n+\tgit update-index --add ND &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '11 - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '\n+\trm -f .git/index MM &&\n+\tcp .orig-A/MM MM &&\n+\tgit update-index --add MM &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '\n+\trm -f .git/index MM &&\n+\tcp .orig-A/MM MM &&\n+\tgit update-index --add MM &&\n+\techo extra >>MM &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '\n+\trm -f .git/index MM &&\n+\tcp .orig-A/MM MM &&\n+\techo extra >>MM &&\n+\tgit update-index --add MM &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '12 - must match A in O && A && B && O!=A && A==B case' '\n+\trm -f .git/index SS &&\n+\tcp .orig-A/SS SS &&\n+\tgit update-index --add SS &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '12 - must match A in O && A && B && O!=A && A==B case' '\n+\trm -f .git/index SS &&\n+\tcp .orig-A/SS SS &&\n+\tgit update-index --add SS &&\n+\techo extra >>SS &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '12 (fail) - must match A in O && A && B && O!=A && A==B case' '\n+\trm -f .git/index SS &&\n+\tcp .orig-A/SS SS &&\n+\techo extra >>SS &&\n+\tgit update-index --add SS &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '13 - must match A in O && A && B && O!=A && O==B case' '\n+\trm -f .git/index MN &&\n+\tcp .orig-A/MN MN &&\n+\tgit update-index --add MN &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '13 - must match A in O && A && B && O!=A && O==B case' '\n+\trm -f .git/index MN &&\n+\tcp .orig-A/MN MN &&\n+\tgit update-index --add MN &&\n+\techo extra >>MN &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '14 - must match and be up-to-date in O && A && B && O==A && O!=B case' '\n+\trm -f .git/index NM &&\n+\tcp .orig-A/NM NM &&\n+\tgit update-index --add NM &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '14 - may match B in O && A && B && O==A && O!=B case' '\n+\trm -f .git/index NM &&\n+\tcp .orig-B/NM NM &&\n+\tgit update-index --add NM &&\n+\techo extra >>NM &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' '\n+\trm -f .git/index NM &&\n+\tcp .orig-A/NM NM &&\n+\tgit update-index --add NM &&\n+\techo extra >>NM &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' '\n+\trm -f .git/index NM &&\n+\tcp .orig-A/NM NM &&\n+\techo extra >>NM &&\n+\tgit update-index --add NM &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '15 - must match A in O && A && B && O==A && O==B case' '\n+\trm -f .git/index NN &&\n+\tcp .orig-A/NN NN &&\n+\tgit update-index --add NN &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '15 - must match A in O && A && B && O==A && O==B case' '\n+\trm -f .git/index NN &&\n+\tcp .orig-A/NN NN &&\n+\tgit update-index --add NN &&\n+\techo extra >>NN &&\n+\tread_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n+\tcheck_result\n+'\n+\n+test_expect_success '15 (fail) - must match A in O && A && B && O==A && O==B case' '\n+\trm -f .git/index NN &&\n+\tcp .orig-A/NN NN &&\n+\techo extra >>NN &&\n+\tgit update-index --add NN &&\n+\tread_tree_must_fail -m $tree_O $tree_A $tree_B\n+'\n+\n+test_expect_success '16 - A matches in one and B matches in another.' '\n+\trm -f .git/index F16 &&\n+\techo F16 >F16 &&\n+\tgit update-index --add F16 &&\n+\ttree0=$(git write-tree) &&\n+\techo E16 >F16 &&\n+\tgit update-index F16 &&\n+\ttree1=$(git write-tree) &&\n+\tread_tree_must_succeed -m $tree0 $tree1 $tree1 $tree0 &&\n+\tgit ls-files --stage\n+'\n \n test_done\n-- \n2.11.0.rc2.30.g7c4be45.dirty\n\n"},{"id":"309104","messageId":"20170110014542.19352-5-sbeller@google.com","threadId":"44844","inReplyTo":"20170110014542.19352-1-sbeller@google.com","subject":"[PATCH 4/4] unpack-trees: support super-prefix option","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-10T01:45:42Z","receivedAt":"2017-01-10T01:46:14Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Add support for the super-prefix option for commands that unpack trees.\nFor testing purposes enable it in read-tree, which has no other path\nrelated output.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n git.c                       |  2 +-\n t/t1001-read-tree-m-2way.sh |  9 +++++++++\n unpack-trees.c              | 39 ++++++++++++++++++++++++++++++++++++---\n 3 files changed, 46 insertions(+), 4 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex dce529fcbf..acbabd1298 100644\n--- a/git.c\n+++ b/git.c\n@@ -471,7 +471,7 @@ static struct cmd_struct commands[] = {\n \t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n \t{ \"pull\", cmd_pull, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"push\", cmd_push, RUN_SETUP },\n-\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n+\t{ \"read-tree\", cmd_read_tree, RUN_SETUP | SUPPORT_SUPER_PREFIX},\n \t{ \"receive-pack\", cmd_receive_pack },\n \t{ \"reflog\", cmd_reflog, RUN_SETUP },\n \t{ \"remote\", cmd_remote, RUN_SETUP },\ndiff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh\nindex 7b70089705..014ba39420 100755\n--- a/t/t1001-read-tree-m-2way.sh\n+++ b/t/t1001-read-tree-m-2way.sh\n@@ -363,6 +363,15 @@ test_expect_success 'a/b (untracked) vs a, plus c/d case test.' '\n \ttest -f a/b\n '\n \n+cat <<-EOF >expect &&\n+\terror: Updating 'fictional/a' would lose untracked files in it\n+EOF\n+\n+test_expect_success 'read-tree supports the super-prefix' '\n+\ttest_must_fail git --super-prefix fictional/ read-tree -u -m \"$treeH\" \"$treeM\" 2>actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'a/b vs a, plus c/d case setup.' '\n \trm -f .git/index &&\n \trm -fr a &&\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 7a6df99d10..bc56195e27 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -52,6 +52,37 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {\n \t  ? ((o)->msgs[(type)])      \\\n \t  : (unpack_plumbing_errors[(type)]) )\n \n+static const char *super_prefixed(const char *path)\n+{\n+\t/*\n+\t * This is used for the error messages above.\n+\t * We need to have exactly two buffer spaces.\n+\t */\n+\tstatic struct strbuf buf[2] = {STRBUF_INIT, STRBUF_INIT};\n+\tstatic int super_prefix_len = -1;\n+\tstatic unsigned idx = 0;\n+\n+\tif (!get_super_prefix())\n+\t\treturn path;\n+\n+\tif (super_prefix_len < 0) {\n+\t\tint i;\n+\n+\t\tfor (i = 0; i < ARRAY_SIZE(buf); i++)\n+\t\t\tstrbuf_addstr(&buf[i], get_super_prefix());\n+\n+\t\tsuper_prefix_len = strlen(get_super_prefix());\n+\t}\n+\n+\tif (++idx >= ARRAY_SIZE(buf))\n+\t\tidx = 0;\n+\n+\tstrbuf_setlen(&buf[idx], super_prefix_len);\n+\tstrbuf_addstr(&buf[idx], path);\n+\n+\treturn buf[idx].buf;\n+}\n+\n void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,\n \t\t\t\t  const char *cmd)\n {\n@@ -172,7 +203,7 @@ static int add_rejected_path(struct unpack_trees_options *o,\n \t\t\t     const char *path)\n {\n \tif (!o->show_all_errors)\n-\t\treturn error(ERRORMSG(o, e), path);\n+\t\treturn error(ERRORMSG(o, e), super_prefixed(path));\n \n \t/*\n \t * Otherwise, insert in a list for future display by\n@@ -196,7 +227,7 @@ static void display_error_msgs(struct unpack_trees_options *o)\n \t\t\tsomething_displayed = 1;\n \t\t\tfor (i = 0; i < rejects->nr; i++)\n \t\t\t\tstrbuf_addf(&path, \"\\t%s\\n\", rejects->items[i].string);\n-\t\t\terror(ERRORMSG(o, e), path.buf);\n+\t\t\terror(ERRORMSG(o, e), super_prefixed(path.buf));\n \t\t\tstrbuf_release(&path);\n \t\t}\n \t\tstring_list_clear(rejects, 0);\n@@ -1918,7 +1949,9 @@ int bind_merge(const struct cache_entry * const *src,\n \t\t\t     o->merge_size);\n \tif (a && old)\n \t\treturn o->gently ? -1 :\n-\t\t\terror(ERRORMSG(o, ERROR_BIND_OVERLAP), a->name, old->name);\n+\t\t\terror(ERRORMSG(o, ERROR_BIND_OVERLAP),\n+\t\t\t      super_prefixed(a->name),\n+\t\t\t      super_prefixed(old->name));\n \tif (!a)\n \t\treturn keep_entry(old, o);\n \telse\n-- \n2.11.0.rc2.30.g7c4be45.dirty\n\n"},{"id":"309161","messageId":"xmqqr34ar6s1.fsf@gitster.mtv.corp.google.com","threadId":"44844","inReplyTo":"20170110014542.19352-3-sbeller@google.com","subject":"Re: [PATCH 2/4] t1000: modernize style","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-01-10T20:37:02Z","receivedAt":"2017-01-10T20:38:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> The preferred style in tests seems to be\n\ns/seems to be/is/;\n\n>\n> test_expect_success 'short description, ended by 2 single quotes' '\n> \there comes the test &&\n> \tand chains over many lines &&\n> \tended by a quote\n> '\n\nThanks.  This is way overdue.  During the time the script has been\ndormant for more than two years, we should have done this.\n"},{"id":"309162","messageId":"xmqqmveyr6kk.fsf@gitster.mtv.corp.google.com","threadId":"44844","inReplyTo":"20170110014542.19352-2-sbeller@google.com","subject":"Re: [PATCH 1/4] read-tree: use OPT_BOOL instead of OPT_SET_INT","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-01-10T20:41:31Z","receivedAt":"2017-01-10T20:41:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> All occurrences of OPT_SET_INT were setting the value to 1;\n> internally OPT_BOOL is just that.\n>\n> Signed-off-by: Stefan Beller <sbeller@google.com>\n> ---\n>  builtin/read-tree.c | 36 ++++++++++++++++++------------------\n>  1 file changed, 18 insertions(+), 18 deletions(-)\n\nThe result is much easier to read, partly because the \"1\" (true) is\nat the very end of the line when OPT_SET_INT() is used for the\nreader to notice that this is merely a boolean.\n\nMore importantly, as OPT_SET_INT() can be used multiple times on the\nsame variable (or field) to set it to different values, it is easier\nto read if OPT_BOOL() is used when OPT_SET_INT() to 1 is not used\nfor that purpose.\n\nThanks.\n\n>> diff --git a/builtin/read-tree.c b/builtin/read-tree.c\n> index fa6edb35b2..8ba64bc785 100644\n> --- a/builtin/read-tree.c\n> +++ b/builtin/read-tree.c\n> @@ -109,34 +109,34 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n>  \t\t{ OPTION_CALLBACK, 0, \"index-output\", NULL, N_(\"file\"),\n>  \t\t  N_(\"write resulting index to <file>\"),\n>  \t\t  PARSE_OPT_NONEG, index_output_cb },\n> -\t\tOPT_SET_INT(0, \"empty\", &read_empty,\n> -\t\t\t    N_(\"only empty the index\"), 1),\n> +\t\tOPT_BOOL(0, \"empty\", &read_empty,\n> +\t\t\t    N_(\"only empty the index\")),\n>  \t\tOPT__VERBOSE(&opts.verbose_update, N_(\"be verbose\")),\n>  \t\tOPT_GROUP(N_(\"Merging\")),\n> -\t\tOPT_SET_INT('m', NULL, &opts.merge,\n> -\t\t\t    N_(\"perform a merge in addition to a read\"), 1),\n> -\t\tOPT_SET_INT(0, \"trivial\", &opts.trivial_merges_only,\n> -\t\t\t    N_(\"3-way merge if no file level merging required\"), 1),\n> -\t\tOPT_SET_INT(0, \"aggressive\", &opts.aggressive,\n> -\t\t\t    N_(\"3-way merge in presence of adds and removes\"), 1),\n> -\t\tOPT_SET_INT(0, \"reset\", &opts.reset,\n> -\t\t\t    N_(\"same as -m, but discard unmerged entries\"), 1),\n> +\t\tOPT_BOOL('m', NULL, &opts.merge,\n> +\t\t\t N_(\"perform a merge in addition to a read\")),\n> +\t\tOPT_BOOL(0, \"trivial\", &opts.trivial_merges_only,\n> +\t\t\t N_(\"3-way merge if no file level merging required\")),\n> +\t\tOPT_BOOL(0, \"aggressive\", &opts.aggressive,\n> +\t\t\t N_(\"3-way merge in presence of adds and removes\")),\n> +\t\tOPT_BOOL(0, \"reset\", &opts.reset,\n> +\t\t\t N_(\"same as -m, but discard unmerged entries\")),\n>  \t\t{ OPTION_STRING, 0, \"prefix\", &opts.prefix, N_(\"<subdirectory>/\"),\n>  \t\t  N_(\"read the tree into the index under <subdirectory>/\"),\n>  \t\t  PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP },\n> -\t\tOPT_SET_INT('u', NULL, &opts.update,\n> -\t\t\t    N_(\"update working tree with merge result\"), 1),\n> +\t\tOPT_BOOL('u', NULL, &opts.update,\n> +\t\t\t N_(\"update working tree with merge result\")),\n>  \t\t{ OPTION_CALLBACK, 0, \"exclude-per-directory\", &opts,\n>  \t\t  N_(\"gitignore\"),\n>  \t\t  N_(\"allow explicitly ignored files to be overwritten\"),\n>  \t\t  PARSE_OPT_NONEG, exclude_per_directory_cb },\n> -\t\tOPT_SET_INT('i', NULL, &opts.index_only,\n> -\t\t\t    N_(\"don't check the working tree after merging\"), 1),\n> +\t\tOPT_BOOL('i', NULL, &opts.index_only,\n> +\t\t\t N_(\"don't check the working tree after merging\")),\n>  \t\tOPT__DRY_RUN(&opts.dry_run, N_(\"don't update the index or the work tree\")),\n> -\t\tOPT_SET_INT(0, \"no-sparse-checkout\", &opts.skip_sparse_checkout,\n> -\t\t\t    N_(\"skip applying sparse checkout filter\"), 1),\n> -\t\tOPT_SET_INT(0, \"debug-unpack\", &opts.debug_unpack,\n> -\t\t\t    N_(\"debug unpack-trees\"), 1),\n> +\t\tOPT_BOOL(0, \"no-sparse-checkout\", &opts.skip_sparse_checkout,\n> +\t\t\t N_(\"skip applying sparse checkout filter\")),\n> +\t\tOPT_BOOL(0, \"debug-unpack\", &opts.debug_unpack,\n> +\t\t\t N_(\"debug unpack-trees\")),\n>  \t\tOPT_END()\n>  \t};\n"},{"id":"309178","messageId":"CAGZ79kbm4GRwNe7J_KP_V3eP8ZyAMEhOy-HL_ytHGtPoe19NPg@mail.gmail.com","threadId":"44844","inReplyTo":"xmqqr34ar6s1.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 2/4] t1000: modernize style","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-10T20:43:12Z","receivedAt":"2017-01-10T20:43:39Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Jan 10, 2017 at 12:37 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>> The preferred style in tests seems to be\n>\n> s/seems to be/is/;\n\nIf this is the only nit, mind to fix up the commit message locally?\n(I was even unsure if we want to have this patch as part\nof a larger series, as it is just refactoring for the sake of refactoring,\ni.e. t1000 doesn't see a new test in this series, only t1001 does)\n\n>\n>>\n>> test_expect_success 'short description, ended by 2 single quotes' '\n>>       here comes the test &&\n>>       and chains over many lines &&\n>>       ended by a quote\n>> '\n>\n> Thanks.  This is way overdue.  During the time the script has been\n> dormant for more than two years, we should have done this.\n\nagreed.\n"},{"id":"309184","messageId":"xmqqy3yipoaw.fsf@gitster.mtv.corp.google.com","threadId":"44844","inReplyTo":"CAGZ79kbm4GRwNe7J_KP_V3eP8ZyAMEhOy-HL_ytHGtPoe19NPg@mail.gmail.com","subject":"Re: [PATCH 2/4] t1000: modernize style","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-01-10T22:01:27Z","receivedAt":"2017-01-10T22:01:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> On Tue, Jan 10, 2017 at 12:37 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Stefan Beller <sbeller@google.com> writes:\n>>\n>>> The preferred style in tests seems to be\n>>\n>> s/seems to be/is/;\n>\n> If this is the only nit, mind to fix up the commit message locally?\n\nCertainly.  It wasn't even meant as a \"nitpick\".  I was just\nconfirming your observation.\n"},{"id":"309233","messageId":"xmqq37gpnuyi.fsf@gitster.mtv.corp.google.com","threadId":"44844","inReplyTo":"20170110014542.19352-5-sbeller@google.com","subject":"Re: [PATCH 4/4] unpack-trees: support super-prefix option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-01-11T21:32:53Z","receivedAt":"2017-01-11T21:34:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> Add support for the super-prefix option for commands that unpack trees.\n> For testing purposes enable it in read-tree, which has no other path\n> related output.\n\n\"path related output\"?  I am not sure I understand this.\n\nWhen read-tree reads N trees, or unpack_trees() is asked to \"merge\"\nN trees, how does --super-prefix supposed to interact with the paths\nin these trees?  Does the prefix added to paths in all trees?\n\nDid you mean that read-tree (and unpack_trees() in general) is a\nwhole-tree operation and there is no path related input (i.e.\npathspec limiting), but if another command that started in the\nsuperproject is running us in its submodule, it wants us to prefix\nthe path to the submodule when we report errors?\n\nIf that is what is going on, I think it makes sense, but it may be\nasking too much from the readers to guess that from \"Add support for\nthe super-prefix option\".\n\n> --- a/t/t1001-read-tree-m-2way.sh\n> +++ b/t/t1001-read-tree-m-2way.sh\n> @@ -363,6 +363,15 @@ test_expect_success 'a/b (untracked) vs a, plus c/d case test.' '\n>  \ttest -f a/b\n>  '\n>  \n> +cat <<-EOF >expect &&\n> +\terror: Updating 'fictional/a' would lose untracked files in it\n> +EOF\n> +\n> +test_expect_success 'read-tree supports the super-prefix' '\n> +\ttest_must_fail git --super-prefix fictional/ read-tree -u -m \"$treeH\" \"$treeM\" 2>actual &&\n> +\ttest_cmp expect actual\n> +'\n> +\n\nPreparing the expected output \"expect\" outside test_expect_success\nblock is also old-school.  Move it inside the new test?\n\n> diff --git a/unpack-trees.c b/unpack-trees.c\n> index 7a6df99d10..bc56195e27 100644\n> --- a/unpack-trees.c\n> +++ b/unpack-trees.c\n> @@ -52,6 +52,37 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {\n>  \t  ? ((o)->msgs[(type)])      \\\n>  \t  : (unpack_plumbing_errors[(type)]) )\n>  \n> +static const char *super_prefixed(const char *path)\n> +{\n> +\t/*\n> +\t * This is used for the error messages above.\n> +\t * We need to have exactly two buffer spaces.\n> +\t */\n> +\tstatic struct strbuf buf[2] = {STRBUF_INIT, STRBUF_INIT};\n> +\tstatic int super_prefix_len = -1;\n> +\tstatic unsigned idx = 0;\n> +\n> +\tif (!get_super_prefix())\n> +\t\treturn path;\n> +\n> +\tif (super_prefix_len < 0) {\n> +\t\tint i;\n> +\n> +\t\tfor (i = 0; i < ARRAY_SIZE(buf); i++)\n> +\t\t\tstrbuf_addstr(&buf[i], get_super_prefix());\n> +\n> +\t\tsuper_prefix_len = strlen(get_super_prefix());\n> +\t}\n> +\n> +\tif (++idx >= ARRAY_SIZE(buf))\n> +\t\tidx = 0;\n> +\n> +\tstrbuf_setlen(&buf[idx], super_prefix_len);\n> +\tstrbuf_addstr(&buf[idx], path);\n> +\n> +\treturn buf[idx].buf;\n> +}\n\nHmph, as a reader of the code, I do not even want to wonder how\nexpensive get_super_prefix() is.  If the executable part of the\nabove were written like this, it would have been easier to\nunderstand:\n\n\tif (super_prefix_len < 0) {\n\t\tif (!get_super_prefix())\n\t\t\tsuper_prefix_len = 0;\n\t\telse {\n\t\t\tint i;\n\t\t\t... prepare buf[] and set super_prefix_len ...;\n                }\n\t}\n\n        if (!super_prefix_len)\n\t\treturn path;\n\n\t... use buf[] to do the prefixing and return it ...\n\n"},{"id":"309237","messageId":"CAGZ79kaHDnVLQr8WLoaD5KKs7EqeW=KbkptF=iHpU5t054Xcdw@mail.gmail.com","threadId":"44844","inReplyTo":"xmqq37gpnuyi.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 4/4] unpack-trees: support super-prefix option","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-11T22:12:12Z","receivedAt":"2017-01-11T22:12:19Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Jan 11, 2017 at 1:32 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>> Add support for the super-prefix option for commands that unpack trees.\n>> For testing purposes enable it in read-tree, which has no other path\n>> related output.\n>\n> \"path related output\"?  I am not sure I understand this.\n\nWell, s/path related output/output of paths/.\n\n> When read-tree reads N trees, or unpack_trees() is asked to \"merge\"\n> N trees, how does --super-prefix supposed to interact with the paths\n> in these trees?  Does the prefix added to paths in all trees?\n\nInternally the super-prefix is ignored. Only the (input and) output\nis using that super prefix for messages.\n\nIt was introduced for grepping recursively into submodules, i.e.\n\ninvoke as\n\n    git grep --recurse-submodules \\\n      -e path/inside/submodule/and/further/down\n    # internally it invokes:\n    git -C .. --super-prefix .. grep ..\n    # which operates \"just normal\" except for the\n    # input parsing and output\n\nThe use case for this patch is working tree related things, i.e.\n    git checkout --recurse-submodules\n    # internally when recursing we call \"git read-tree -u\", but\n    # reporting could be:\n    Your local changes to the following files would be overwritten by checkout:\n      path/inside/submodule/file.txt\n\n\n>\n> Did you mean that read-tree (and unpack_trees() in general) is a\n> whole-tree operation and there is no path related input (i.e.\n> pathspec limiting), but if another command that started in the\n> superproject is running us in its submodule, it wants us to prefix\n> the path to the submodule when we report errors?\n\nYes. I tried to explain it better above, but you got it here.\n\n>\n> If that is what is going on, I think it makes sense, but it may be\n> asking too much from the readers to guess that from \"Add support for\n> the super-prefix option\".\n\nI need to enhance the commit message by a lot then.\n\n>\n>> --- a/t/t1001-read-tree-m-2way.sh\n>> +++ b/t/t1001-read-tree-m-2way.sh\n>> @@ -363,6 +363,15 @@ test_expect_success 'a/b (untracked) vs a, plus c/d case test.' '\n>>       test -f a/b\n>>  '\n>>\n>> +cat <<-EOF >expect &&\n>> +     error: Updating 'fictional/a' would lose untracked files in it\n>> +EOF\n>> +\n>> +test_expect_success 'read-tree supports the super-prefix' '\n>> +     test_must_fail git --super-prefix fictional/ read-tree -u -m \"$treeH\" \"$treeM\" 2>actual &&\n>> +     test_cmp expect actual\n>> +'\n>> +\n>\n> Preparing the expected output \"expect\" outside test_expect_success\n> block is also old-school.  Move it inside the new test?\n\nI looked into that. What is our current stance on using single/double quotes?\nMost tests use single quotes for the test title as well as the test\ninstructions,\nsuch that double quotes can be used naturally in there. But single quotes\ncannot be used even escaped, such that we need to do a thing like\n\nsq=\"'\"\n\ntest_expect_success 'test title' '\n    cat <<-EOF >expect &&\n        error for ${sq}path${sq}\n    EOF\n    test instructions go here\n'\n\nthough that is not used as often as I would think as\ngrep \\${sq} yields t1507 and t3005.\n\n>\n> Hmph, as a reader of the code, I do not even want to wonder how\n> expensive get_super_prefix() is.  If the executable part of the\n> above were written like this, it would have been easier to\n> understand:\n>\n>         if (super_prefix_len < 0) {\n>                 if (!get_super_prefix())\n>                         super_prefix_len = 0;\n>                 else {\n>                         int i;\n>                         ... prepare buf[] and set super_prefix_len ...;\n>                 }\n>         }\n>\n>         if (!super_prefix_len)\n>                 return path;\n>\n>         ... use buf[] to do the prefixing and return it ...\n>\n\ngood point. I'll fix that.\n"},{"id":"309238","messageId":"xmqqh955mb1p.fsf@gitster.mtv.corp.google.com","threadId":"44844","inReplyTo":"CAGZ79kaHDnVLQr8WLoaD5KKs7EqeW=KbkptF=iHpU5t054Xcdw@mail.gmail.com","subject":"Re: [PATCH 4/4] unpack-trees: support super-prefix option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-01-11T23:28:18Z","receivedAt":"2017-01-11T23:28:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n>> Preparing the expected output \"expect\" outside test_expect_success\n>> block is also old-school.  Move it inside the new test?\n>\n> I looked into that. What is our current stance on using single/double quotes?\n\nUsing dq around executable part, i.e.\n\n\ttest_expect_success title \"\n\t\techo \\\"'foo'\\\"\n\t\"\n\nis a million-times more grave sin even if the test initially does\nnot refer to any variable in its body.  Somebody will eventually\nneed to add a line that refers to a variable and either forgets to\nquote \\$ in front or properly quotes it.  The former makes the\nvariable interpolated while the arguments to the test_expect_success\nis prepared (which is a bug) and the latter makes the result quite\nugly, like so:\n\n\ttest_expect_success title \"\n\t\tsq=\\' var=foo &&\n\t\techo \\\"\\${sq}\\$value\\${sq}\\\"\n\t\"\n\nEnclosing the body always in sq-pair does mean something ugly like\nthis from the beginning once you need to use sq inside:\n\n\ttest_expect_success title '\n\t\tsq='\\'' &&\n\t\techo \"${sq}foo${sq}\"\n\t'\n\nor\n\n\ttest_expect_success title '\n\t\techo \"'\\''foo'\\''\"\n\t'\n\nbut the ugliness is localized to places where single quote is\nabsolutely needed, and '\\'' is something eyes soon get used to as an\nidiom [*1*].  It does not affect every reference of variables like\nenclosing with dq does.\n\n\n[Footnote]\n\n*1* That \"idiom\"-ness is the reason why the last example above is\n    not written like this:\n\n\ttest_expect_success title '\n\t\techo \"'\\'foo\\''\"\n\t'\n\n    even though the sq pair surrounding \"foo\" is not technically\n    necessary.  It lets us think of the string as almost always is\n    inside sq context, with the single exception that we step\n    outside sq context and append a sq by saying bs-sq (\\').\n"},{"id":"309240","messageId":"CAGZ79kb30nG-TAnXuUKM+exxoh816sRogwhU-hjaL+onmFR-qQ@mail.gmail.com","threadId":"44844","inReplyTo":"xmqqh955mb1p.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 4/4] unpack-trees: support super-prefix option","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-11T23:57:59Z","receivedAt":"2017-01-11T23:58:07Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Jan 11, 2017 at 3:28 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>>> Preparing the expected output \"expect\" outside test_expect_success\n>>> block is also old-school.  Move it inside the new test?\n>>\n>> I looked into that. What is our current stance on using single/double quotes?\n>\n> Using dq around executable part, i.e.\n>\n>         test_expect_success title \"\n>                 echo \\\"'foo'\\\"\n>         \"\n>\n> is a million-times more grave sin even if the test initially does\n> not refer to any variable in its body.  Somebody will eventually\n> need to add a line that refers to a variable and either forgets to\n> quote \\$ in front or properly quotes it.\n\nagreed.\n\n>  The former makes the\n> variable interpolated while the arguments to the test_expect_success\n> is prepared (which is a bug) and the latter makes the result quite\n> ugly, like so:\n>\n>         test_expect_success title \"\n>                 sq=\\' var=foo &&\n>                 echo \\\"\\${sq}\\$value\\${sq}\\\"\n>         \"\n>\n> Enclosing the body always in sq-pair does mean something ugly like\n> this from the beginning once you need to use sq inside:\n>\n>         test_expect_success title '\n>                 sq='\\'' &&\n>                 echo \"${sq}foo${sq}\"\n>         '\n\nThis one fails\nerror: bug in the test script: broken &&-chain:\n                sq=' &&\n                echo \"${sq}foo${sq}\"\nboth other occurrences of using ${sq} are defining sq outside\n(one as sq=\\' and the other as sq=\"'\")\n\nSo I think we either have to keep sq out of the test,\n    sq=\"'\"\n    test_expect_success title '\n         echo \"${sq}foo${sq}\"\n    '\n\nor do the echo/printf trick inside:\n\n    test_expect_success title '\n         sq=$(echo -e \"\\x27\") &&\n         echo \"${sq}foo${sq}\"\n    '\n\nEh, I just realize the '\\'' works inside here-doc, too.\nNevermind then, I'll resend it with just quoted sq in the here-doc then.\n\nThanks,\nStefan\n"},{"id":"309241","messageId":"20170112001253.27679-1-sbeller@google.com","threadId":"44844","inReplyTo":"xmqq37gpnuyi.fsf@gitster.mtv.corp.google.com","subject":"[PATCHv2 4/4] unpack-trees: support super-prefix option","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-12T00:12:53Z","receivedAt":"2017-01-12T00:13:09Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"In the future we want to support working tree operations within submodules,\ne.g. \"git checkout --recurse-submodules\", which will update the submodule\nto the commit as recorded in its superproject. In the submodule the\nunpack-tree operation is carried out as usual, but the reporting to the\nuser needs to prefix any path with the superproject. The mechanism for\nthis is the super-prefix. (see 74866d757, git: make super-prefix option)\n\nAdd support for the super-prefix option for commands that unpack trees\nby wrapping any path output in unpacking trees in the newly introduced\nsuper_prefixed function. This new function prefixes any path with the\nsuper-prefix if there is one.  Assuming the submodule case doesn't happen\nin the majority of the cases, we'd want to have a fast behavior for no\nsuper prefix, i.e. no reallocation/copying, but just returning path.\n\nAnother aspect of introducing the `super_prefixed` function is to consider\nwho owns the memory and if this is the right place where the path gets\nmodified. As the super prefix ought to change the output behavior only and\nnot the actual unpack tree part, it is fine to be that late in the line.\nAs we get passed in 'const char *path', we cannot change the path itself,\nwhich means in case of a super prefix we have to copy over the path.\nWe need two static buffers in that function as the error messages\ncontain at most two paths.\n\nFor testing purposes enable it in read-tree, which has no output\nof paths other than an unpack-trees.c. These are all converted in\nthis patch.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n\nThis is only patchv4 that is rerolled, patches 1-3 remain as is.\n\nThe test uses '\\'' now, and the super_prefixed function is rewritten\nusing the flow Junio suggested.\n\nThe commit message got enhanced.\n\nThanks,\nStefan\n\n git.c                       |  2 +-\n t/t1001-read-tree-m-2way.sh |  8 ++++++++\n unpack-trees.c              | 38 +++++++++++++++++++++++++++++++++++---\n 3 files changed, 44 insertions(+), 4 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex dce529fcbf..acbabd1298 100644\n--- a/git.c\n+++ b/git.c\n@@ -471,7 +471,7 @@ static struct cmd_struct commands[] = {\n \t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n \t{ \"pull\", cmd_pull, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"push\", cmd_push, RUN_SETUP },\n-\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n+\t{ \"read-tree\", cmd_read_tree, RUN_SETUP | SUPPORT_SUPER_PREFIX},\n \t{ \"receive-pack\", cmd_receive_pack },\n \t{ \"reflog\", cmd_reflog, RUN_SETUP },\n \t{ \"remote\", cmd_remote, RUN_SETUP },\ndiff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh\nindex 7b70089705..5ededd8e40 100755\n--- a/t/t1001-read-tree-m-2way.sh\n+++ b/t/t1001-read-tree-m-2way.sh\n@@ -363,6 +363,14 @@ test_expect_success 'a/b (untracked) vs a, plus c/d case test.' '\n \ttest -f a/b\n '\n \n+test_expect_success 'read-tree supports the super-prefix' '\n+\tcat <<-EOF >expect &&\n+\t\terror: Updating '\\''fictional/a'\\'' would lose untracked files in it\n+\tEOF\n+\ttest_must_fail git --super-prefix fictional/ read-tree -u -m \"$treeH\" \"$treeM\" 2>actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'a/b vs a, plus c/d case setup.' '\n \trm -f .git/index &&\n \trm -fr a &&\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 7a6df99d10..0a24472359 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -52,6 +52,36 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {\n \t  ? ((o)->msgs[(type)])      \\\n \t  : (unpack_plumbing_errors[(type)]) )\n \n+static const char *super_prefixed(const char *path)\n+{\n+\tstatic struct strbuf buf[2] = {STRBUF_INIT, STRBUF_INIT};\n+\tstatic int super_prefix_len = -1;\n+\tstatic unsigned idx = 0;\n+\n+\tif (super_prefix_len < 0) {\n+\t\tif (!get_super_prefix())\n+\t\t\tsuper_prefix_len = 0;\n+\t\telse {\n+\t\t\tint i;\n+\n+\t\t\tsuper_prefix_len = strlen(get_super_prefix());\n+\t\t\tfor (i = 0; i < ARRAY_SIZE(buf); i++)\n+\t\t\t\tstrbuf_addstr(&buf[i], get_super_prefix());\n+\t\t}\n+\t}\n+\n+\tif (!super_prefix_len)\n+\t\treturn path;\n+\n+\tif (++idx >= ARRAY_SIZE(buf))\n+\t\tidx = 0;\n+\n+\tstrbuf_setlen(&buf[idx], super_prefix_len);\n+\tstrbuf_addstr(&buf[idx], path);\n+\n+\treturn buf[idx].buf;\n+}\n+\n void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,\n \t\t\t\t  const char *cmd)\n {\n@@ -172,7 +202,7 @@ static int add_rejected_path(struct unpack_trees_options *o,\n \t\t\t     const char *path)\n {\n \tif (!o->show_all_errors)\n-\t\treturn error(ERRORMSG(o, e), path);\n+\t\treturn error(ERRORMSG(o, e), super_prefixed(path));\n \n \t/*\n \t * Otherwise, insert in a list for future display by\n@@ -196,7 +226,7 @@ static void display_error_msgs(struct unpack_trees_options *o)\n \t\t\tsomething_displayed = 1;\n \t\t\tfor (i = 0; i < rejects->nr; i++)\n \t\t\t\tstrbuf_addf(&path, \"\\t%s\\n\", rejects->items[i].string);\n-\t\t\terror(ERRORMSG(o, e), path.buf);\n+\t\t\terror(ERRORMSG(o, e), super_prefixed(path.buf));\n \t\t\tstrbuf_release(&path);\n \t\t}\n \t\tstring_list_clear(rejects, 0);\n@@ -1918,7 +1948,9 @@ int bind_merge(const struct cache_entry * const *src,\n \t\t\t     o->merge_size);\n \tif (a && old)\n \t\treturn o->gently ? -1 :\n-\t\t\terror(ERRORMSG(o, ERROR_BIND_OVERLAP), a->name, old->name);\n+\t\t\terror(ERRORMSG(o, ERROR_BIND_OVERLAP),\n+\t\t\t      super_prefixed(a->name),\n+\t\t\t      super_prefixed(old->name));\n \tif (!a)\n \t\treturn keep_entry(old, o);\n \telse\n-- \n2.11.0.259.g7b30ecf4f0\n\n"},{"id":"309297","messageId":"xmqqtw94hs8f.fsf@gitster.mtv.corp.google.com","threadId":"44844","inReplyTo":"20170112001253.27679-1-sbeller@google.com","subject":"Re: [PATCHv2 4/4] unpack-trees: support super-prefix option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-01-12T21:40:32Z","receivedAt":"2017-01-12T21:40:41Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> This is only patchv4 that is rerolled, patches 1-3 remain as is.\n\nGood timing, as I was about to send a reminder to suggest rerolling\n4/4 alone ;-)\n\n> +static const char *super_prefixed(const char *path)\n> +{\n\nThere used to be a comment that explains why we keep two static\nbuffers around here.  Even though it is in the log message, the\nin-code comment would save people trouble of having to go through\n\"git blame\" output.\n\nI'd say something like\n\n\t/*\n\t * It is necessary and sufficient to have two static buffers\n\t * as the return value of this function is fed to error()\n\t * using the unpack_*_errors[] templates we can see above.\n\t */\n\nperhaps.\n\n> +\tstatic struct strbuf buf[2] = {STRBUF_INIT, STRBUF_INIT};\n> +\tstatic int super_prefix_len = -1;\n> +\tstatic unsigned idx = 0;\n> +\n\nIf we initialize this to 1 (or even better, \"ARRAY_SIZE(buf) - 1\"),\nthen we would use buf[0] first and then buf[1], which feels more\nnatural to me.\n\nOther than that, this looks OK.  Will queue.\n\nThanks.\n\n> +\tif (super_prefix_len < 0) {\n> +\t\tif (!get_super_prefix())\n> +\t\t\tsuper_prefix_len = 0;\n> +\t\telse {\n> +\t\t\tint i;\n> +\n> +\t\t\tsuper_prefix_len = strlen(get_super_prefix());\n> +\t\t\tfor (i = 0; i < ARRAY_SIZE(buf); i++)\n> +\t\t\t\tstrbuf_addstr(&buf[i], get_super_prefix());\n> +\t\t}\n> +\t}\n> +\n> +\tif (!super_prefix_len)\n> +\t\treturn path;\n> +\n> +\tif (++idx >= ARRAY_SIZE(buf))\n> +\t\tidx = 0;\n> +\n> +\tstrbuf_setlen(&buf[idx], super_prefix_len);\n> +\tstrbuf_addstr(&buf[idx], path);\n> +\n> +\treturn buf[idx].buf;\n> +}\n> +\n>  void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,\n>  \t\t\t\t  const char *cmd)\n>  {\n> @@ -172,7 +202,7 @@ static int add_rejected_path(struct unpack_trees_options *o,\n>  \t\t\t     const char *path)\n>  {\n>  \tif (!o->show_all_errors)\n> -\t\treturn error(ERRORMSG(o, e), path);\n> +\t\treturn error(ERRORMSG(o, e), super_prefixed(path));\n>  \n>  \t/*\n>  \t * Otherwise, insert in a list for future display by\n> @@ -196,7 +226,7 @@ static void display_error_msgs(struct unpack_trees_options *o)\n>  \t\t\tsomething_displayed = 1;\n>  \t\t\tfor (i = 0; i < rejects->nr; i++)\n>  \t\t\t\tstrbuf_addf(&path, \"\\t%s\\n\", rejects->items[i].string);\n> -\t\t\terror(ERRORMSG(o, e), path.buf);\n> +\t\t\terror(ERRORMSG(o, e), super_prefixed(path.buf));\n>  \t\t\tstrbuf_release(&path);\n>  \t\t}\n>  \t\tstring_list_clear(rejects, 0);\n> @@ -1918,7 +1948,9 @@ int bind_merge(const struct cache_entry * const *src,\n>  \t\t\t     o->merge_size);\n>  \tif (a && old)\n>  \t\treturn o->gently ? -1 :\n> -\t\t\terror(ERRORMSG(o, ERROR_BIND_OVERLAP), a->name, old->name);\n> +\t\t\terror(ERRORMSG(o, ERROR_BIND_OVERLAP),\n> +\t\t\t      super_prefixed(a->name),\n> +\t\t\t      super_prefixed(old->name));\n>  \tif (!a)\n>  \t\treturn keep_entry(old, o);\n>  \telse\n"},{"id":"309300","messageId":"CAGZ79kZWYytJbXJZ=qeStuSe3tZ3qiCZZ-01Y0Ud9TcqsorjMw@mail.gmail.com","threadId":"44844","inReplyTo":"xmqqtw94hs8f.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCHv2 4/4] unpack-trees: support super-prefix option","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-01-12T22:19:35Z","receivedAt":"2017-01-12T22:19:41Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Jan 12, 2017 at 1:40 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>> This is only patchv4 that is rerolled, patches 1-3 remain as is.\n>\n> Good timing, as I was about to send a reminder to suggest rerolling\n> 4/4 alone ;-)\n>\n>> +static const char *super_prefixed(const char *path)\n>> +{\n>\n> There used to be a comment that explains why we keep two static\n> buffers around here.  Even though it is in the log message, the\n> in-code comment would save people trouble of having to go through\n> \"git blame\" output.\n>\n> I'd say something like\n>\n>         /*\n>          * It is necessary and sufficient to have two static buffers\n>          * as the return value of this function is fed to error()\n>          * using the unpack_*_errors[] templates we can see above.\n>          */\n>\n> perhaps.\n\nIf you think it helps, I can reroll with such a comment.\nAt the time of fixing up for v4 I felt like it is overly verbose.\nSuch a comment is only useful in understanding the choice of 2.\nI thought it was sufficient in the log as once you're interested in\nthat function you'd read the output of blame anyway.\n\nOn the other hand having statically allocated arrays of fixed size is\ndangerous in terms of maintainability, i.e. down the road someone\nthinks this is a good function to reuse and then they may run into\nsubtle bugs as they will not be aware of the internally static buffer\nthat is overwritten after a certain time.\n\n>\n>> +     static struct strbuf buf[2] = {STRBUF_INIT, STRBUF_INIT};\n>> +     static int super_prefix_len = -1;\n>> +     static unsigned idx = 0;\n>> +\n>\n> If we initialize this to 1 (or even better, \"ARRAY_SIZE(buf) - 1\"),\n> then we would use buf[0] first and then buf[1], which feels more\n> natural to me.\n\nYes I agree, though I overcomplicating things just so that they feel\nmore natural seems wrong as well.\n\nAt the time I assumed that having a static variable initialized to 0\nwas slightly cheaper, as the init code just memsets all of .bss to 0\nunlike the .data segment that has to be crafted manually.\nBut to get that variable into the .bss section reliably we'd have\nto omit the \"=0\". (My compiler recognized that it can be put into\n.bss because it is 0)\n\n>\n> Other than that, this looks OK.  Will queue.\n>\n> Thanks.\n\nThanks,\nStefan\n"},{"id":"309366","messageId":"295f0f45-e5ba-f6fd-57e4-6bf684617f13@gmail.com","threadId":"44844","inReplyTo":"152c0fbf-084c-847f-2a30-a45ea3dd26f2@gmail.com","subject":"Re: [RFC/PATCH 0/4] working tree operations: support superprefix","fromName":"Brian J. Davis","fromEmail":"bitminer@gmail.com","sentAt":"2017-01-13T17:56:26Z","receivedAt":"2017-01-13T17:50:54Z","isPatch":true,"sender":{"key":"bitminer@gmail.com","avatar":null},"body":"Resending original as plain text as git@verger.kernel.org rejected HTML \nencoding as potential virus.  Apologies for dupes in inbox. Hopefully \nthis works.\n\nIn response to a post at:\n\nhttps://groups.google.com/forum/#!topic/git-users/BVLcKHhSUKo\n\nI was asked to post here to explain a potential problem with current \nmodules implementation.  Apologies if I am posting in the wrong place... \nso good bad or otherwise here goes:\n\n+-------------------------------\nWith:\n\ngit push origin branchname\n\nor\n\ngit push server2 branchname\n\nI can push or pull from multiple servers so no problem as git supports this.\n\nNow the problem with use of submodules\n\nsubmodules are listed:\n\nsubmodule.directory_to_\ncheckout/proj1_dir.url=https://git.someserver1/git/proj1_dir \n<https://git.someserver1/git/proj1_dir>\n\nbut if say I want to pull from some server 2 and do a\n\ngit submodule update --init --recursive\n\nwhat I would get is from someserver1 not someserver2 as there is no \n\"origin\" support for submodules.  Is this correct?  If so can origin \nsupport be added to submodules?\n+-------------------------------\n\nSo above was post from google group.  Maybe above is enough to explain \nthe problem that can result, but if not here is a discussion as to why \nthis can be confusing resulting to pushing or pulling from the incorrect \nserver.\n\nLets say projects starts at origin on https://server0.org. Project is \nthen brought in house to server https://indhouse.corp by developer A.\n\nDeveloper A then changes the submodule projects to point to indhouse and \nchanges submodules in super project to point to indhouse so everything \nis great.\n\nThen Developer B clones from indhouse makes changes to submodule1 and \nsubmodule1 and pushes them to indhouse.  Dev A tells Dev B hey thoes \nchanges are great why don't you push to public server0 so every one can \nget thoes changes.  Dev B then git push origin branch_name on submodule1 \nand push origin on submodule 2 and superproject.  And everything is \ngreat ... right?\n\nYes by now those who know git know what dev B  forgot or more to the \npoint what git does not support in a \"clean\" way.  For those who don't \nenter the life of dev C\n\nSo dev C clones from server0 and performs a git submodule update --init \n--recursive.  Now Dev C is on the www and can't see indhouse.corp and \n... kerpow... Dev B and Dev C just experienced one of the many SW mines \non the battlefield.\n\nI ask that git devs first see if I am correct with this assessment as I \ncould be wrong... maybe there is a way of doing this... and if not add a \nfeature to git to handle submodules and multiple origins cleanly.... and \nyes beating dev B with rubber chicken might be a solution though I am \nlooking for a slightly better option.\n"}]}