~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/check.py

  • Committer: Vincent Ladeuil
  • Date: 2009-06-22 12:52:39 UTC
  • mto: (4471.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4472.
  • Revision ID: v.ladeuil+lp@free.fr-20090622125239-kabo9smxt9c3vnir
Use a consistent scheme for naming pyrex source files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
# TODO: Check ancestries are correct for every revision: includes
18
18
# every committed so far, and in a reasonable order.
21
21
 
22
22
# TODO: Check for extra files in the control directory.
23
23
 
24
 
# TODO: Check revision, inventory and entry objects have all 
 
24
# TODO: Check revision, inventory and entry objects have all
25
25
# required fields.
26
26
 
27
27
# TODO: Get every revision in the revision-store even if they're not
32
32
# raising them.  If there's more than one exception it'd be good to see them
33
33
# all.
34
34
 
35
 
from bzrlib import errors
 
35
from bzrlib import errors, osutils
36
36
from bzrlib import repository as _mod_repository
37
37
from bzrlib import revision
 
38
from bzrlib.branch import Branch
 
39
from bzrlib.bzrdir import BzrDir
38
40
from bzrlib.errors import BzrCheckError
 
41
from bzrlib.repository import Repository
 
42
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
 
43
from bzrlib.trace import log_error, note
39
44
import bzrlib.ui
40
 
from bzrlib.trace import log_error, note
 
45
from bzrlib.workingtree import WorkingTree
41
46
 
42
47
class Check(object):
43
48
    """Check a repository"""
55
60
        self.missing_revision_cnt = 0
56
61
        # maps (file-id, version) -> sha1; used by InventoryFile._check
57
62
        self.checked_texts = {}
58
 
        self.checked_weaves = {}
 
63
        self.checked_weaves = set()
59
64
        self.unreferenced_versions = set()
60
65
        self.inconsistent_parents = []
 
66
        self.rich_roots = repository.supports_rich_root()
 
67
        self.text_key_references = {}
61
68
 
62
69
    def check(self):
63
70
        self.repository.lock_read()
66
73
            self.progress.update('retrieving inventory', 0, 2)
67
74
            # do not put in init, as it should be done with progess,
68
75
            # and inside the lock.
69
 
            self.inventory_weave = self.repository.get_inventory_weave()
 
76
            self.inventory_weave = self.repository.inventories
70
77
            self.progress.update('checking revision graph', 1)
71
78
            self.check_revision_graph()
72
79
            self.plan_revisions()
96
103
        repository = self.repository
97
104
        self.planned_revisions = repository.all_revision_ids()
98
105
        self.progress.clear()
99
 
        inventoried = set(self.inventory_weave.versions())
 
106
        inventoried = set(key[-1] for key in self.inventory_weave.keys())
100
107
        awol = set(self.planned_revisions) - inventoried
101
108
        if len(awol) > 0:
102
109
            raise BzrCheckError('Stored revisions missing from inventory'
161
168
        rev_id - the one to check
162
169
        """
163
170
        rev = self.repository.get_revision(rev_id)
164
 
                
 
171
 
165
172
        if rev.revision_id != rev_id:
166
173
            raise BzrCheckError('wrong internal revision id in revision {%s}'
167
174
                                % rev_id)
168
175
 
169
176
        for parent in rev.parent_ids:
170
177
            if not parent in self.planned_revisions:
 
178
                # rev has a parent we didn't know about.
171
179
                missing_links = self.missing_parent_links.get(parent, [])
172
180
                missing_links.append(rev_id)
173
181
                self.missing_parent_links[parent] = missing_links
176
184
                if self.repository.has_revision(parent):
177
185
                    missing_ancestry = self.repository.get_ancestry(parent)
178
186
                    for missing in missing_ancestry:
179
 
                        if (missing is not None 
 
187
                        if (missing is not None
180
188
                            and missing not in self.planned_revisions):
181
189
                            self.planned_revisions.append(missing)
182
190
                else:
183
191
                    self.ghosts.append(rev_id)
184
192
 
185
193
        if rev.inventory_sha1:
 
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.
186
199
            inv_sha1 = self.repository.get_inventory_sha1(rev_id)
187
200
            if inv_sha1 != rev.inventory_sha1:
188
201
                raise BzrCheckError('Inventory sha1 hash doesn\'t match'
193
206
    def check_weaves(self):
194
207
        """Check all the weaves we can get our hands on.
195
208
        """
196
 
        n_weaves = 1
197
209
        weave_ids = []
198
 
        if self.repository.weave_store.listable():
199
 
            weave_ids = list(self.repository.weave_store)
200
 
            n_weaves = len(weave_ids) + 1
201
 
        self.progress.update('checking versionedfile', 0, n_weaves)
 
210
        self.progress.update('checking inventory', 0, 2)
202
211
        self.inventory_weave.check(progress_bar=self.progress)
203
 
        files_in_revisions = {}
204
 
        revisions_of_files = {}
205
 
        weave_checker = self.repository._get_versioned_file_checker()
206
 
        for i, weave_id in enumerate(weave_ids):
207
 
            self.progress.update('checking versionedfile', i, n_weaves)
208
 
            w = self.repository.weave_store.get_weave(weave_id,
209
 
                    self.repository.get_transaction())
210
 
            # No progress here, because it looks ugly.
211
 
            w.check()
212
 
            result = weave_checker.check_file_version_parents(w, weave_id)
213
 
            bad_parents, unused_versions = result
214
 
            bad_parents = bad_parents.items()
215
 
            for revision_id, (weave_parents, correct_parents) in bad_parents:
216
 
                self.inconsistent_parents.append(
217
 
                    (revision_id, weave_id, weave_parents, correct_parents))
218
 
            for revision_id in unused_versions:
219
 
                self.unreferenced_versions.add((weave_id, revision_id))
220
 
            self.checked_weaves[weave_id] = True
 
212
        self.progress.update('checking text storage', 1, 2)
 
213
        self.repository.texts.check(progress_bar=self.progress)
 
214
        weave_checker = self.repository._get_versioned_file_checker(
 
215
            text_key_references=self.text_key_references)
 
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)
221
230
 
222
231
    def _check_revision_tree(self, rev_id):
223
232
        tree = self.repository.revision_tree(rev_id)
224
233
        inv = tree.inventory
225
 
        seen_ids = {}
226
 
        for file_id in inv:
 
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
227
239
            if file_id in seen_ids:
228
240
                raise BzrCheckError('duplicated file_id {%s} '
229
241
                                    'in inventory for revision {%s}'
230
242
                                    % (file_id, rev_id))
231
 
            seen_ids[file_id] = True
232
 
        for file_id in inv:
233
 
            ie = inv[file_id]
 
243
            seen_ids.add(file_id)
234
244
            ie.check(self, rev_id, inv, tree)
235
 
        seen_names = {}
236
 
        for path, ie in inv.iter_entries():
237
245
            if path in seen_names:
238
246
                raise BzrCheckError('duplicated path %s '
239
247
                                    'in inventory for revision {%s}'
240
248
                                    % (path, rev_id))
241
 
            seen_names[path] = True
242
 
 
243
 
 
 
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
 
258
 
 
259
 
 
260
@deprecated_function(deprecated_in((1,6,0)))
244
261
def check(branch, verbose):
245
262
    """Run consistency checks on a branch.
246
 
    
247
 
    Results are reported through logging.
248
 
    
 
263
 
 
264
    Results are reported through logging.
 
265
 
 
266
    Deprecated in 1.6.  Please use check_branch instead.
 
267
 
 
268
    :raise BzrCheckError: if there's a consistency error.
 
269
    """
 
270
    check_branch(branch, verbose)
 
271
 
 
272
 
 
273
def check_branch(branch, verbose):
 
274
    """Run consistency checks on a branch.
 
275
 
 
276
    Results are reported through logging.
 
277
 
249
278
    :raise BzrCheckError: if there's a consistency error.
250
279
    """
251
280
    branch.lock_read()
252
281
    try:
253
282
        branch_result = branch.check()
254
 
        repo_result = branch.repository.check([branch.last_revision()])
255
283
    finally:
256
284
        branch.unlock()
257
285
    branch_result.report_results(verbose)
258
 
    repo_result.report_results(verbose)
259
 
 
260
 
 
261
 
 
 
286
 
 
287
 
 
288
def check_dwim(path, verbose, do_branch=False, do_repo=False, do_tree=False):
 
289
    try:
 
290
        tree, branch, repo, relpath = \
 
291
                        BzrDir.open_containing_tree_branch_or_repository(path)
 
292
    except errors.NotBranchError:
 
293
        tree = branch = repo = None
 
294
 
 
295
    if do_tree:
 
296
        if tree is not None:
 
297
            note("Checking working tree at '%s'."
 
298
                 % (tree.bzrdir.root_transport.base,))
 
299
            tree._check()
 
300
        else:
 
301
            log_error("No working tree found at specified location.")
 
302
 
 
303
    if branch is not None:
 
304
        # We have a branch
 
305
        if repo is None:
 
306
            # The branch is in a shared repository
 
307
            repo = branch.repository
 
308
        branches = [branch]
 
309
    elif repo is not None:
 
310
        branches = repo.find_branches(using=True)
 
311
 
 
312
    if repo is not None:
 
313
        repo.lock_read()
 
314
        try:
 
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:
 
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)
 
328
        finally:
 
329
            repo.unlock()
 
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.")