{"thread":{"id":"7452","subject":"Sanity checking request","startedAt":"2007-03-28T09:57:20Z","lastAt":"2007-04-01T16:08:33Z","messageCount":7,"participants":["Junio C Hamano","Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"38246","messageId":"7vwt11itbz.fsf@assigned-by-dhcp.cox.net","threadId":"7452","inReplyTo":null,"subject":"Sanity checking request","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-28T09:57:20Z","receivedAt":"2007-03-28T09:57:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"We've been saying that:\n\n\tgit read-tree -m $tree\n\nis a quicker way to do \"git read-tree $tree\" (i.e. populate the\nindex from a given tree), and except for the reuse of cached\nstat info to gain performance, there is no difference.\n\nWell, I think I broke it with fcc387d on May 17 2006, and I am\nwondering what the correct way to fix that should be.  It\ndepends on how -u and -i options to git-read-tree are meant to\nbe used.\n\nOn one hand, one could argue that \"git read-tree -m $tree\"\nshould behave the same way as \"git read-tree -m -u $tree\" except\nthat it does not do the checkout part.  The in-code comment for\nthe -i option says \"a merge will not even look at the working\ntree\", implying that it will without the option, so running\nverify_update() and verify_absense() even though update option\nis not explicitly passed (hence read-tree itself does not do the\ncheckout) might be the right thing to do.  Admittedly, when I\nintroduced the above breakage, I wasn't consciously making such\ndesign decision (I was more interested in making two- and\nthree-tree case work).  Then \"git read-tree -i -m $tree\" would\nbecome the new right way to do a quicker \"git read-tree $tree\"\nif we take this route.\n\nThe only in-tree user of single-tree merge is in git-commit.  We\ncould do this:\n\ndiff --git a/git-commit.sh b/git-commit.sh\nindex 3656d60..292cf96 100755\n--- a/git-commit.sh\n+++ b/git-commit.sh\n@@ -371,7 +371,7 @@ t,)\n \t\tif test -z \"$initial_commit\"\n \t\tthen\n \t\t\tcp \"$THIS_INDEX\" \"$TMP_INDEX\"\n-\t\t\tGIT_INDEX_FILE=\"$TMP_INDEX\" git-read-tree -m HEAD\n+\t\t\tGIT_INDEX_FILE=\"$TMP_INDEX\" git-read-tree -i -m HEAD\n \t\telse\n \t\t\trm -f \"$TMP_INDEX\"\n \t\tfi || exit\n\n\nAlternatively, we could make -i implied for one-tree merge\nunless -u is given, which is the attached.\n\nWhat do you think?\n\n-- >8 --\nread-tree -m $TREE: do not look at working tree.\n\nA merging single-tree read-tree has been advertised as a quicker\nway to do the equivalent single-tree read-tree without any other\ndifference, but currently it looks at the working tree and does\nbogus checks to detect if the paths have local changes and\nsuch.  Disable them.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex 793eae0..2a1d3c8 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -236,6 +236,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t\tswitch (stage - 1) {\n \t\tcase 1:\n \t\t\topts.fn = opts.prefix ? bind_merge : oneway_merge;\n+\t\t\tif (!opts.update)\n+\t\t\t\topts.index_only = 1;\n \t\t\tbreak;\n \t\tcase 2:\n \t\t\topts.fn = twoway_merge;\n"},{"id":"38254","messageId":"Pine.LNX.4.64.0703280759230.6730@woody.linux-foundation.org","threadId":"7452","inReplyTo":"7vwt11itbz.fsf@assigned-by-dhcp.cox.net","subject":"Re: Sanity checking request","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-03-28T15:13:38Z","receivedAt":"2007-03-28T15:13:38Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 28 Mar 2007, Junio C Hamano wrote:\n>\n> We've been saying that:\n> \n> \tgit read-tree -m $tree\n> \n> is a quicker way to do \"git read-tree $tree\" (i.e. populate the\n> index from a given tree), and except for the reuse of cached\n> stat info to gain performance, there is no difference.\n\nThat was never technically correct. You need to use the \"--reset\" flag \ninstead of \"-m\" if you want to just do a \"git-read-tree\" that also \npopulates the index stat information.\n\nWithout \"--reset\", any old unmerged entries will be error cases.\n\nOf course, when it comes to \"git commit\", you do *not* want to use \n\"--reset\", as erroring out when hitting an unmerged index entry is likely \nthe right thing, even for the \"git commit <paths>\" case.\n\nThat said, I actually think the newer \"git read-tree -m\" behaviour makes \nsense. So I think we're much better off adding \"-i\" to git-commit.sh, than \nto force \"-i\" on when doing the one-way merge. The latter change just \neffectively disables a possible check entirely, the former at least allows \nother users to actually use that form if they ever want to.\n\n(Looking at git-commit.sh, the thing I *really* think we should do is to \nhave a \"GIT_INDEX_FILE_OUTPUT\" environment variable that does locking on \nthe input file, but writes the result to another file: rigth now \ngit-commit.sh (a) wastes time copying the old index file by hand and (b) \nas a result doesn't even honor any locking on it. I think whether it uses \n\"-i\" or not is actually less important - if you commit only a subset of \nfiles, maybe the extra checks in git-read-tree are actually ok?)\n\n\t\tLinus\n"},{"id":"38260","messageId":"7vwt11f9b9.fsf@assigned-by-dhcp.cox.net","threadId":"7452","inReplyTo":"Pine.LNX.4.64.0703280759230.6730@woody.linux-foundation.org","subject":"Re: Sanity checking request","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-28T19:38:02Z","receivedAt":"2007-03-28T19:38:02Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> That said, I actually think the newer \"git read-tree -m\" behaviour makes \n> sense. So I think we're much better off adding \"-i\" to git-commit.sh, than \n> to force \"-i\" on when doing the one-way merge. The latter change just \n> effectively disables a possible check entirely, the former at least allows \n> other users to actually use that form if they ever want to.\n\nThanks, I agree.\n\n> (Looking at git-commit.sh, the thing I *really* think we should do is to \n> have a \"GIT_INDEX_FILE_OUTPUT\" environment variable that does locking on \n> the input file, but writes the result to another file: rigth now \n> git-commit.sh (a) wastes time copying the old index file by hand and (b) \n> as a result doesn't even honor any locking on it. I think whether it uses \n> \"-i\" or not is actually less important - if you commit only a subset of \n> files, maybe the extra checks in git-read-tree are actually ok?)\n\nGood point on locking.\n\nThe reason missing -i matters because it defeats the previous\n158d0577:\n\ncommit 158d0577891441c01457bbcaf45585d3b50f5d75\nAuthor: Junio C Hamano <junkio@cox.net>\nDate:   Sat Dec 9 22:32:43 2006 -0800\n\n    git-commit: allow --only to lose what was staged earlier.\n    \n    The command used to have a safety valve to prevent this sequence:\n    \n    \tedit foo\n    \tgit update-index foo\n    \tedit foo\n    \tgit diff foo\n    \tgit commit --only foo\n    \n    The reason for this was because an inexperienced user might\n    mistakenly think what is shown with the last-minute diff\n    contains all the change that is being committed (instead, what\n    the user asked to check was an incremental diff since what has\n    been staged so far).  However, this turns out to only annoy\n    people who know what they are doing.  Inexperienced people\n    would not be using the first \"update-index\" anyway, in which\n    case they would see the full changes in the \"git diff\".\n    \n    Signed-off-by: Junio C Hamano <junkio@cox.net>\n\nand that is why I noticed this issue.\n"},{"id":"38458","messageId":"7v4po04nit.fsf_-_@assigned-by-dhcp.cox.net","threadId":"7452","inReplyTo":"Pine.LNX.4.64.0703280759230.6730@woody.linux-foundation.org","subject":"[PATCH 0/2] Alternate index output file","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-01T06:27:54Z","receivedAt":"2007-04-01T06:27:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> (Looking at git-commit.sh, the thing I *really* think we should do is to \n> have a \"GIT_INDEX_FILE_OUTPUT\" environment variable that does locking on \n> the input file, but writes the result to another file: rigth now \n> git-commit.sh (a) wastes time copying the old index file by hand and (b) \n> as a result doesn't even honor any locking on it.\n\nI've done this with an environment variable, and it passes all\nthe tests, but I think for this application an environment is\nreally a mistake.  As expected, the change to git-commit.sh\nlooks like:\n\n        diff --git a/git-commit.sh b/git-commit.sh\n        index 292cf96..20c0dc8 100755\n        --- a/git-commit.sh\n        +++ b/git-commit.sh\n        @@ -370,8 +370,8 @@ t,)\n                        # the same way.\n                        if test -z \"$initial_commit\"\n                        then\n        -\t\t\tcp \"$THIS_INDEX\" \"$TMP_INDEX\"\n        -\t\t\tGIT_INDEX_FILE=\"$TMP_INDEX\" git-read-tree -i -m HEAD\n        +\t\t\t_GIT_INDEX_OUTPUT=\"$TMP_INDEX\" \\\n        +\t\t\tGIT_INDEX_FILE=\"$THIS_INDEX\" git-read-tree -i -m HEAD\n                        else\n                                rm -f \"$TMP_INDEX\"\n                        fi || exit\n\nHowever, I had to say something like this in the documentation:\n\n        diff --git a/Documentation/git.txt b/Documentation/git.txt\n        index dceacfa..bc025d6 100644\n        --- a/Documentation/git.txt\n        +++ b/Documentation/git.txt\n        @@ -311,6 +311,15 @@ git so take care if using Cogito etc.\n                index file. If not specified, the default of `$GIT_DIR/index`\n                is used.\n\n        +'_GIT_INDEX_OUTPUT'::\n        +\tWhen this environment is defined, plumbing level\n        +\tcommands that update the index writes the resulting\n        +\tindex to this file, instead of the usual\n        +\t`GIT_INDEX_FILE` (or its default `$GIT_DIR/index`).\n        +\tThis is solely meant to be used by Porcelain to drive\n        +\tlow-level plumbing.  Defining this in user's environment\n        +\tis always an error.  Do not use it.\n        +\n         'GIT_OBJECT_DIRECTORY'::\n                If the object storage directory is specified via this\n                environment variable then the sha1 directories are created\n\nIf a curious user has the environment variable set to something\nother than the file GIT_INDEX_FILE points at, almost everything\nwill break.  This should instead be a command line parameter to\ntell these plumbing commands to write the result in the named\nfile, to prevent stupid mistakes.\n"},{"id":"38460","messageId":"7vtzw038vl.fsf_-_@assigned-by-dhcp.cox.net","threadId":"7452","inReplyTo":"7v4po04nit.fsf_-_@assigned-by-dhcp.cox.net","subject":"[PATCH 1/2] _GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index file.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-01T06:29:34Z","receivedAt":"2007-04-01T06:29:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When defined, this allows plumbing commands that update the\nindex (add, apply, checkout-index, merge-recursive, mv,\nread-tree, rm, update-index, and write-tree) to write their\nresulting index to an alternative index file while holding a\nlock to the original index file.  With this, git-commit that\njumps the index does not have to perform an extra copy of the\nindex file, and more importantly, it can do the update while\nholding the lock on the index.\n\nHowever, I think the interface to let an environment variable\nspecify the output is a mistake, as shown in the documentation.\nIf a curious user has the environment variable set to something\nother than the file GIT_INDEX_FILE points at, almost everything\nwill break.  This should instead be a command line parameter to\ntell these plumbing commands to write the result in the named\nfile, to prevent stupid mistakes.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n Documentation/git.txt    |    9 +++++++++\n builtin-add.c            |    4 ++--\n builtin-apply.c          |    6 +++---\n builtin-checkout-index.c |    7 ++-----\n builtin-mv.c             |    4 ++--\n builtin-read-tree.c      |    4 ++--\n builtin-rm.c             |    4 ++--\n builtin-update-index.c   |    4 ++--\n builtin-write-tree.c     |    2 +-\n cache.h                  |    5 +++++\n git-commit.sh            |    4 ++--\n lockfile.c               |   17 +++++++++++++++++\n merge-recursive.c        |    4 ++--\n 13 files changed, 51 insertions(+), 23 deletions(-)\n\ndiff --git a/Documentation/git.txt b/Documentation/git.txt\nindex dceacfa..bc025d6 100644\n--- a/Documentation/git.txt\n+++ b/Documentation/git.txt\n@@ -311,6 +311,15 @@ git so take care if using Cogito etc.\n \tindex file. If not specified, the default of `$GIT_DIR/index`\n \tis used.\n \n+'_GIT_INDEX_OUTPUT'::\n+\tWhen this environment is defined, plumbing level\n+\tcommands that update the index writes the resulting\n+\tindex to this file, instead of the usual\n+\t`GIT_INDEX_FILE` (or its default `$GIT_DIR/index`).\n+\tThis is solely meant to be used by Porcelain to drive\n+\tlow-level plumbing.  Defining this in user's environment\n+\tis always an error.  Do not use it.\n+\n 'GIT_OBJECT_DIRECTORY'::\n \tIf the object storage directory is specified via this\n \tenvironment variable then the sha1 directories are created\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 9fcf514..54422d8 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -133,7 +133,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \n \tgit_config(git_add_config);\n \n-\tnewfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);\n+\tnewfd = hold_locked_index(&lock_file, 1);\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n@@ -209,7 +209,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \n \tif (active_cache_changed) {\n \t\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t\t    close(newfd) || commit_lock_file(&lock_file))\n+\t\t    close(newfd) || commit_locked_index(&lock_file))\n \t\t\tdie(\"Unable to write new index file\");\n \t}\n \ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex 27a182b..12011c1 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -2664,8 +2664,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)\n \n \twrite_index = check_index && apply;\n \tif (write_index && newfd < 0)\n-\t\tnewfd = hold_lock_file_for_update(&lock_file,\n-\t\t\t\t\t\t  get_index_file(), 1);\n+\t\tnewfd = hold_locked_index(&lock_file, 1);\n+\n \tif (check_index) {\n \t\tif (read_cache() < 0)\n \t\t\tdie(\"unable to read index file\");\n@@ -2872,7 +2872,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)\n \n \tif (write_index) {\n \t\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t\t    close(newfd) || commit_lock_file(&lock_file))\n+\t\t    close(newfd) || commit_locked_index(&lock_file))\n \t\t\tdie(\"Unable to write new index file\");\n \t}\n \ndiff --git a/builtin-checkout-index.c b/builtin-checkout-index.c\nindex afe4b0e..8460f97 100644\n--- a/builtin-checkout-index.c\n+++ b/builtin-checkout-index.c\n@@ -202,10 +202,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)\n \t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--index\")) {\n \t\t\tstate.refresh_cache = 1;\n \t\t\tif (newfd < 0)\n-\t\t\t\tnewfd = hold_lock_file_for_update\n-\t\t\t\t\t(&lock_file, get_index_file(), 1);\n-\t\t\tif (newfd < 0)\n-\t\t\t\tdie(\"cannot open index.lock file.\");\n+\t\t\t\tnewfd = hold_locked_index(&lock_file, 1);\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"-z\")) {\n@@ -302,7 +299,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)\n \n \tif (0 <= newfd &&\n \t    (write_cache(newfd, active_cache, active_nr) ||\n-\t     close(newfd) || commit_lock_file(&lock_file)))\n+\t     close(newfd) || commit_locked_index(&lock_file)))\n \t\tdie(\"Unable to write new index file\");\n \treturn 0;\n }\ndiff --git a/builtin-mv.c b/builtin-mv.c\nindex 737af35..820aca1 100644\n--- a/builtin-mv.c\n+++ b/builtin-mv.c\n@@ -77,7 +77,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \n \tgit_config(git_default_config);\n \n-\tnewfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);\n+\tnewfd = hold_locked_index(&lock_file, 1);\n \tif (read_cache() < 0)\n \t\tdie(\"index file corrupt\");\n \n@@ -285,7 +285,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \t\tif (active_cache_changed) {\n \t\t\tif (write_cache(newfd, active_cache, active_nr) ||\n \t\t\t    close(newfd) ||\n-\t\t\t    commit_lock_file(&lock_file))\n+\t\t\t    commit_locked_index(&lock_file))\n \t\t\t\tdie(\"Unable to write new index file\");\n \t\t}\n \t}\ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex 793eae0..87048f8 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -100,7 +100,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \tsetup_git_directory();\n \tgit_config(git_default_config);\n \n-\tnewfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);\n+\tnewfd = hold_locked_index(&lock_file, 1);\n \n \tgit_config(git_default_config);\n \n@@ -267,7 +267,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t}\n \n \tif (write_cache(newfd, active_cache, active_nr) ||\n-\t    close(newfd) || commit_lock_file(&lock_file))\n+\t    close(newfd) || commit_locked_index(&lock_file))\n \t\tdie(\"unable to write new index file\");\n \treturn 0;\n }\ndiff --git a/builtin-rm.c b/builtin-rm.c\nindex bf42003..8a0738f 100644\n--- a/builtin-rm.c\n+++ b/builtin-rm.c\n@@ -110,7 +110,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \n \tgit_config(git_default_config);\n \n-\tnewfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);\n+\tnewfd = hold_locked_index(&lock_file, 1);\n \n \tif (read_cache() < 0)\n \t\tdie(\"index file corrupt\");\n@@ -220,7 +220,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \n \tif (active_cache_changed) {\n \t\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t\t    close(newfd) || commit_lock_file(&lock_file))\n+\t\t    close(newfd) || commit_locked_index(&lock_file))\n \t\t\tdie(\"Unable to write new index file\");\n \t}\n \ndiff --git a/builtin-update-index.c b/builtin-update-index.c\nindex 71cef63..84993d7 100644\n--- a/builtin-update-index.c\n+++ b/builtin-update-index.c\n@@ -495,7 +495,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t/* We can't free this memory, it becomes part of a linked list parsed atexit() */\n \tlock_file = xcalloc(1, sizeof(struct lock_file));\n \n-\tnewfd = hold_lock_file_for_update(lock_file, get_index_file(), 0);\n+\tnewfd = hold_locked_index(lock_file, 0);\n \tif (newfd < 0)\n \t\tlock_error = errno;\n \n@@ -661,7 +661,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\t\t    get_index_file(), strerror(lock_error));\n \t\t}\n \t\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t\t    close(newfd) || commit_lock_file(lock_file))\n+\t\t    close(newfd) || commit_locked_index(lock_file))\n \t\t\tdie(\"Unable to write new index file\");\n \t}\n \ndiff --git a/builtin-write-tree.c b/builtin-write-tree.c\nindex 90fc1cf..c88bbd1 100644\n--- a/builtin-write-tree.c\n+++ b/builtin-write-tree.c\n@@ -18,7 +18,7 @@ int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)\n \t/* We can't free this memory, it becomes part of a linked list parsed atexit() */\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));\n \n-\tnewfd = hold_lock_file_for_update(lock_file, get_index_file(), 0);\n+\tnewfd = hold_locked_index(lock_file, 1);\n \n \tentries = read_cache();\n \tif (entries < 0)\ndiff --git a/cache.h b/cache.h\nindex 384b260..59a05c1 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -147,6 +147,7 @@ enum object_type {\n #define DEFAULT_GIT_DIR_ENVIRONMENT \".git\"\n #define DB_ENVIRONMENT \"GIT_OBJECT_DIRECTORY\"\n #define INDEX_ENVIRONMENT \"GIT_INDEX_FILE\"\n+#define INDEX_OUTPUT_ENVIRONMENT \"_GIT_INDEX_OUTPUT\"\n #define GRAFT_ENVIRONMENT \"GIT_GRAFT_FILE\"\n #define TEMPLATE_DIR_ENVIRONMENT \"GIT_TEMPLATE_DIR\"\n #define CONFIG_ENVIRONMENT \"GIT_CONFIG\"\n@@ -212,6 +213,10 @@ struct lock_file {\n };\n extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);\n extern int commit_lock_file(struct lock_file *);\n+\n+extern int hold_locked_index(struct lock_file *, int);\n+extern int commit_locked_index(struct lock_file *);\n+\n extern void rollback_lock_file(struct lock_file *);\n extern int delete_ref(const char *, unsigned char *sha1);\n \ndiff --git a/git-commit.sh b/git-commit.sh\nindex 292cf96..20c0dc8 100755\n--- a/git-commit.sh\n+++ b/git-commit.sh\n@@ -370,8 +370,8 @@ t,)\n \t\t# the same way.\n \t\tif test -z \"$initial_commit\"\n \t\tthen\n-\t\t\tcp \"$THIS_INDEX\" \"$TMP_INDEX\"\n-\t\t\tGIT_INDEX_FILE=\"$TMP_INDEX\" git-read-tree -i -m HEAD\n+\t\t\t_GIT_INDEX_OUTPUT=\"$TMP_INDEX\" \\\n+\t\t\tGIT_INDEX_FILE=\"$THIS_INDEX\" git-read-tree -i -m HEAD\n \t\telse\n \t\t\trm -f \"$TMP_INDEX\"\n \t\tfi || exit\ndiff --git a/lockfile.c b/lockfile.c\nindex 4824f4d..2023ebb 100644\n--- a/lockfile.c\n+++ b/lockfile.c\n@@ -65,6 +65,23 @@ int commit_lock_file(struct lock_file *lk)\n \treturn i;\n }\n \n+int hold_locked_index(struct lock_file *lk, int die_on_error)\n+{\n+\treturn hold_lock_file_for_update(lk, get_index_file(), die_on_error);\n+}\n+\n+int commit_locked_index(struct lock_file *lk)\n+{\n+\tchar *output = getenv(INDEX_OUTPUT_ENVIRONMENT);\n+\tif (output && *output) {\n+\t\tint result = rename(lk->filename, output);\n+\t\tlk->filename[0] = 0;\n+\t\treturn result;\n+\t}\n+\telse\n+\t\treturn commit_lock_file(lk);\n+}\n+\n void rollback_lock_file(struct lock_file *lk)\n {\n \tif (lk->filename[0])\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex e1aebd7..f46aaae 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1378,7 +1378,7 @@ int main(int argc, char *argv[])\n \tif (show(3))\n \t\tprintf(\"Merging %s with %s\\n\", branch1, branch2);\n \n-\tindex_fd = hold_lock_file_for_update(lock, get_index_file(), 1);\n+\tindex_fd = hold_locked_index(lock, 1);\n \n \tfor (i = 0; i < bases_count; i++) {\n \t\tstruct commit *ancestor = get_ref(bases[i]);\n@@ -1388,7 +1388,7 @@ int main(int argc, char *argv[])\n \n \tif (active_cache_changed &&\n \t    (write_cache(index_fd, active_cache, active_nr) ||\n-\t     close(index_fd) || commit_lock_file(lock)))\n+\t     close(index_fd) || commit_locked_index(lock)))\n \t\t\tdie (\"unable to write %s\", get_index_file());\n \n \treturn clean ? 0: 1;\n-- \n1.5.1.rc3.26.g4f01\n"},{"id":"38459","messageId":"7vslbk38vi.fsf_-_@assigned-by-dhcp.cox.net","threadId":"7452","inReplyTo":"7v4po04nit.fsf_-_@assigned-by-dhcp.cox.net","subject":"[PATCH 2/2] git-read-tree --index-output=<file>","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-01T06:29:37Z","receivedAt":"2007-04-01T06:29:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This corrects the interface mistake of the previous one, and\ngive a command line parameter to the only plumbing command that\ncurrently needs it, \"read-tree\".\n\nWe can add the set_alternate_index_output() to other plumbing\ncommands that update the index if/when needed.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n Documentation/git-read-tree.txt |   14 +++++++++++++-\n Documentation/git.txt           |    9 ---------\n builtin-read-tree.c             |    7 ++++++-\n cache.h                         |    2 +-\n git-commit.sh                   |    4 ++--\n lockfile.c                      |   11 ++++++++---\n 6 files changed, 30 insertions(+), 17 deletions(-)\n\ndiff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt\nindex 0ff2890..69f2223 100644\n--- a/Documentation/git-read-tree.txt\n+++ b/Documentation/git-read-tree.txt\n@@ -8,7 +8,7 @@ git-read-tree - Reads tree information into the index\n \n SYNOPSIS\n --------\n-'git-read-tree' (<tree-ish> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] <tree-ish1> [<tree-ish2> [<tree-ish3>]])\n+'git-read-tree' (<tree-ish> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]])\n \n \n DESCRIPTION\n@@ -86,6 +86,18 @@ OPTIONS\n \tfile (usually '.gitignore') and allows such an untracked\n \tbut explicitly ignored file to be overwritten.\n \n+--index-output=<file>::\n+\tInstead of writing the results out to `$GIT_INDEX_FILE`,\n+\tplace the resulting index to the named file.  While the\n+\tcommand is operating, the original index file is locked\n+\twith the same mechanism as usual.  The file must be\n+\tallow to be rename(2)ed into from a temporary file that\n+\tis created next to the usual index file; typically this\n+\tmeans it needs to be in the same filesystem as the index\n+\tfile itself, and you need write permission to the\n+\tdirectory the index file and index output file is\n+\tlocated in.\n+\n <tree-ish#>::\n \tThe id of the tree object(s) to be read/merged.\n \ndiff --git a/Documentation/git.txt b/Documentation/git.txt\nindex bc025d6..dceacfa 100644\n--- a/Documentation/git.txt\n+++ b/Documentation/git.txt\n@@ -311,15 +311,6 @@ git so take care if using Cogito etc.\n \tindex file. If not specified, the default of `$GIT_DIR/index`\n \tis used.\n \n-'_GIT_INDEX_OUTPUT'::\n-\tWhen this environment is defined, plumbing level\n-\tcommands that update the index writes the resulting\n-\tindex to this file, instead of the usual\n-\t`GIT_INDEX_FILE` (or its default `$GIT_DIR/index`).\n-\tThis is solely meant to be used by Porcelain to drive\n-\tlow-level plumbing.  Defining this in user's environment\n-\tis always an error.  Do not use it.\n-\n 'GIT_OBJECT_DIRECTORY'::\n \tIf the object storage directory is specified via this\n \tenvironment variable then the sha1 directories are created\ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex 87048f8..213bd93 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -84,7 +84,7 @@ static void prime_cache_tree(void)\n \n }\n \n-static const char read_tree_usage[] = \"git-read-tree (<sha> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] <sha1> [<sha2> [<sha3>]])\";\n+static const char read_tree_usage[] = \"git-read-tree (<sha> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <sha1> [<sha2> [<sha3>]])\";\n \n static struct lock_file lock_file;\n \n@@ -128,6 +128,11 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t\t\tcontinue;\n \t\t}\n \n+\t\tif (!prefixcmp(arg, \"--index-output=\")) {\n+\t\t\tset_alternate_index_output(arg + 15);\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\t/* \"--prefix=<subdirectory>/\" means keep the current index\n \t\t *  entries and put the entries from the tree under the\n \t\t * given subdirectory.\ndiff --git a/cache.h b/cache.h\nindex 59a05c1..592331f 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -147,7 +147,6 @@ enum object_type {\n #define DEFAULT_GIT_DIR_ENVIRONMENT \".git\"\n #define DB_ENVIRONMENT \"GIT_OBJECT_DIRECTORY\"\n #define INDEX_ENVIRONMENT \"GIT_INDEX_FILE\"\n-#define INDEX_OUTPUT_ENVIRONMENT \"_GIT_INDEX_OUTPUT\"\n #define GRAFT_ENVIRONMENT \"GIT_GRAFT_FILE\"\n #define TEMPLATE_DIR_ENVIRONMENT \"GIT_TEMPLATE_DIR\"\n #define CONFIG_ENVIRONMENT \"GIT_CONFIG\"\n@@ -216,6 +215,7 @@ extern int commit_lock_file(struct lock_file *);\n \n extern int hold_locked_index(struct lock_file *, int);\n extern int commit_locked_index(struct lock_file *);\n+extern void set_alternate_index_output(const char *);\n \n extern void rollback_lock_file(struct lock_file *);\n extern int delete_ref(const char *, unsigned char *sha1);\ndiff --git a/git-commit.sh b/git-commit.sh\nindex 20c0dc8..9e0959a 100755\n--- a/git-commit.sh\n+++ b/git-commit.sh\n@@ -370,8 +370,8 @@ t,)\n \t\t# the same way.\n \t\tif test -z \"$initial_commit\"\n \t\tthen\n-\t\t\t_GIT_INDEX_OUTPUT=\"$TMP_INDEX\" \\\n-\t\t\tGIT_INDEX_FILE=\"$THIS_INDEX\" git-read-tree -i -m HEAD\n+\t\t\tGIT_INDEX_FILE=\"$THIS_INDEX\" \\\n+\t\t\tgit-read-tree --index-output=\"$TMP_INDEX\" -i -m HEAD\n \t\telse\n \t\t\trm -f \"$TMP_INDEX\"\n \t\tfi || exit\ndiff --git a/lockfile.c b/lockfile.c\nindex 2023ebb..bed6b21 100644\n--- a/lockfile.c\n+++ b/lockfile.c\n@@ -4,6 +4,7 @@\n #include \"cache.h\"\n \n static struct lock_file *lock_file_list;\n+static const char *alternate_index_output;\n \n static void remove_lock_file(void)\n {\n@@ -70,11 +71,15 @@ int hold_locked_index(struct lock_file *lk, int die_on_error)\n \treturn hold_lock_file_for_update(lk, get_index_file(), die_on_error);\n }\n \n+void set_alternate_index_output(const char *name)\n+{\n+\talternate_index_output = name;\n+}\n+\n int commit_locked_index(struct lock_file *lk)\n {\n-\tchar *output = getenv(INDEX_OUTPUT_ENVIRONMENT);\n-\tif (output && *output) {\n-\t\tint result = rename(lk->filename, output);\n+\tif (alternate_index_output) {\n+\t\tint result = rename(lk->filename, alternate_index_output);\n \t\tlk->filename[0] = 0;\n \t\treturn result;\n \t}\n-- \n1.5.1.rc3.26.g4f01\n"},{"id":"38469","messageId":"Pine.LNX.4.64.0704010904430.6730@woody.linux-foundation.org","threadId":"7452","inReplyTo":"7v4po04nit.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 0/2] Alternate index output file","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-04-01T16:08:33Z","receivedAt":"2007-04-01T16:08:33Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 31 Mar 2007, Junio C Hamano wrote:\n>\n> If a curious user has the environment variable set to something\n> other than the file GIT_INDEX_FILE points at, almost everything\n> will break.  This should instead be a command line parameter to\n> tell these plumbing commands to write the result in the named\n> file, to prevent stupid mistakes.\n\nI agree, that sounds sane. In general, we should probably support \ncommand-line parameters for most of those things, rather than force the \nuse of environment parameters (the way we already do with \"--author\", for \nexample).\n\n\t\tLinus\n"}]}