~bzr-pqm/bzr/bzr.dev

2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2005, 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1 by mbp at sourcefrog
import from baz patch-364
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1 by mbp at sourcefrog
import from baz patch-364
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1 by mbp at sourcefrog
import from baz patch-364
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
1335 by Martin Pool
doc
17
# TODO: Check ancestries are correct for every revision: includes
18
# every committed so far, and in a reasonable order.
19
1347 by Martin Pool
- refactor check code into method object
20
# TODO: Also check non-mainline revisions mentioned as parents.
21
22
# TODO: Check for extra files in the control directory.
23
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
24
# TODO: Check revision, inventory and entry objects have all
1348 by Martin Pool
- more refactoring of check code
25
# required fields.
26
1185.16.101 by mbp at sourcefrog
todo
27
# TODO: Get every revision in the revision-store even if they're not
28
# referenced by history and make sure they're all valid.
1347 by Martin Pool
- refactor check code into method object
29
1616.1.5 by Martin Pool
Cleanup and document some check code
30
# TODO: Perhaps have a way to record errors other than by raising exceptions;
31
# would perhaps be enough to accumulate exception objects in a list without
32
# raising them.  If there's more than one exception it'd be good to see them
33
# all.
34
3015.3.8 by Daniel Watkins
Added _scan_for_branches.
35
from bzrlib import errors, osutils
2745.6.16 by Aaron Bentley
Update from review
36
from bzrlib import repository as _mod_repository
2745.6.47 by Andrew Bennetts
Move check_parents out of VersionedFile.
37
from bzrlib import revision
3015.3.2 by Daniel Watkins
Check.check now takes a path rather than a branch.
38
from bzrlib.branch import Branch
3015.3.40 by Daniel Watkins
Modified bzrlib.check.check_dwim to use bzrlib.bzrdir.BzrDir.open_containing_tree_branch_or_repository.
39
from bzrlib.bzrdir import BzrDir
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
40
from bzrlib.errors import BzrCheckError
3015.3.3 by Daniel Watkins
Added _check_repository.
41
from bzrlib.repository import Repository
3015.3.59 by Daniel Watkins
Further tweaks as requested on-list.
42
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
3015.3.35 by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning.
43
from bzrlib.trace import log_error, note
1104 by Martin Pool
- Add a simple UIFactory
44
import bzrlib.ui
3015.3.11 by Daniel Watkins
Move WT checking from builtins to check.
45
from bzrlib.workingtree import WorkingTree
1104 by Martin Pool
- Add a simple UIFactory
46
1347 by Martin Pool
- refactor check code into method object
47
class Check(object):
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
48
    """Check a repository"""
1449 by Robert Collins
teach check about ghosts
49
1616.1.5 by Martin Pool
Cleanup and document some check code
50
    # The Check object interacts with InventoryEntry.check, etc.
51
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
52
    def __init__(self, repository):
53
        self.repository = repository
1383 by Martin Pool
- untabify only
54
        self.checked_text_cnt = 0
55
        self.checked_rev_cnt = 0
1449 by Robert Collins
teach check about ghosts
56
        self.ghosts = []
1365 by Martin Pool
- try to avoid checking texts repeatedly
57
        self.repeated_text_cnt = 0
1449 by Robert Collins
teach check about ghosts
58
        self.missing_parent_links = {}
1348 by Martin Pool
- more refactoring of check code
59
        self.missing_inventory_sha_cnt = 0
60
        self.missing_revision_cnt = 0
1616.1.5 by Martin Pool
Cleanup and document some check code
61
        # maps (file-id, version) -> sha1; used by InventoryFile._check
1365 by Martin Pool
- try to avoid checking texts repeatedly
62
        self.checked_texts = {}
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
63
        self.checked_weaves = set()
2988.1.8 by Robert Collins
Change check and reconcile to use the new _generate_text_key_index rather
64
        self.unreferenced_versions = set()
2745.6.33 by Andrew Bennetts
Add VersionedFile.check_parents, and use it instead of find_bad_ancestors in reconcile.
65
        self.inconsistent_parents = []
4145.2.1 by Ian Clatworthy
faster check
66
        self.rich_roots = repository.supports_rich_root()
67
        self.text_key_references = {}
676 by Martin Pool
- lock branch while checking
68
1449 by Robert Collins
teach check about ghosts
69
    def check(self):
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
70
        self.repository.lock_read()
