X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=builtin-read-tree.c;h=b93178a4ba02d234e907d10d39e9d56051171dbc;hb=0a2586c807fadc4b13a741e693471765870f6bb4;hp=f0b8dad6eb5c469b78f08c12aa0f62befbb54e80;hpb=a755dfe45c10ccd9f180d3c267602ad18d127d6a;p=git.git diff --git a/builtin-read-tree.c b/builtin-read-tree.c index f0b8dad6..b93178a4 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -9,6 +9,8 @@ #include "object.h" #include "tree.h" +#include "cache-tree.h" +#include "tree-walk.h" #include #include #include "builtin.h" @@ -163,7 +165,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len, struct tree *tree = lookup_tree(posns[i]->sha1); any_dirs = 1; parse_tree(tree); - subposns[i] = tree->entries; + subposns[i] = create_tree_entry_list(tree); posns[i] = posns[i]->next; src[i + merge] = &df_conflict_entry; continue; @@ -368,7 +370,7 @@ static int unpack_trees(merge_fn_t fn) if (len) { posns = xmalloc(len * sizeof(struct tree_entry_list *)); for (i = 0; i < len; i++) { - posns[i] = ((struct tree *) posn->item)->entries; + posns[i] = create_tree_entry_list((struct tree *) posn->item); posn = posn->next; } if (unpack_trees_rec(posns, len, "", fn, &indpos)) @@ -428,6 +430,12 @@ static void verify_uptodate(struct cache_entry *ce) die("Entry '%s' not uptodate. Cannot merge.", ce->name); } +static void invalidate_ce_path(struct cache_entry *ce) +{ + if (ce) + cache_tree_invalidate_path(active_cache_tree, ce->name); +} + /* * We do not want to remove or overwrite a working tree file that * is not tracked. @@ -458,10 +466,13 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old) *merge = *old; } else { verify_uptodate(old); + invalidate_ce_path(old); } } - else + else { verify_absent(merge->name, "overwritten"); + invalidate_ce_path(merge); + } merge->ce_flags &= ~htons(CE_STAGEMASK); add_cache_entry(merge, ADD_CACHE_OK_TO_ADD); @@ -476,6 +487,7 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old) verify_absent(ce->name, "removed"); ce->ce_mode = 0; add_cache_entry(ce, ADD_CACHE_OK_TO_ADD); + invalidate_ce_path(ce); return 1; } @@ -751,6 +763,7 @@ static int read_cache_unmerged(void) struct cache_entry *ce = active_cache[i]; if (ce_stage(ce)) { deleted++; + invalidate_ce_path(ce); continue; } if (deleted) @@ -761,6 +774,51 @@ static int read_cache_unmerged(void) return deleted; } +static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) +{ + struct tree_desc desc; + int cnt = 0; + + memcpy(it->sha1, tree->object.sha1, 20); + desc.buf = tree->buffer; + desc.size = tree->size; + + while (desc.size) { + unsigned mode; + const char *name; + const unsigned char *sha1; + + 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); + if (!subtree->object.parsed) + parse_tree(subtree); + sub = cache_tree_sub(it, name); + 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) +{ + struct tree *tree = (struct tree *)trees->item; + if (!tree) + return; + active_cache_tree = cache_tree(); + prime_cache_tree_rec(active_cache_tree, tree); + +} + static const char read_tree_usage[] = "git-read-tree ( | -m [--aggressive] [-u | -i] [ []])"; static struct cache_file cache_file; @@ -862,10 +920,9 @@ int cmd_read_tree(int argc, const char **argv, char **envp) fn = twoway_merge; break; case 3: - fn = threeway_merge; - break; default: fn = threeway_merge; + cache_tree_free(&active_cache_tree); break; } @@ -876,6 +933,18 @@ int cmd_read_tree(int argc, const char **argv, char **envp) } unpack_trees(fn); + + /* + * When reading only one tree (either the most basic form, + * "-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. + */ + if (trees && trees->item && (!merge || (stage == 2))) { + cache_tree_free(&active_cache_tree); + prime_cache_tree(); + } + if (write_cache(newfd, active_cache, active_nr) || commit_index_file(&cache_file)) die("unable to write new index file");