|
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 |
|
8 | 9 | #ifndef DEBUG |
9 | 10 | #define DEBUG 0 |
@@ -732,3 +733,80 @@ int update_main_cache_tree(int flags) |
732 | 733 | the_index.cache_tree = cache_tree(); |
733 | 734 | return cache_tree_update(&the_index, flags); |
734 | 735 | } |
| 736 | + |
| 737 | +static void verify_one(struct index_state *istate, |
| 738 | + struct cache_tree *it, |
| 739 | + struct strbuf *path) |
| 740 | +{ |
| 741 | + int i, pos, len = path->len; |
| 742 | + struct strbuf tree_buf = STRBUF_INIT; |
| 743 | + struct object_id new_oid; |
| 744 | + |
| 745 | + for (i = 0; i < it->subtree_nr; i++) { |
| 746 | + strbuf_addf(path, "%s/", it->down[i]->name); |
| 747 | + verify_one(istate, it->down[i]->cache_tree, path); |
| 748 | + strbuf_setlen(path, len); |
| 749 | + } |
| 750 | + |
| 751 | + if (it->entry_count < 0 || |
| 752 | + /* no verification on tests (t7003) that replace trees */ |
| 753 | + lookup_replace_object(the_repository, &it->oid) != &it->oid) |
| 754 | + return; |
| 755 | + |
| 756 | + if (path->len) { |
| 757 | + pos = index_name_pos(istate, path->buf, path->len); |
| 758 | + pos = -pos - 1; |
| 759 | + } else { |
| 760 | + pos = 0; |
| 761 | + } |
| 762 | + |
| 763 | + i = 0; |
| 764 | + while (i < it->entry_count) { |
| 765 | + struct cache_entry *ce = istate->cache[pos + i]; |
| 766 | + const char *slash; |
| 767 | + struct cache_tree_sub *sub = NULL; |
| 768 | + const struct object_id *oid; |
| 769 | + const char *name; |
| 770 | + unsigned mode; |
| 771 | + int entlen; |
| 772 | + |
| 773 | + if (ce->ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE)) |
| 774 | + BUG("%s with flags 0x%x should not be in cache-tree", |
| 775 | + ce->name, ce->ce_flags); |
| 776 | + name = ce->name + path->len; |
| 777 | + slash = strchr(name, '/'); |
| 778 | + if (slash) { |
| 779 | + entlen = slash - name; |
| 780 | + sub = find_subtree(it, ce->name + path->len, entlen, 0); |
| 781 | + if (!sub || sub->cache_tree->entry_count < 0) |
| 782 | + BUG("bad subtree '%.*s'", entlen, name); |
| 783 | + oid = &sub->cache_tree->oid; |
| 784 | + mode = S_IFDIR; |
| 785 | + i += sub->cache_tree->entry_count; |
| 786 | + } else { |
| 787 | + oid = &ce->oid; |
| 788 | + mode = ce->ce_mode; |
| 789 | + entlen = ce_namelen(ce) - path->len; |
| 790 | + i++; |
| 791 | + } |
| 792 | + strbuf_addf(&tree_buf, "%o %.*s%c", mode, entlen, name, '\0'); |
| 793 | + strbuf_add(&tree_buf, oid->hash, the_hash_algo->rawsz); |
| 794 | + } |
| 795 | + hash_object_file(tree_buf.buf, tree_buf.len, tree_type, &new_oid); |
| 796 | + if (oidcmp(&new_oid, &it->oid)) |
| 797 | + BUG("cache-tree for path %.*s does not match. " |
| 798 | + "Expected %s got %s", len, path->buf, |
| 799 | + oid_to_hex(&new_oid), oid_to_hex(&it->oid)); |
| 800 | + strbuf_setlen(path, len); |
| 801 | + strbuf_release(&tree_buf); |
| 802 | +} |
| 803 | + |
| 804 | +void cache_tree_verify(struct index_state *istate) |
| 805 | +{ |
| 806 | + struct strbuf path = STRBUF_INIT; |
| 807 | + |
| 808 | + if (!istate->cache_tree) |
| 809 | + return; |
| 810 | + verify_one(istate, istate->cache_tree, &path); |
| 811 | + strbuf_release(&path); |
| 812 | +} |
0 commit comments