~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/check.py

  • Committer: Martin Pool
  • Date: 2005-09-19 07:52:30 UTC
  • Revision ID: mbp@sourcefrog.net-20050919075230-bd8a133ef1671044
- remove RevisionReference; just hold parent ids directly

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