|
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