_GIT_INDEX_OUTPUT: allow plumbing to output to an alternative index file.
authorJunio C Hamano <junkio@cox.net>
Sun, 1 Apr 2007 06:09:02 +0000 (23:09 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 4 Apr 2007 06:44:32 +0000 (23:44 -0700)
When defined, this allows plumbing commands that update the
index (add, apply, checkout-index, merge-recursive, mv,
read-tree, rm, update-index, and write-tree) to write their
resulting index to an alternative index file while holding a
lock to the original index file.  With this, git-commit that
jumps the index does not have to make an extra copy of the index
file, and more importantly, it can do the update while holding
the lock on the index.

However, I think the interface to let an environment variable
specify the output is a mistake, as shown in the documentation.
If a curious user has the environment variable set to something
other than the file GIT_INDEX_FILE points at, almost everything
will break.  This should instead be a command line parameter to
tell these plumbing commands to write the result in the named
file, to prevent stupid mistakes.

Signed-off-by: Junio C Hamano <junkio@cox.net>
13 files changed:
Documentation/git.txt
builtin-add.c
builtin-apply.c
builtin-checkout-index.c
builtin-mv.c
builtin-read-tree.c
builtin-rm.c
builtin-update-index.c
builtin-write-tree.c
cache.h
git-commit.sh
lockfile.c
merge-recursive.c

index 9defc332736e1b6297ac003e491706d5ce32e834..8fa1a0a58827e84b884d6c997686564dae1a6a58 100644 (file)
@@ -315,6 +315,14 @@ git so take care if using Cogito etc.
        index file. If not specified, the default of `$GIT_DIR/index`
        is used.
 
+'_GIT_INDEX_OUTPUT'::
+       When this environment is defined, plumbing level
+       commands that update the index writes the resulting
+       index to this file, instead of `$GIT_INDEX_FILE` (or its
+       default `$GIT_DIR/index`).  This is solely meant to be
+       used by Porcelain to drive low-level plumbing.  Defining
+       this in user's environment is always an error.
+
 'GIT_OBJECT_DIRECTORY'::
        If the object storage directory is specified via this
        environment variable then the sha1 directories are created
index 9fcf514dbc4cb76e15b47142e77c4019997ecd5d..54422d84a7f61fe2674555734f885872c7156c0b 100644 (file)
@@ -133,7 +133,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
        git_config(git_add_config);
 
-       newfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);
+       newfd = hold_locked_index(&lock_file, 1);
 
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
@@ -209,7 +209,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
        if (active_cache_changed) {
                if (write_cache(newfd, active_cache, active_nr) ||
-                   close(newfd) || commit_lock_file(&lock_file))
+                   close(newfd) || commit_locked_index(&lock_file))
                        die("Unable to write new index file");
        }
 
index 27a182bfaa826711b2e6c4c775fbd6e83b243f7e..12011c1c9ef866c6c8dedc2df3f5b39034918c54 100644 (file)
@@ -2664,8 +2664,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
 
        write_index = check_index && apply;
        if (write_index && newfd < 0)
-               newfd = hold_lock_file_for_update(&lock_file,
-                                                 get_index_file(), 1);
+               newfd = hold_locked_index(&lock_file, 1);
+
        if (check_index) {
                if (read_cache() < 0)
                        die("unable to read index file");
@@ -2872,7 +2872,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
 
        if (write_index) {
                if (write_cache(newfd, active_cache, active_nr) ||
-                   close(newfd) || commit_lock_file(&lock_file))
+                   close(newfd) || commit_locked_index(&lock_file))
                        die("Unable to write new index file");
        }
 
index afe4b0e4520f47f1dace1383bfc2b364b1b1def0..8460f97b6637127d78b58caf2e29d25f3ad0b5a0 100644 (file)
@@ -202,10 +202,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
                if (!strcmp(arg, "-u") || !strcmp(arg, "--index")) {
                        state.refresh_cache = 1;
                        if (newfd < 0)
-                               newfd = hold_lock_file_for_update
-                                       (&lock_file, get_index_file(), 1);
-                       if (newfd < 0)
-                               die("cannot open index.lock file.");
+                               newfd = hold_locked_index(&lock_file, 1);
                        continue;
                }
                if (!strcmp(arg, "-z")) {
@@ -302,7 +299,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 
        if (0 <= newfd &&
            (write_cache(newfd, active_cache, active_nr) ||
-            close(newfd) || commit_lock_file(&lock_file)))
+            close(newfd) || commit_locked_index(&lock_file)))
                die("Unable to write new index file");
        return 0;
 }
index 737af350b873e90c787cb49960236fc19b62a3bf..820aca122e9603535e9f3393b861b91b14ecfe15 100644 (file)
@@ -77,7 +77,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
 
        git_config(git_default_config);
 
-       newfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);
+       newfd = hold_locked_index(&lock_file, 1);
        if (read_cache() < 0)
                die("index file corrupt");
 
@@ -285,7 +285,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                if (active_cache_changed) {
                        if (write_cache(newfd, active_cache, active_nr) ||
                            close(newfd) ||
-                           commit_lock_file(&lock_file))
+                           commit_locked_index(&lock_file))
                                die("Unable to write new index file");
                }
        }
index 793eae0a5f4cc3d21788a3642f156410ce1ad89d..87048f82ee22cc3f2310bb7329328c31127280e0 100644 (file)
@@ -100,7 +100,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
        setup_git_directory();
        git_config(git_default_config);
 
-       newfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);
+       newfd = hold_locked_index(&lock_file, 1);
 
        git_config(git_default_config);
 
