~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/check.py

  • Committer: Martin Pool
  • Date: 2005-09-20 08:06:24 UTC
  • Revision ID: mbp@sourcefrog.net-20050920080624-25bfe88297f9eaa2
- doc

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
17
 
 
18
# TODO: Check ancestries are correct for every revision: includes
 
19
# every committed so far, and in a reasonable order.
 
20
 
 
21
import bzrlib.ui
 
22
from bzrlib.trace import note, warning
 
23
from bzrlib.osutils import rename, sha_string
18
24
 
19
25
def _update_store_entry(obj, obj_id, branch, store_name, store):
20
26
    """This is just a meta-function, which handles both revision entries
22
28
    """
23
29
    from bzrlib.trace import mutter
24
30
    import tempfile, os, errno
25
 
    from osutils import rename
26
31
    obj_tmp = tempfile.TemporaryFile()
27
32
    obj.write_xml(obj_tmp)
28
33
    obj_tmp.seek(0)
70
75
    :param inv_id:  The inventory id for this inventory
71
76
    :param branch:  The Branch where this entry will be stored.
72
77
    """
73
 
    _update_store_entry(inv, inv_id, branch,
74
 
            'inventory-store', branch.inventory_store)
 
78
    raise NotImplementedError("can't update existing inventory entry")
 
79
 
75
80
 
76
81
def check(branch):
77
82
    """Run consistency checks on a branch.
81
86
    TODO: Check for extra files in the control directory.