1594.1.3 by Robert Collins
Fixup pb usage to use nested_progress_bar.
71
        self.progress = bzrlib.ui.ui_factory.nested_progress_bar()
1449 by Robert Collins
teach check about ghosts
72
        try:
2819.2.3 by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph.
73
            self.progress.update('retrieving inventory', 0, 2)
1510 by Robert Collins
Merge from mpool, adjusting check to retain HTTP support.
74
            # do not put in init, as it should be done with progess,
75
            # and inside the lock.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
76
            self.inventory_weave = self.repository.inventories
2819.2.3 by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph.
77
            self.progress.update('checking revision graph', 1)
78
            self.check_revision_graph()
1510 by Robert Collins
Merge from mpool, adjusting check to retain HTTP support.
79
            self.plan_revisions()
80
            revno = 0
81
            while revno < len(self.planned_revisions):
82
                rev_id = self.planned_revisions[revno]
83
                self.progress.update('checking revision', revno,
1449 by Robert Collins
teach check about ghosts
84
                                     len(self.planned_revisions))
1510 by Robert Collins
Merge from mpool, adjusting check to retain HTTP support.
85
                revno += 1
1449 by Robert Collins
teach check about ghosts
86
                self.check_one_rev(rev_id)
2745.6.16 by Aaron Bentley
Update from review
87
            # check_weaves is done after the revision scan so that
2988.1.8 by Robert Collins
Change check and reconcile to use the new _generate_text_key_index rather
88
            # revision index is known to be valid.
2745.6.3 by Aaron Bentley
Implement versionedfile checking for bzr check
89
            self.check_weaves()
1185.35.34 by Aaron Bentley
Made bzr check for stored revisions missing from ancestry
90
        finally:
1594.1.3 by Robert Collins
Fixup pb usage to use nested_progress_bar.
91
            self.progress.finished()
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
92
            self.repository.unlock()
1449 by Robert Collins
teach check about ghosts
93
2819.2.3 by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph.
94
    def check_revision_graph(self):
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
95
        if not self.repository.revision_graph_can_have_wrong_parents():
96
            # This check is not necessary.
2819.2.3 by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph.
97
            self.revs_with_bad_parents_in_index = None
98
            return
99
        bad_revisions = self.repository._find_inconsistent_revision_parents()
100
        self.revs_with_bad_parents_in_index = list(bad_revisions)
101
1510 by Robert Collins
Merge from mpool, adjusting check to retain HTTP support.
102
    def plan_revisions(self):
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
103
        repository = self.repository
3221.17.2 by Ian Clatworthy
back out unnecessary list() around repo.all_revision_ids in check.py
104
        self.planned_revisions = repository.all_revision_ids()
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
105
        self.progress.clear()
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
106
        inventoried = set(key[-1] for key in self.inventory_weave.keys())
2745.6.3 by Aaron Bentley
Implement versionedfile checking for bzr check
107
        awol = set(self.planned_revisions) - inventoried
1510 by Robert Collins
Merge from mpool, adjusting check to retain HTTP support.
108
        if len(awol) > 0:
109
            raise BzrCheckError('Stored revisions missing from inventory'
110
                '{%s}' % ','.join([f for f in awol]))
111
1449 by Robert Collins
teach check about ghosts
112
    def report_results(self, verbose):
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
113
        note('checked repository %s format %s',
114
             self.repository.bzrdir.root_transport,
115
             self.repository._format)
1365 by Martin Pool
- try to avoid checking texts repeatedly
116
        note('%6d revisions', self.checked_rev_cnt)
2745.6.47 by Andrew Bennetts
Move check_parents out of VersionedFile.
117
        note('%6d file-ids', len(self.checked_weaves))
1365 by Martin Pool
- try to avoid checking texts repeatedly
118
        note('%6d unique file texts', self.checked_text_cnt)
119
        note('%6d repeated file texts', self.repeated_text_cnt)
2988.1.8 by Robert Collins
Change check and reconcile to use the new _generate_text_key_index rather
120
        note('%6d unreferenced text versions',
121
             len(self.unreferenced_versions))
1348 by Martin Pool
- more refactoring of check code
122
        if self.missing_inventory_sha_cnt:
1449 by Robert Collins
teach check about ghosts
123
            note('%6d revisions are missing inventory_sha1',
1383 by Martin Pool
- untabify only
124
                 self.missing_inventory_sha_cnt)
