Merge branch 'jc/maint-read-tree-multi'
authorJunio C Hamano <gitster@pobox.com>
Thu, 23 Apr 2009 02:36:19 +0000 (19:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 23 Apr 2009 02:36:19 +0000 (19:36 -0700)
* jc/maint-read-tree-multi:
checkout branch: prime cache-tree fully
read-tree -m A B: prime cache-tree from the switched-to tree
Move prime_cache_tree() to cache-tree.c
read-tree A B: do not corrupt cache-tree

1  2 
builtin-checkout.c
builtin-read-tree.c
diff --combined builtin-checkout.c
index 383598c9bf06394ff44345e1c56ccb6adb4a9d80,efa1ebfe07f99e5092710fb951f9e23f16dd1b85..15f0c32c7a7ed62afe31e3bafb2d7306ba4a3402
@@@ -5,6 -5,7 +5,7 @@@
  #include "commit.h"
  #include "tree.h"
  #include "tree-walk.h"
+ #include "cache-tree.h"
  #include "unpack-trees.h"
  #include "dir.h"
  #include "run-command.h"
@@@ -178,7 -179,7 +179,7 @@@ static int checkout_merged(int pos, str
        /*
         * NEEDSWORK:
         * There is absolutely no reason to write this as a blob object
 -       * and create a phoney cache entry just to leak.  This hack is
 +       * and create a phony cache entry just to leak.  This hack is
         * primarily to get to the write_entry() machinery that massages
         * the contents to work-tree format and writes out which only
         * allows it for a cache entry.  The code in write_entry() needs
@@@ -292,8 -293,6 +293,8 @@@ static void show_local_changes(struct o
        init_revisions(&rev, NULL);
        rev.abbrev = 0;
        rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS;
 +      if (diff_setup_done(&rev.diffopt) < 0)
 +              die("diff_setup_done failed");
        add_pending_object(&rev, head, NULL);
        run_diff_index(&rev, 0);
  }
@@@ -350,11 -349,16 +351,11 @@@ struct branch_info 
  static void setup_branch_path(struct branch_info *branch)
  {
        struct strbuf buf = STRBUF_INIT;
 -      int ret;
  
 -      if ((ret = interpret_nth_last_branch(branch->name, &buf))
 -          && ret == strlen(branch->name)) {
 +      strbuf_branchname(&buf, branch->name);
 +      if (strcmp(buf.buf, branch->name))
                branch->name = xstrdup(buf.buf);
 -              strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
 -      } else {
 -              strbuf_addstr(&buf, "refs/heads/");
 -              strbuf_addstr(&buf, branch->name);
 -      }
 +      strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
        branch->path = strbuf_detach(&buf, NULL);
  }
  
@@@ -364,14 -368,17 +365,17 @@@ static int merge_working_tree(struct ch
        int ret;
        struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
        int newfd = hold_locked_index(lock_file, 1);
+       int reprime_cache_tree = 0;
  
        if (read_cache() < 0)
                return error("corrupt index file");
  
+       cache_tree_free(&active_cache_tree);
        if (opts->force) {
                ret = reset_tree(new->commit->tree, opts, 1);
                if (ret)
                        return ret;
+               reprime_cache_tree = 1;
        } else {
                struct tree_desc trees[2];
                struct tree *tree;
                topts.verbose_update = !opts->quiet;
                topts.fn = twoway_merge;
                topts.dir = xcalloc(1, sizeof(*topts.dir));
 -              topts.dir->show_ignored = 1;
 +              topts.dir->flags |= DIR_SHOW_IGNORED;
                topts.dir->exclude_per_dir = ".gitignore";
                tree = parse_tree_indirect(old->commit->object.sha1);
                init_tree_desc(&trees[0], tree->buffer, tree->size);
                init_tree_desc(&trees[1], tree->buffer, tree->size);
  
                ret = unpack_trees(2, trees, &topts);
-               if (ret == -1) {
+               if (ret != -1) {
+                       reprime_cache_tree = 1;
+               } else {
                        /*
                         * Unpack couldn't do a trivial merge; either
                         * give up or do a real merge, depending on
                }
        }
  
+       if (reprime_cache_tree)
+               prime_cache_tree(&active_cache_tree, new->commit->tree);
        if (write_cache(newfd, active_cache, active_nr) ||
            commit_locked_index(lock_file))
                die("unable to write new index file");
@@@ -550,8 -561,8 +558,8 @@@ static int switch_branches(struct check
  
        if (!old.commit && !opts->force) {
                if (!opts->quiet) {
 -                      fprintf(stderr, "warning: You appear to be on a branch yet to be born.\n");
 -                      fprintf(stderr, "warning: Forcing checkout of %s.\n", new->name);
 +                      warning("You appear to be on a branch yet to be born.");
 +                      warning("Forcing checkout of %s.", new->name);
                }
                opts->force = 1;
        }
@@@ -730,11 -741,12 +738,11 @@@ no_reference
  
        if (opts.new_branch) {
                struct strbuf buf = STRBUF_INIT;
 -              strbuf_addstr(&buf, "refs/heads/");
 -              strbuf_addstr(&buf, opts.new_branch);
 +              if (strbuf_check_branch_ref(&buf, opts.new_branch))
 +                      die("git checkout: we do not like '%s' as a branch name.",
 +                          opts.new_branch);
                if (!get_sha1(buf.buf, rev))
                        die("git checkout: branch %s already exists", opts.new_branch);
 -              if (check_ref_format(buf.buf))
 -                      die("git checkout: we do not like '%s' as a branch name.", opts.new_branch);
                strbuf_release(&buf);
        }
  
diff --combined builtin-read-tree.c
index 8e0273864d6af8de2a31868dcfbeda29cd36c2fc,391d709704320dba7a918fdd79b68c6c604d33b2..82e25eaa0758d8b9584592f4072f81eeccb0bf1d
@@@ -29,41 -29,6 +29,6 @@@ static int list_tree(unsigned char *sha
        return 0;
  }
  
- static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
- {
-       struct tree_desc desc;
-       struct name_entry entry;
-       int cnt;
-       hashcpy(it->sha1, tree->object.sha1);
-       init_tree_desc(&desc, tree->buffer, tree->size);
-       cnt = 0;
-       while (tree_entry(&desc, &entry)) {
-               if (!S_ISDIR(entry.mode))
-                       cnt++;
-               else {
-                       struct cache_tree_sub *sub;
-                       struct tree *subtree = lookup_tree(entry.sha1);
-                       if (!subtree->object.parsed)
-                               parse_tree(subtree);
-                       sub = cache_tree_sub(it, entry.path);
-                       sub->cache_tree = cache_tree();
-                       prime_cache_tree_rec(sub->cache_tree, subtree);
-                       cnt += sub->cache_tree->entry_count;
-               }
-       }
-       it->entry_count = cnt;
- }
- static void prime_cache_tree(void)
- {
-       if (!nr_trees)
-               return;
-       active_cache_tree = cache_tree();
-       prime_cache_tree_rec(active_cache_tree, trees[0]);
- }
  static const char read_tree_usage[] = "git read-tree (<sha> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <sha1> [<sha2> [<sha3>]])";
  
  static struct lock_file lock_file;
@@@ -170,7 -135,7 +135,7 @@@ int cmd_read_tree(int argc, const char 
                                die("more than one --exclude-per-directory are given.");
  
                        dir = xcalloc(1, sizeof(*opts.dir));
 -                      dir->show_ignored = 1;
 +                      dir->flags |= DIR_SHOW_IGNORED;
                        dir->exclude_per_dir = arg + 24;
                        opts.dir = dir;
                        /* We do not need to nor want to do read-directory
                case 3:
                default:
                        opts.fn = threeway_merge;
-                       cache_tree_free(&active_cache_tree);
                        break;
                }
  
                        opts.head_idx = 1;
        }
  
+       cache_tree_free(&active_cache_tree);
        for (i = 0; i < nr_trees; i++) {
                struct tree *tree = trees[i];
                parse_tree(tree);
         * "-m ent" or "--reset ent" form), we can obtain a fully
         * valid cache-tree because the index must match exactly
         * what came from the tree.
+        *
+        * The same holds true if we are switching between two trees
+        * using read-tree -m A B.  The index must match B after that.
         */
-       if (nr_trees && !opts.prefix && (!opts.merge || (stage == 2))) {
-               cache_tree_free(&active_cache_tree);
-               prime_cache_tree();
-       }
+       if (nr_trees == 1 && !opts.prefix)
+               prime_cache_tree(&active_cache_tree, trees[0]);
+       else if (nr_trees == 2 && opts.merge)
+               prime_cache_tree(&active_cache_tree, trees[1]);
  
        if (write_cache(newfd, active_cache, active_nr) ||
            commit_locked_index(&lock_file))