/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/check.py

  • Committer: Jelmer Vernooij
  • Date: 2017-10-27 00:18:42 UTC
  • mto: This revision was merged to the branch mainline in revision 6799.
  • Revision ID: jelmer@jelmer.uk-20171027001842-o77sekj0g2t2zwbn
Properly escape backslashes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
so that when the dependent object is checked, matches can be pulled out and
40
40
evaluated in-line rather than re-reading the same data many times.
41
41
check_refs are tuples (kind, value). Currently defined kinds are:
 
42
 
42
43
* 'trees', where value is a revid and the looked up objects are revision trees.
43
44
* 'lefthand-distance', where value is a revid and the looked up objects are the
44
45
  distance along the lefthand path to NULL for that revid.
46
47
  indicating that the revision was found/not found.
47
48
"""
48
49
 
49
 
from bzrlib import errors
50
 
from bzrlib.branch import Branch
51
 
from bzrlib.bzrdir import BzrDir
52
 
from bzrlib.revision import NULL_REVISION
53
 
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
54
 
from bzrlib.trace import note
55
 
import bzrlib.ui
56
 
from bzrlib.workingtree import WorkingTree
 
50
from __future__ import absolute_import
 
51
 
 
52
from . import (
 
53
    errors,
 
54
    ui,
 
55
    )
 
56
from .branch import Branch
 
57
from .controldir import ControlDir
 
58
from .revision import NULL_REVISION
 
59
from .sixish import (
 
60
    viewitems,
 
61
    )
 
62
from .trace import note
 
63
from .workingtree import WorkingTree
 
64
from .i18n import gettext
57
65
 
58
66
class Check(object):
59
67
    """Check a repository"""
60
68
 
 
69
    def __init__(self, repository, check_repo=True):
 
70
        self.repository = repository
 
71
 
 
72
    def report_results(self, verbose):
 
73
        raise NotImplementedError(self.report_results)
 
74
 
 
75
 
 
76
class VersionedFileCheck(Check):
 
77
    """Check a versioned file repository"""
 
78
 
61
79
    # The Check object interacts with InventoryEntry.check, etc.
62
80
 
63
81
    def __init__(self, repository, check_repo=True):
88
106
        if callback_refs is None:
89
107
            callback_refs = {}
90
108
        self.repository.lock_read()
91
 
        self.progress = bzrlib.ui.ui_factory.nested_progress_bar()
 
109
        self.progress = ui.ui_factory.nested_progress_bar()
92
110
        try:
93
 
            self.progress.update('check', 0, 4)
 
111
            self.progress.update(gettext('check'), 0, 4)
94
112
            if self.check_repo:
95
 
                self.progress.update('checking revisions', 0)
 
113
                self.progress.update(gettext('checking revisions'), 0)
96
114
                self.check_revisions()
97
 
                self.progress.update('checking commit contents', 1)
 
115
                self.progress.update(gettext('checking commit contents'), 1)
98
116
                self.repository._check_inventories(self)
99
 
                self.progress.update('checking file graphs', 2)
 
117
                self.progress.update(gettext('checking file graphs'), 2)
100
118
                # check_weaves is done after the revision scan so that
101
119
                # revision index is known to be valid.
102
120
                self.check_weaves()
103
 
            self.progress.update('checking branches and trees', 3)
 
121
            self.progress.update(gettext('checking branches and trees'), 3)
104
122
            if callback_refs:
105
123
                repo = self.repository
106
124
                # calculate all refs, and callback the objects requesting them.
113
131
                # landing].
114
132
                distances = set()
115
133
                existences = set()
116
 
                for ref, wantlist in callback_refs.iteritems():
 
134
                for ref, wantlist in viewitems(callback_refs):
117
135
                    wanting_items.update(wantlist)
118
136
                    kind, value = ref
119
137
                    if kind == 'trees':
126
144
                        raise AssertionError(
127
145
                            'unknown ref kind for ref %s' % ref)
128
146
                node_distances = repo.get_graph().find_lefthand_distances(distances)
129
 
                for key, distance in node_distances.iteritems():
 
147
                for key, distance in viewitems(node_distances):
130
148
                    refs[('lefthand-distance', key)] = distance
131
149
                    if key in existences and distance > 0:
132
150
                        refs[('revision-existence', key)] = True
163
181
 
164
182
    def check_revisions(self):
165
183
        """Scan revisions, checking data directly available as we go."""
166
 
        revision_iterator = self.repository._iter_revisions(None)
 
184
        revision_iterator = self.repository.iter_revisions(
 
185
            self.repository.all_revision_ids())
167
186
        revision_iterator = self._check_revisions(revision_iterator)
168
187
        # We read the all revisions here:
169
188
        # - doing this allows later code to depend on the revision index.
170
189
        # - we can fill out existence flags at this point
171
190
        # - we can read the revision inventory sha at this point
172
191
        # - we can check properties and serialisers etc.
173
 
        if not self.repository.revision_graph_can_have_wrong_parents():
 
192
        if not self.repository._format.revision_graph_can_have_wrong_parents:
174
193
            # The check against the index isn't needed.
175
194
            self.revs_with_bad_parents_in_index = None
176
195
            for thing in revision_iterator:
187
206
            result.report_results(verbose)
188
207
 
189
208
    def _report_repo_results(self, verbose):
190
 
        note('checked repository %s format %s',
 
209
        note(gettext('checked repository {0} format {1}').format(
191
210
            self.repository.user_url,
192
 
            self.repository._format)
193
 
        note('%6d revisions', self.checked_rev_cnt)
194
 
        note('%6d file-ids', len(self.checked_weaves))
 
211
            self.repository._format))
 
212
        note(gettext('%6d revisions'), self.checked_rev_cnt)
 
213
        note(gettext('%6d file-ids'), len(self.checked_weaves))
195
214
        if verbose:
196
 
            note('%6d unreferenced text versions',
 
215
            note(gettext('%6d unreferenced text versions'),
197
216
                len(self.unreferenced_versions))
198
217
        if verbose and len(self.unreferenced_versions):
199
218
                for file_id, revision_id in self.unreferenced_versions:
200
 
                    note('unreferenced version: {%s} in %s', revision_id,
201
 
                        file_id)
 
219
                    note(gettext('unreferenced version: {{{0}}} in {1}').format(revision_id,
 
220
                        file_id))
202
221
        if self.missing_inventory_sha_cnt:
203
 
            note('%6d revisions are missing inventory_sha1',
 
222
            note(gettext('%6d revisions are missing inventory_sha1'),
204
223
                 self.missing_inventory_sha_cnt)
205
224
        if self.missing_revision_cnt:
206
 
            note('%6d revisions are mentioned but not present',
 
225
            note(gettext('%6d revisions are mentioned but not present'),
207
226
                 self.missing_revision_cnt)
208
227
        if len(self.ghosts):
209
 
            note('%6d ghost revisions', len(self.ghosts))
 
228
            note(gettext('%6d ghost revisions'), len(self.ghosts))
210
229
            if verbose:
211
230
                for ghost in self.ghosts:
212
231
                    note('      %s', ghost)
213
232
        if len(self.missing_parent_links):
214
 
            note('%6d revisions missing parents in ancestry',
 
233
            note(gettext('%6d revisions missing parents in ancestry'),
215
234
                 len(self.missing_parent_links))
216
235
            if verbose:
217
 
                for link, linkers in self.missing_parent_links.items():
218
 
                    note('      %s should be in the ancestry for:', link)
 
236
                for link, linkers in viewitems(self.missing_parent_links):
 
237
                    note(gettext('      %s should be in the ancestry for:'), link)
219
238
                    for linker in linkers:
220
239
                        note('       * %s', linker)
221
240
        if len(self.inconsistent_parents):
222
 
            note('%6d inconsistent parents', len(self.inconsistent_parents))
 
241
            note(gettext('%6d inconsistent parents'), len(self.inconsistent_parents))
223
242
            if verbose:
224
243
                for info in self.inconsistent_parents:
225
244
                    revision_id, file_id, found_parents, correct_parents = info
226
 
                    note('      * %s version %s has parents %r '
227
 
                         'but should have %r'
228
 
                         % (file_id, revision_id, found_parents,
 
245
                    note(gettext('      * {0} version {1} has parents {2!r} '
 
246
                         'but should have {3!r}').format(
 
247
                         file_id, revision_id, found_parents,
229
248
                             correct_parents))
230
249
        if self.revs_with_bad_parents_in_index:
231
 
            note('%6d revisions have incorrect parents in the revision index',
 
250
            note(gettext(
 
251
                 '%6d revisions have incorrect parents in the revision index'),
232
252
                 len(self.revs_with_bad_parents_in_index))
233
253
            if verbose:
234
254
                for item in self.revs_with_bad_parents_in_index:
235
255
                    revision_id, index_parents, actual_parents = item
236
 
                    note(
237
 
                        '       %s has wrong parents in index: '
238
 
                        '%r should be %r',
239
 
                        revision_id, index_parents, actual_parents)
 
256
                    note(gettext(
 
257
                        '       {0} has wrong parents in index: '
 
258
                        '{1!r} should be {2!r}').format(
 
259
                        revision_id, index_parents, actual_parents))
240
260
        for item in self._report_items:
241
261
            note(item)
242
262
 
247
267
        :param rev: A revision or None to indicate a missing revision.
248
268
        """