1348 by Martin Pool
- more refactoring of check code
125
        if self.missing_revision_cnt:
1449 by Robert Collins
teach check about ghosts
126
            note('%6d revisions are mentioned but not present',
1383 by Martin Pool
- untabify only
127
                 self.missing_revision_cnt)
1449 by Robert Collins
teach check about ghosts
128
        if len(self.ghosts):
129
            note('%6d ghost revisions', len(self.ghosts))
130
            if verbose:
131
                for ghost in self.ghosts:
132
                    note('      %s', ghost)
133
        if len(self.missing_parent_links):
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
134
            note('%6d revisions missing parents in ancestry',
1449 by Robert Collins
teach check about ghosts
135
                 len(self.missing_parent_links))
136
            if verbose:
137
                for link, linkers in self.missing_parent_links.items():
138
                    note('      %s should be in the ancestry for:', link)
139
                    for linker in linkers:
140
                        note('       * %s', linker)
2745.6.6 by Aaron Bentley
Add unreferenced ancestors to check output
141
            if verbose:
2988.1.8 by Robert Collins
Change check and reconcile to use the new _generate_text_key_index rather
142
                for file_id, revision_id in self.unreferenced_versions:
143
                    log_error('unreferenced version: {%s} in %s', revision_id,
2745.6.6 by Aaron Bentley
Add unreferenced ancestors to check output
144
                        file_id)
2745.6.39 by Andrew Bennetts
Use scenario in test_check too, and make check actually report inconsistent parents to the end user.
145
        if len(self.inconsistent_parents):
146
            note('%6d inconsistent parents', len(self.inconsistent_parents))
147
            if verbose:
148
                for info in self.inconsistent_parents:
149
                    revision_id, file_id, found_parents, correct_parents = info
150
                    note('      * %s version %s has parents %r '
151
                         'but should have %r'
152
                         % (file_id, revision_id, found_parents,
153
                             correct_parents))
2819.2.3 by Andrew Bennetts
Add test that repo.check will report on wrong parents in the revision graph.
154
        if self.revs_with_bad_parents_in_index:
155
            note('%6d revisions have incorrect parents in the revision index',
156
                 len(self.revs_with_bad_parents_in_index))
157
            if verbose:
158
                for item in self.revs_with_bad_parents_in_index:
159
                    revision_id, index_parents, actual_parents = item
160
                    note(
161
                        '       %s has wrong parents in index: '
162
                        '%r should be %r',
163
                        revision_id, index_parents, actual_parents)
1449 by Robert Collins
teach check about ghosts
164
165
    def check_one_rev(self, rev_id):
