X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=cache-tree.c;h=d91743775dfbe98d99d8ab25a270af320c8b984e;hb=452c6d506b1a6dcf24d4ceaa592afc39c1c1a60e;hp=3d8f218a5f9e838b15e1d56113a4dd56904ee544;hpb=96aa7adda3b0254e4b9904f53bb38cd76bfea7bb;p=git.git diff --git a/cache-tree.c b/cache-tree.c index 3d8f218a5..d91743775 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -1,5 +1,6 @@ #include "cache.h" #include "tree.h" +#include "tree-walk.h" #include "cache-tree.h" #ifndef DEBUG @@ -328,7 +329,8 @@ static int update_one(struct cache_tree *it, entlen = pathlen - baselen; } if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) - return error("invalid object %s", sha1_to_hex(sha1)); + 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 */ @@ -513,6 +515,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; @@ -537,28 +541,32 @@ 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) @@ -591,3 +599,68 @@ int write_cache_as_tree(unsigned char *sha1, int missing_ok, const char *prefix) return 0; } + +static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) +{ + struct tree_desc desc; + struct name_entry entry; + int cnt; + + hashcpy(it->sha1, tree->object.sha1); + init_tree_desc(&desc, tree->buffer, tree->size); + cnt = 0; + while (tree_entry(&desc, &entry)) { + if (!S_ISDIR(entry.mode)) + cnt++; + else { + struct cache_tree_sub *sub; + struct tree *subtree = lookup_tree(entry.sha1); + if (!subtree->object.parsed) + parse_tree(subtree); + sub = cache_tree_sub(it, entry.path); + sub->cache_tree = cache_tree(); + prime_cache_tree_rec(sub->cache_tree, subtree); + cnt += sub->cache_tree->entry_count; + } + } + it->entry_count = cnt; +} + +void prime_cache_tree(struct cache_tree **it, struct tree *tree) +{ + cache_tree_free(it); + *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; +}