~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/check.py

  • Committer: Martin Pool
  • Date: 2005-06-20 02:50:08 UTC
  • Revision ID: mbp@sourcefrog.net-20050620025008-43e29d64489fe946
- split out a new 'bzr upgrade' command separate from 
  (but based on) 'bzr check', so that the code in each is simpler

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
 
20
20
 
21
 
def check(branch, update=False):
 
21
def check(branch):
22
22
    """Run consistency checks on a branch.
23
 
 
24
 
    If update is True, for revisions missing certain information
25
 
    (right now this is inventory_sha1 and revision_sha1),
26
 
    update them to include the appropriate values.
27
23
    """
28
 
    import sys
29
 
 
30
24
    from bzrlib.trace import mutter
31
25
    from bzrlib.errors import BzrCheckError
32
26
    from bzrlib.osutils import fingerprint_file
33
27
    from bzrlib.progress import ProgressBar
34
28
 
35
 
    if update:
36
 
        branch.lock_write()
37
 
    else:
38
 
        branch.lock_read()
 
29
    branch.lock_read()
39
30
 
40
31
    try:
41
 
 
42
 
        out = sys.stdout
43
 
 
44
32
        pb = ProgressBar(show_spinner=True)
45
33
        last_ptr = None
46
34
        checked_revs = {}
53
41
 
54
42
        checked_texts = {}
55
43
 
56
 
        updated_revisions = []
57
 
 
58
 
        # Set to True in the case that the previous revision entry
59
 
        # was updated, since this will affect future revision entries
60
 
        updated_previous_revision = False
61
 
 
62
 
        for rid in history:
 
44
        for rev_id in history:
63
45
            revno += 1
64
46
            pb.update('checking revision', revno, revcount)
65
 
            mutter('    revision {%s}' % rid)
66
 
            rev = branch.get_revision(rid)
67
 
            if rev.revision_id != rid:
68
 
                raise BzrCheckError('wrong internal revision id in revision {%s}' % rid)
 
47
            mutter('    revision {%s}' % rev_id)
 
48
            rev = branch.get_revision(rev_id)
 
49
            if rev.revision_id != rev_id:
 
50
                raise BzrCheckError('wrong internal revision id in revision {%s}' % rev_id)
69
51
            if rev.precursor != last_ptr:
70
 
                raise BzrCheckError('mismatched precursor in revision {%s}' % rid)
71
 
            last_ptr = rid
72
 
            if rid in checked_revs:
73
 
                raise BzrCheckError('repeated revision {%s}' % rid)
74
 
            checked_revs[rid] = True
 
52
                raise BzrCheckError('mismatched precursor in revision {%s}' % rev_id)
 
53
            last_ptr = rev_id
 
54
            if rev_id in checked_revs:
 
55
                raise BzrCheckError('repeated revision {%s}' % rev_id)
 
56
            checked_revs[rev_id] = True
75
57
 
76
58
            ## TODO: Check all the required fields are present on the revision.
77
59
 
78
 
            updated = False
79
60
            if rev.inventory_sha1:
80
 
                #mutter('    checking inventory hash {%s}' % rev.inventory_sha1)
81
61
                inv_sha1 = branch.get_inventory_sha1(rev.inventory_id)
82
62
                if inv_sha1 != rev.inventory_sha1:
83
63
                    raise BzrCheckError('Inventory sha1 hash doesn\'t match'
84
 
                        ' value in revision {%s}' % rid)
85
 
            elif update:
86
 
                inv_sha1 = branch.get_inventory_sha1(rev.inventory_id)
87
 
                rev.inventory_sha1 = inv_sha1
88
 
                updated = True
 
64
                        ' value in revision {%s}' % rev_id)
89
65
            else:
90
66
                missing_inventory_sha_cnt += 1
91
 
                mutter("no inventory_sha1 on revision {%s}" % rid)
 
67
                mutter("no inventory_sha1 on revision {%s}" % rev_id)
92
68
 
93
69
            if rev.precursor:
94
70
                if rev.precursor_sha1:
95
71
                    precursor_sha1 = branch.get_revision_sha1(rev.precursor)
96
 
                    if updated_previous_revision: 
97
 
                        # we don't expect the hashes to match, because
98
 
                        # we had to modify the previous revision_history entry.
99
 
                        rev.precursor_sha1 = precursor_sha1
100
 
                        updated = True
101
 
                    else:
102
 
                        #mutter('    checking precursor hash {%s}' % rev.precursor_sha1)
103
 
                        if rev.precursor_sha1 != precursor_sha1:
104
 
                            raise BzrCheckError('Precursor sha1 hash doesn\'t match'
105
 
                                ' value in revision {%s}' % rid)
106
 
                elif update:
107
 
                    precursor_sha1 = branch.get_revision_sha1(rev.precursor)