249
269
        if rev.revision_id != rev_id:
250
 
            self._report_items.append(
251
 
                'Mismatched internal revid {%s} and index revid {%s}' % (
 
270
            self._report_items.append(gettext(
 
271
                'Mismatched internal revid {{{0}}} and index revid {{{1}}}').format(
252
272
                rev.revision_id, rev_id))
253
273
            rev_id = rev.revision_id
254
274
        # Check this revision tree etc, and count as seen when we encounter a
277
297
        existing = self.pending_keys.get(key)
278
298
        if existing:
279
299
            if sha1 != existing[1]:
280
 
                self._report_items.append('Multiple expected sha1s for %s. {%s}'
281
 
                    ' expects {%s}, {%s} expects {%s}', (
 
300
                self._report_items.append(gettext('Multiple expected sha1s for {0}. {{{1}}}'
 
301
                    ' expects {{{2}}}, {{{3}}} expects {{{4}}}').format(
282
302
                    key, referer, sha1, existing[1], existing[0]))
283
303
        else:
284
304
            self.pending_keys[key] = (kind, sha1, referer)
287
307
        """Check all the weaves we can get our hands on.
288
308
        """
289
309
        weave_ids = []
290
 
        storebar = bzrlib.ui.ui_factory.nested_progress_bar()
 
310
        storebar = ui.ui_factory.nested_progress_bar()
291
311
        try:
292
312
            self._check_weaves(storebar)
293
313
        finally:
304
324
                text_key_references=self.text_key_references,
305
325
                ancestors=self.ancestors)
306
326
        storebar.update('file-graph', 1)
307
 
        result = weave_checker.check_file_version_parents(
 
327
        wrongs, unused_versions = weave_checker.check_file_version_parents(
308
328
            self.repository.texts)
309
329
        self.checked_weaves = weave_checker.file_ids
310
 
        bad_parents, unused_versions = result
311
 
        bad_parents = bad_parents.items()
312
 
        for text_key, (stored_parents, correct_parents) in bad_parents:
 
330
        for text_key, (stored_parents, correct_parents) in viewitems(wrongs):
313
331
            # XXX not ready for id join/split operations.
314
332
            weave_id = text_key[0]
315
333
            revision_id = text_key[-1]
328
346
            self.text_key_references[key] = True
329
347
 
330
348
 
331
 
@deprecated_function(deprecated_in((1,6,0)))
332
 
def check(branch, verbose):
333
 
    """Run consistency checks on a branch.
334
 
 
335
 
    Results are reported through logging.
336
 
 
337
 
    Deprecated in 1.6.  Please use check_dwim instead.
338
 
 
339
 
    :raise BzrCheckError: if there's a consistency error.
340
 
    """
341
 
    check_branch(branch, verbose)
342
 
 
343
 
 
344
 
@deprecated_function(deprecated_in((1,16,0)))
345
 
def check_branch(branch, verbose):
346
 
    """Run consistency checks on a branch.
347
 
 
348
 
    Results are reported through logging.
349
 
 
350
 
    :raise BzrCheckError: if there's a consistency error.
351
 
    """
352
 
    branch.lock_read()
353
 
    try:
354
 
        needed_refs = {}
355
 
        for ref in branch._get_check_refs():
356
 
            needed_refs.setdefault(ref, []).append(branch)
357
 
        result = branch.repository.check([branch.last_revision()], needed_refs)
358
 
        branch_result = result.other_results[0]
359
 
    finally:
360
 
        branch.unlock()
361
 
    branch_result.report_results(verbose)
362
 
 
363
 
 
364
349
def scan_branch(branch, needed_refs, to_unlock):
365
350
    """Scan a branch for refs.
366
351
 
368
353
    :param needed_refs: Refs we are accumulating.
369
354
    :param to_unlock: The unlock list accumulating.
370
355
    """
371
 
    note("Checking branch at '%s'." % (branch.base,))
 
356
    note(gettext("Checking branch at '%s'.") % (branch.base,))
372
357
    branch.lock_read()
373
358
    to_unlock.append(branch)
374
359
    branch_refs = branch._get_check_refs()
388
373
    """
389
374
    if base_tree is not None and tree.basedir == base_tree.basedir:
390
375
        return
391
 
    note("Checking working tree at '%s'." % (tree.basedir,))
 
376
    note(gettext("Checking working tree at '%s'.") % (tree.basedir,))
392
377
    tree.lock_read()
393
378
    to_unlock.append(tree)
394
379
    tree_refs = tree._get_check_refs()
405
390
    """
406
391
    try:
407
392
        base_tree, branch, repo, relpath = \
408
 
                        BzrDir.open_containing_tree_branch_or_repository(path)
 
393
                        ControlDir.open_containing_tree_branch_or_repository(path)
409
394
    except errors.NotBranchError:
410
395
        base_tree = branch = repo = None
411
396
 
432
417
                for branch in branches:
433
418
                    if do_tree:
434
419
                        try:
435
 
                            tree = branch.bzrdir.open_workingtree()
 
420
                            tree = branch.controldir.open_workingtree()
436
421
                            saw_tree = True
437
422
                        except (errors.NotLocalUrl, errors.NoWorkingTree):
438
423
                            pass
441
426
                    if do_branch:
442
427
                        scan_branch(branch, needed_refs, to_unlock)
443
428
            if do_branch and not branches:
444
 
                note("No branch found at specified location.")
 
429
                note(gettext("No branch found at specified location."))
445
430
            if do_tree and base_tree is None and not saw_tree:
446
 
                note("No working tree found at specified location.")
 
431
                note(gettext("No working tree found at specified location."))
447
432
            if do_repo or do_branch or do_tree:
448
433
                if do_repo:
449
 
                    note("Checking repository at '%s'."
 
434
                    note(gettext("Checking repository at '%s'.")
450
435
                         % (repo.user_url,))
451
436
                result = repo.check(None, callback_refs=needed_refs,
452
437
                    check_repo=do_repo)
453
438
                result.report_results(verbose)
454
439
        else:
455
440
            if do_tree:
456
 
                note("No working tree found at specified location.")
 
441
                note(gettext("No working tree found at specified location."))
457
442
            if do_branch:
458
 
                note("No branch found at specified location.")
 
443
                note(gettext("No branch found at specified location."))
459
444
            if do_repo:
460
 
                note("No repository found at specified location.")
 
445
                note(gettext("No repository found at specified location."))
461
446
    finally:
462
447
        for thing in to_unlock:
463
448
            thing.unlock()