| 
4 | 4 | #include "tree-walk.h"  | 
5 | 5 | #include "cache-tree.h"  | 
6 | 6 | #include "object-store.h"  | 
 | 7 | +#include "replace-object.h"  | 
7 | 8 | #include "gvfs.h"  | 
8 | 9 | 
 
  | 
9 | 10 | #ifndef DEBUG_CACHE_TREE  | 
@@ -457,7 +458,9 @@ int cache_tree_update(struct index_state *istate, int flags)  | 
457 | 458 | 
 
  | 
458 | 459 | 	if (i)  | 
459 | 460 | 		return i;  | 
 | 461 | +	trace_performance_enter();  | 
460 | 462 | 	i = update_one(it, cache, entries, "", 0, &skip, flags);  | 
 | 463 | +	trace_performance_leave("cache_tree_update");  | 
461 | 464 | 	if (i < 0)  | 
462 | 465 | 		return i;  | 
463 | 466 | 	istate->cache_changed |= CACHE_TREE_CHANGED;  | 
@@ -742,3 +745,80 @@ int cache_tree_matches_traversal(struct cache_tree *root,  | 
742 | 745 | 		return it->entry_count;  | 
743 | 746 | 	return 0;  | 
744 | 747 | }  | 
 | 748 | + | 
 | 749 | +static void verify_one(struct index_state *istate,  | 
 | 750 | +		       struct cache_tree *it,  | 
 | 751 | +		       struct strbuf *path)  | 
 | 752 | +{  | 
 | 753 | +	int i, pos, len = path->len;  | 
 | 754 | +	struct strbuf tree_buf = STRBUF_INIT;  | 
 | 755 | +	struct object_id new_oid;  | 
 | 756 | + | 
 | 757 | +	for (i = 0; i < it->subtree_nr; i++) {  | 
 | 758 | +		strbuf_addf(path, "%s/", it->down[i]->name);  | 
 | 759 | +		verify_one(istate, it->down[i]->cache_tree, path);  | 
 | 760 | +		strbuf_setlen(path, len);  | 
 | 761 | +	}  | 
 | 762 | + | 
 | 763 | +	if (it->entry_count < 0 ||  | 
 | 764 | +	    /* no verification on tests (t7003) that replace trees */  | 
 | 765 | +	    lookup_replace_object(the_repository, &it->oid) != &it->oid)  | 
 | 766 | +		return;  | 
 | 767 | + | 
 | 768 | +	if (path->len) {  | 
 | 769 | +		pos = index_name_pos(istate, path->buf, path->len);  | 
 | 770 | +		pos = -pos - 1;  | 
 | 771 | +	} else {  | 
 | 772 | +		pos = 0;  | 
 | 773 | +	}  | 
 | 774 | + | 
 | 775 | +	i = 0;  | 
 | 776 | +	while (i < it->entry_count) {  | 
 | 777 | +		struct cache_entry *ce = istate->cache[pos + i];  | 
 | 778 | +		const char *slash;  | 
 | 779 | +		struct cache_tree_sub *sub = NULL;  | 
 | 780 | +		const struct object_id *oid;  | 
 | 781 | +		const char *name;  | 
 | 782 | +		unsigned mode;  | 
 | 783 | +		int entlen;  | 
 | 784 | + | 
 | 785 | +		if (ce->ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE))  | 
 | 786 | +			BUG("%s with flags 0x%x should not be in cache-tree",  | 
 | 787 | +			    ce->name, ce->ce_flags);  | 
 | 788 | +		name = ce->name + path->len;  | 
 | 789 | +		slash = strchr(name, '/');  | 
 | 790 | +		if (slash) {  | 
 | 791 | +			entlen = slash - name;  | 
 | 792 | +			sub = find_subtree(it, ce->name + path->len, entlen, 0);  | 
 | 793 | +			if (!sub || sub->cache_tree->entry_count < 0)  | 
 | 794 | +				BUG("bad subtree '%.*s'", entlen, name);  | 
 | 795 | +			oid = &sub->cache_tree->oid;  | 
 | 796 | +			mode = S_IFDIR;  | 
 | 797 | +			i += sub->cache_tree->entry_count;  | 
 | 798 | +		} else {  | 
 | 799 | +			oid = &ce->oid;  | 
 | 800 | +			mode = ce->ce_mode;  | 
 | 801 | +			entlen = ce_namelen(ce) - path->len;  | 
 | 802 | +			i++;  | 
 | 803 | +		}  | 
 | 804 | +		strbuf_addf(&tree_buf, "%o %.*s%c", mode, entlen, name, '\0');  | 
 | 805 | +		strbuf_add(&tree_buf, oid->hash, the_hash_algo->rawsz);  | 
 | 806 | +	}  | 
 | 807 | +	hash_object_file(tree_buf.buf, tree_buf.len, tree_type, &new_oid);  | 
 | 808 | +	if (oidcmp(&new_oid, &it->oid))  | 
 | 809 | +		BUG("cache-tree for path %.*s does not match. "  | 
 | 810 | +		    "Expected %s got %s", len, path->buf,  | 
 | 811 | +		    oid_to_hex(&new_oid), oid_to_hex(&it->oid));  | 
 | 812 | +	strbuf_setlen(path, len);  | 
 | 813 | +	strbuf_release(&tree_buf);  | 
 | 814 | +}  | 
 | 815 | + | 
 | 816 | +void cache_tree_verify(struct index_state *istate)  | 
 | 817 | +{  | 
 | 818 | +	struct strbuf path = STRBUF_INIT;  | 
 | 819 | + | 
 | 820 | +	if (!istate->cache_tree)  | 
 | 821 | +		return;  | 
 | 822 | +	verify_one(istate, istate->cache_tree, &path);  | 
 | 823 | +	strbuf_release(&path);  | 
 | 824 | +}  | 
0 commit comments