From: Junio C Hamano Date: Tue, 30 May 2006 05:16:56 +0000 (-0700) Subject: Merge branch 'jc/lt-tree-n-cache-tree' into next X-Git-Tag: v1.4.1-rc1~53 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/5029f6458f99cabce6d80bba09da2137f86cc59e?ds=inline;hp=-c Merge branch 'jc/lt-tree-n-cache-tree' into next * 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. --- 5029f6458f99cabce6d80bba09da2137f86cc59e diff --combined builtin-read-tree.c index 6a2ceba9ce,00cdb5a6d9..d70411f2af --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@@ -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 #include #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 = { @@@ -41,6 -50,39 +51,39 @@@ 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; @@@ -816,14 -833,11 +859,11 @@@ 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 ( | -m [--aggressive] [-u | -i] [ []])"; +static const char read_tree_usage[] = "git-read-tree ( | [[-m [--aggressive] | --reset | --prefix=] [-u | -i]] [ []])"; static struct cache_file cache_file; @@@ -890,24 -904,9 +930,24 @@@ int cmd_read_tree(int argc, const char continue; } + /* "--prefix=/" 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; @@@ -928,7 -927,7 +968,7 @@@ /* "-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"); @@@ -950,31 -949,12 +990,31 @@@ 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 ae65b42056,976a5a459c..b03c2012ef --- a/fetch.c +++ 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; }