149
149
if self._partial_revision_history_cache[-1] == _mod_revision.NULL_REVISION:
150
150
self._partial_revision_history_cache.pop()
152
def _get_check_refs(self):
153
"""Get the references needed for check().
157
revid = self.last_revision()
158
return [('revision-existence', revid), ('lefthand-distance', revid)]
153
161
def open(base, _unsupported=False, possible_transports=None):
154
162
"""Open the branch rooted at base.
438
446
# start_revision_id.
439
447
if self._merge_sorted_revisions_cache is None:
440
448
last_revision = self.last_revision()
441
graph = self.repository.get_graph()
442
parent_map = dict(((key, value) for key, value in
443
graph.iter_ancestry([last_revision]) if value is not None))
444
revision_graph = repository._strip_NULL_ghosts(parent_map)
445
revs = tsort.merge_sort(revision_graph, last_revision, None,
447
# Drop the sequence # before caching
448
self._merge_sorted_revisions_cache = [r[1:] for r in revs]
449
last_key = (last_revision,)
450
known_graph = self.repository.revisions.get_known_graph_ancestry(
452
self._merge_sorted_revisions_cache = known_graph.merge_sort(
450
454
filtered = self._filter_merge_sorted_revisions(
451
455
self._merge_sorted_revisions_cache, start_revision_id,
452
456
stop_revision_id, stop_rule)
462
466
"""Iterate over an inclusive range of sorted revisions."""
463
467
rev_iter = iter(merge_sorted_revisions)
464
468
if start_revision_id is not None:
465
for rev_id, depth, revno, end_of_merge in rev_iter:
469
for node in rev_iter:
470
rev_id = node.key[-1]
466
471
if rev_id != start_revision_id:
469
474
# The decision to include the start or not
470
475
# depends on the stop_rule if a stop is provided
472
iter([(rev_id, depth, revno, end_of_merge)]),
476
# so pop this node back into the iterator
477
rev_iter = chain(iter([node]), rev_iter)
475
479
if stop_revision_id is None:
476
for rev_id, depth, revno, end_of_merge in rev_iter:
477
yield rev_id, depth, revno, end_of_merge
481
for node in rev_iter:
482
rev_id = node.key[-1]
483
yield (rev_id, node.merge_depth, node.revno,
478
485
elif stop_rule == 'exclude':
479
for rev_id, depth, revno, end_of_merge in rev_iter:
486
for node in rev_iter:
487
rev_id = node.key[-1]
480
488
if rev_id == stop_revision_id:
482
yield rev_id, depth, revno, end_of_merge
490
yield (rev_id, node.merge_depth, node.revno,
483
492
elif stop_rule == 'include':
484
for rev_id, depth, revno, end_of_merge in rev_iter:
485
yield rev_id, depth, revno, end_of_merge
493
for node in rev_iter:
494
rev_id = node.key[-1]
495
yield (rev_id, node.merge_depth, node.revno,
486
497
if rev_id == stop_revision_id:
488
499
elif stop_rule == 'with-merges':
491
502
left_parent = stop_rev.parent_ids[0]
493
504
left_parent = _mod_revision.NULL_REVISION
494
for rev_id, depth, revno, end_of_merge in rev_iter:
505
for node in rev_iter:
506
rev_id = node.key[-1]
495
507
if rev_id == left_parent:
497
yield rev_id, depth, revno, end_of_merge
509
yield (rev_id, node.merge_depth, node.revno,
499
512
raise ValueError('invalid stop_rule %r' % stop_rule)
1139
1152
revision_id: if not None, the revision history in the new branch will
1140
1153
be truncated to end with revision_id.
1155
if (repository_policy is not None and
1156
repository_policy.requires_stacking()):
1157
to_bzrdir._format.require_stacking(_skip_repo=True)
1142
1158
result = to_bzrdir.create_branch()
1143
1159
result.lock_write()
1222
1238
Callers will typically also want to check the repository.
1240
:param refs: Calculated refs for this branch as specified by
1241
branch._get_check_refs()
1224
1242
:return: A BranchCheckResult.
1226
ret = BranchCheckResult(self)
1227
mainline_parent_id = None
1244
result = BranchCheckResult(self)
1228
1245
last_revno, last_revision_id = self.last_revision_info()
1229
real_rev_history = []
1231
for revid in self.repository.iter_reverse_revision_history(
1233
real_rev_history.append(revid)
1234
except errors.RevisionNotPresent:
1235
ret.ghosts_in_mainline = True
1237
ret.ghosts_in_mainline = False
1238
real_rev_history.reverse()
1239
if len(real_rev_history) != last_revno:
1240
raise errors.BzrCheckError('revno does not match len(mainline)'
1241
' %s != %s' % (last_revno, len(real_rev_history)))
1242
# TODO: We should probably also check that real_rev_history actually
1243
# matches self.revision_history()
1244
for revision_id in real_rev_history:
1246
revision = self.repository.get_revision(revision_id)
1247
except errors.NoSuchRevision, e:
1248
raise errors.BzrCheckError("mainline revision {%s} not in repository"
1250
# In general the first entry on the revision history has no parents.
1251
# But it's not illegal for it to have parents listed; this can happen
1252
# in imports from Arch when the parents weren't reachable.
1253
if mainline_parent_id is not None:
1254
if mainline_parent_id not in revision.parent_ids:
1255
raise errors.BzrCheckError("previous revision {%s} not listed among "
1257
% (mainline_parent_id, revision_id))
1258
mainline_parent_id = revision_id
1246
actual_revno = refs[('lefthand-distance', last_revision_id)]
1247
if actual_revno != last_revno:
1248
result.errors.append(errors.BzrCheckError(
1249
'revno does not match len(mainline) %s != %s' % (
1250
last_revno, actual_revno)))
1251
# TODO: We should probably also check that self.revision_history
1252
# matches the repository for older branch formats.
1253
# If looking for the code that cross-checks repository parents against
1254
# the iter_reverse_revision_history output, that is now a repository
1261
1258
def _get_checkout_format(self):
1262
1259
"""Return the most suitable metadir for a checkout of this branch.
2075
2072
BranchFormat.register_format(__format6)
2076
2073
BranchFormat.register_format(__format7)
2077
2074
BranchFormat.register_format(__format8)
2078
BranchFormat.set_default_format(__format6)
2075
BranchFormat.set_default_format(__format7)
2079
2076
_legacy_formats = [BzrBranchFormat4(),
2081
2078
network_format_registry.register(
2847
2844
:param verbose: Requests more detailed display of what was checked,
2850
note('checked branch %s format %s',
2852
self.branch._format)
2853
if self.ghosts_in_mainline:
2854
note('branch contains ghosts in mainline')
2847
note('checked branch %s format %s', self.branch.base,
2848
self.branch._format)
2849
for error in self.errors:
2850
note('found error:%s', error)
2857
2853
class Converter5to6(object):