~spiv/+junk/bzr-cross-check

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from bzrlib.commands import Command, builtin_command_registry
from bzrlib import (
    bzrdir,
    errors,
    trace,
    )

class cmd_cross_check(Command):

    __doc__ = """Check that 2 or more repos agree data in common.

    Currently this only checks that the contents of inventories are the same in
    all repos.

    Use ``--verbose`` to get details of the differences.
    """
    
    takes_args = ['repository*']

    takes_options = ['revision', 'verbose']

    def run(self, revision=None, repository_list=None, verbose=False):
        if not repository_list or len(repository_list) < 2:
            raise errors.BzrCommandError("At least 2 repos required.")
        repos = []
        possible_transports = []
        for repo_path in repository_list:
            bd, leftover_path = bzrdir.BzrDir.open_containing(repo_path,
                    possible_transports=possible_transports)
            possible_transports.append(bd.root_transport)
            repo = bd.find_repository()
            self.add_cleanup(repo.lock_read().unlock)
            repos.append(repo)

        first_repo, other_repos = repos[0], repos[1:]
        assert other_repos
        common_inv_keys = set(first_repo.inventories.keys())
        all_inv_keys = set(common_inv_keys)
        for repo in other_repos:
            inv_keys = repo.inventories.keys()
            common_inv_keys.intersection_update(inv_keys)
            all_inv_keys.update(inv_keys)
        self.outf.write('%d common inventories to check (%d seen)\n' %
                (len(common_inv_keys), len(all_inv_keys)))
        trace.mutter('common invs: %r', common_inv_keys)
        #trace.mutter('all invs: %r', all_inv_keys)

        for inv_key in common_inv_keys:
            inv_id = inv_key[-1]
            first_inv = first_repo.get_inventory(inv_id)
            expected_root_1 = first_inv.id_to_entry.key()
            expected_root_2 = first_inv.parent_id_basename_to_file_id.key()
            for repo in other_repos:
                inv = repo.get_inventory(inv_id)
                root_1 = inv.id_to_entry.key()
                root_2 = inv.parent_id_basename_to_file_id.key()
                if root_1 != expected_root_1:
                    self.outf.write(
                        'disagree id_to_entry for %s: %r %r\n'
                        % (inv_id, expected_root_1, root_1))
                    if verbose:
                        self.outf.write(first_inv.id_to_entry._dump_tree(True))
                        self.outf.write(inv.id_to_entry._dump_tree(True))
                if root_2 != expected_root_2:
                    self.outf.write(
                        'disagree parent_id_basename_to_file_id for %s: %r %r\n'
                        % (inv_id, expected_root_2, root_2))
                    if verbose:
                        self.outf.write(first_inv.parent_id_basename_to_file_id._dump_tree(True))
                        self.outf.write(inv.parent_id_basename_to_file_id._dump_tree(True))


builtin_command_registry.register(cmd_cross_check)