@@ -267,7 +267,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
        }
 
        if (write_cache(newfd, active_cache, active_nr) ||
-           close(newfd) || commit_lock_file(&lock_file))
+           close(newfd) || commit_locked_index(&lock_file))
                die("unable to write new index file");
        return 0;
 }
index bf42003a7e79f96bf4964b116ddd3ee79350e682..8a0738f83dd31a847bf486ddb3aefef94af5e049 100644 (file)
@@ -110,7 +110,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
        git_config(git_default_config);
 
-       newfd = hold_lock_file_for_update(&lock_file, get_index_file(), 1);
+       newfd = hold_locked_index(&lock_file, 1);
 
        if (read_cache() < 0)
                die("index file corrupt");
@@ -220,7 +220,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
        if (active_cache_changed) {
                if (write_cache(newfd, active_cache, active_nr) ||
-                   close(newfd) || commit_lock_file(&lock_file))
+                   close(newfd) || commit_locked_index(&lock_file))
                        die("Unable to write new index file");
        }
 
index 71cef633c0e36b3a33fa29eccb8579a9304b0777..84993d7c523debd598cf4ccb092e50f1fdac6976 100644 (file)
@@ -495,7 +495,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
        /* We can't free this memory, it becomes part of a linked list parsed atexit() */
        lock_file = xcalloc(1, sizeof(struct lock_file));
 
-       newfd = hold_lock_file_for_update(lock_file, get_index_file(), 0);
+       newfd = hold_locked_index(lock_file, 0);
        if (newfd < 0)
                lock_error = errno;
 
@@ -661,7 +661,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                            get_index_file(), strerror(lock_error));
                }
                if (write_cache(newfd, active_cache, active_nr) ||
-                   close(newfd) || commit_lock_file(lock_file))
+                   close(newfd) || commit_locked_index(lock_file))
                        die("Unable to write new index file");
        }
 
index 90fc1cfcf40d057cd654edd1454f56cd823efd66..c88bbd1b9be0fe2c033e2fe9daef0a8a2dae03a5 100644 (file)
@@ -18,7 +18,7 @@ int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)
        /* We can't free this memory, it becomes part of a linked list parsed atexit() */
        struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
 
-       newfd = hold_lock_file_for_update(lock_file, get_index_file(), 0);
+       newfd = hold_locked_index(lock_file, 1);
 
        entries = read_cache();
        if (entries < 0)
diff --git a/cache.h b/cache.h
index 384b260227dfb2fa30ecc175681b9b8d73a3577a..59a05c1a459fcbb014b3d93ac434608a09fa8d30 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -147,6 +147,7 @@ enum object_type {
 #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
 #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
 #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
+#define INDEX_OUTPUT_ENVIRONMENT "_GIT_INDEX_OUTPUT"
 #define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
 #define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR"
 #define CONFIG_ENVIRONMENT "GIT_CONFIG"
@@ -212,6 +213,10 @@ struct lock_file {
 };
 extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
 extern int commit_lock_file(struct lock_file *);
+
+extern int hold_locked_index(struct lock_file *, int);
+extern int commit_locked_index(struct lock_file *);
+
 extern void rollback_lock_file(struct lock_file *);
 extern int delete_ref(const char *, unsigned char *sha1);
 
index 292cf967e3cbc77e7b49eb7252a756194e917418..20c0dc806f8cb42b4094ab7ad56b8eb582c1827f 100755 (executable)
@@ -370,8 +370,8 @@ t,)
                # the same way.
                if test -z "$initial_commit"
                then
-                       cp "$THIS_INDEX" "$TMP_INDEX"
-                       GIT_INDEX_FILE="$TMP_INDEX" git-read-tree -i -m HEAD
+                       _GIT_INDEX_OUTPUT="$TMP_INDEX" \
+                       GIT_INDEX_FILE="$THIS_INDEX" git-read-tree -i -m HEAD
                else
                        rm -f "$TMP_INDEX"
                fi || exit
index 4824f4dc026e7b3f978fe4e9b2154335359e9d2e..2023ebb6ffa4642a49b46cbce99bd49d3befebb6 100644 (file)
@@ -65,6 +65,23 @@ int commit_lock_file(struct lock_file *lk)
        return i;
 }
 
+int hold_locked_index(struct lock_file *lk, int die_on_error)
+{
+       return hold_lock_file_for_update(lk, get_index_file(), die_on_error);
+}
+
+int commit_locked_index(struct lock_file *lk)
+{
+       char *output = getenv(INDEX_OUTPUT_ENVIRONMENT);
+       if (output && *output) {
+               int result = rename(lk->filename, output);
+               lk->filename[0] = 0;
+               return result;
+       }
+       else
+               return commit_lock_file(lk);
+}
+
 void rollback_lock_file(struct lock_file *lk)
 {
        if (lk->filename[0])
index e1aebd77274bb75e9fda95b2d64f69a9dda4276a..f46aaae858dcc9c613f630a7ba9c195d6d802dd1 100644 (file)
@@ -1378,7 +1378,7 @@ int main(int argc, char *argv[])
        if (show(3))
                printf("Merging %s with %s\n", branch1, branch2);
 
-       index_fd = hold_lock_file_for_update(lock, get_index_file(), 1);
+       index_fd = hold_locked_index(lock, 1);
 
        for (i = 0; i < bases_count; i++) {
                struct commit *ancestor = get_ref(bases[i]);
@@ -1388,7 +1388,7 @@ int main(int argc, char *argv[])
 
        if (active_cache_changed &&
            (write_cache(index_fd, active_cache, active_nr) ||
-            close(index_fd) || commit_lock_file(lock)))
+            close(index_fd) || commit_locked_index(lock)))
                        die ("unable to write %s", get_index_file());
 
        return clean ? 0: 1;