Merge branch 'jc/lt-tree-n-cache-tree' into next
authorJunio C Hamano <junkio@cox.net>
Tue, 30 May 2006 05:16:56 +0000 (22:16 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 30 May 2006 05:16:56 +0000 (22:16 -0700)
* jc/lt-tree-n-cache-tree:
adjust to the rebased series by Linus.
Remove last vestiges of generic tree_entry_list
Convert fetch.c: process_tree() to raw tree walker
Convert "mark_tree_uninteresting()" to raw tree walker
Remove unused "zeropad" entry from tree_list_entry
fsck-objects: avoid unnecessary tree_entry_list usage
Remove "tree->entries" tree-entry list from tree parser
builtin-read-tree.c: avoid tree_entry_list in prime_cache_tree_rec()
Switch "read_tree_recursive()" over to tree-walk functionality
Make "tree_entry" have a SHA1 instead of a union of object pointers
Make "struct tree" contain the pointer to the tree buffer
Make git-diff-tree indicate when it flushes
Remove unnecessary output from t3600-rm.

1  2 
builtin-read-tree.c
fetch.c
diff --combined builtin-read-tree.c
index 6a2ceba9ce0d67cf8ccd4567f7a9779dba66e20b,00cdb5a6d9388c3a20e106c2047e7f6580b05ec6..d70411f2afc6f6efa3d3479b97f68c24db099051
@@@ -9,8 -9,8 +9,8 @@@
  
  #include "object.h"
  #include "tree.h"
- #include "cache-tree.h"
  #include "tree-walk.h"
+ #include "cache-tree.h"
  #include <sys/time.h>
  #include <signal.h>
  #include "builtin.h"
@@@ -24,14 -24,23 +24,24 @@@ static int trivial_merges_only = 0
  static int aggressive = 0;
  static int verbose_update = 0;
  static volatile int progress_update = 0;
 +static const char *prefix = NULL;
  
  static int head_idx = -1;
  static int merge_size = 0;
  
  static struct object_list *trees = NULL;
  
- static struct cache_entry df_conflict_entry = { 
+ static struct cache_entry df_conflict_entry = {
+ };
+ struct tree_entry_list {
+       struct tree_entry_list *next;
+       unsigned directory : 1;
+       unsigned executable : 1;
+       unsigned symlink : 1;
+       unsigned int mode;
+       const char *name;
+       const unsigned char *sha1;
  };
  
  static struct tree_entry_list df_conflict_list = {
  
  typedef int (*merge_fn_t)(struct cache_entry **src);
  
+ static struct tree_entry_list *create_tree_entry_list(struct tree *tree)
+ {
+       struct tree_desc desc;
+       struct tree_entry_list *ret = NULL;
+       struct tree_entry_list **list_p = &ret;
+       desc.buf = tree->buffer;
+       desc.size = tree->size;
+       while (desc.size) {
+               unsigned mode;
+               const char *path;
+               const unsigned char *sha1;
+               struct tree_entry_list *entry;
+               sha1 = tree_entry_extract(&desc, &path, &mode);
+               update_tree_entry(&desc);
+               entry = xmalloc(sizeof(struct tree_entry_list));
+               entry->name = path;
+               entry->sha1 = sha1;
+               entry->mode = mode;
+               entry->directory = S_ISDIR(mode) != 0;
+               entry->executable = (mode & S_IXUSR) != 0;
+               entry->symlink = S_ISLNK(mode) != 0;
+               entry->next = NULL;
+               *list_p = entry;
+               list_p = &entry->next;
+       }
+       return ret;
+ }
  static int entcmp(const char *name1, int dir1, const char *name2, int dir2)
  {
        int len1 = strlen(name1);
@@@ -374,8 -416,7 +417,8 @@@ static int unpack_trees(merge_fn_t fn
                        posns[i] = create_tree_entry_list((struct tree *) posn->item);
                        posn = posn->next;
                }
 -              if (unpack_trees_rec(posns, len, "", fn, &indpos))
 +              if (unpack_trees_rec(posns, len, prefix ? prefix : "",
 +                                   fn, &indpos))
                        return -1;
        }
  
@@@ -724,28 -765,6 +767,28 @@@ static int twoway_merge(struct cache_en
                return deleted_entry(oldtree, current);
  }
  
 +/*
 + * Bind merge.
 + *
 + * Keep the index entries at stage0, collapse stage1 but make sure
 + * stage0 does not have anything there.
 + */
 +static int bind_merge(struct cache_entry **src)
 +{
 +      struct cache_entry *old = src[0];
 +      struct cache_entry *a = src[1];
 +
 +      if (merge_size != 1)
 +              return error("Cannot do a bind merge of %d trees\n",
 +                           merge_size);
 +      if (a && old)
 +              die("Entry '%s' overlaps.  Cannot bind.", a->name);
 +      if (!a)
 +              return keep_entry(old);
 +      else
 +              return merged_entry(a, NULL);
 +}
 +
  /*
   * One-way merge.
   *
@@@ -761,10 -780,8 +804,10 @@@ static int oneway_merge(struct cache_en
                return error("Cannot do a oneway merge of %d trees",
                             merge_size);
  
 -      if (!a)
 +      if (!a) {
 +              invalidate_ce_path(old);
                return deleted_entry(old, old);
 +      }
        if (old && same(old, a)) {
                if (reset) {
                        struct stat st;
@@@ -803,12 -820,12 +846,12 @@@ static int read_cache_unmerged(void
  static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
  {
        struct tree_desc desc;
-       int cnt = 0;
+       int cnt;
  
        memcpy(it->sha1, tree->object.sha1, 20);
        desc.buf = tree->buffer;
        desc.size = tree->size;
+       cnt = 0;
        while (desc.size) {
                unsigned mode;
                const char *name;
  
                sha1 = tree_entry_extract(&desc, &name, &mode);
                update_tree_entry(&desc);
                if (!S_ISDIR(mode))
                        cnt++;
                else {
                        struct cache_tree_sub *sub;
-                       struct tree *subtree;
-                       subtree = lookup_tree(sha1);
+                       struct tree *subtree = lookup_tree(sha1);
                        if (!subtree->object.parsed)
                                parse_tree(subtree);
                        sub = cache_tree_sub(it, name);
@@@ -845,7 -859,7 +885,7 @@@ static void prime_cache_tree(void
  
  }
  
 -static const char read_tree_usage[] = "git-read-tree (<sha> | -m [--aggressive] [-u | -i] <sha1> [<sha2> [<sha3>]])";
 +static const char read_tree_usage[] = "git-read-tree (<sha> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] <sha1> [<sha2> [<sha3>]])";
  
  static struct cache_file cache_file;
  
@@@ -890,24 -904,9 +930,24 @@@ int cmd_read_tree(int argc, const char 
                        continue;
                }
  
 +              /* "--prefix=<subdirectory>/" means keep the current index
 +               *  entries and put the entries from the tree under the
 +               * given subdirectory.
 +               */
 +              if (!strncmp(arg, "--prefix=", 9)) {
 +                      if (stage || merge || prefix)
 +                              usage(read_tree_usage);
 +                      prefix = arg + 9;
 +                      merge = 1;
 +                      stage = 1;
 +                      if (read_cache_unmerged())
 +                              die("you need to resolve your current index first");
 +                      continue;
 +              }
 +
                /* This differs from "-m" in that we'll silently ignore unmerged entries */
                if (!strcmp(arg, "--reset")) {
 -                      if (stage || merge)
 +                      if (stage || merge || prefix)
                                usage(read_tree_usage);
                        reset = 1;
                        merge = 1;
  
                /* "-m" stands for "merge", meaning we start in stage 1 */
                if (!strcmp(arg, "-m")) {
 -                      if (stage || merge)
 +                      if (stage || merge || prefix)
                                usage(read_tree_usage);
                        if (read_cache_unmerged())
                                die("you need to resolve your current index first");
        if ((update||index_only) && !merge)
                usage(read_tree_usage);
  
 +      if (prefix) {
 +              int pfxlen = strlen(prefix);
 +              int pos;
 +              if (prefix[pfxlen-1] != '/')
 +                      die("prefix must end with /");
 +              if (stage != 2)
 +                      die("binding merge takes only one tree");
 +              pos = cache_name_pos(prefix, pfxlen);
 +              if (0 <= pos)
 +                      die("corrupt index file");
 +              pos = -pos-1;
 +              if (pos < active_nr &&
 +                  !strncmp(active_cache[pos]->name, prefix, pfxlen))
 +                      die("subdirectory '%s' already exists.", prefix);
 +              pos = cache_name_pos(prefix, pfxlen-1);
 +              if (0 <= pos)
 +                      die("file '%.*s' already exists.", pfxlen-1, prefix);
 +      }
 +
        if (merge) {
                if (stage < 2)
                        die("just how do you expect me to merge %d trees?", stage-1);
                switch (stage - 1) {
                case 1:
 -                      fn = oneway_merge;
 +                      fn = prefix ? bind_merge : oneway_merge;
                        break;
                case 2:
                        fn = twoway_merge;
diff --combined fetch.c
index ae65b420569464fb83e715a69012751f1716075e,976a5a459c466b05b2caf27a58a979598daf05d3..b03c2012ef511ca2cbba2a1bd5e2361c256a12e9
+++ b/fetch.c
@@@ -3,12 -3,12 +3,13 @@@
  #include "cache.h"
  #include "commit.h"
  #include "tree.h"
+ #include "tree-walk.h"
  #include "tag.h"
  #include "blob.h"
  #include "refs.h"
  
  const char *write_ref = NULL;
 +const char *write_ref_log_details = NULL;
  
  int get_tree = 0;
  int get_history = 0;
@@@ -37,27 -37,32 +38,32 @@@ static int process(struct object *obj)
  
  static int process_tree(struct tree *tree)
  {
-       struct tree_entry_list *entry;
+       struct tree_desc desc;
  
        if (parse_tree(tree))
                return -1;
  
-       entry = create_tree_entry_list(tree);
-       while (entry) {
-               struct tree_entry_list *next = entry->next;
+       desc.buf = tree->buffer;
+       desc.size = tree->size;
+       while (desc.size) {
+               unsigned mode;
+               const char *name;
+               const unsigned char *sha1;
  
-               if (entry->directory) {
-                       struct tree *tree = lookup_tree(entry->sha1);
+               sha1 = tree_entry_extract(&desc, &name, &mode);
+               update_tree_entry(&desc);
+               if (S_ISDIR(mode)) {
+                       struct tree *tree = lookup_tree(sha1);
                        process_tree(tree);
                } else {
-                       struct blob *blob = lookup_blob(entry->sha1);
+                       struct blob *blob = lookup_blob(sha1);
                        process(&blob->object);
                }
-               free(entry);
-               entry = next;
        }
        free(tree->buffer);
        tree->buffer = NULL;
+       tree->size = 0;
        return 0;
  }
  
@@@ -209,48 -214,23 +215,48 @@@ static int mark_complete(const char *pa
  
  int pull(char *target)
  {
 +      struct ref_lock *lock;
        unsigned char sha1[20];
 +      char *msg;
 +      int ret;
  
        save_commit_buffer = 0;
        track_object_refs = 0;
 +      if (write_ref) {
 +              lock = lock_ref_sha1(write_ref, NULL, 0);
 +              if (!lock) {
 +                      error("Can't lock ref %s", write_ref);
 +                      return -1;
 +              }
 +      }
  
        if (!get_recover)
                for_each_ref(mark_complete);
  
 -      if (interpret_target(target, sha1))
 -              return error("Could not interpret %s as something to pull",
 -                           target);
 -      if (process(lookup_unknown_object(sha1)))
 +      if (interpret_target(target, sha1)) {
 +              error("Could not interpret %s as something to pull", target);
 +              unlock_ref(lock);
                return -1;
 -      if (loop())
 +      }
 +      if (process(lookup_unknown_object(sha1))) {
 +              unlock_ref(lock);
                return -1;
 -      
 -      if (write_ref)
 -              write_ref_sha1_unlocked(write_ref, sha1);
 +      }
 +      if (loop()) {
 +              unlock_ref(lock);
 +              return -1;
 +      }
 +
 +      if (write_ref) {
 +              if (write_ref_log_details) {
 +                      msg = xmalloc(strlen(write_ref_log_details) + 12);
 +                      sprintf(msg, "fetch from %s", write_ref_log_details);
 +              } else
 +                      msg = NULL;
 +              ret = write_ref_sha1(lock, sha1, msg ? msg : "fetch (unknown)");
 +              if (msg)
 +                      free(msg);
 +              return ret;
 +      }
        return 0;
  }