summaryrefslogtreecommitdiff
path: root/cache-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'cache-tree.c')
-rw-r--r--cache-tree.c131
1 files changed, 103 insertions, 28 deletions
diff --git a/cache-tree.c b/cache-tree.c
index c52e4303df..9d454d24bc 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -3,6 +3,8 @@
#include "tree.h"
#include "tree-walk.h"
#include "cache-tree.h"
+#include "object-store.h"
+#include "replace-object.h"
#ifndef DEBUG
#define DEBUG 0
@@ -320,10 +322,11 @@ static int update_one(struct cache_tree *it,
struct cache_tree_sub *sub = NULL;
const char *path, *slash;
int pathlen, entlen;
- const unsigned char *sha1;
+ const struct object_id *oid;
unsigned mode;
int expected_missing = 0;
int contains_ita = 0;
+ int ce_missing_ok;
path = ce->name;
pathlen = ce_namelen(ce);
@@ -338,7 +341,7 @@ static int update_one(struct cache_tree *it,
die("cache-tree.c: '%.*s' in '%s' not found",
entlen, path + baselen, path);
i += sub->count;
- sha1 = sub->cache_tree->oid.hash;
+ oid = &sub->cache_tree->oid;
mode = S_IFDIR;
contains_ita = sub->cache_tree->entry_count < 0;
if (contains_ita) {
@@ -347,19 +350,22 @@ static int update_one(struct cache_tree *it,
}
}
else {
- sha1 = ce->oid.hash;
+ oid = &ce->oid;
mode = ce->ce_mode;
entlen = pathlen - baselen;
i++;
}
- if (is_null_sha1(sha1) ||
- (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1))) {
+ ce_missing_ok = mode == S_IFGITLINK || missing_ok ||
+ (repository_format_partial_clone &&
+ ce_skip_worktree(ce));
+ if (is_null_oid(oid) ||
+ (!ce_missing_ok && !has_object_file(oid))) {
strbuf_release(&buffer);
if (expected_missing)
return -1;
return error("invalid object %06o %s for '%.*s'",
- mode, sha1_to_hex(sha1), entlen+baselen, path);
+ mode, oid_to_hex(oid), entlen+baselen, path);
}
/*
@@ -385,12 +391,12 @@ static int update_one(struct cache_tree *it,
/*
* "sub" can be an empty tree if all subentries are i-t-a.
*/
- if (contains_ita && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN))
+ if (contains_ita && is_empty_tree_oid(oid))
continue;
strbuf_grow(&buffer, entlen + 100);
strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
- strbuf_add(&buffer, sha1, 20);
+ strbuf_add(&buffer, oid->hash, the_hash_algo->rawsz);
#if DEBUG
fprintf(stderr, "cache-tree update-one %o %.*s\n",
@@ -401,7 +407,7 @@ static int update_one(struct cache_tree *it,
if (repair) {
struct object_id oid;
hash_object_file(buffer.buf, buffer.len, tree_type, &oid);
- if (has_sha1_file(oid.hash))
+ if (has_object_file(&oid))
oidcpy(&it->oid, &oid);
else
to_invalidate = 1;
@@ -432,7 +438,9 @@ int cache_tree_update(struct index_state *istate, int flags)
if (i)
return i;
+ trace_performance_enter();
i = update_one(it, cache, entries, "", 0, &skip, flags);
+ trace_performance_leave("cache_tree_update");
if (i < 0)
return i;
istate->cache_changed |= CACHE_TREE_CHANGED;
@@ -465,7 +473,7 @@ static void write_one(struct strbuf *buffer, struct cache_tree *it,
#endif
if (0 <= it->entry_count) {
- strbuf_add(buffer, it->oid.hash, 20);
+ strbuf_add(buffer, it->oid.hash, the_hash_algo->rawsz);
}
for (i = 0; i < it->subtree_nr; i++) {
struct cache_tree_sub *down = it->down[i];
@@ -492,6 +500,7 @@ static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
char *ep;
struct cache_tree *it;
int i, subtree_nr;
+ const unsigned rawsz = the_hash_algo->rawsz;
it = NULL;
/* skip name, but make sure name exists */
@@ -520,11 +529,11 @@ static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
goto free_return;
buf++; size--;
if (0 <= it->entry_count) {
- if (size < 20)
+ if (size < rawsz)
goto free_return;
- hashcpy(it->oid.hash, (const unsigned char*)buf);
- buf += 20;
- size -= 20;
+ oidread(&it->oid, (const unsigned char *)buf);
+ buf += rawsz;
+ size -= rawsz;
}
#if DEBUG
@@ -599,7 +608,7 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat
return it;
}
-int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
+int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
{
int entries, was_valid;
struct lock_file lock_file = LOCK_INIT;
@@ -640,21 +649,16 @@ int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, co
ret = WRITE_TREE_PREFIX_ERROR;
goto out;
}
- hashcpy(sha1, subtree->oid.hash);
+ oidcpy(oid, &subtree->oid);
}
else
- hashcpy(sha1, index_state->cache_tree->oid.hash);
+ oidcpy(oid, &index_state->cache_tree->oid);
out:
rollback_lock_file(&lock_file);
return ret;
}
-int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
-{
- return write_index_as_tree(sha1, &the_index, get_index_file(), flags, prefix);
-}
-
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
{
struct tree_desc desc;
@@ -669,7 +673,8 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
cnt++;
else {
struct cache_tree_sub *sub;
- struct tree *subtree = lookup_tree(entry.oid);
+ struct tree *subtree = lookup_tree(the_repository,
+ entry.oid);
if (!subtree->object.parsed)
parse_tree(subtree);
sub = cache_tree_sub(it, entry.path);
@@ -716,14 +721,84 @@ int cache_tree_matches_traversal(struct cache_tree *root,
it = find_cache_tree_from_traversal(root, info);
it = cache_tree_find(it, ent->path);
- if (it && it->entry_count > 0 && !oidcmp(ent->oid, &it->oid))
+ if (it && it->entry_count > 0 && oideq(ent->oid, &it->oid))
return it->entry_count;
return 0;
}
-int update_main_cache_tree(int flags)
+static void verify_one(struct index_state *istate,
+ struct cache_tree *it,
+ struct strbuf *path)
{
- if (!the_index.cache_tree)
- the_index.cache_tree = cache_tree();
- return cache_tree_update(&the_index, flags);
+ int i, pos, len = path->len;
+ struct strbuf tree_buf = STRBUF_INIT;
+ struct object_id new_oid;
+
+ for (i = 0; i < it->subtree_nr; i++) {
+ strbuf_addf(path, "%s/", it->down[i]->name);
+ verify_one(istate, it->down[i]->cache_tree, path);
+ strbuf_setlen(path, len);
+ }
+
+ if (it->entry_count < 0 ||
+ /* no verification on tests (t7003) that replace trees */
+ lookup_replace_object(the_repository, &it->oid) != &it->oid)
+ return;
+
+ if (path->len) {
+ pos = index_name_pos(istate, path->buf, path->len);
+ pos = -pos - 1;
+ } else {
+ pos = 0;
+ }
+
+ i = 0;
+ while (i < it->entry_count) {
+ struct cache_entry *ce = istate->cache[pos + i];
+ const char *slash;
+ struct cache_tree_sub *sub = NULL;
+ const struct object_id *oid;
+ const char *name;
+ unsigned mode;
+ int entlen;
+
+ if (ce->ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE))
+ BUG("%s with flags 0x%x should not be in cache-tree",
+ ce->name, ce->ce_flags);
+ name = ce->name + path->len;
+ slash = strchr(name, '/');
+ if (slash) {
+ entlen = slash - name;
+ sub = find_subtree(it, ce->name + path->len, entlen, 0);
+ if (!sub || sub->cache_tree->entry_count < 0)
+ BUG("bad subtree '%.*s'", entlen, name);
+ oid = &sub->cache_tree->oid;
+ mode = S_IFDIR;
+ i += sub->cache_tree->entry_count;
+ } else {
+ oid = &ce->oid;
+ mode = ce->ce_mode;
+ entlen = ce_namelen(ce) - path->len;
+ i++;
+ }
+ strbuf_addf(&tree_buf, "%o %.*s%c", mode, entlen, name, '\0');
+ strbuf_add(&tree_buf, oid->hash, the_hash_algo->rawsz);
+ }
+ hash_object_file(tree_buf.buf, tree_buf.len, tree_type, &new_oid);
+ if (!oideq(&new_oid, &it->oid))
+ BUG("cache-tree for path %.*s does not match. "
+ "Expected %s got %s", len, path->buf,
+ oid_to_hex(&new_oid), oid_to_hex(&it->oid));
+ strbuf_setlen(path, len);
+ strbuf_release(&tree_buf);
+}
+
+void cache_tree_verify(struct index_state *istate)
+{
+ struct strbuf path = STRBUF_INIT;
+
+ if (!istate->cache_tree)
+ return;
+ verify_one(istate, istate->cache_tree, &path);
+ strbuf_release(&path);
}