108
 
                    rev.precursor_sha1 = precursor_sha1
109
 
                    updated = True
110
 
 
111
 
            if updated:
112
 
                updated_previous_revision = True
113
 
                # We had to update this revision entries hashes
114
 
                # Now we need to write out a new value
115
 
                # This is a little bit invasive, since we are *rewriting* a
116
 
                # revision entry. I'm not supremely happy about it, but
117
 
                # there should be *some* way of making old entries have
118
 
                # the full meta information.
119
 
                import tempfile, os, errno
120
 
                rev_tmp = tempfile.TemporaryFile()
121
 
                rev.write_xml(rev_tmp)
122
 
                rev_tmp.seek(0)
123
 
 
124
 
                tmpfd, tmp_path = tempfile.mkstemp(prefix=rid, suffix='.gz',
125
 
                    dir=branch.controlfilename('revision-store'))
126
 
                os.close(tmpfd)
127
 
                def special_rename(p1, p2):
128
 
                    if sys.platform == 'win32':
129
 
                        try:
130
 
                            os.remove(p2)
131
 
                        except OSError, e:
132
 
                            if e.errno != e.ENOENT:
133
 
                                raise
134
 
                    os.rename(p1, p2)
135
 
 
136
 
                try:
137
 
                    # TODO: We may need to handle the case where the old revision
138
 
                    # entry was not compressed (and thus did not end with .gz)
139
 
 
140
 
                    # Remove the old revision entry out of the way
141
 
                    rev_path = branch.controlfilename(['revision-store', rid+'.gz'])
142
 
                    special_rename(rev_path, tmp_path)
143
 
                    branch.revision_store.add(rev_tmp, rid) # Add the new one
144
 
                    os.remove(tmp_path) # Remove the old name
145
 
                    mutter('    Updated revision entry {%s}' % rid)
146
 
                except:
147
 
                    # On any exception, restore the old entry
148
 
                    special_rename(tmp_path, rev_path)
149
 
                    raise
150
 
                rev_tmp.close()
151
 
                updated_revisions.append(rid)
152
 
            else:
153
 
                updated_previous_revision = False
 
72
                    #mutter('    checking precursor hash {%s}' % rev.precursor_sha1)
 
73
                    if rev.precursor_sha1 != precursor_sha1:
 
74
                        raise BzrCheckError('Precursor sha1 hash doesn\'t match'
 
75
                            ' value in revision {%s}' % rev_id)
154
76
 
155
77
            inv = branch.get_inventory(rev.inventory_id)
156
78
            seen_ids = {}
161
83
                if file_id in seen_ids:
162
84
                    raise BzrCheckError('duplicated file_id {%s} '
163
85
                                        'in inventory for revision {%s}'
164
 
                                        % (file_id, rid))
 
86
                                        % (file_id, rev_id))
165
87
                seen_ids[file_id] = True
166
88
 
167
89
            i = 0
168
 
            len_inv = len(inv)
169
90
            for file_id in inv:
170
91
                i += 1
171
92
                if i & 31 == 0:
176
97
                if ie.parent_id != None:
177
98
                    if ie.parent_id not in seen_ids:
178
99
                        raise BzrCheckError('missing parent {%s} in inventory for revision {%s}'
179
 
                                % (ie.parent_id, rid))
 
100
                                % (ie.parent_id, rev_id))
180
101
 
181
102
                if ie.kind == 'file':
182
103
                    if ie.text_id in checked_texts:
196
117
                elif ie.kind == 'directory':
197
118
                    if ie.text_sha1 != None or ie.text_size != None or ie.text_id != None:
198
119
                        raise BzrCheckError('directory {%s} has text in revision {%s}'
199
 
                                % (file_id, rid))
 
120
                                % (file_id, rev_id))
200
121
 
201
122
            pb.tick()
202
123
            for path, ie in inv.iter_entries():
203
124
                if path in seen_names:
204
 
                    raise BzrCheckError('duplicated path %r '
 
125
                    raise BzrCheckError('duplicated path %s '
205
126
                                        'in inventory for revision {%s}'
206
 
                                        % (path, revid))
 
127
                                        % (path, rev_id))
207
128
            seen_names[path] = True
208
129
 
209
130
    finally:
212
133
    pb.clear()
213
134
 
214
135
    print 'checked %d revisions, %d file texts' % (revcount, len(checked_texts))
215
 
    if updated_revisions:
216
 
        print '%d revisions updated to current format' % len(updated_revisions)
217
136
    if missing_inventory_sha_cnt:
218
137
        print '%d revisions are missing inventory_sha1' % missing_inventory_sha_cnt
219
 
        print '  (use bzr check --update to fix them)'
 
138
        print '  (use "bzr upgrade" to fix them)'