X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=cache-tree.c;h=8de39590d57e14d08ee4d04b74965191aa905b29;hb=95099731bf2c79ccf5870655e36caa4215f0ced0;hp=37bf35e636f0966662416f0693dbea5c1cc73311;hpb=77f143bf3e218857ec8e5244d7e862e8e0c1a041;p=git.git diff --git a/cache-tree.c b/cache-tree.c index 37bf35e63..8de39590d 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -22,8 +22,10 @@ void cache_tree_free(struct cache_tree **it_p) if (!it) return; for (i = 0; i < it->subtree_nr; i++) - if (it->down[i]) + if (it->down[i]) { cache_tree_free(&it->down[i]->cache_tree); + free(it->down[i]); + } free(it->down); free(it); *it_p = NULL; @@ -148,7 +150,7 @@ void cache_tree_invalidate_path(struct cache_tree *it, const char *path) } static int verify_cache(struct cache_entry **cache, - int entries) + int entries, int silent) { int i, funny; @@ -157,6 +159,8 @@ static int verify_cache(struct cache_entry **cache, for (i = 0; i < entries; i++) { struct cache_entry *ce = cache[i]; if (ce_stage(ce) || (ce->ce_flags & CE_INTENT_TO_ADD)) { + if (silent) + return -1; if (10 < ++funny) { fprintf(stderr, "...\n"); break; @@ -328,8 +332,11 @@ static int update_one(struct cache_tree *it, mode = ce->ce_mode; entlen = pathlen - baselen; } - if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) - return error("invalid object %s", sha1_to_hex(sha1)); + if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) { + strbuf_release(&buffer); + return error("invalid object %06o %s for '%.*s'", + mode, sha1_to_hex(sha1), entlen+baselen, path); + } if (ce->ce_flags & CE_REMOVE) continue; /* entry being removed */ @@ -365,10 +372,11 @@ int cache_tree_update(struct cache_tree *it, struct cache_entry **cache, int entries, int missing_ok, - int dryrun) + int dryrun, + int silent) { int i; - i = verify_cache(cache, entries); + i = verify_cache(cache, entries, silent); if (i) return i; i = update_one(it, cache, entries, "", 0, missing_ok, dryrun); @@ -514,6 +522,8 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size) static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path) { + if (!it) + return NULL; while (*path) { const char *slash; struct cache_tree_sub *sub; @@ -538,31 +548,35 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat return it; } -int write_cache_as_tree(unsigned char *sha1, int missing_ok, const char *prefix) +int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix) { int entries, was_valid, newfd; + struct lock_file *lock_file; /* * We can't free this memory, it becomes part of a linked list * parsed atexit() */ - struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); + lock_file = xcalloc(1, sizeof(struct lock_file)); newfd = hold_locked_index(lock_file, 1); entries = read_cache(); if (entries < 0) return WRITE_TREE_UNREADABLE_INDEX; + if (flags & WRITE_TREE_IGNORE_CACHE_TREE) + cache_tree_free(&(active_cache_tree)); if (!active_cache_tree) active_cache_tree = cache_tree(); was_valid = cache_tree_fully_valid(active_cache_tree); - if (!was_valid) { + int missing_ok = flags & WRITE_TREE_MISSING_OK; + if (cache_tree_update(active_cache_tree, active_cache, active_nr, - missing_ok, 0) < 0) + missing_ok, 0, 0) < 0) return WRITE_TREE_UNMERGED_INDEX; if (0 <= newfd) { if (!write_cache(newfd, active_cache, active_nr) && @@ -625,3 +639,43 @@ void prime_cache_tree(struct cache_tree **it, struct tree *tree) *it = cache_tree(); prime_cache_tree_rec(*it, tree); } + +/* + * find the cache_tree that corresponds to the current level without + * exploding the full path into textual form. The root of the + * cache tree is given as "root", and our current level is "info". + * (1) When at root level, info->prev is NULL, so it is "root" itself. + * (2) Otherwise, find the cache_tree that corresponds to one level + * above us, and find ourselves in there. + */ +static struct cache_tree *find_cache_tree_from_traversal(struct cache_tree *root, + struct traverse_info *info) +{ + struct cache_tree *our_parent; + + if (!info->prev) + return root; + our_parent = find_cache_tree_from_traversal(root, info->prev); + return cache_tree_find(our_parent, info->name.path); +} + +int cache_tree_matches_traversal(struct cache_tree *root, + struct name_entry *ent, + struct traverse_info *info) +{ + struct cache_tree *it; + + it = find_cache_tree_from_traversal(root, info); + it = cache_tree_find(it, ent->path); + if (it && it->entry_count > 0 && !hashcmp(ent->sha1, it->sha1)) + return it->entry_count; + return 0; +} + +int update_main_cache_tree (int silent) +{ + if (!the_index.cache_tree) + the_index.cache_tree = cache_tree(); + return cache_tree_update(the_index.cache_tree, + the_index.cache, the_index.cache_nr, 0, 0, silent); +}