cache-tree: protect against "git prune".
[git.git] / update-index.c
index ce1db38..86f5394 100644 (file)
@@ -6,6 +6,11 @@
 #include "cache.h"
 #include "strbuf.h"
 #include "quote.h"
+#include "tree.h"
+#include "cache-tree.h"
+
+static unsigned char active_cache_sha1[20];
+static struct cache_tree *active_cache_tree;
 
 /*
  * Default to not allowing changes to the list of files. The
@@ -70,6 +75,7 @@ static int mark_valid(const char *path)
                        active_cache[pos]->ce_flags &= ~htons(CE_VALID);
                        break;
                }
+               cache_tree_invalidate_path(active_cache_tree, path);
                active_cache_changed = 1;
                return 0;
        }
@@ -83,6 +89,12 @@ static int add_file_to_cache(const char *path)
        struct stat st;
 
        status = lstat(path, &st);
+
+       /* We probably want to do this in remove_file_from_cache() and
+        * add_cache_entry() instead...
+        */
+       cache_tree_invalidate_path(active_cache_tree, path);
+
        if (status < 0 || S_ISDIR(st.st_mode)) {
                /* When we used to have "path" and now we want to add
                 * "path/file", we need a way to remove "path" before
@@ -114,8 +126,7 @@ static int add_file_to_cache(const char *path)
 
        namelen = strlen(path);
        size = cache_entry_size(namelen);
-       ce = xmalloc(size);
-       memset(ce, 0, size);
+       ce = xcalloc(1, size);
        memcpy(ce->name, path, namelen);
        ce->ce_flags = htons(namelen);
        fill_stat_cache_info(ce, &st);
@@ -312,8 +323,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
 
        len = strlen(path);
        size = cache_entry_size(len);
-       ce = xmalloc(size);
-       memset(ce, 0, size);
+       ce = xcalloc(1, size);
 
        memcpy(ce->sha1, sha1, 20);
        memcpy(ce->name, path, len);
@@ -327,6 +337,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
                return error("%s: cannot add to the index - missing --add option?",
                             path);
        report("add '%s'", path);
+       cache_tree_invalidate_path(active_cache_tree, path);
        return 0;
 }
 
@@ -351,6 +362,7 @@ static int chmod_path(int flip, const char *path)
        default:
                return -1;
        }
+       cache_tree_invalidate_path(active_cache_tree, path);
        active_cache_changed = 1;
        return 0;
 }
@@ -369,6 +381,7 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
                        die("Unable to mark file %s", path);
                return;
        }
+       cache_tree_invalidate_path(active_cache_tree, path);
 
        if (force_remove) {
                if (remove_file_from_cache(p))
@@ -444,6 +457,7 @@ static void read_index_info(int line_termination)
                                free(path_name);
                        continue;
                }
+               cache_tree_invalidate_path(active_cache_tree, path_name);
 
                if (!mode) {
                        /* mode == 0 means there is no such path -- remove */
@@ -487,9 +501,10 @@ int main(int argc, const char **argv)
        if (newfd < 0)
                die("unable to create new cachefile");
 
-       entries = read_cache();
+       entries = read_cache_1(active_cache_sha1);
        if (entries < 0)
                die("cache corrupted");
+       active_cache_tree = read_cache_tree(active_cache_sha1);
 
        for (i = 1 ; i < argc; i++) {
                const char *path = argv[i];
@@ -577,9 +592,11 @@ int main(int argc, const char **argv)
                                break;
                        }
                        if (!strcmp(path, "--index-info")) {
+                               if (i != argc - 1)
+                                       die("--index-info must be at the end");
                                allow_add = allow_replace = allow_remove = 1;
                                read_index_info(line_termination);
-                               continue;
+                               break;
                        }
                        if (!strcmp(path, "--ignore-missing")) {
                                not_new = 1;
@@ -613,9 +630,11 @@ int main(int argc, const char **argv)
                }
        }
        if (active_cache_changed) {
-               if (write_cache(newfd, active_cache, active_nr) ||
+               if (write_cache_1(newfd, active_cache, active_nr,
+                                 active_cache_sha1) ||
                    commit_index_file(&cache_file))
                        die("Unable to write new cachefile");
+               write_cache_tree(active_cache_sha1, active_cache_tree);
        }
 
        return has_errors ? 1 : 0;