diff options
author | Junio C Hamano <junkio@cox.net> | 2006-01-14 21:46:58 -0800 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2006-05-01 22:29:16 -0700 |
commit | f4c6f2d328e2f30ad63fdfca26a5e4a11cef35bf (patch) | |
tree | b394985c4b2c49d3eece7f129a94775080c9c168 /read-tree.c | |
parent | fsck-objects: mark objects reachable from cache-tree (diff) | |
download | tgif-f4c6f2d328e2f30ad63fdfca26a5e4a11cef35bf.tar.xz |
read-tree: --prefix=<path>/ option.
With "--prefix=<path>/" option, read-tree keeps the current
index contents, and reads the contents of named tree-ish under
directory at `<prefix>`. The original index file cannot have
anything at the path `<prefix>` itself, and have nothing in
`<prefix>/` directory. This can be used to graft an
independent tree into a subdirectory of the current index.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'read-tree.c')
-rw-r--r-- | read-tree.c | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/read-tree.c b/read-tree.c index 66c0120f13..8b91affe89 100644 --- a/read-tree.c +++ b/read-tree.c @@ -21,6 +21,7 @@ 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; @@ -369,7 +370,8 @@ static int unpack_trees(merge_fn_t fn) posns[i] = ((struct tree *) posn->item)->entries; posn = posn->next; } - if (unpack_trees_rec(posns, len, "", fn, &indpos)) + if (unpack_trees_rec(posns, len, prefix ? prefix : "", + fn, &indpos)) return -1; } @@ -678,6 +680,28 @@ static int twoway_merge(struct cache_entry **src) } /* + * Bind merge. + * + * Keep the index entries at stage0, collapse stage1 but make sure + * stage0 does not have anything in prefix. + */ +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) + return merged_entry(old, NULL); + if (old) + die("Entry '%s' overlaps. Cannot bind.", a->name); + + return merged_entry(a, NULL); +} + +/* * One-way merge. * * The rule is: @@ -758,7 +782,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; @@ -803,9 +827,24 @@ int main(int argc, char **argv) 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; @@ -826,7 +865,7 @@ int main(int argc, char **argv) /* "-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"); @@ -848,12 +887,31 @@ int main(int argc, char **argv) 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; @@ -879,8 +937,8 @@ int main(int argc, char **argv) * valid cache-tree because the index must match exactly * what came from the tree. */ - if (trees->item && (!merge || (stage == 2))) { - cache_tree_free(&active_cache_tree); + if (trees->item && !prefix && (!merge || (stage == 2))) { + cache_tree_free(&active_cache_tree); prime_cache_tree(); } |