cache-tree: verify valid cache-tree in the test suite
This makes sure that cache-tree is consistent with the index. The main purpose is to catch potential problems by saving the index in unpack_trees() but the line in write_index() would also help spot missing invalidation in other code. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
5697ca9aa5
commit
4592e6080f
78
cache-tree.c
78
cache-tree.c
@ -4,6 +4,7 @@
|
||||
#include "tree-walk.h"
|
||||
#include "cache-tree.h"
|
||||
#include "object-store.h"
|
||||
#include "replace-object.h"
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
@ -732,3 +733,80 @@ int update_main_cache_tree(int flags)
|
||||
the_index.cache_tree = cache_tree();
|
||||
return cache_tree_update(&the_index, flags);
|
||||
}
|
||||
|
||||
static void verify_one(struct index_state *istate,
|
||||
struct cache_tree *it,
|
||||
struct strbuf *path)
|
||||
{
|
||||
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 (oidcmp(&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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user