1383 by Martin Pool
- untabify only
166
        """Check one revision.
167
168
        rev_id - the one to check
169
        """
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
170
        rev = self.repository.get_revision(rev_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
171
1383 by Martin Pool
- untabify only
172
        if rev.revision_id != rev_id:
173
            raise BzrCheckError('wrong internal revision id in revision {%s}'
174
                                % rev_id)
175
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
176
        for parent in rev.parent_ids:
177
            if not parent in self.planned_revisions:
4084.4.1 by Robert Collins
Minor comments clarifying check.py.
178
                # rev has a parent we didn't know about.
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
179
                missing_links = self.missing_parent_links.get(parent, [])
180
                missing_links.append(rev_id)
181
                self.missing_parent_links[parent] = missing_links
182
                # list based so somewhat slow,
183
                # TODO have a planned_revisions list and set.
184
                if self.repository.has_revision(parent):
185
                    missing_ancestry = self.repository.get_ancestry(parent)
186
                    for missing in missing_ancestry:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
187
                        if (missing is not None
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
188
                            and missing not in self.planned_revisions):
189
                            self.planned_revisions.append(missing)
1449 by Robert Collins
teach check about ghosts
190
                else:
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
191
                    self.ghosts.append(rev_id)
1383 by Martin Pool
- untabify only
192
193
        if rev.inventory_sha1:
4084.4.1 by Robert Collins
Minor comments clarifying check.py.
194
            # Loopback - this is currently circular logic as the
195
            # knit get_inventory_sha1 call returns rev.inventory_sha1.
196
            # Repository.py's get_inventory_sha1 should instead return
197
            # inventories.get_record_stream([(revid,)]).next().sha1 or
198
            # similar.
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
199
            inv_sha1 = self.repository.get_inventory_sha1(rev_id)
1383 by Martin Pool
- untabify only
200
            if inv_sha1 != rev.inventory_sha1:
201
                raise BzrCheckError('Inventory sha1 hash doesn\'t match'
202
                    ' value in revision {%s}' % rev_id)
203
        self._check_revision_tree(rev_id)
1362 by Martin Pool
- keep track of number of checked revisions
204
        self.checked_rev_cnt += 1
1349 by Martin Pool
- more refactoring of check code
205
1185.50.28 by John Arbash Meinel
Lots of updates for 'bzr check'
206
    def check_weaves(self):
207
        """Check all the weaves we can get our hands on.
208
        """
209
        weave_ids = []
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
210
        self.progress.update('checking inventory', 0, 2)
1185.50.28 by John Arbash Meinel
Lots of updates for 'bzr check'
211
        self.inventory_weave.check(progress_bar=self.progress)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
212
        self.progress.update('checking text storage', 1, 2)
213
        self.repository.texts.check(progress_bar=self.progress)
4145.2.1 by Ian Clatworthy
faster check
214
        weave_checker = self.repository._get_versioned_file_checker(
215
            text_key_references=self.text_key_references)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
216
        result = weave_checker.check_file_version_parents(
217
            self.repository.texts, progress_bar=self.progress)
218
        self.checked_weaves = weave_checker.file_ids
219
        bad_parents, unused_versions = result
220
        bad_parents = bad_parents.items()
221
        for text_key, (stored_parents, correct_parents) in bad_parents:
222
            # XXX not ready for id join/split operations.
223
            weave_id = text_key[0]
224
            revision_id = text_key[-1]
225
            weave_parents = tuple([parent[-1] for parent in stored_parents])
226
            correct_parents = tuple([parent[-1] for parent in correct_parents])
227
            self.inconsistent_parents.append(
228
                (revision_id, weave_id, weave_parents, correct_parents))
229
        self.unreferenced_versions.update(unused_versions)
1185.50.28 by John Arbash Meinel
Lots of updates for 'bzr check'
230
1349 by Martin Pool
- more refactoring of check code
231
    def _check_revision_tree(self, rev_id):
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
232
        tree = self.repository.revision_tree(rev_id)
1383 by Martin Pool
- untabify only
233
        inv = tree.inventory
4145.2.1 by Ian Clatworthy
faster check
234
        seen_ids = set()
235
        seen_names = set()
236
        for path, ie in inv.iter_entries():
237
            self._add_entry_to_text_key_references(inv, ie)
238
            file_id = ie.file_id
1383 by Martin Pool
- untabify only
239
            if file_id in seen_ids:
240
                raise BzrCheckError('duplicated file_id {%s} '
241
                                    'in inventory for revision {%s}'
242
                                    % (file_id, rev_id))
4145.2.1 by Ian Clatworthy
faster check
243
            seen_ids.add(file_id)
1092.2.20 by Robert Collins
symlink and weaves, whaddya know
244
            ie.check(self, rev_id, inv, tree)
1383 by Martin Pool
- untabify only
245
            if path in seen_names:
246
                raise BzrCheckError('duplicated path %s '
247
                                    'in inventory for revision {%s}'
248
                                    % (path, rev_id))
4145.2.1 by Ian Clatworthy
faster check
249
            seen_names.add(path)
250
251
    def _add_entry_to_text_key_references(self, inv, entry):
252
        if not self.rich_roots and entry == inv.root:
253
            return
254
        key = (entry.file_id, entry.revision)
255
        self.text_key_references.setdefault(key, False)
256
        if entry.revision == inv.revision_id:
257
            self.text_key_references[key] = True
1349 by Martin Pool
- more refactoring of check code
258
1347 by Martin Pool
- refactor check code into method object
259
3015.3.59 by Daniel Watkins
Further tweaks as requested on-list.
260
@deprecated_function(deprecated_in((1,6,0)))
3015.3.35 by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning.
261
def check(branch, verbose):
262
    """Run consistency checks on a branch.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
263
3015.3.35 by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning.
264
    Results are reported through logging.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
265
3015.3.58 by Daniel Watkins
Various other cleanup as requested by reviews.
266
    Deprecated in 1.6.  Please use check_branch instead.
3015.3.37 by Daniel Watkins
Added deprecation comment to docstring.
267
3015.3.35 by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning.
268
    :raise BzrCheckError: if there's a consistency error.
269
    """
270
    check_branch(branch, verbose)
271
272
3015.3.7 by Daniel Watkins
Fixed failing tests.
273
def check_branch(branch, verbose):
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
274
    """Run consistency checks on a branch.
3015.3.35 by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning.
275
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
276
    Results are reported through logging.
3015.3.35 by Daniel Watkins
Reintroduced bzrlib.check.check() with a deprecation warning.
277
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
278
    :raise BzrCheckError: if there's a consistency error.
279
    """
280
    branch.lock_read()
281
    try:
282
        branch_result = branch.check()
283
    finally:
284
        branch.unlock()
285
    branch_result.report_results(verbose)
2745.6.47 by Andrew Bennetts
Move check_parents out of VersionedFile.
286
287
3015.4.5 by Daniel Watkins
Each option selects only the specific thing to be checked.
288
def check_dwim(path, verbose, do_branch=False, do_repo=False, do_tree=False):
3015.4.16 by Daniel Watkins
Added implementation of error reporting when objects are missing.
289
    try:
290
        tree, branch, repo, relpath = \
3015.4.11 by Daniel Watkins
Fixed long line.
291
                        BzrDir.open_containing_tree_branch_or_repository(path)
3015.4.16 by Daniel Watkins
Added implementation of error reporting when objects are missing.
292
    except errors.NotBranchError:
293
        tree = branch = repo = None
3015.3.23 by Daniel Watkins
Abstracted discovery of elements away.
294
3015.4.5 by Daniel Watkins
Each option selects only the specific thing to be checked.
295
    if do_tree:
296
        if tree is not None:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
297
            note("Checking working tree at '%s'."
3015.4.5 by Daniel Watkins
Each option selects only the specific thing to be checked.
298
                 % (tree.bzrdir.root_transport.base,))
3015.4.10 by Daniel Watkins
Merged check changes.
299
            tree._check()
3015.4.16 by Daniel Watkins
Added implementation of error reporting when objects are missing.
300
        else:
301
            log_error("No working tree found at specified location.")
3015.3.23 by Daniel Watkins
Abstracted discovery of elements away.
302
3015.4.5 by Daniel Watkins
Each option selects only the specific thing to be checked.
303
    if branch is not None:
3015.3.20 by Daniel Watkins
Made code path a little clearer.
304
        # We have a branch
3015.3.5 by Daniel Watkins
Removed needless duplication of repository checks.
305
        if repo is None:
3015.3.10 by Daniel Watkins
Reorganised comments.
306
            # The branch is in a shared repository
3015.3.5 by Daniel Watkins
Removed needless duplication of repository checks.
307
            repo = branch.repository
3015.3.18 by Daniel Watkins
Improved errors.
308
        branches = [branch]
3015.3.59 by Daniel Watkins
Further tweaks as requested on-list.
309
    elif repo is not None:
310
        branches = repo.find_branches(using=True)
3015.3.9 by Daniel Watkins
Scan for branches and check them.
311
3015.3.4 by Daniel Watkins
If not in a branch or a repo, that check is simply skipped.
312
    if repo is not None:
3015.3.21 by Daniel Watkins
Fixed misused 'repository'.
313
        repo.lock_read()
3015.3.19 by Daniel Watkins
Repositories are now held read-locked for as long as possible.
314
        try:
3015.4.3 by Daniel Watkins
Implemented CLI options.
315
            if do_repo:
316
                note("Checking repository at '%s'."
317
                     % (repo.bzrdir.root_transport.base,))
318
                result = repo.check()
319
                result.report_results(verbose)
320
            if do_branch:
3015.4.16 by Daniel Watkins
Added implementation of error reporting when objects are missing.
321
                if branches == []:
322
                    log_error("No branch found at specified location.")
323
                else:
324
                    for branch in branches:
325
                        note("Checking branch at '%s'."
326
                             % (branch.bzrdir.root_transport.base,))
327
                        check_branch(branch, verbose)
3015.3.19 by Daniel Watkins
Repositories are now held read-locked for as long as possible.
328
        finally:
3015.3.21 by Daniel Watkins
Fixed misused 'repository'.
329
            repo.unlock()
3015.4.16 by Daniel Watkins
Added implementation of error reporting when objects are missing.
330
    else:
331
        if do_branch:
332
            log_error("No branch found at specified location.")
333
        if do_repo:
334
            log_error("No repository found at specified location.")