{"thread":{"id":"27348","subject":"What's cooking in git.git (May 2011, #06; Fri, 13)","startedAt":"2011-05-13T20:03:44Z","lastAt":"2011-05-19T18:21:52Z","messageCount":12,"participants":["Junio C Hamano","Nguyen Thai Ngoc Duy","Jens Lehmann"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"167829","messageId":"7vd3jm74gv.fsf@alter.siamese.dyndns.org","threadId":"27348","inReplyTo":null,"subject":"What's cooking in git.git (May 2011, #06; Fri, 13)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-13T20:03:44Z","receivedAt":"2011-05-13T20:03:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Here are the topics that have been cooking.  Commits prefixed with '-' are\nonly in 'pu' while commits prefixed with '+' are in 'next'.\n\nI am somewhat frustrated that I see almost no reviews on gitweb\npatches. Does this mean nobody is interested in viewing the projects\non gitweb? How can we improve this lack of review bandwidth situation?\n\nThe main part of this cycle is expected to run thru May, aiming for a\nfeature freeze in early June.\n\nWe are about to finish the week #3 of this cycle.\n\n--------------------------------------------------\n[Graduated to \"master\"]\n\n* bf/commit-template-no-cleanup (2011-05-11) 1 commit\n  (merged to 'next' on 2011-05-11 at 01fde0d)\n + Do not strip empty lines / trailing spaces from a commit message template\n\n* cn/log-parse-opt (2011-04-14) 1 commit\n  (merged to 'next' on 2011-04-28 at 02f2eac)\n + log: convert to parse-options\n\n* jc/fix-add-u-unmerged (2011-04-23) 1 commit\n  (merged to 'next' on 2011-04-28 at f7ed821)\n + Fix \"add -u\" that sometimes fails to resolve unmerged paths\n (this branch is used by jc/add-delete-default.)\n\n* jc/t1506-shell-param-expansion-gotcha (2011-05-09) 1 commit\n  (merged to 'next' on 2011-05-11 at 6c8619e)\n + t1507: avoid \"${parameter<op>'word'}\" inside double-quotes\n\n* jh/dirstat-lines (2011-04-29) 8 commits\n  (merged to 'next' on 2011-04-29 at a302674)\n + Mark dirstat error messages for translation\n + Improve error handling when parsing dirstat parameters\n + New --dirstat=lines mode, doing dirstat analysis based on diffstat\n + Allow specifying --dirstat cut-off percentage as a floating point number\n + Add config variable for specifying default --dirstat behavior\n + Refactor --dirstat parsing; deprecate --cumulative and --dirstat-by-file\n + Make --dirstat=0 output directories that contribute < 0.1% of changes\n + Add several testcases for --dirstat and friends\n\n* jn/setup-revisions-glob-and-friends-passthru (2011-04-21) 2 commits\n  (merged to 'next' on 2011-04-28 at 6006cc4)\n + revisions: allow --glob and friends in parse_options-enabled commands\n + revisions: split out handle_revision_pseudo_opt function\n\n* js/maint-1.6.6-send-pack-stateless-rpc-deadlock-fix (2011-05-05) 2 commits\n + send-pack: unbreak push over stateless rpc\n + send-pack: avoid deadlock when pack-object dies early\n (this branch is used by js/maint-send-pack-stateless-rpc-deadlock-fix.)\n\n* js/maint-send-pack-stateless-rpc-deadlock-fix (2011-05-05) 2 commits\n  (merged to 'next' on 2011-05-05 at 3f4ffb9)\n + Merge branch 'js/maint-1.6.6-send-pack-stateless-rpc-deadlock-fix' into js/maint-send-pack-stateless-rpc-deadlock-fix\n  (merged to 'next' on 2011-04-28 at db7e04a)\n + Merge branch 'js/maint-1.6.6-send-pack-stateless-rpc-deadlock-fix' into js/maint-send-pack-stateless-rpc-deadlock-fix\n (this branch uses js/maint-1.6.6-send-pack-stateless-rpc-deadlock-fix.)\n\n* rr/rerere-libify-clear-gc (2011-05-08) 1 commit\n  (merged to 'next' on 2011-05-11 at b1d8c88)\n + rerere: libify rerere_clear() and rerere_gc()\n\nThis is pure code movement.  Changing them to suit the need of other\ncallers can be built on it as separate patches.\n\n--------------------------------------------------\n[New Topics]\n\n* jc/maint-1.6.6-pathspec-stdin-and-cmdline (2011-05-11) 1 commit\n + setup_revisions(): take pathspec from command line and --stdin correctly\n (this branch is used by jc/magic-pathspec, jc/maint-1.7.4-pathspec-stdin-and-cmdline and jc/maint-pathspec-stdin-and-cmdline.)\n\n* jc/maint-1.7.4-pathspec-stdin-and-cmdline (2011-05-11) 1 commit\n - Merge branch 'jc/maint-1.6.6-pathspec-stdin-and-cmdline'\n (this branch uses jc/maint-1.6.6-pathspec-stdin-and-cmdline; is tangled with jc/magic-pathspec and jc/maint-pathspec-stdin-and-cmdline.)\n\n* jc/maint-pathspec-stdin-and-cmdline (2011-05-11) 2 commits\n - Merge branch 'jc/maint-1.7.4-pathspec-stdin-and-cmdline'\n - Merge branch 'jc/maint-1.6.6-pathspec-stdin-and-cmdline'\n (this branch uses jc/maint-1.6.6-pathspec-stdin-and-cmdline; is tangled with jc/magic-pathspec and jc/maint-1.7.4-pathspec-stdin-and-cmdline.)\n\nThese are to fix an ancient bug where feeding \"git log --stdin path\" with\nan input that also has additional pathspec corrupted memory.\n\n* jl/read-tree-m-dry-run (2011-05-11) 1 commit\n - Teach read-tree the -n|--dry-run option\n\nLooked good. We _might_ want to make -n simply ignore -u, though.\n\n* jc/streaming (2011-05-12) 5 commits\n - write_entry(): use streaming API for writing working tree files\n - stream: a streaming interface to read from the object store\n - sha1_object_info_extended(): expose a bit more information from object-info\n - write_entry(): separate two helper functions out\n - packed_object_info_detail(): do not return a string\n (this branch uses jc/convert.)\n\nThe counterpart to jc/bigfile to cover the write-out codepath. This does\nnot yet have \"read directly from pack or loose object without slurping the\nwhole thing in memory\" yet, which is still work in progress.\n\n--------------------------------------------------\n[Stalled]\n\n* mg/diff-stat-count (2011-05-03) 2 commits\n - diff-options.txt: describe --stat-{width,name-width,count}\n - diff: introduce --stat-count to limit the stat lines\n\nThere was a miscounting spotted.  Need another round.\n\n* jn/gitweb-js (2011-04-28) 13 commits\n - gitweb: Make JavaScript ability to adjust timezones configurable\n - gitweb.js: Add UI for selecting common timezone to display dates\n - gitweb: JavaScript ability to adjust time based on timezone\n - gitweb: Unify the way long timestamp is displayed\n - gitweb: Refactor generating of long dates into format_timestamp_html\n - gitweb.js: Provide getElementsByClassName method (if it not exists)\n - gitweb.js: Introduce code to handle cookies from JavaScript\n - gitweb.js: Extract and improve datetime handling\n - gitweb.js: Provide default values for padding in padLeftStr and padLeft\n - gitweb.js: Update and improve comments in JavaScript files\n - gitweb: Split JavaScript for maintability, combining on build\n - Remove gitweb/gitweb.cgi and other legacy targets from main Makefile\n - git-instaweb: Simplify build dependency on gitweb\n\nRerolled.  Waiting for comments.\n\n* jn/ctags-more (2011-04-29) 3 commits\n - gitweb: Optional grouping of projects by category\n - gitweb: Modularized git_get_project_description to be more generic\n - gitweb: Split git_project_list_body in two functions\n\nWaiting for comments.\n\n* jc/require-work-tree-exists (2011-05-08) 1 commit\n - require-work-tree wants more than what its name says\n\nMake \"git pull\" run from a random place work as long as GIT_DIR and\nGIT_WORK_TREE are set up correctly.  I am not absolutely sure if that\nis a sane use case, though. May drop.\n\n* jc/add-delete-default (2011-04-27) 1 commit\n - git add: notice removal of tracked paths by default\n\n* jk/maint-merge-rename-create (2011-03-25) 3 commits\n - merge: turn on rewrite detection\n - merge: handle renames with replacement content\n - t3030: fix accidental success in symlink rename\n\nPeff wanted to reroll this.\n\n* jc/index-pack (2011-02-27) 5 commits\n - index-pack --verify: read anomalous offsets from v2 idx file\n - write_idx_file: need_large_offset() helper function\n - index-pack: --verify\n - write_idx_file: introduce a struct to hold idx customization options\n - index-pack: group the delta-base array entries also by type\n\nStill a WIP. Need to put histogram output into index-pack --verify to\nreally kill verify-pack.\n\n* jc/dotdot-is-parent-directory (2011-05-04) 1 commit\n - specifying ranges: we did not mean to make \"..\" an empty set\n\nUpdated documentation, but I do not feel a strong enough annoyance to push\nthis forward. May drop.\n\n* jk/tag-contains (2010-07-05) 4 commits\n - Why is \"git tag --contains\" so slow?\n - default core.clockskew variable to one day\n - limit \"contains\" traversals based on commit timestamp\n - tag: speed up --contains calculation\n\nThe idea of the bottom one is probably Ok, except that the use of object\nflags needs to be rethought, or at least the helper needs to be moved to\nbuiltin/tag.c to make it clear that it should not be used outside the\ncurrent usage context.\n\n* jc/advice-about-to-lose-commit (2011-05-06) 1 commit\n - checkout: honor advice.detachedHead when reattaching to a branch\n\nNeeds to tighten the advice to only govern the generic How-to part.\n\n--------------------------------------------------\n[Cooking]\n\n* jc/bigfile (2011-05-12) 3 commits\n - Bigfile: teach \"git add\" to send a large file straight to a pack\n - index_fd(): split into two helper functions\n - index_fd(): turn write_object and format_check arguments into one flag\n\nThis covers the entry point for a big file to the system. Other parts that\nneed to know about them are the exit point (i.e. write_entry()), packing\nand repacking (as long as bigfilethreshold is sane this should work),\ndiffs and status (avoid slurping large binary in core only to do nothing,\nwhich we already should), and transport (receive-pack/fetch-pack call\neither unpack-objects or index-pack, which still want to hold the full\nobject in-core and need to be fixed).\n\n* jc/convert (2011-05-09) 4 commits\n - convert: make it harder to screw up adding a conversion attribute\n - convert: make it safer to add conversion attributes\n - convert: give saner names to crlf/eol variables, types and functions\n - convert: rename the \"eol\" global variable to \"core_eol\"\n (this branch is used by jc/streaming.)\n\nJust a clean-up.\nWill merge to \"next\" by the end of week #3.\n\n* jk/blame-line-porcelain (2011-05-09) 3 commits\n - blame: add --line-porcelain output format\n - blame: refactor porcelain output\n - add tests for various blame formats\n\n* ms/tagname-does-not-begin-with-dash (2011-05-10) 1 commit\n - tag: disallow '-' as tag name\n\nWill merge to \"next\" by the end of week #3.\n\n* fc/completion-zsh (2011-05-10) 1 commit\n + git-completion: fix regression in zsh support\n (this branch is used by sg/completion-updates.)\n\n* nd/sparse-co-fix (2011-05-10) 2 commits\n - sparse checkout: do not eagerly decide the fate for whole directory\n - t1011: fix sparse-checkout initialization and add new file\n\n* kk/maint-prefix-in-config-mak (2011-05-09) 3 commits\n  (merged to 'next' on 2011-05-09 at 267a3aa)\n + Honor $(prefix) set in config.mak* when defining ETC_GIT*\n + Revert \"Honor $(prefix) set in config.mak* when defining ETC_GIT* and sysconfdir\"\n  (merged to 'next' on 2011-05-02 at c747ba3)\n + Honor $(prefix) set in config.mak* when defining ETC_GIT* and sysconfdir\n\nOne revert and replace the whole thing from J6t. The end result looked\nreasonable.\n\nWill merge to \"master\" by the end of week #4.\n\n* ci/commit--interactive-atomic (2011-05-10) 6 commits\n  (merged to 'next' on 2011-05-11 at 7f36fd8)\n + Test atomic git-commit --interactive\n + Add commit to list of config.singlekey commands\n + Add support for -p/--patch to git-commit\n + Allow git commit --interactive with paths\n + t7501.8: feed a meaningful command\n + Use a temporary index for git commit --interactive\n\nWill merge to \"master\" by the end of week #4.\n\n* ab/i18n-scripts (2011-05-08) 48 commits\n - i18n: git-bisect bisect_next_check \"You need to\" message\n - i18n: git-bisect [Y/n] messages\n - i18n: git-bisect bisect_replay + $1 messages\n - i18n: git-bisect bisect_reset + $1 messages\n - i18n: git-bisect bisect_run + $@ messages\n - i18n: git-bisect die + eval_gettext messages\n - i18n: git-bisect die + gettext messages\n - i18n: git-bisect echo + eval_gettext message\n - i18n: git-bisect echo + gettext messages\n - i18n: git-bisect gettext + echo message\n - i18n: git-bisect add git-sh-i18n\n - i18n: git-stash drop_stash say/die messages\n - i18n: git-stash \"unknown option\" message\n - i18n: git-stash die + eval_gettext $1 messages\n - i18n: git-stash die + eval_gettext $* messages\n - i18n: git-stash die + eval_gettext messages\n - i18n: git-stash die + gettext messages\n - i18n: git-stash say + gettext messages\n - i18n: git-stash echo + gettext message\n - i18n: git-stash add git-sh-i18n\n - i18n: git-submodule \"blob\" and \"submodule\" messages\n - i18n: git-submodule \"path not initialized\" message\n - i18n: git-submodule \"[...] path is ignored\" message\n - i18n: git-submodule \"Entering [...]\" message\n - i18n: git-submodule $errmsg messages\n - i18n: git-submodule \"Submodule change[...]\" messages\n - i18n: git-submodule \"cached cannot be used\" message\n - i18n: git-submodule $update_module say + die messages\n - i18n: git-submodule die + eval_gettext messages\n - i18n: git-submodule say + eval_gettext messages\n - i18n: git-submodule echo + eval_gettext messages\n - i18n: git-submodule add git-sh-i18n\n - i18n: git-pull eval_gettext + warning message\n - i18n: git-pull eval_gettext + die message\n - i18n: git-pull die messages\n - i18n: git-pull add git-sh-i18n\n - i18n: git-am printf(1) message to eval_gettext\n - i18n: git-am core say messages\n - i18n: git-am \"Falling back\" say message\n - i18n: git-am \"Apply?\" message\n - i18n: git-am clean_abort messages\n - i18n: git-am cannot_fallback messages\n - i18n: git-am die messages\n - i18n: git-am echo + gettext message\n - i18n: git-am eval_gettext messages\n - i18n: git-am multi-line getttext $msg; echo\n - i18n: git-am one-line gettext $msg; echo\n - i18n: git-am add git-sh-i18n\n (this branch uses ab/i18n-scripts-basic.)\n\n* ab/i18n-scripts-basic (2011-05-08) 4 commits\n - Makefile: add xgettext target for *.sh files\n - git-sh-i18n.sh: add GIT_GETTEXT_POISON support\n - git-sh-i18n.sh: add no-op gettext() and eval_gettext() wrappers\n - git-sh-i18n--envsubst: our own envsubst(1) for eval_gettext()\n (this branch is used by ab/i18n-scripts.)\n\nWill be re-rolled to work around systems whose environment variable names\nare case insensitive.\n\n* mg/merge-ff-config (2011-05-06) 3 commits\n  (merged to 'next' on 2011-05-08 at 977b432)\n + tests: check git does not barf on merge.ff values for future versions of git\n + merge: introduce merge.ff configuration variable\n + Merge branch 'jc/maint-branch-mergeoptions' into mg/merge-ff-config\n\nWill merge to \"master\" by the end of week #4.\n\n* mk/grep-pcre (2011-05-09) 10 commits\n - git-grep: do not die upon -F/-P when grep.extendedRegexp is set.\n - git-grep: Bail out when -P is used with -F or -E\n - grep: Add basic tests\n - configure: Check for libpcre\n - git-grep: Learn PCRE\n - grep: Extract compile_regexp_failed() from compile_regexp()\n - grep: Fix a typo in a comment\n  (merged to 'next' on 2011-05-08 at 5d3bede)\n + grep: Put calls to fixmatch() and regmatch() into patmatch()\n + contrib/completion: --line-number to git grep\n + Documentation: Add --line-number to git-grep synopsis\n\nWill merge to \"next\" by the end of week #3.\n\n* sg/completion-updates (2011-05-10) 4 commits\n  (merged to 'next' on 2011-05-10 at eaf5398)\n + Merge branch 'fc/completion-zsh' into sg/completion-updates\n + Revert \"completion: don't declare 'local words' to make zsh happy\"\n  (merged to 'next' on 2011-05-08 at 761178c)\n + completion: move private shopt shim for zsh to __git_ namespace\n  (merged to 'next' on 2011-05-02 at 0fd443a)\n + completion: don't declare 'local words' to make zsh happy\n (this branch uses fc/completion-zsh.)\n\nThis reverts the \"local words only on bash\" thingy and uses the\nworkaround blessed by zsh folks instead.\n\nWill merge to \"master\" by the end of week #4.\n\n* ld/p4-preserve-user-names (2011-05-10) 3 commits\n - git-p4: warn if git authorship won't be retained\n  (merged to 'next' on 2011-05-11 at bc14314)\n + git-p4: small improvements to user-preservation\n  (merged to 'next' on 2011-04-29 at 25116c8)\n + git-p4: add option to preserve user names\n\nA re-roll of the tip one looked good but did not come in time for\nmorning cycle today.\n\nWill merge to \"next\".\n\n* jc/magic-pathspec (2011-05-12) 13 commits\n  (merged to 'next' on 2011-05-12 at 656c8b5)\n + t3703: Skip tests using directory name \":\" on Windows\n  (merged to 'next' on 2011-05-11 at 86d1d6d)\n + revision.c: leave a note for \"a lone :\" enhancement\n + Merge branch 'jc/maint-1.6.6-pathspec-stdin-and-cmdline'\n  (merged to 'next' on 2011-05-11 at aaad95e)\n + t3703, t4208: add test cases for magic pathspec\n + rev/path disambiguation: further restrict \"misspelled index entry\" diag\n + fix overslow :/no-such-string-ever-existed diagnostics\n + fix overstrict :<path> diagnosis\n + grep: use get_pathspec() correctly\n + pathspec: drop \"lone : means no pathspec\" from get_pathspec()\n + Revert \"magic pathspec: add \":(icase)path\" to match case insensitively\"\n  (merged to 'next' on 2011-04-25 at 788cd46)\n + magic pathspec: add \":(icase)path\" to match case insensitively\n + magic pathspec: futureproof shorthand form\n + magic pathspec: add tentative \":/path/from/top/level\" pathspec support\n (this branch uses jc/maint-1.6.6-pathspec-stdin-and-cmdline; is tangled with jc/maint-1.7.4-pathspec-stdin-and-cmdline and jc/maint-pathspec-stdin-and-cmdline.)\n\nThis seems to need more time to mature than I expected.\n"},{"id":"167835","messageId":"BANLkTimHdZ_9PUg509Yb7g2Oyp3qk0cKdA@mail.gmail.com","threadId":"27348","inReplyTo":"7vd3jm74gv.fsf@alter.siamese.dyndns.org","subject":"Re: What's cooking in git.git (May 2011, #06; Fri, 13)","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-05-14T03:03:30Z","receivedAt":"2011-05-14T03:03:30Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sat, May 14, 2011 at 3:03 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> * jc/streaming (2011-05-12) 5 commits\n>  - write_entry(): use streaming API for writing working tree files\n>  - stream: a streaming interface to read from the object store\n>  - sha1_object_info_extended(): expose a bit more information from object-info\n>  - write_entry(): separate two helper functions out\n>  - packed_object_info_detail(): do not return a string\n>  (this branch uses jc/convert.)\n>\n> The counterpart to jc/bigfile to cover the write-out codepath. This does\n> not yet have \"read directly from pack or loose object without slurping the\n> whole thing in memory\" yet, which is still work in progress.\n\nYou haven't sent this to git@vger, or it failed to deliver to me.\n\nAnyway, do you plan to extend sha1_object_info_extended() further, to\nsupport external storage too (git-annex way for example)?\n-- \nDuy\n"},{"id":"167855","messageId":"7vsjsh5gjw.fsf@alter.siamese.dyndns.org","threadId":"27348","inReplyTo":"BANLkTimHdZ_9PUg509Yb7g2Oyp3qk0cKdA@mail.gmail.com","subject":"Re: What's cooking in git.git (May 2011, #06; Fri, 13)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-14T17:37:55Z","receivedAt":"2011-05-14T17:37:55Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:\n\n>> The counterpart to jc/bigfile to cover the write-out codepath. This does\n>> not yet have \"read directly from pack or loose object without slurping the\n>> whole thing in memory\" yet, which is still work in progress.\n>\n> You haven't sent this to git@vger, or it failed to deliver to me.\n\nThat is because it is still in flux and not ready for public viewing yet.\n\n> Anyway, do you plan to extend sha1_object_info_extended() further...\n\nBy definition a topic that is still in flux does not have concrete plans\nfor everything. I haven't gone far enough to be interested in adding a\nsupport for something the other parts of the system do not support.\n\nIt is a lot more important to support the data types and representations\nthat are supported by the other parts of the system already, and fill the\nmissing parts. \"git add\" will learn to handle huge blobs natively in the\njc/bigfile topic. This topic is about handling huge blobs in the checkout\ncodepath. Without it, the system is useless if you cannot check them out\neven if you can add them.\n\nThe sending side of \"git push\" (aka \"send-pack\") and \"git fetch\" (aka\n\"upload-pack\") should also be Ok because pack-objects has known to handle\nlarge blob in a pack by copying the bits straight without re-deltifying.\n\nI however think the receiving end still wants to hold everything in core.\nIt would be the natural next thing to fix around this area before doing\nanything else. If somebody is interested, look at the receiving end\n(\"index-pack\" and \"unpack-objects\") while I am still busy in this topic.\n\nMultiple people working on separate independent areas who share a\nreasonably narrow common agenda tend to speed up the development.  At the\nvery end of Linus era of git, after he wrote pack-objects, he worked on\nthe object transfer protocols and unpack-objects, and I took the local use\nof the data in packed objects in read_sha1_file() codepath. There weren't\nmuch overlap or conflicting design decision in our works, and it turned\nout great. The common agenda in this case was to make the new object\nrepresentation (i.e. packs) useful throughout the system.\n\nOn the other hand, multiple people working in a similar area with\ndifferent agenda tend to step on each other's toes.\n"},{"id":"167879","messageId":"BANLkTi=TW=8_-Vrh=h1LekPTFzQOzZj-iw@mail.gmail.com","threadId":"27348","inReplyTo":"7vsjsh5gjw.fsf@alter.siamese.dyndns.org","subject":"Re: What's cooking in git.git (May 2011, #06; Fri, 13)","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-05-15T04:51:00Z","receivedAt":"2011-05-15T04:51:00Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sun, May 15, 2011 at 12:37 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> The sending side of \"git push\" (aka \"send-pack\") and \"git fetch\" (aka\n> \"upload-pack\") should also be Ok because pack-objects has known to handle\n> large blob in a pack by copying the bits straight without re-deltifying.\n\nSending a lot increases chance of unexpected disconnecting. But that's\nnot the focus now.\n\n> I however think the receiving end still wants to hold everything in core.\n> It would be the natural next thing to fix around this area before doing\n> anything else. If somebody is interested, look at the receiving end\n> (\"index-pack\" and \"unpack-objects\") while I am still busy in this topic.\n\nI looked at index-pack before. Will see how to fix it (that is if I'm\nnot busy with pathspec stuff)\n-- \nDuy\n"},{"id":"167898","messageId":"4DD0043D.1050101@web.de","threadId":"27348","inReplyTo":"7vd3jm74gv.fsf@alter.siamese.dyndns.org","subject":"Re: What's cooking in git.git (May 2011, #06; Fri, 13)","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2011-05-15T16:50:05Z","receivedAt":"2011-05-15T16:50:05Z","isPatch":false,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 13.05.2011 22:03, schrieb Junio C Hamano:\n> * jl/read-tree-m-dry-run (2011-05-11) 1 commit\n>  - Teach read-tree the -n|--dry-run option\n> \n> Looked good. We _might_ want to make -n simply ignore -u, though.\n\nFine by me. Do you want me to send an updated version? If so,\nshould a warning be issued in that case or should that just\nhappen silently?\n"},{"id":"167918","messageId":"7vfwofpvai.fsf@alter.siamese.dyndns.org","threadId":"27348","inReplyTo":"4DD0043D.1050101@web.de","subject":"Re: What's cooking in git.git (May 2011, #06; Fri, 13)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-15T20:23:49Z","receivedAt":"2011-05-15T20:23:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jens Lehmann <Jens.Lehmann@web.de> writes:\n\n> Am 13.05.2011 22:03, schrieb Junio C Hamano:\n>> * jl/read-tree-m-dry-run (2011-05-11) 1 commit\n>>  - Teach read-tree the -n|--dry-run option\n>> \n>> Looked good. We _might_ want to make -n simply ignore -u, though.\n>\n> Fine by me. Do you want me to send an updated version? If so,\n> should a warning be issued in that case or should that just\n> happen silently?\n\nLater we _may_ have a condition where \"read-tree -m\" with some options\n(except \"-n\") may succeed but \"read-tree -m -u\" with the same other\noptions may fail, and the reason to have \"-n\" is so that the caller can\ntell if the operation may or may not fail in advance without changing the\nstate. Singling out \"do not write INDEX\" was a mistake to begin with.\n\nHow about \"simply ignore\" aka \"silently\"?  We do not even have to make it\nsound like an user error, if we explain the option like this.\n\nI think the change to the implementation would be trivial, but you would\nprobably want to update the tests in 1002 (remove the one at the end that\nchecks -u/-n incompatibility, and perhaps make sure \"-n -u\" combination\ndoes not touch anything as advertised).\n\nThanks.\n\ndiff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt\nindex a35849f..46a96f2 100644\n--- a/Documentation/git-read-tree.txt\n+++ b/Documentation/git-read-tree.txt\n@@ -55,8 +55,8 @@ OPTIONS\n \n -n::\n --dry-run::\n-\tDon't write the index file. This option isn't allowed together\n-\twith -u.\n+\tCheck if the command would error out, without updating the index\n+\tnor the files in the working tree for real.\n \n -v::\n \tShow the progress of checking files out.\n"},{"id":"168078","messageId":"4DD2CFD4.7060508@web.de","threadId":"27348","inReplyTo":"7vfwofpvai.fsf@alter.siamese.dyndns.org","subject":"[WIP PATCH] Teach read-tree the -n|--dry-run option","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2011-05-17T19:43:16Z","receivedAt":"2011-05-17T19:43:16Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Using this option tells read-tree to not update the index. That makes it\npossible to check if updating the index would be successful without\nchanging anything. Using this option will silently ignore -u.\n\nThe relevant tests in the t10?? range were extended to do a read-tree -n\nbefore the real read-tree to make sure neither the index nor any local\nfiles were changed with -n and the same exit code as without -n is\nreturned.\n\nSigned-off-by: Jens Lehmann <Jens.Lehmann@web.de>\n---\n\nAm 15.05.2011 22:23, schrieb Junio C Hamano:\n> Later we _may_ have a condition where \"read-tree -m\" with some options\n> (except \"-n\") may succeed but \"read-tree -m -u\" with the same other\n> options may fail, and the reason to have \"-n\" is so that the caller can\n> tell if the operation may or may not fail in advance without changing the\n> state. Singling out \"do not write INDEX\" was a mistake to begin with.\n> \n> I think the change to the implementation would be trivial, but you would\n> probably want to update the tests in 1002 (remove the one at the end that\n> checks -u/-n incompatibility, and perhaps make sure \"-n -u\" combination\n> does not touch anything as advertised).\n\nI added two convenience functions read_tree_u_must_[succeed|fail]() which\nwork pretty much the way read_tree_must_[succeed|fail]() do but with the\nadded functionality that they check git diff-files before and after the\nread-tree -n too.\n\nI went through all the test cases in the t10?? range and replaced every\nrelevant call to \"git read-tree\" with a call to one of those functions\n(the only exception being plain resets of the work tree in tests that did\nnot test read-tree themselves).\n\nThe only exceptions where I could not make that replacement without\nbreaking a test were:\n\n* t1001:381 (#25) new file conflicts with untracked directory\n  This should have been detected by verify_absent_1(), but that function\n  is left early when opts->update is 0. Will look into that.\n\n* t1004:209 (#13) unlinking an un-unlink-able symlink\n  This is an issue of wrong directory permissions, it should be ok that\n  -n doesn't detect this as this is not a version control issue. I will\n  document that in the commit message.\n\n* 1011:95  (#5)  read-tree with empty .git/info/sparse-checkout\n* t1011:163 (#11) read-tree updates worktree, dirty case\n  Not sure about those two as I haven't got much experience with sparse\n  checkout. Will dig further, pointers welcome.\n\nApart from these four all other tests look good.\n\n\n Documentation/git-read-tree.txt      |    5 ++\n builtin/read-tree.c                  |    7 ++-\n t/t1000-read-tree-m-3way.sh          |   96 ++++++++++++++++++++--------------\n t/t1001-read-tree-m-2way.sh          |   61 ++++++++++++++-------\n t/t1002-read-tree-m-u-2way.sh        |   91 ++++++++++++++++++--------------\n t/t1004-read-tree-m-u-wf.sh          |   44 ++++++++++++----\n t/t1005-read-tree-reset.sh           |   23 ++++++--\n t/t1008-read-tree-overlay.sh         |   10 +++-\n t/t1011-read-tree-sparse-checkout.sh |   33 ++++++++----\n t/t1012-read-tree-df.sh              |   19 +++++--\n t/t1020-subdirectory.sh              |   15 +++++-\n 11 files changed, 266 insertions(+), 138 deletions(-)\n\ndiff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt\nindex 26fdadc..46a96f2 100644\n--- a/Documentation/git-read-tree.txt\n+++ b/Documentation/git-read-tree.txt\n@@ -53,6 +53,11 @@ OPTIONS\n \ttrees that are not directly related to the current\n \tworking tree status into a temporary index file.\n\n+-n::\n+--dry-run::\n+\tCheck if the command would error out, without updating the index\n+\tnor the files in the working tree for real.\n+\n -v::\n \tShow the progress of checking files out.\n\ndiff --git a/builtin/read-tree.c b/builtin/read-tree.c\nindex 93c9281..c0da227 100644\n--- a/builtin/read-tree.c\n+++ b/builtin/read-tree.c\n@@ -98,7 +98,7 @@ static struct lock_file lock_file;\n\n int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n {\n-\tint i, newfd, stage = 0;\n+\tint i, newfd, stage = 0, dry_run = 0;\n \tunsigned char sha1[20];\n \tstruct tree_desc t[MAX_UNPACK_TREES];\n \tstruct unpack_trees_options opts;\n@@ -130,6 +130,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t\t  PARSE_OPT_NONEG, exclude_per_directory_cb },\n \t\tOPT_SET_INT('i', NULL, &opts.index_only,\n \t\t\t    \"don't check the working tree after merging\", 1),\n+\t\tOPT__DRY_RUN(&dry_run, \"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    \"skip applying sparse checkout filter\", 1),\n \t\tOPT_SET_INT(0, \"debug-unpack\", &opts.debug_unpack,\n@@ -183,6 +184,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t\tdie(\"--exclude-per-directory is meaningless unless -u\");\n \tif (opts.merge && !opts.index_only)\n \t\tsetup_work_tree();\n+\tif (opts.update && dry_run)\n+\t\topts.update = 0;\n\n \tif (opts.merge) {\n \t\tif (stage < 2)\n@@ -219,7 +222,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \tif (unpack_trees(nr_trees, t, &opts))\n \t\treturn 128;\n\n-\tif (opts.debug_unpack)\n+\tif (opts.debug_unpack || dry_run)\n \t\treturn 0; /* do not write the index out */\n\n \t/*\ndiff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh\nindex ca8a409..a386cfd 100755\n--- a/t/t1000-read-tree-m-3way.sh\n+++ b/t/t1000-read-tree-m-3way.sh\n@@ -131,13 +131,29 @@ check_result () {\n     test_cmp expected current\n }\n\n+read_tree_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    git read-tree \"$@\"\n+}\n+\n+read_tree_must_fail () {\n+    git ls-files -s >pre-dry-run &&\n+    test_must_fail git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_must_fail git read-tree \"$@\"\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-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n # This starts out with the first head, which is the normal\n@@ -146,9 +162,9 @@ 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-     git read-tree $tree_A &&\n+     read_tree_must_succeed $tree_A &&\n      git checkout-index -f -u -a &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n : <<\\END_OF_CASE_TABLE\n@@ -211,7 +227,7 @@ 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-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -219,7 +235,7 @@ test_expect_success \\\n     \"rm -f .git/index NA &&\n      cp .orig-B/NA NA &&\n      git update-index --add NA &&\n-     git read-tree -m $tree_O $tree_A $tree_B\"\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@@ -227,14 +243,14 @@ test_expect_success \\\n      cp .orig-B/NA NA &&\n      git update-index --add NA &&\n      echo extra >>NA &&\n-     git read-tree -m $tree_O $tree_A $tree_B\"\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-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -243,7 +259,7 @@ test_expect_success \\\n      cp .orig-A/AN AN &&\n      git update-index --add AN &&\n      echo extra >>AN &&\n-     git read-tree -m $tree_O $tree_A $tree_B\"\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@@ -251,7 +267,7 @@ test_expect_success \\\n      cp .orig-A/AN AN &&\n      echo extra >>AN &&\n      git update-index --add AN &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -259,7 +275,7 @@ test_expect_success \\\n     \"rm -f .git/index AA &&\n      cp .orig-A/AA AA &&\n      git update-index --add AA &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -268,7 +284,7 @@ test_expect_success \\\n      cp .orig-A/AA AA &&\n      git update-index --add AA &&\n      echo extra >>AA &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -277,7 +293,7 @@ test_expect_success \\\n      cp .orig-A/AA AA &&\n      echo extra >>AA &&\n      git update-index --add AA &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -285,7 +301,7 @@ test_expect_success \\\n     \"rm -f .git/index LL &&\n      cp .orig-A/LL LL &&\n      git update-index --add LL &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -294,7 +310,7 @@ test_expect_success \\\n      cp .orig-A/LL LL &&\n      git update-index --add LL &&\n      echo extra >>LL &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -303,7 +319,7 @@ test_expect_success \\\n      cp .orig-A/LL LL &&\n      echo extra >>LL &&\n      git update-index --add LL &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -311,7 +327,7 @@ test_expect_success \\\n      rm -f .git/index DD &&\n      echo DD >DD &&\n      git update-index --add DD &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -319,7 +335,7 @@ test_expect_success \\\n      rm -f .git/index DM &&\n      cp .orig-B/DM DM &&\n      git update-index --add DM &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -327,7 +343,7 @@ test_expect_success \\\n      rm -f .git/index DN &&\n      cp .orig-B/DN DN &&\n      git update-index --add DN &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -335,7 +351,7 @@ test_expect_success \\\n     \"rm -f .git/index MD &&\n      cp .orig-A/MD MD &&\n      git update-index --add MD &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -344,7 +360,7 @@ test_expect_success \\\n      cp .orig-A/MD MD &&\n      git update-index --add MD &&\n      echo extra >>MD &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -353,7 +369,7 @@ test_expect_success \\\n      cp .orig-A/MD MD &&\n      echo extra >>MD &&\n      git update-index --add MD &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -361,7 +377,7 @@ test_expect_success \\\n     \"rm -f .git/index ND &&\n      cp .orig-A/ND ND &&\n      git update-index --add ND &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -370,7 +386,7 @@ test_expect_success \\\n      cp .orig-A/ND ND &&\n      git update-index --add ND &&\n      echo extra >>ND &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -379,7 +395,7 @@ test_expect_success \\\n      cp .orig-A/ND ND &&\n      echo extra >>ND &&\n      git update-index --add ND &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -387,7 +403,7 @@ test_expect_success \\\n     \"rm -f .git/index MM &&\n      cp .orig-A/MM MM &&\n      git update-index --add MM &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -396,7 +412,7 @@ test_expect_success \\\n      cp .orig-A/MM MM &&\n      git update-index --add MM &&\n      echo extra >>MM &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -405,7 +421,7 @@ test_expect_success \\\n      cp .orig-A/MM MM &&\n      echo extra >>MM &&\n      git update-index --add MM &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -413,7 +429,7 @@ test_expect_success \\\n     \"rm -f .git/index SS &&\n      cp .orig-A/SS SS &&\n      git update-index --add SS &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -422,7 +438,7 @@ test_expect_success \\\n      cp .orig-A/SS SS &&\n      git update-index --add SS &&\n      echo extra >>SS &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -431,7 +447,7 @@ test_expect_success \\\n      cp .orig-A/SS SS &&\n      echo extra >>SS &&\n      git update-index --add SS &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -439,7 +455,7 @@ test_expect_success \\\n     \"rm -f .git/index MN &&\n      cp .orig-A/MN MN &&\n      git update-index --add MN &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -448,7 +464,7 @@ test_expect_success \\\n      cp .orig-A/MN MN &&\n      git update-index --add MN &&\n      echo extra >>MN &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -456,7 +472,7 @@ test_expect_success \\\n     \"rm -f .git/index NM &&\n      cp .orig-A/NM NM &&\n      git update-index --add NM &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -465,7 +481,7 @@ test_expect_success \\\n      cp .orig-B/NM NM &&\n      git update-index --add NM &&\n      echo extra >>NM &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -474,7 +490,7 @@ test_expect_success \\\n      cp .orig-A/NM NM &&\n      git update-index --add NM &&\n      echo extra >>NM &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -483,7 +499,7 @@ test_expect_success \\\n      cp .orig-A/NM NM &&\n      echo extra >>NM &&\n      git update-index --add NM &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n test_expect_success \\\n@@ -491,7 +507,7 @@ test_expect_success \\\n     \"rm -f .git/index NN &&\n      cp .orig-A/NN NN &&\n      git update-index --add NN &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -500,7 +516,7 @@ test_expect_success \\\n      cp .orig-A/NN NN &&\n      git update-index --add NN &&\n      echo extra >>NN &&\n-     git read-tree -m $tree_O $tree_A $tree_B &&\n+     read_tree_must_succeed -m $tree_O $tree_A $tree_B &&\n      check_result\"\n\n test_expect_success \\\n@@ -509,7 +525,7 @@ test_expect_success \\\n      cp .orig-A/NN NN &&\n      echo extra >>NN &&\n      git update-index --add NN &&\n-     test_must_fail git read-tree -m $tree_O $tree_A $tree_B\n+     read_tree_must_fail -m $tree_O $tree_A $tree_B\n \"\n\n # #16\n@@ -522,7 +538,7 @@ test_expect_success \\\n     echo E16 >F16 &&\n     git update-index F16 &&\n     tree1=`git write-tree` &&\n-    git read-tree -m $tree0 $tree1 $tree1 $tree0 &&\n+    read_tree_must_succeed -m $tree0 $tree1 $tree1 $tree0 &&\n     git ls-files --stage'\n\n test_done\ndiff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh\nindex 680d992..54e69ce 100755\n--- a/t/t1001-read-tree-m-2way.sh\n+++ b/t/t1001-read-tree-m-2way.sh\n@@ -48,6 +48,25 @@ check_cache_at () {\n \tesac\n }\n\n+read_tree_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    git read-tree \"$@\"\n+}\n+\n+read_tree_u_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git diff-files >pre-dry-run-wt &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    git diff-files >post-dry-run-wt &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_cmp pre-dry-run-wt post-dry-run-wt &&\n+    git read-tree \"$@\"\n+}\n+\n cat >bozbar-old <<\\EOF\n This is a sample file used in two-way fast-forward merge\n tests.  Its second line ends with a magic word bozbar\n@@ -94,7 +113,7 @@ echo '+100644 X 0\tyomin' >expected\n test_expect_success \\\n     '4 - carry forward local addition.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -106,7 +125,7 @@ test_expect_success \\\n test_expect_success \\\n     '5 - carry forward local addition.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -120,7 +139,7 @@ test_expect_success \\\n test_expect_success \\\n     '6 - local addition already has the same.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -131,7 +150,7 @@ test_expect_success \\\n test_expect_success \\\n     '7 - local addition already has the same.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -144,7 +163,7 @@ test_expect_success \\\n test_expect_success \\\n     '8 - conflicting addition.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -153,7 +172,7 @@ test_expect_success \\\n test_expect_success \\\n     '9 - conflicting addition.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -163,7 +182,7 @@ test_expect_success \\\n test_expect_success \\\n     '10 - path removed.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -174,7 +193,7 @@ test_expect_success \\\n test_expect_success \\\n     '11 - dirty path removed.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -184,7 +203,7 @@ test_expect_success \\\n test_expect_success \\\n     '12 - unmatching local changes being removed.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -193,7 +212,7 @@ test_expect_success \\\n test_expect_success \\\n     '13 - unmatching local changes being removed.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -208,7 +227,7 @@ EOF\n test_expect_success \\\n     '14 - unchanged in two heads.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -221,7 +240,7 @@ test_expect_success \\\n test_expect_success \\\n     '15 - unchanged in two heads.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -235,7 +254,7 @@ test_expect_success \\\n test_expect_success \\\n     '16 - conflicting local change.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -244,7 +263,7 @@ test_expect_success \\\n test_expect_success \\\n     '17 - conflicting local change.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -254,7 +273,7 @@ test_expect_success \\\n test_expect_success \\\n     '18 - local change already having a good result.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -266,7 +285,7 @@ test_expect_success \\\n test_expect_success \\\n     '19 - local change already having a good result, further modified.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -279,7 +298,7 @@ test_expect_success \\\n test_expect_success \\\n     '20 - no local change, use new tree.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -291,7 +310,7 @@ test_expect_success \\\n test_expect_success \\\n     '21 - no local change, dirty cache.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -302,7 +321,7 @@ test_expect_success \\\n test_expect_success \\\n     '22 - local change cache updated.' \\\n     'rm -f .git/index &&\n-     git read-tree $treeH &&\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@@ -386,7 +405,7 @@ test_expect_success \\\n\n test_expect_success \\\n     'a/b vs a, plus c/d case test.' \\\n-    'git read-tree -u -m \"$treeH\" \"$treeM\" &&\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\n@@ -401,7 +420,7 @@ test_expect_success '-m references the correct modified tree' '\n \techo a >file-a &&\n \tgit add file-a &&\n \tgit ls-tree $(git write-tree) file-a >expect &&\n-\tgit read-tree -m HEAD initial-mod &&\n+\tread_tree_must_succeed -m HEAD initial-mod &&\n \tgit ls-tree $(git write-tree) file-a >actual &&\n \ttest_cmp expect actual\n '\ndiff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh\nindex a4a17e0..9211711 100755\n--- a/t/t1002-read-tree-m-u-2way.sh\n+++ b/t/t1002-read-tree-m-u-2way.sh\n@@ -33,6 +33,17 @@ check_cache_at () {\n \tesac\n }\n\n+read_tree_u_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git diff-files >pre-dry-run-wt &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    git diff-files >post-dry-run-wt &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_cmp pre-dry-run-wt post-dry-run-wt &&\n+    git read-tree \"$@\"\n+}\n+\n test_expect_success \\\n     setup \\\n     'echo frotz >frotz &&\n@@ -56,8 +67,8 @@ test_expect_success \\\n test_expect_success \\\n     '1, 2, 3 - no carry forward' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >1-3.out &&\n      cmp M.out 1-3.out &&\n      sum bozbar frotz nitfol >actual3.sum &&\n@@ -69,11 +80,11 @@ test_expect_success \\\n test_expect_success \\\n     '4 - carry forward local addition.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo \"+100644 X 0\tyomin\" >expected &&\n      echo yomin >yomin &&\n      git update-index --add yomin &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >4.out || return 1\n      git diff -U0 --no-index M.out 4.out >4diff.out\n      compare_change 4diff.out expected &&\n@@ -87,12 +98,12 @@ test_expect_success \\\n test_expect_success \\\n     '5 - carry forward local addition.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n-     git read-tree -m -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n+     read_tree_u_must_succeed -m -u $treeH &&\n      echo yomin >yomin &&\n      git update-index --add yomin &&\n      echo yomin yomin >yomin &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >5.out || return 1\n      git diff -U0 --no-index M.out 5.out >5diff.out\n      compare_change 5diff.out expected &&\n@@ -107,10 +118,10 @@ test_expect_success \\\n test_expect_success \\\n     '6 - local addition already has the same.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo frotz >frotz &&\n      git update-index --add frotz &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >6.out &&\n      test_cmp M.out 6.out &&\n      check_cache_at frotz clean &&\n@@ -123,11 +134,11 @@ test_expect_success \\\n test_expect_success \\\n     '7 - local addition already has the same.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo frotz >frotz &&\n      git update-index --add frotz &&\n      echo frotz frotz >frotz &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >7.out &&\n      test_cmp M.out 7.out &&\n      check_cache_at frotz dirty &&\n@@ -141,27 +152,27 @@ test_expect_success \\\n test_expect_success \\\n     '8 - conflicting addition.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo frotz frotz >frotz &&\n      git update-index --add frotz &&\n-     if git read-tree -m -u $treeH $treeM; then false; else :; fi'\n+     if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'\n\n test_expect_success \\\n     '9 - conflicting addition.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo frotz frotz >frotz &&\n      git update-index --add frotz &&\n      echo frotz >frotz &&\n-     if git read-tree -m -u $treeH $treeM; then false; else :; fi'\n+     if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'\n\n test_expect_success \\\n     '10 - path removed.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo rezrov >rezrov &&\n      git update-index --add rezrov &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >10.out &&\n      cmp M.out 10.out &&\n      sum bozbar frotz nitfol >actual10.sum &&\n@@ -170,28 +181,28 @@ test_expect_success \\\n test_expect_success \\\n     '11 - dirty path removed.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo rezrov >rezrov &&\n      git update-index --add rezrov &&\n      echo rezrov rezrov >rezrov &&\n-     if git read-tree -m -u $treeH $treeM; then false; else :; fi'\n+     if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'\n\n test_expect_success \\\n     '12 - unmatching local changes being removed.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo rezrov rezrov >rezrov &&\n      git update-index --add rezrov &&\n-     if git read-tree -m -u $treeH $treeM; then false; else :; fi'\n+     if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'\n\n test_expect_success \\\n     '13 - unmatching local changes being removed.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo rezrov rezrov >rezrov &&\n      git update-index --add rezrov &&\n      echo rezrov >rezrov &&\n-     if git read-tree -m -u $treeH $treeM; then false; else :; fi'\n+     if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'\n\n cat >expected <<EOF\n -100644 X 0\tnitfol\n@@ -201,10 +212,10 @@ EOF\n test_expect_success \\\n     '14 - unchanged in two heads.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo nitfol nitfol >nitfol &&\n      git update-index --add nitfol &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >14.out &&\n      test_must_fail git diff -U0 --no-index M.out 14.out >14diff.out &&\n      compare_change 14diff.out expected &&\n@@ -221,11 +232,11 @@ test_expect_success \\\n test_expect_success \\\n     '15 - unchanged in two heads.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo nitfol nitfol >nitfol &&\n      git update-index --add nitfol &&\n      echo nitfol nitfol nitfol >nitfol &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >15.out &&\n      test_must_fail git diff -U0 --no-index M.out 15.out >15diff.out &&\n      compare_change 15diff.out expected &&\n@@ -242,27 +253,27 @@ test_expect_success \\\n test_expect_success \\\n     '16 - conflicting local change.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo bozbar bozbar >bozbar &&\n      git update-index --add bozbar &&\n-     if git read-tree -m -u $treeH $treeM; then false; else :; fi'\n+     if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'\n\n test_expect_success \\\n     '17 - conflicting local change.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo bozbar bozbar >bozbar &&\n      git update-index --add bozbar &&\n      echo bozbar bozbar bozbar >bozbar &&\n-     if git read-tree -m -u $treeH $treeM; then false; else :; fi'\n+     if read_tree_u_must_succeed -m -u $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 nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo gnusto >bozbar &&\n      git update-index --add bozbar &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >18.out &&\n      test_cmp M.out 18.out &&\n      check_cache_at bozbar clean &&\n@@ -272,11 +283,11 @@ test_expect_success \\\n test_expect_success \\\n     '19 - local change already having a good result, further modified.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo gnusto >bozbar &&\n      git update-index --add bozbar &&\n      echo gnusto gnusto >bozbar &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >19.out &&\n      test_cmp M.out 19.out &&\n      check_cache_at bozbar dirty &&\n@@ -292,10 +303,10 @@ test_expect_success \\\n test_expect_success \\\n     '20 - no local change, use new tree.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo bozbar >bozbar &&\n      git update-index --add bozbar &&\n-     git read-tree -m -u $treeH $treeM &&\n+     read_tree_u_must_succeed -m -u $treeH $treeM &&\n      git ls-files --stage >20.out &&\n      test_cmp M.out 20.out &&\n      check_cache_at bozbar clean &&\n@@ -305,11 +316,11 @@ test_expect_success \\\n test_expect_success \\\n     '21 - no local change, dirty cache.' \\\n     'rm -f .git/index nitfol bozbar rezrov frotz &&\n-     git read-tree --reset -u $treeH &&\n+     read_tree_u_must_succeed --reset -u $treeH &&\n      echo bozbar >bozbar &&\n      git update-index --add bozbar &&\n      echo gnusto gnusto >bozbar &&\n-     if git read-tree -m -u $treeH $treeM; then false; else :; fi'\n+     if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi'\n\n # Also make sure we did not break DF vs DF/DF case.\n test_expect_success \\\n@@ -336,7 +347,7 @@ test_expect_success \\\n      rm -fr DF &&\n      echo DF >DF &&\n      git update-index --add DF &&\n-     git read-tree -m -u $treeDF $treeDFDF &&\n+     read_tree_u_must_succeed -m -u $treeDF $treeDFDF &&\n      git ls-files --stage >DFDFcheck.out &&\n      test_cmp DFDF.out DFDFcheck.out &&\n      check_cache_at DF/DF clean'\ndiff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh\nindex eb8e3d4..1e9b5d8 100755\n--- a/t/t1004-read-tree-m-u-wf.sh\n+++ b/t/t1004-read-tree-m-u-wf.sh\n@@ -6,6 +6,28 @@ test_description='read-tree -m -u checks working tree files'\n\n # two-tree test\n\n+read_tree_u_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git diff-files >pre-dry-run-wt &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    git diff-files >post-dry-run-wt &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_cmp pre-dry-run-wt post-dry-run-wt &&\n+    git read-tree \"$@\"\n+}\n+\n+read_tree_u_must_fail () {\n+    git ls-files -s >pre-dry-run &&\n+    git diff-files >pre-dry-run-wt &&\n+    test_must_fail git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    git diff-files >post-dry-run-wt &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_cmp pre-dry-run-wt post-dry-run-wt &&\n+    test_must_fail git read-tree \"$@\"\n+}\n+\n test_expect_success 'two-way setup' '\n\n \tmkdir subdir &&\n@@ -29,7 +51,7 @@ test_expect_success 'two-way not clobbering' '\n\n \techo >file2 master creates untracked file2 &&\n \techo >subdir/file2 master creates untracked subdir/file2 &&\n-\tif err=`git read-tree -m -u master side 2>&1`\n+\tif err=`read_tree_u_must_succeed -m -u master side 2>&1`\n \tthen\n \t\techo should have complained\n \t\tfalse\n@@ -42,7 +64,7 @@ echo file2 >.gitignore\n\n test_expect_success 'two-way with incorrect --exclude-per-directory (1)' '\n\n-\tif err=`git read-tree -m --exclude-per-directory=.gitignore master side 2>&1`\n+\tif err=`read_tree_u_must_succeed -m --exclude-per-directory=.gitignore master side 2>&1`\n \tthen\n \t\techo should have complained\n \t\tfalse\n@@ -53,7 +75,7 @@ test_expect_success 'two-way with incorrect --exclude-per-directory (1)' '\n\n test_expect_success 'two-way with incorrect --exclude-per-directory (2)' '\n\n-\tif err=`git read-tree -m -u --exclude-per-directory=foo --exclude-per-directory=.gitignore master side 2>&1`\n+\tif err=`read_tree_u_must_succeed -m -u --exclude-per-directory=foo --exclude-per-directory=.gitignore master side 2>&1`\n \tthen\n \t\techo should have complained\n \t\tfalse\n@@ -64,7 +86,7 @@ test_expect_success 'two-way with incorrect --exclude-per-directory (2)' '\n\n test_expect_success 'two-way clobbering a ignored file' '\n\n-\tgit read-tree -m -u --exclude-per-directory=.gitignore master side\n+\tread_tree_u_must_succeed -m -u --exclude-per-directory=.gitignore master side\n '\n\n rm -f .gitignore\n@@ -84,7 +106,7 @@ test_expect_success 'three-way not complaining on an untracked path in both' '\n \techo >file2 file two is untracked on the master side &&\n \techo >subdir/file2 file two is untracked on the master side &&\n\n-\tgit read-tree -m -u branch-point master side\n+\tread_tree_u_must_succeed -m -u branch-point master side\n '\n\n test_expect_success 'three-way not clobbering a working tree file' '\n@@ -94,7 +116,7 @@ test_expect_success 'three-way not clobbering a working tree file' '\n \tgit checkout master &&\n \techo >file3 file three created in master, untracked &&\n \techo >subdir/file3 file three created in master, untracked &&\n-\tif err=`git read-tree -m -u branch-point master side 2>&1`\n+\tif err=`read_tree_u_must_succeed -m -u branch-point master side 2>&1`\n \tthen\n \t\techo should have complained\n \t\tfalse\n@@ -113,7 +135,7 @@ test_expect_success 'three-way not complaining on an untracked file' '\n \techo >file3 file three created in master, untracked &&\n \techo >subdir/file3 file three created in master, untracked &&\n\n-\tgit read-tree -m -u --exclude-per-directory=.gitignore branch-point master side\n+\tread_tree_u_must_succeed -m -u --exclude-per-directory=.gitignore branch-point master side\n '\n\n test_expect_success '3-way not overwriting local changes (setup)' '\n@@ -137,7 +159,7 @@ test_expect_success '3-way not overwriting local changes (our side)' '\n \tgit reset --hard &&\n\n \techo >>file1 \"local changes\" &&\n-\tgit read-tree -m -u branch-point side-a side-b &&\n+\tread_tree_u_must_succeed -m -u branch-point side-a side-b &&\n \tgrep \"new line to be kept\" file1 &&\n \tgrep \"local changes\" file1\n\n@@ -151,7 +173,7 @@ test_expect_success '3-way not overwriting local changes (their side)' '\n \tgit reset --hard &&\n\n \techo >>file2 \"local changes\" &&\n-\ttest_must_fail git read-tree -m -u branch-point side-a side-b &&\n+\tread_tree_u_must_fail -m -u branch-point side-a side-b &&\n \t! grep \"new line to be kept\" file2 &&\n \tgrep \"local changes\" file2\n\n@@ -173,7 +195,7 @@ test_expect_success SYMLINKS 'funny symlink in work tree' '\n \tgit add a/b &&\n \tgit commit -m \"we add a/b\" &&\n\n-\tgit read-tree -m -u sym-a sym-a sym-b\n+\tread_tree_u_must_succeed -m -u sym-a sym-a sym-b\n\n '\n\n@@ -209,7 +231,7 @@ test_expect_success 'D/F setup' '\n test_expect_success 'D/F' '\n\n \tgit checkout side-b &&\n-\tgit read-tree -m -u branch-point side-b side-a &&\n+\tread_tree_u_must_succeed -m -u branch-point side-b side-a &&\n \tgit ls-files -u >actual &&\n \t(\n \t\ta=$(git rev-parse branch-point:subdir/file2)\ndiff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh\nindex 8499116..33a6a18 100755\n--- a/t/t1005-read-tree-reset.sh\n+++ b/t/t1005-read-tree-reset.sh\n@@ -6,6 +6,17 @@ test_description='read-tree -u --reset'\n\n # two-tree test\n\n+read_tree_u_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git diff-files >pre-dry-run-wt &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    git diff-files >post-dry-run-wt &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_cmp pre-dry-run-wt post-dry-run-wt &&\n+    git read-tree \"$@\"\n+}\n+\n test_expect_success 'setup' '\n   git init &&\n   mkdir df &&\n@@ -22,13 +33,13 @@ test_expect_success 'setup' '\n '\n\n test_expect_success 'reset should work' '\n-  git read-tree -u --reset HEAD^ &&\n+  read_tree_u_must_succeed -u --reset HEAD^ &&\n   git ls-files >actual &&\n   test_cmp expect actual\n '\n\n test_expect_success 'reset should remove remnants from a failed merge' '\n-  git read-tree --reset -u HEAD &&\n+  read_tree_u_must_succeed --reset -u HEAD &&\n   git ls-files -s >expect &&\n   sha1=$(git rev-parse :new) &&\n   (\n@@ -37,13 +48,13 @@ test_expect_success 'reset should remove remnants from a failed merge' '\n   ) | git update-index --index-info &&\n   >old &&\n   git ls-files -s &&\n-  git read-tree --reset -u HEAD &&\n+  read_tree_u_must_succeed --reset -u HEAD &&\n   git ls-files -s >actual &&\n   ! test -f old\n '\n\n test_expect_success 'Porcelain reset should remove remnants too' '\n-  git read-tree --reset -u HEAD &&\n+  read_tree_u_must_succeed --reset -u HEAD &&\n   git ls-files -s >expect &&\n   sha1=$(git rev-parse :new) &&\n   (\n@@ -58,7 +69,7 @@ test_expect_success 'Porcelain reset should remove remnants too' '\n '\n\n test_expect_success 'Porcelain checkout -f should remove remnants too' '\n-  git read-tree --reset -u HEAD &&\n+  read_tree_u_must_succeed --reset -u HEAD &&\n   git ls-files -s >expect &&\n   sha1=$(git rev-parse :new) &&\n   (\n@@ -73,7 +84,7 @@ test_expect_success 'Porcelain checkout -f should remove remnants too' '\n '\n\n test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '\n-  git read-tree --reset -u HEAD &&\n+  read_tree_u_must_succeed --reset -u HEAD &&\n   git ls-files -s >expect &&\n   sha1=$(git rev-parse :new) &&\n   (\ndiff --git a/t/t1008-read-tree-overlay.sh b/t/t1008-read-tree-overlay.sh\nindex f9e0028..b88a35f 100755\n--- a/t/t1008-read-tree-overlay.sh\n+++ b/t/t1008-read-tree-overlay.sh\n@@ -4,6 +4,14 @@ test_description='test multi-tree read-tree without merging'\n\n . ./test-lib.sh\n\n+read_tree_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    git read-tree \"$@\"\n+}\n+\n test_expect_success setup '\n \techo one >a &&\n \tgit add a &&\n@@ -21,7 +29,7 @@ test_expect_success setup '\n '\n\n test_expect_success 'multi-read' '\n-\tgit read-tree initial master side &&\n+\tread_tree_must_succeed initial master side &&\n \t(echo a; echo b/c) >expect &&\n \tgit ls-files >actual &&\n \ttest_cmp expect actual\ndiff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh\nindex de84e35..6d47c37 100755\n--- a/t/t1011-read-tree-sparse-checkout.sh\n+++ b/t/t1011-read-tree-sparse-checkout.sh\n@@ -13,6 +13,17 @@ test_description='sparse checkout tests\n\n . ./test-lib.sh\n\n+read_tree_u_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git diff-files >pre-dry-run-wt &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    git diff-files >post-dry-run-wt &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_cmp pre-dry-run-wt post-dry-run-wt &&\n+    git read-tree \"$@\"\n+}\n+\n test_expect_success 'setup' '\n \tcat >expected <<-\\EOF &&\n \t100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0\tinit.t\n@@ -41,7 +52,7 @@ test_expect_success 'setup' '\n '\n\n test_expect_success 'read-tree without .git/info/sparse-checkout' '\n-\tgit read-tree -m -u HEAD &&\n+\tread_tree_u_must_succeed -m -u HEAD &&\n \tgit ls-files --stage >result &&\n \ttest_cmp expected result &&\n \tgit ls-files -t >result &&\n@@ -50,7 +61,7 @@ test_expect_success 'read-tree without .git/info/sparse-checkout' '\n\n test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' '\n \techo >.git/info/sparse-checkout &&\n-\tgit read-tree -m -u HEAD &&\n+\tread_tree_u_must_succeed -m -u HEAD &&\n \tgit ls-files -t >result &&\n \ttest_cmp expected.swt result &&\n \ttest -f init.t &&\n@@ -60,7 +71,7 @@ test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' '\n test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled' '\n \tgit config core.sparsecheckout true &&\n \techo >.git/info/sparse-checkout &&\n-\tgit read-tree --no-sparse-checkout -m -u HEAD &&\n+\tread_tree_u_must_succeed --no-sparse-checkout -m -u HEAD &&\n \tgit ls-files -t >result &&\n \ttest_cmp expected.swt result &&\n \ttest -f init.t &&\n@@ -87,7 +98,7 @@ test_expect_success 'match directories with trailing slash' '\n \tEOF\n\n \techo sub/ > .git/info/sparse-checkout &&\n-\tgit read-tree -m -u HEAD &&\n+\tread_tree_u_must_succeed -m -u HEAD &&\n \tgit ls-files -t > result &&\n \ttest_cmp expected.swt-noinit result &&\n \ttest ! -f init.t &&\n@@ -96,7 +107,7 @@ test_expect_success 'match directories with trailing slash' '\n\n test_expect_success 'match directories without trailing slash' '\n \techo sub >>.git/info/sparse-checkout &&\n-\tgit read-tree -m -u HEAD &&\n+\tread_tree_u_must_succeed -m -u HEAD &&\n \tgit ls-files -t >result &&\n \ttest_cmp expected.swt-noinit result &&\n \ttest ! -f init.t &&\n@@ -105,7 +116,7 @@ test_expect_success 'match directories without trailing slash' '\n\n test_expect_success 'match directory pattern' '\n \techo \"s?b\" >>.git/info/sparse-checkout &&\n-\tgit read-tree -m -u HEAD &&\n+\tread_tree_u_must_succeed -m -u HEAD &&\n \tgit ls-files -t >result &&\n \ttest_cmp expected.swt-noinit result &&\n \ttest ! -f init.t &&\n@@ -120,7 +131,7 @@ test_expect_success 'checkout area changes' '\n \tEOF\n\n \techo init.t >.git/info/sparse-checkout &&\n-\tgit read-tree -m -u HEAD &&\n+\tread_tree_u_must_succeed -m -u HEAD &&\n \tgit ls-files -t >result &&\n \ttest_cmp expected.swt-nosub result &&\n \ttest -f init.t &&\n@@ -130,7 +141,7 @@ test_expect_success 'checkout area changes' '\n test_expect_success 'read-tree updates worktree, absent case' '\n \techo sub/added >.git/info/sparse-checkout &&\n \tgit checkout -f top &&\n-\tgit read-tree -m -u HEAD^ &&\n+\tread_tree_u_must_succeed -m -u HEAD^ &&\n \ttest ! -f init.t\n '\n\n@@ -147,14 +158,14 @@ test_expect_success 'read-tree removes worktree, dirty case' '\n \techo init.t >.git/info/sparse-checkout &&\n \tgit checkout -f top &&\n \techo dirty >added &&\n-\tgit read-tree -m -u HEAD^ &&\n+\tread_tree_u_must_succeed -m -u HEAD^ &&\n \tgrep -q dirty added\n '\n\n test_expect_success 'read-tree adds to worktree, absent case' '\n \techo init.t >.git/info/sparse-checkout &&\n \tgit checkout -f removed &&\n-\tgit read-tree -u -m HEAD^ &&\n+\tread_tree_u_must_succeed -u -m HEAD^ &&\n \ttest ! -f sub/added\n '\n\n@@ -163,7 +174,7 @@ test_expect_success 'read-tree adds to worktree, dirty case' '\n \tgit checkout -f removed &&\n \tmkdir sub &&\n \techo dirty >sub/added &&\n-\tgit read-tree -u -m HEAD^ &&\n+\tread_tree_u_must_succeed -u -m HEAD^ &&\n \tgrep -q dirty sub/added\n '\n\ndiff --git a/t/t1012-read-tree-df.sh b/t/t1012-read-tree-df.sh\nindex 9811d46..d3e814d 100755\n--- a/t/t1012-read-tree-df.sh\n+++ b/t/t1012-read-tree-df.sh\n@@ -36,6 +36,17 @@ checkindex () {\n \ttest_cmp expect current\n }\n\n+read_tree_u_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git diff-files >pre-dry-run-wt &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    git diff-files >post-dry-run-wt &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_cmp pre-dry-run-wt post-dry-run-wt &&\n+    git read-tree \"$@\"\n+}\n+\n test_expect_success setup '\n \tmaketree O-000 a/b-2/c/d a/b/c/d a/x &&\n \tmaketree A-000 a/b-2/c/d a/b/c/d a/x &&\n@@ -53,7 +64,7 @@ test_expect_success setup '\n\n test_expect_success '3-way (1)' '\n \tsettree A-000 &&\n-\tgit read-tree -m -u O-000 A-000 B-000 &&\n+\tread_tree_u_must_succeed -m -u O-000 A-000 B-000 &&\n \tcheckindex <<-EOF\n \t3 a/b\n \t0 a/b-2/c/d\n@@ -65,7 +76,7 @@ test_expect_success '3-way (1)' '\n\n test_expect_success '3-way (2)' '\n \tsettree A-001 &&\n-\tgit read-tree -m -u O-000 A-001 B-000 &&\n+\tread_tree_u_must_succeed -m -u O-000 A-001 B-000 &&\n \tcheckindex <<-EOF\n \t3 a/b\n \t0 a/b-2/c/d\n@@ -78,7 +89,7 @@ test_expect_success '3-way (2)' '\n\n test_expect_success '3-way (3)' '\n \tsettree A-010 &&\n-\tgit read-tree -m -u O-010 A-010 B-010 &&\n+\tread_tree_u_must_succeed -m -u O-010 A-010 B-010 &&\n \tcheckindex <<-EOF\n \t2 t\n \t1 t-0\n@@ -92,7 +103,7 @@ test_expect_success '3-way (3)' '\n\n test_expect_success '2-way (1)' '\n \tsettree O-020 &&\n-\tgit read-tree -m -u O-020 A-020 &&\n+\tread_tree_u_must_succeed -m -u O-020 A-020 &&\n \tcheckindex <<-EOF\n \t0 ds/dma/ioat/Makefile\n \t0 ds/dma/ioat/registers.h\ndiff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh\nindex ddc3921..a9d2a71 100755\n--- a/t/t1020-subdirectory.sh\n+++ b/t/t1020-subdirectory.sh\n@@ -8,6 +8,17 @@ test_description='Try various core-level commands in subdirectory.\n\n . ./test-lib.sh\n\n+read_tree_u_must_succeed () {\n+    git ls-files -s >pre-dry-run &&\n+    git diff-files >pre-dry-run-wt &&\n+    git read-tree -n \"$@\" &&\n+    git ls-files -s >post-dry-run &&\n+    git diff-files >post-dry-run-wt &&\n+    test_cmp pre-dry-run post-dry-run &&\n+    test_cmp pre-dry-run-wt post-dry-run-wt &&\n+    git read-tree \"$@\"\n+}\n+\n test_expect_success setup '\n \tlong=\"a b c d e f g h i j k l m n o p q r s t u v w x y z\" &&\n \tfor c in $long; do echo $c; done >one &&\n@@ -98,13 +109,13 @@ test_expect_success 'checkout-index' '\n test_expect_success 'read-tree' '\n \trm -f one dir/two &&\n \ttree=`git write-tree` &&\n-\tgit read-tree --reset -u \"$tree\" &&\n+\tread_tree_u_must_succeed --reset -u \"$tree\" &&\n \tcmp one original.one &&\n \tcmp dir/two original.two &&\n \t(\n \t\tcd dir &&\n \t\trm -f two &&\n-\t\tgit read-tree --reset -u \"$tree\" &&\n+\t\tread_tree_u_must_succeed --reset -u \"$tree\" &&\n \t\tcmp two ../original.two &&\n \t\tcmp ../one ../original.one\n \t)\n-- \n1.7.5.1.340.g084d4.dirty\n"},{"id":"168082","messageId":"4DD2E562.90605@web.de","threadId":"27348","inReplyTo":"4DD2CFD4.7060508@web.de","subject":"Re: [WIP PATCH] Teach read-tree the -n|--dry-run option","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2011-05-17T21:15:14Z","receivedAt":"2011-05-17T21:15:14Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 17.05.2011 21:43, schrieb Jens Lehmann:\n> The only exceptions where I could not make that replacement without\n> breaking a test were:\n> \n> * t1001:381 (#25) new file conflicts with untracked directory\n>   This should have been detected by verify_absent_1(), but that function\n>   is left early when opts->update is 0. Will look into that.\n> \n> * 1011:95  (#5)  read-tree with empty .git/info/sparse-checkout\n> * t1011:163 (#11) read-tree updates worktree, dirty case\n>   Not sure about those two as I haven't got much experience with sparse\n>   checkout. Will dig further, pointers welcome.\n\nI found the reason for all three failures, patch coming.\n"},{"id":"168086","messageId":"7vpqnheygi.fsf@alter.siamese.dyndns.org","threadId":"27348","inReplyTo":"4DD2CFD4.7060508@web.de","subject":"Re: [WIP PATCH] Teach read-tree the -n|--dry-run option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-17T22:47:41Z","receivedAt":"2011-05-17T22:47:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jens Lehmann <Jens.Lehmann@web.de> writes:\n\n>> I think the change to the implementation would be trivial, but you would\n>> probably want to update the tests in 1002 (remove the one at the end that\n>> checks -u/-n incompatibility, and perhaps make sure \"-n -u\" combination\n>> does not touch anything as advertised).\n>\n> I added two convenience functions read_tree_u_must_[succeed|fail]() which\n> work pretty much the way read_tree_must_[succeed|fail]() do but with the\n> added functionality that they check git diff-files before and after the\n> read-tree -n too.\n\nSounds sensible.\n\n> The only exceptions where I could not make that replacement without\n> breaking a test were:\n>\n> * t1001:381 (#25) new file conflicts with untracked directory\n>   This should have been detected by verify_absent_1(), but that function\n>   is left early when opts->update is 0. Will look into that.\n\nThanks. This is the kind of corner case I was worried about when I said\n\"we might have a case where read-tree -m succeeds but read-tree -m -u\ndoesn't\". Fixing it would mean that ...\n\n> @@ -183,6 +184,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n>  \t\tdie(\"--exclude-per-directory is meaningless unless -u\");\n>  \tif (opts.merge && !opts.index_only)\n>  \t\tsetup_work_tree();\n> +\tif (opts.update && dry_run)\n> +\t\topts.update = 0;\n>\n>  \tif (opts.merge) {\n>  \t\tif (stage < 2)\n\n... this hunk must go, right?\n\n> diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh\n> index 680d992..54e69ce 100755\n> --- a/t/t1001-read-tree-m-2way.sh\n> +++ b/t/t1001-read-tree-m-2way.sh\n> @@ -48,6 +48,25 @@ check_cache_at () {\n>  \tesac\n>  }\n>\n> +read_tree_must_succeed () {\n> +...\n> +}\n> +\n> +read_tree_u_must_succeed () {\n> +...\n> +}\n\nNow at this point wouldn't it make more sense to move these helpers to\nlib-read-tree.sh or something and .-source it from all nine tests?\n"},{"id":"168237","messageId":"4DD557AF.4030700@web.de","threadId":"27348","inReplyTo":"7vpqnheygi.fsf@alter.siamese.dyndns.org","subject":"[RFC PATCH] unpack-trees: add check_worktree flag to enable dry-run functionality","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2011-05-19T17:47:27Z","receivedAt":"2011-05-19T17:47:27Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"To enable the users of unpack_trees() to check if a work tree update would\nsucceed without actually touching the work tree the new check_worktree\nflag is added to struct unpack_trees_options. This is necessary because\nwhen update is set to 0 testing for absent new files and sparse handling\nwere disabled. This is fine when e.g. only the index should be updated but\nis not sufficient when the user wants to check if a work tree update would\nsucceed.\n\nNow users can set update to 0 and check_worktree to 1 to see if an\nunpack_tree() with update=1 run would succeed. The only class of problems\nthat are not detected at the moment are file system conditions like ENOSPC\nor missing permissions.\n\nSigned-off-by: Jens Lehmann <Jens.Lehmann@web.de>\n---\nAm 18.05.2011 00:47, schrieb Junio C Hamano:\n> Jens Lehmann <Jens.Lehmann@web.de> writes:\n>> The only exceptions where I could not make that replacement without\n>> breaking a test were:\n>>\n>> * t1001:381 (#25) new file conflicts with untracked directory\n>>   This should have been detected by verify_absent_1(), but that function\n>>   is left early when opts->update is 0. Will look into that.\n> \n> Thanks. This is the kind of corner case I was worried about when I said\n> \"we might have a case where read-tree -m succeeds but read-tree -m -u\n> doesn't\". Fixing it would mean that ...\n\nMaybe something like this patch?\n\n>> @@ -183,6 +184,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n>>  \t\tdie(\"--exclude-per-directory is meaningless unless -u\");\n>>  \tif (opts.merge && !opts.index_only)\n>>  \t\tsetup_work_tree();\n>> +\tif (opts.update && dry_run)\n>> +\t\topts.update = 0;\n>>\n>>  \tif (opts.merge) {\n>>  \t\tif (stage < 2)\n> \n> ... this hunk must go, right?\n\nBut this is the \"don't update the work tree when -n is used together\nwith -u\" part, so it is needed, no? With this patch applied first and\nopts.check_worktree set to 1 inside that if() added there all tests\nsucceed.\n\n> Now at this point wouldn't it make more sense to move these helpers to\n> lib-read-tree.sh or something and .-source it from all nine tests?\n\nSure, will do in the next round.\n\n\n unpack-trees.c |    4 ++--\n unpack-trees.h |    3 ++-\n 2 files changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 500ebcf..b6dca8f 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1001,7 +1001,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \tstate.refresh_cache = 1;\n\n \tmemset(&el, 0, sizeof(el));\n-\tif (!core_apply_sparse_checkout || !o->update)\n+\tif (!core_apply_sparse_checkout || (!o->update && !o->check_worktree))\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tif (add_excludes_from_file_to_list(git_path(\"info/sparse-checkout\"), \"\", 0, NULL, &el, 0) < 0)\n@@ -1368,7 +1368,7 @@ static int verify_absent_1(struct cache_entry *ce,\n \tint len;\n \tstruct stat st;\n\n-\tif (o->index_only || o->reset || !o->update)\n+\tif (o->index_only || o->reset || (!o->update && !o->check_worktree))\n \t\treturn 0;\n\n \tlen = check_leading_path(ce->name, ce_namelen(ce));\ndiff --git a/unpack-trees.h b/unpack-trees.h\nindex cd11a08..402bbdb 100644\n--- a/unpack-trees.h\n+++ b/unpack-trees.h\n@@ -46,7 +46,8 @@ struct unpack_trees_options {\n \t\t     debug_unpack,\n \t\t     skip_sparse_checkout,\n \t\t     gently,\n-\t\t     show_all_errors;\n+\t\t     show_all_errors,\n+\t\t     check_worktree; /* check work tree contents even if !update */\n \tconst char *prefix;\n \tint cache_bottom;\n \tstruct dir_struct *dir;\n-- \n1.7.5.1.340.g5ecaf\n"},{"id":"168242","messageId":"7vei3u7e25.fsf@alter.siamese.dyndns.org","threadId":"27348","inReplyTo":"4DD557AF.4030700@web.de","subject":"Re: [RFC PATCH] unpack-trees: add check_worktree flag to enable dry-run functionality","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-19T18:14:42Z","receivedAt":"2011-05-19T18:14:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jens Lehmann <Jens.Lehmann@web.de> writes:\n\n>>> +\tif (opts.update && dry_run)\n>>> +\t\topts.update = 0;\n>> \n>> ... this hunk must go, right?\n>\n> But this is the \"don't update the work tree when -n is used together\n> with -u\" part, so it is needed, no? With this patch applied first and\n> opts.check_worktree set to 1 inside that if() added there all tests\n> succeed.\n\nI would say the natural way to do your \"dry-run\" would be to change the\ninner guts of unpack_trees() codepath that currently does\n\n\tif (opts.update) {\n\t\tif (do something to the work tree and get non-zero on failure)\n\t\t\tdie(\"... cannot update '%s'\", path);\n\t}\n\nwith your \"-n\" work to\n\n\tif (opts.update) {\n        \tif (opts.dry_run) {\n\t\t\tif (would the work tree operation fail?)\n\t\t\t\tsay(\"... update would fail because ... '%s'\", path);\n\t\t} else {\n\t\t\tif (do something to the work tree and get non-zero on failure)\n\t\t\t\tdie(\"... cannot update '%s'\", path);\n\t\t}\n\t}\n\nand that was why I thought you would want to keep the original value of\nopts.update. I wouldn't think of a good way to make the code that kicks\nin when both update and dry_run are set if you clear update that early in\nthe codepath.\n\nOf course you could implement a roundabout logic that says something like\n\n\tif (!update && !pretending_to_update)\n        \treturn 0; /* we are not updating */\n\n\tif (update)\n        \tdo work tree operations;\n\telse if (pretending_to_update)\n        \tcheck if work tree operations would fail;\n\telse\n\t\tdo nothing;\n\nBut I think that is going backwards. The point of \"-n\" == dry-run is to\ncover all cases, and your initial round was only covering \"no -u\" case and\nin this round we are trying to also cover \"-u\" case. With the approach to\nadd \"check-worktree\", if we have the third mode of operation (the first\ntwo being the existing \"without -u\" and \"with -u\"), would you add yet\nanother \"check-distim\"?\n\nWouldn't the interaction with these true \"operation modes\" and \"dry run\"\nbe a lot simpler to read and implement that way?  In other words, which\none do you find easier between these two to follow?\n\n\tif (opts.update) {\n\t\tif (opts.dry-run)\n                \tcheck if we can update but do not update in real;\n\t\telse\n                \tdo update and die if we can't;\n\t} else if (opts.distim) {\n\t\tif (opts.dry-run)\n                \tcheck if we can distim but do not actually distim it;\n\t\telse\n                \tdo distim and die if we cannot;\n\t} ...\n\nvs\n\n\tif (!opts.update && !opts.distim && !opts.check_worktree && !opts.check_distim)\n\t\treturn;\n\n\tif (opts.update || opts.check_worktree) {\n\t\tif (opts.check_worktree)\n                \tcheck if we can update but do not update in real;\n\t\telse\n                \tdo update and die if we can't;\n\t} else if (opts.distim || opts.check_distim) {\n\t\tif (opts.check_distim)\n                \tcheck if we can distim but do not distim in real;\n\t\telse\n                \tdo distim and die if we can't;\n        }\n"},{"id":"168244","messageId":"4DD55FC0.4000505@web.de","threadId":"27348","inReplyTo":"7vei3u7e25.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC PATCH] unpack-trees: add check_worktree flag to enable dry-run functionality","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2011-05-19T18:21:52Z","receivedAt":"2011-05-19T18:21:52Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 19.05.2011 20:14, schrieb Junio C Hamano:\n> Jens Lehmann <Jens.Lehmann@web.de> writes:\n> \n>>>> +\tif (opts.update && dry_run)\n>>>> +\t\topts.update = 0;\n>>>\n>>> ... this hunk must go, right?\n>>\n>> But this is the \"don't update the work tree when -n is used together\n>> with -u\" part, so it is needed, no? With this patch applied first and\n>> opts.check_worktree set to 1 inside that if() added there all tests\n>> succeed.\n> \n> I would say the natural way to do your \"dry-run\" would be to change the\n> inner guts of unpack_trees() codepath that currently does\n> \n> \tif (opts.update) {\n> \t\tif (do something to the work tree and get non-zero on failure)\n> \t\t\tdie(\"... cannot update '%s'\", path);\n> \t}\n> \n> with your \"-n\" work to\n> \n> \tif (opts.update) {\n>         \tif (opts.dry_run) {\n> \t\t\tif (would the work tree operation fail?)\n> \t\t\t\tsay(\"... update would fail because ... '%s'\", path);\n> \t\t} else {\n> \t\t\tif (do something to the work tree and get non-zero on failure)\n> \t\t\t\tdie(\"... cannot update '%s'\", path);\n> \t\t}\n> \t}\n> \n> and that was why I thought you would want to keep the original value of\n> opts.update. I wouldn't think of a good way to make the code that kicks\n> in when both update and dry_run are set if you clear update that early in\n> the codepath.\n\nAh, now I get it ... Thanks, will add a dry_run flag that keeps update\nfrom changing anything.\n"}]}