82
87
    """
83
88
    from bzrlib.trace import mutter
84
 
    from bzrlib.errors import BzrCheckError
 
89
    from bzrlib.errors import BzrCheckError, NoSuchRevision
85
90
    from bzrlib.osutils import fingerprint_file
86
 
    from bzrlib.progress import ProgressBar
87
91
    from bzrlib.inventory import ROOT_ID
88
92
    from bzrlib.branch import gen_root_id
89
93
 
90
94
    branch.lock_read()
91
95
 
92
96
    try:
93
 
        pb = ProgressBar(show_spinner=True)
94
97
        last_rev_id = None
95
98
 
96
99
        missing_inventory_sha_cnt = 0
97
100
        missing_revision_sha_cnt = 0
 
101
        missing_revision_cnt = 0
98
102
 
99
103
        history = branch.revision_history()
100
104
        revno = 0
101
105
        revcount = len(history)
102
 
        mismatch_inv_id = []
103
 
 
104
 
        # for all texts checked, text_id -> sha1
105
 
        checked_texts = {}
 
106
 
 
107
        checked_text_count = 0
 
108
 
 
109
        progress = bzrlib.ui.ui_factory.progress_bar()
106
110
 
107
111
        for rev_id in history:
108
112
            revno += 1
109
 
            pb.update('checking revision', revno, revcount)
110
 
            mutter('    revision {%s}' % rev_id)
 
113
            progress.update('checking revision', revno, revcount)
 
114
            # mutter('    revision {%s}' % rev_id)
111
115
            rev = branch.get_revision(rev_id)
112
116
            if rev.revision_id != rev_id:
113
117
                raise BzrCheckError('wrong internal revision id in revision {%s}'
114
118
                                    % rev_id)
115
119
 
116
120
            # check the previous history entry is a parent of this entry
117
 
            if rev.parents:
 
121
            if rev.parent_ids:
118
122
                if last_rev_id is None:
119
123
                    raise BzrCheckError("revision {%s} has %d parents, but is the "
120
124
                                        "start of the branch"
121
 
                                        % (rev_id, len(rev.parents)))
122
 
                for prr in rev.parents:
123
 
                    if prr.revision_id == last_rev_id:
 
125
                                        % (rev_id, len(rev.parent_ids)))
 
126
                for parent_id in rev.parent_ids:
 
127
                    if parent_id == last_rev_id:
124
128
                        break
125
129
                else:
126
130
                    raise BzrCheckError("previous revision {%s} not listed among "
127
131
                                        "parents of {%s}"
128
132
                                        % (last_rev_id, rev_id))
129
 
 
130
 
                for prr in rev.parents:
131
 
                    if prr.revision_sha1 is None:
132
 
                        missing_revision_sha_cnt += 1
133
 
                        continue
134
 
                    prid = prr.revision_id
135
 
                    actual_sha = branch.get_revision_sha1(prid)
136
 
                    if prr.revision_sha1 != actual_sha:
137
 
                        raise BzrCheckError("mismatched revision sha1 for "
138
 
                                            "parent {%s} of {%s}: %s vs %s"
139
 
                                            % (prid, rev_id,
140
 
                                               prr.revision_sha1, actual_sha))
141
133
            elif last_rev_id:
142
 
                raise BzrCheckError("revision {%s} has no parents listed but preceded "
143
 
                                    "by {%s}"
 
134
                raise BzrCheckError("revision {%s} has no parents listed "
 
135
                                    "but preceded by {%s}"
144
136
                                    % (rev_id, last_rev_id))
145
137
 
146
 
            if rev.inventory_id != rev_id:
147
 
                mismatch_inv_id.append(rev_id)
148
 
 
149
138
            ## TODO: Check all the required fields are present on the revision.
150
139
 
151
140
            if rev.inventory_sha1:
152
 
                inv_sha1 = branch.get_inventory_sha1(rev.inventory_id)
 
141
                inv_sha1 = branch.get_inventory_sha1(rev_id)
153
142
                if inv_sha1 != rev.inventory_sha1:
154
143
                    raise BzrCheckError('Inventory sha1 hash doesn\'t match'
155
144
                        ' value in revision {%s}' % rev_id)
157
146
                missing_inventory_sha_cnt += 1
158
147
                mutter("no inventory_sha1 on revision {%s}" % rev_id)
159
148
 
160
 
            inv = branch.get_inventory(rev.inventory_id)
 
149
            tree = branch.revision_tree(rev_id)
 
150
            inv = tree.inventory
161
151
            seen_ids = {}
162
152
            seen_names = {}
163
153
 
173
163
            for file_id in inv:
174
164
                i += 1
175
165
                if i & 31 == 0:
176
 
                    pb.tick()
 
166
                    progress.tick()
177
167
 
178
168
                ie = inv[file_id]
179
169
 
183
173
                                % (ie.parent_id, rev_id))
184
174
 
185
175
                if ie.kind == 'file':
186
 
                    if ie.text_id in checked_texts:
187
 
                        fp = checked_texts[ie.text_id]
188
 
                    else:
189
 
                        if not ie.text_id in branch.text_store:
190
 
                            raise BzrCheckError('text {%s} not in text_store' % ie.text_id)
191
 
 
192
 
                        tf = branch.text_store[ie.text_id]
193
 
                        fp = fingerprint_file(tf)
194
 
                        checked_texts[ie.text_id] = fp
195
 
 
196
 
                    if ie.text_size != fp['size']:
 
176
                    text = tree.get_file_text(file_id)
 
177
                    checked_text_count += 1 
 
178
                    if ie.text_size != len(text):
197
179
                        raise BzrCheckError('text {%s} wrong size' % ie.text_id)
198
 
                    if ie.text_sha1 != fp['sha1']:
 
180
                    if ie.text_sha1 != sha_string(text):
199
181
                        raise BzrCheckError('text {%s} wrong sha1' % ie.text_id)
200
182
                elif ie.kind == 'directory':
201
183
                    if ie.text_sha1 != None or ie.text_size != None or ie.text_id != None:
202
184
                        raise BzrCheckError('directory {%s} has text in revision {%s}'
203
185
                                % (file_id, rev_id))
204
186
 
205
 
            pb.tick()
 
187
            progress.tick()
206
188
            for path, ie in inv.iter_entries():
207
189
                if path in seen_names:
208
190
                    raise BzrCheckError('duplicated path %s '
209
191
                                        'in inventory for revision {%s}'
210
192
                                        % (path, rev_id))
211
 
            seen_names[path] = True
 
193
                seen_names[path] = True
212
194
            last_rev_id = rev_id
213
195
 
214
196
    finally:
215
197
        branch.unlock()
216
198
 
217
 
    pb.clear()
 
199
    progress.clear()
218
200
 
219
 
    print 'checked %d revisions, %d file texts' % (revcount, len(checked_texts))
 
201
    note('checked %d revisions, %d file texts' % (revcount, checked_text_count))
220
202
    
221
203
    if missing_inventory_sha_cnt:
222
 
        print '%d revisions are missing inventory_sha1' % missing_inventory_sha_cnt
223
 
 
224
 
    if missing_revision_sha_cnt:
225
 
        print '%d parent links are missing revision_sha1' % missing_revision_sha_cnt
226
 
 
227
 
    if (missing_inventory_sha_cnt
228
 
        or missing_revision_sha_cnt):
229
 
        print '  (use "bzr upgrade" to fix them)'
230
 
 
231
 
    if mismatch_inv_id:
232
 
        print '%d revisions have mismatched inventory ids:' % len(mismatch_inv_id)
233
 
        for rev_id in mismatch_inv_id:
234
 
            print '  ', rev_id
 
204
        note('%d revisions are missing inventory_sha1' % missing_inventory_sha_cnt)
 
205
 
 
206
    ##if missing_revision_sha_cnt:
 
207
    ##    note('%d parent links are missing revision_sha1' % missing_revision_sha_cnt)
 
208
 
 
209
    if missing_revision_cnt:
 
210
        note('%d revisions are mentioned but not present' % missing_revision_cnt)
 
211
 
 
212
    if missing_revision_cnt:
 
213
        print '%d revisions are mentioned but not present' % missing_revision_cnt
 
214
 
 
215
    # stub this out for now because the main bzr branch has references
 
216
    # to revisions that aren't present in the store -- mbp 20050804
 
217
#    if (missing_inventory_sha_cnt
 
218
#        or missing_revision_sha_cnt):
 
219
#        print '  (use "bzr upgrade" to fix them)'