Code

[PATCH] Bugfix: read-cache.c:write_cache() misrecords number of entries.
[git.git] / read-tree.c
index cf6d28e2c9ee689a5ea49d715bc56773b266efa8..ee7a46c909efbc78c59b49d2147165297158882e 100644 (file)
@@ -124,6 +124,15 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old, stru
        return 1;
 }
 
+static int deleted_entry(struct cache_entry *ce, struct cache_entry *old, struct cache_entry **dst)
+{
+       if (old)
+               verify_uptodate(old);
+       ce->ce_mode = 0;
+       *dst++ = ce;
+       return 1;
+}
+
 static int threeway_merge(struct cache_entry *stages[4], struct cache_entry **dst)
 {
        struct cache_entry *old = stages[0];
@@ -183,23 +192,21 @@ static int twoway_merge(struct cache_entry **src, struct cache_entry **dst)
                }
                else if (oldtree && !newtree && same(current, oldtree)) {
                        /* 10 or 11 */
-                       verify_uptodate(current);
-                       return 0;
+                       return deleted_entry(oldtree, current, dst);
                }
                else if (oldtree && newtree &&
                         same(current, oldtree) && !same(current, newtree)) {
                        /* 20 or 21 */
-                       verify_uptodate(current);
-                       return merged_entry(newtree, NULL, dst);
+                       return merged_entry(newtree, current, dst);
                }
                else
                        /* all other failures */
                        return -1;
        }
        else if (newtree)
-               return merged_entry(newtree, NULL, dst);
+               return merged_entry(newtree, current, dst);
        else
-               return 0;
+               return deleted_entry(oldtree, current, dst);
 }
 
 /*
@@ -236,6 +243,11 @@ static void check_updates(struct cache_entry **src, int nr)
        unsigned short mask = htons(CE_UPDATE);
        while (nr--) {
                struct cache_entry *ce = *src++;
+               if (!ce->ce_mode) {
+                       if (update)
+                               unlink(ce->name);
+                       continue;
+               }
                if (ce->ce_flags & mask) {
                        ce->ce_flags &= ~mask;
                        if (update)
@@ -275,13 +287,35 @@ static void merge_cache(struct cache_entry **src, int nr, merge_fn_t fn)
        check_updates(active_cache, active_nr);
 }
 
-static char *read_tree_usage = "git-read-tree (<sha> | -m <sha1> [<sha2> [<sha3>]])";
+static int read_cache_unmerged(void)
+{
+       int i, deleted;
+       struct cache_entry **dst;
+
+       read_cache();
+       dst = active_cache;
+       deleted = 0;
+       for (i = 0; i < active_nr; i++) {
+               struct cache_entry *ce = active_cache[i];
+               if (ce_stage(ce)) {
+                       deleted++;
+                       continue;
+               }
+               if (deleted)
+                       *dst = ce;
+               dst++;
+       }
+       active_nr -= deleted;
+       return deleted;
+}
+
+static char *read_tree_usage = "git-read-tree (<sha> | -m [-u] <sha1> [<sha2> [<sha3>]])";
 
 static struct cache_file cache_file;
 
 int main(int argc, char **argv)
 {
-       int i, newfd, merge;
+       int i, newfd, merge, reset;
        unsigned char sha1[20];
 
        newfd = hold_index_file_for_update(&cache_file, get_index_file());
@@ -289,6 +323,7 @@ int main(int argc, char **argv)
                die("unable to create new cachefile");
 
        merge = 0;
+       reset = 0;
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
 
@@ -298,16 +333,22 @@ int main(int argc, char **argv)
                        continue;
                }
 
+               /* This differs from "-m" in that we'll silently ignore unmerged entries */
+               if (!strcmp(arg, "--reset")) {
+                       if (stage || merge)
+                               usage(read_tree_usage);
+                       reset = 1;
+                       merge = 1;
+                       stage = 1;
+                       read_cache_unmerged();
+               }
+
                /* "-m" stands for "merge", meaning we start in stage 1 */
                if (!strcmp(arg, "-m")) {
-                       int i;
-                       if (stage)
-                               die("-m needs to come first");
-                       read_cache();
-                       for (i = 0; i < active_nr; i++) {
-                               if (ce_stage(active_cache[i]))
-                                       die("you need to resolve your current index first");
-                       }
+                       if (stage || merge)
+                               usage(read_tree_usage);
+                       if (read_cache_unmerged())
+                               die("you need to resolve your current index first");
                        stage = 1;
                        merge = 1;
                        continue;
@@ -320,6 +361,8 @@ int main(int argc, char **argv)
                        die("failed to unpack tree object %s", arg);
                stage++;
        }
+       if (update && !merge)
+               usage(read_tree_usage);
        if (merge) {
                static const merge_fn_t merge_function[] = {
                        [1] = oneway_merge,