14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
from .lazy_import import lazy_import
17
from __future__ import absolute_import
19
from bzrlib.lazy_import import lazy_import
18
20
lazy_import(globals(), """
27
33
revision as _mod_revision,
34
testament as _mod_testament,
30
from breezy.i18n import gettext
38
from bzrlib.bundle import serializer
39
from bzrlib.i18n import gettext
38
from .decorators import only_raises
39
from .inter import InterObject
40
from .lock import _RelockDebugMixin, LogicalLockResult
49
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
50
from bzrlib.inter import InterObject
51
from bzrlib.lock import _RelockDebugMixin, LogicalLockResult
52
from bzrlib.trace import (
42
53
log_exception_quietly, note, mutter, mutter_callsite, warning)
97
93
:param revprops: Optional dictionary of revision properties.
98
94
:param revision_id: Optional revision id.
99
95
:param lossy: Whether to discard data that can not be natively
100
represented, when pushing to a foreign VCS
96
represented, when pushing to a foreign VCS
102
98
self._config_stack = config_stack
103
99
self._lossy = lossy
105
101
if committer is None:
106
102
self._committer = self._config_stack.get('email')
107
elif not isinstance(committer, str):
108
self._committer = committer.decode() # throw if non-ascii
103
elif not isinstance(committer, unicode):
104
self._committer = committer.decode() # throw if non-ascii
110
106
self._committer = committer
108
self._new_revision_id = revision_id
112
109
self.parents = parents
113
110
self.repository = repository
142
139
def _validate_unicode_text(self, text, context):
143
140
"""Verify things like commit messages don't have bogus characters."""
144
# TODO(jelmer): Make this repository-format specific
146
142
raise ValueError('Invalid value for %s: %r' % (context, text))
148
144
def _validate_revprops(self, revprops):
149
for key, value in revprops.items():
145
for key, value in revprops.iteritems():
150
146
# We know that the XML serializers do not round trip '\r'
151
147
# correctly, so refuse to accept them
152
if not isinstance(value, str):
148
if not isinstance(value, basestring):
153
149
raise ValueError('revision property (%s) is not a valid'
154
150
' (unicode) string: %r' % (key, value))
155
# TODO(jelmer): Make this repository-format specific
156
151
self._validate_unicode_text(value,
157
152
'revision property (%s)' % (key,))
197
196
:raises: CannotSetRevisionId
199
if not self.repository._format.supports_setting_revision_ids:
200
if revision_id is not None:
201
raise CannotSetRevisionId()
203
if revision_id is None:
198
if self._new_revision_id is None:
204
199
self._new_revision_id = self._gen_revision_id()
205
200
self.random_revid = True
207
self._new_revision_id = revision_id
208
202
self.random_revid = False
204
def will_record_deletes(self):
205
"""Tell the commit builder that deletes are being notified.
207
This enables the accumulation of an inventory delta; for the resulting
208
commit to be valid, deletes against the basis MUST be recorded via
209
builder.record_delete().
211
raise NotImplementedError(self.will_record_deletes)
210
213
def record_iter_changes(self, tree, basis_revision_id, iter_changes):
211
214
"""Record a new tree via iter_changes.
239
242
def __repr__(self):
240
243
return "RepositoryWriteLockResult(%s, %s)" % (self.repository_token,
244
class WriteGroup(object):
245
"""Context manager that manages a write group.
247
Raising an exception will result in the write group being aborted.
250
def __init__(self, repository, suppress_errors=False):
251
self.repository = repository
252
self._suppress_errors = suppress_errors
255
self.repository.start_write_group()
258
def __exit__(self, exc_type, exc_val, exc_tb):
260
self.repository.abort_write_group(self._suppress_errors)
263
self.repository.commit_write_group()
266
247
######################################################################
270
class Repository(controldir.ControlComponent, _RelockDebugMixin):
251
class Repository(_RelockDebugMixin, controldir.ControlComponent):
271
252
"""Repository holding history for one or more branches.
273
254
The repository holds and retrieves historical information including
274
255
revisions and file history. It's normally accessed only by the Branch,
275
256
which views a particular line of development through that history.
277
See VersionedFileRepository in breezy.vf_repository for the
258
See VersionedFileRepository in bzrlib.vf_repository for the
278
259
base class for most Bazaar repositories.
281
# Does this repository implementation support random access to
282
# items in the tree, or just bulk fetching/pushing of data?
283
supports_random_access = True
285
262
def abort_write_group(self, suppress_errors=False):
286
263
"""Commit the contents accrued within the current write group.
295
272
# has an unlock or relock occured ?
296
273
if suppress_errors:
298
'(suppressed) mismatched lock context and write group. %r, %r',
299
self._write_group, self.get_transaction())
275
'(suppressed) mismatched lock context and write group. %r, %r',
276
self._write_group, self.get_transaction())
301
278
raise errors.BzrError(
302
279
'mismatched lock context and write group. %r, %r' %
303
280
(self._write_group, self.get_transaction()))
305
282
self._abort_write_group()
306
except Exception as exc:
283
except Exception, exc:
307
284
self._write_group = None
308
285
if not suppress_errors:
310
287
mutter('abort_write_group failed')
311
288
log_exception_quietly()
312
note(gettext('brz: ERROR (ignored): %s'), exc)
289
note(gettext('bzr: ERROR (ignored): %s'), exc)
313
290
self._write_group = None
315
292
def _abort_write_group(self):
533
511
revisions: The total revision count in the repository.
534
512
size: An estimate disk size of the repository in bytes.
536
with self.lock_read():
538
if revid and committers:
539
result['committers'] = 0
540
if revid and revid != _mod_revision.NULL_REVISION:
541
graph = self.get_graph()
543
all_committers = set()
544
revisions = [r for (r, p) in graph.iter_ancestry([revid])
545
if r != _mod_revision.NULL_REVISION]
548
# ignore the revisions in the middle - just grab first and last
549
revisions = revisions[0], revisions[-1]
550
for revision in self.get_revisions(revisions):
551
if not last_revision:
552
last_revision = revision
554
all_committers.add(revision.committer)
555
first_revision = revision
557
result['committers'] = len(all_committers)
558
result['firstrev'] = (first_revision.timestamp,
559
first_revision.timezone)
560
result['latestrev'] = (last_revision.timestamp,
561
last_revision.timezone)
515
if revid and committers:
516
result['committers'] = 0
517
if revid and revid != _mod_revision.NULL_REVISION:
518
graph = self.get_graph()
520
all_committers = set()
521
revisions = [r for (r, p) in graph.iter_ancestry([revid])
522
if r != _mod_revision.NULL_REVISION]
525
# ignore the revisions in the middle - just grab first and last
526
revisions = revisions[0], revisions[-1]
527
for revision in self.get_revisions(revisions):
528
if not last_revision:
529
last_revision = revision
531
all_committers.add(revision.committer)
532
first_revision = revision
534
result['committers'] = len(all_committers)
535
result['firstrev'] = (first_revision.timestamp,
536
first_revision.timezone)
537
result['latestrev'] = (last_revision.timestamp,
538
last_revision.timezone)
564
541
def find_branches(self, using=False):
565
542
"""Find branches underneath this repository.
592
566
value = (controldir.list_branches(), None)
593
567
return True, value
595
for branches, repository in controldir.ControlDir.find_controldirs(
570
for branches, repository in controldir.ControlDir.find_bzrdirs(
596
571
self.user_transport, evaluate=Evaluator()):
597
572
if branches is not None:
598
for branch in branches:
600
574
if not using and repository is not None:
601
for branch in repository.find_branches():
575
ret.extend(repository.find_branches())
604
579
def search_missing_revision_ids(self, other,
605
find_ghosts=True, revision_ids=None, if_present_ids=None,
580
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
581
find_ghosts=True, revision_ids=None, if_present_ids=None,
607
583
"""Return the revision ids that other has that this does not.
609
585
These are returned in topological order.
611
revision_ids: only return revision ids included by revision_id.
587
revision_id: only return revision ids included by revision_id.
613
with self.lock_read():
614
return InterRepository.get(other, self).search_missing_revision_ids(
615
find_ghosts=find_ghosts, revision_ids=revision_ids,
616
if_present_ids=if_present_ids, limit=limit)
589
if symbol_versioning.deprecated_passed(revision_id):
590
symbol_versioning.warn(
591
'search_missing_revision_ids(revision_id=...) was '
592
'deprecated in 2.4. Use revision_ids=[...] instead.',
593
DeprecationWarning, stacklevel=3)
594
if revision_ids is not None:
595
raise AssertionError(
596
'revision_ids is mutually exclusive with revision_id')
597
if revision_id is not None:
598
revision_ids = [revision_id]
599
return InterRepository.get(other, self).search_missing_revision_ids(
600
find_ghosts=find_ghosts, revision_ids=revision_ids,
601
if_present_ids=if_present_ids, limit=limit)
716
700
# TODO: lift out to somewhere common with RemoteRepository
717
701
# <https://bugs.launchpad.net/bzr/+bug/401646>
718
702
if (self.has_same_location(source)
719
and self._has_same_fallbacks(source)):
703
and self._has_same_fallbacks(source)):
720
704
# check that last_revision is in 'from' and then return a
722
706
if (revision_id is not None and
723
not _mod_revision.is_null(revision_id)):
707
not _mod_revision.is_null(revision_id)):
724
708
self.get_revision(revision_id)
726
710
inter = InterRepository.get(source, self)
728
revision_id=revision_id, find_ghosts=find_ghosts, lossy=lossy)
711
return inter.fetch(revision_id=revision_id, find_ghosts=find_ghosts)
713
def create_bundle(self, target, base, fileobj, format=None):
714
return serializer.write_bundle(self, target, base, fileobj, format)
730
716
def get_commit_builder(self, branch, parents, config_stack, timestamp=None,
731
717
timezone=None, committer=None, revprops=None,
808
794
def sprout(self, to_bzrdir, revision_id=None):
809
795
"""Create a descendent repository for new development.
811
797
Unlike clone, this does not copy the settings of the repository.
813
with self.lock_read():
814
dest_repo = self._create_sprouting_repo(to_bzrdir, shared=False)
815
dest_repo.fetch(self, revision_id=revision_id)
799
dest_repo = self._create_sprouting_repo(to_bzrdir, shared=False)
800
dest_repo.fetch(self, revision_id=revision_id)
818
def _create_sprouting_repo(self, a_controldir, shared):
820
a_controldir._format, self.controldir._format.__class__):
803
def _create_sprouting_repo(self, a_bzrdir, shared):
804
if not isinstance(a_bzrdir._format, self.bzrdir._format.__class__):
821
805
# use target default format.
822
dest_repo = a_controldir.create_repository()
806
dest_repo = a_bzrdir.create_repository()
824
808
# Most control formats need the repository to be specifically
825
809
# created, but on some old all-in-one formats it's not needed
827
dest_repo = self._format.initialize(
828
a_controldir, shared=shared)
811
dest_repo = self._format.initialize(a_bzrdir, shared=shared)
829
812
except errors.UninitializableFormat:
830
dest_repo = a_controldir.open_repository()
813
dest_repo = a_bzrdir.open_repository()
833
817
def has_revision(self, revision_id):
834
818
"""True if this repository has a copy of the revision."""
835
with self.lock_read():
836
return revision_id in self.has_revisions((revision_id,))
819
return revision_id in self.has_revisions((revision_id,))
838
822
def has_revisions(self, revision_ids):
839
823
"""Probe to find out the presence of multiple revisions.
861
845
def get_revisions(self, revision_ids):
862
846
"""Get many revisions at once.
864
Repositories that need to check data on every revision read should
848
Repositories that need to check data on every revision read should
865
849
subclass this method.
868
for revid, rev in self.iter_revisions(revision_ids):
870
raise errors.NoSuchRevision(self, revid)
872
return [revs[revid] for revid in revision_ids]
874
def iter_revisions(self, revision_ids):
875
"""Iterate over revision objects.
877
:param revision_ids: An iterable of revisions to examine. None may be
878
passed to request all revisions known to the repository. Note that
879
not all repositories can find unreferenced revisions; for those
880
repositories only referenced ones will be returned.
881
:return: An iterator of (revid, revision) tuples. Absent revisions (
882
those asked for but not available) are returned as (revid, None).
883
N.B.: Revisions are not necessarily yielded in order.
885
raise NotImplementedError(self.iter_revisions)
887
def get_revision_delta(self, revision_id):
888
"""Return the delta for one revision.
890
The delta is relative to the left-hand predecessor of the
893
with self.lock_read():
894
r = self.get_revision(revision_id)
895
return list(self.get_revision_deltas([r]))[0]
897
def get_revision_deltas(self, revisions, specific_files=None):
851
raise NotImplementedError(self.get_revisions)
853
def get_deltas_for_revisions(self, revisions, specific_fileids=None):
898
854
"""Produce a generator of revision deltas.
900
Note that the input is a sequence of REVISIONS, not revision ids.
856
Note that the input is a sequence of REVISIONS, not revision_ids.
901
857
Trees will be held in memory until the generator exits.
902
858
Each delta is relative to the revision's lefthand predecessor.
904
specific_files should exist in the first revision.
906
:param specific_files: if not None, the result is filtered
907
so that only those files, their parents and their
860
:param specific_fileids: if not None, the result is filtered
861
so that only those file-ids, their parents and their
908
862
children are included.
910
from .tree import InterTree
911
864
# Get the revision-ids of interest
912
865
required_trees = set()
913
866
for revision in revisions:
914
867
required_trees.add(revision.revision_id)
915
868
required_trees.update(revision.parent_ids[:1])
918
t.get_revision_id(): t
919
for t in self.revision_trees(required_trees)}
870
# Get the matching filtered trees. Note that it's more
871
# efficient to pass filtered trees to changes_from() rather
872
# than doing the filtering afterwards. changes_from() could
873
# arguably do the filtering itself but it's path-based, not
874
# file-id based, so filtering before or afterwards is
876
if specific_fileids is None:
877
trees = dict((t.get_revision_id(), t) for
878
t in self.revision_trees(required_trees))
880
trees = dict((t.get_revision_id(), t) for
881
t in self._filtered_revision_trees(required_trees,
921
884
# Calculate the deltas
922
885
for revision in revisions:
924
887
old_tree = self.revision_tree(_mod_revision.NULL_REVISION)
926
889
old_tree = trees[revision.parent_ids[0]]
927
intertree = InterTree.get(old_tree, trees[revision.revision_id])
928
yield intertree.compare(specific_files=specific_files)
929
if specific_files is not None:
931
p for p in intertree.find_source_paths(
932
specific_files).values()
890
yield trees[revision.revision_id].changes_from(old_tree)
893
def get_revision_delta(self, revision_id, specific_fileids=None):
894
"""Return the delta for one revision.
896
The delta is relative to the left-hand predecessor of the
899
:param specific_fileids: if not None, the result is filtered
900
so that only those file-ids, their parents and their
901
children are included.
903
r = self.get_revision(revision_id)
904
return list(self.get_deltas_for_revisions([r],
905
specific_fileids=specific_fileids))[0]
935
908
def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
936
raise NotImplementedError(self.store_revision_signature)
909
signature = gpg_strategy.sign(plaintext)
910
self.add_signature_text(revision_id, signature)
938
912
def add_signature_text(self, revision_id, signature):
939
913
"""Store a signature text for a revision.
971
958
partial_history = [known_revid]
972
959
distance_from_known = known_revno - revno
973
960
if distance_from_known < 0:
974
raise errors.RevnoOutOfBounds(revno, (0, known_revno))
962
'requested revno (%d) is later than given known revno (%d)'
963
% (revno, known_revno))
977
966
self, partial_history, stop_index=distance_from_known)
978
except errors.RevisionNotPresent as err:
967
except errors.RevisionNotPresent, err:
979
968
if err.revision_id == known_revid:
980
969
# The start revision (known_revid) wasn't found.
981
raise errors.NoSuchRevision(self, known_revid)
982
971
# This is a stacked repository with no fallbacks, or a there's a
983
972
# left-hand ghost. Either way, even though the revision named in
984
973
# the error isn't in this repo, we know it's the next step in this
1069
1063
elif revision_id is None:
1070
1064
raise ValueError('get_parent_map(None) is not valid')
1072
query_keys.append((revision_id,))
1066
query_keys.append((revision_id ,))
1073
1067
vf = self.revisions.without_fallbacks()
1074
for (revision_id,), parent_keys in (
1075
vf.get_parent_map(query_keys).items()):
1068
for ((revision_id,), parent_keys) in \
1069
vf.get_parent_map(query_keys).iteritems():
1076
1070
if parent_keys:
1077
1071
result[revision_id] = tuple([parent_revid
1078
for (parent_revid,) in parent_keys])
1072
for (parent_revid,) in parent_keys])
1080
1074
result[revision_id] = (_mod_revision.NULL_REVISION,)
1215
1222
raise errors.NonAsciiRevisionId(method, self)
1225
class MetaDirRepository(Repository):
1226
"""Repositories in the new meta-dir layout.
1228
:ivar _transport: Transport for access to repository control files,
1229
typically pointing to .bzr/repository.
1232
def __init__(self, _format, a_bzrdir, control_files):
1233
super(MetaDirRepository, self).__init__(_format, a_bzrdir, control_files)
1234
self._transport = control_files._transport
1236
def is_shared(self):
1237
"""Return True if this repository is flagged as a shared repository."""
1238
return self._transport.has('shared-storage')
1241
def set_make_working_trees(self, new_value):
1242
"""Set the policy flag for making working trees when creating branches.
1244
This only applies to branches that use this repository.
1246
The default is 'True'.
1247
:param new_value: True to restore the default, False to disable making
1252
self._transport.delete('no-working-trees')
1253
except errors.NoSuchFile:
1256
self._transport.put_bytes('no-working-trees', '',
1257
mode=self.bzrdir._get_file_mode())
1259
def make_working_trees(self):
1260
"""Returns the policy for making working trees on new branches."""
1261
return not self._transport.has('no-working-trees')
1264
def update_feature_flags(self, updated_flags):
1265
"""Update the feature flags for this branch.
1267
:param updated_flags: Dictionary mapping feature names to necessities
1268
A necessity can be None to indicate the feature should be removed
1270
self._format._update_feature_flags(updated_flags)
1271
self.control_transport.put_bytes('format', self._format.as_string())
1218
1274
class RepositoryFormatRegistry(controldir.ControlComponentFormatRegistry):
1219
1275
"""Repository format registry."""
1221
1277
def get_default(self):
1222
1278
"""Return the current default format."""
1223
return controldir.format_registry.make_controldir('default').repository_format
1279
return controldir.format_registry.make_bzrdir('default').repository_format
1226
1282
network_format_registry = registry.FormatRegistry()
1461
class RepositoryFormatMetaDir(bzrdir.BzrFormat, RepositoryFormat):
1462
"""Common base class for the new repositories using the metadir layout."""
1464
rich_root_data = False
1465
supports_tree_reference = False
1466
supports_external_lookups = False
1467
supports_leaving_lock = True
1468
supports_nesting_repositories = True
1471
def _matchingbzrdir(self):
1472
matching = bzrdir.BzrDirMetaFormat1()
1473
matching.repository_format = self
1477
RepositoryFormat.__init__(self)
1478
bzrdir.BzrFormat.__init__(self)
1480
def _create_control_files(self, a_bzrdir):
1481
"""Create the required files and the initial control_files object."""
1482
# FIXME: RBC 20060125 don't peek under the covers
1483
# NB: no need to escape relative paths that are url safe.
1484
repository_transport = a_bzrdir.get_repository_transport(self)
1485
control_files = lockable_files.LockableFiles(repository_transport,
1486
'lock', lockdir.LockDir)
1487
control_files.create_lock()
1488
return control_files
1490
def _upload_blank_content(self, a_bzrdir, dirs, files, utf8_files, shared):
1491
"""Upload the initial blank content."""
1492
control_files = self._create_control_files(a_bzrdir)
1493
control_files.lock_write()
1494
transport = control_files._transport
1496
utf8_files += [('shared-storage', '')]
1498
transport.mkdir_multi(dirs, mode=a_bzrdir._get_dir_mode())
1499
for (filename, content_stream) in files:
1500
transport.put_file(filename, content_stream,
1501
mode=a_bzrdir._get_file_mode())
1502
for (filename, content_bytes) in utf8_files:
1503
transport.put_bytes_non_atomic(filename, content_bytes,
1504
mode=a_bzrdir._get_file_mode())
1506
control_files.unlock()
1509
def find_format(klass, a_bzrdir):
1510
"""Return the format for the repository object in a_bzrdir.
1512
This is used by bzr native formats that have a "format" file in
1513
the repository. Other methods may be used by different types of
1517
transport = a_bzrdir.get_repository_transport(None)
1518
format_string = transport.get_bytes("format")
1519
except errors.NoSuchFile:
1520
raise errors.NoRepositoryPresent(a_bzrdir)
1521
return klass._find_format(format_registry, 'repository', format_string)
1523
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
1525
RepositoryFormat.check_support_status(self,
1526
allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
1528
bzrdir.BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
1529
recommend_upgrade=recommend_upgrade, basedir=basedir)
1416
1532
# formats which have no format string are not discoverable or independently
1417
1533
# creatable on disk, so are not registered in format_registry. They're
1418
# all in breezy.bzr.knitreponow. When an instance of one of these is
1534
# all in bzrlib.repofmt.knitreponow. When an instance of one of these is
1419
1535
# needed, it's constructed directly by the ControlDir. Non-native formats where
1420
1536
# the repository is not separately opened are similar.
1422
1538
format_registry.register_lazy(
1423
b'Bazaar-NG Knit Repository Format 1',
1424
'breezy.bzr.knitrepo',
1539
'Bazaar-NG Knit Repository Format 1',
1540
'bzrlib.repofmt.knitrepo',
1425
1541
'RepositoryFormatKnit1',
1428
1544
format_registry.register_lazy(
1429
b'Bazaar Knit Repository Format 3 (bzr 0.15)\n',
1430
'breezy.bzr.knitrepo',
1545
'Bazaar Knit Repository Format 3 (bzr 0.15)\n',
1546
'bzrlib.repofmt.knitrepo',
1431
1547
'RepositoryFormatKnit3',
1434
1550
format_registry.register_lazy(
1435
b'Bazaar Knit Repository Format 4 (bzr 1.0)\n',
1436
'breezy.bzr.knitrepo',
1551
'Bazaar Knit Repository Format 4 (bzr 1.0)\n',
1552
'bzrlib.repofmt.knitrepo',
1437
1553
'RepositoryFormatKnit4',
1441
1557
# post-subtrees to allow ease of testing.
1442
1558
# NOTE: These are experimental in 0.92. Stable in 1.0 and above
1443
1559
format_registry.register_lazy(
1444
b'Bazaar pack repository format 1 (needs bzr 0.92)\n',
1445
'breezy.bzr.knitpack_repo',
1560
'Bazaar pack repository format 1 (needs bzr 0.92)\n',
1561
'bzrlib.repofmt.knitpack_repo',
1446
1562
'RepositoryFormatKnitPack1',
1448
1564
format_registry.register_lazy(
1449
b'Bazaar pack repository format 1 with subtree support (needs bzr 0.92)\n',
1450
'breezy.bzr.knitpack_repo',
1565
'Bazaar pack repository format 1 with subtree support (needs bzr 0.92)\n',
1566
'bzrlib.repofmt.knitpack_repo',
1451
1567
'RepositoryFormatKnitPack3',
1453
1569
format_registry.register_lazy(
1454
b'Bazaar pack repository format 1 with rich root (needs bzr 1.0)\n',
1455
'breezy.bzr.knitpack_repo',
1570
'Bazaar pack repository format 1 with rich root (needs bzr 1.0)\n',
1571
'bzrlib.repofmt.knitpack_repo',
1456
1572
'RepositoryFormatKnitPack4',
1458
1574
format_registry.register_lazy(
1459
b'Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n',
1460
'breezy.bzr.knitpack_repo',
1575
'Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n',
1576
'bzrlib.repofmt.knitpack_repo',
1461
1577
'RepositoryFormatKnitPack5',
1463
1579
format_registry.register_lazy(
1464
b'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6.1)\n',
1465
'breezy.bzr.knitpack_repo',
1580
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6.1)\n',
1581
'bzrlib.repofmt.knitpack_repo',
1466
1582
'RepositoryFormatKnitPack5RichRoot',
1468
1584
format_registry.register_lazy(
1469
b'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6)\n',
1470
'breezy.bzr.knitpack_repo',
1585
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6)\n',
1586
'bzrlib.repofmt.knitpack_repo',
1471
1587
'RepositoryFormatKnitPack5RichRootBroken',
1473
1589
format_registry.register_lazy(
1474
b'Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n',
1475
'breezy.bzr.knitpack_repo',
1590
'Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n',
1591
'bzrlib.repofmt.knitpack_repo',
1476
1592
'RepositoryFormatKnitPack6',
1478
1594
format_registry.register_lazy(
1479
b'Bazaar RepositoryFormatKnitPack6RichRoot (bzr 1.9)\n',
1480
'breezy.bzr.knitpack_repo',
1595
'Bazaar RepositoryFormatKnitPack6RichRoot (bzr 1.9)\n',
1596
'bzrlib.repofmt.knitpack_repo',
1481
1597
'RepositoryFormatKnitPack6RichRoot',
1483
1599
format_registry.register_lazy(
1484
b'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
1485
'breezy.bzr.groupcompress_repo',
1600
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
1601
'bzrlib.repofmt.groupcompress_repo',
1486
1602
'RepositoryFormat2a',
1489
1605
# Development formats.
1490
1606
# Check their docstrings to see if/when they are obsolete.
1491
1607
format_registry.register_lazy(
1492
(b"Bazaar development format 2 with subtree support "
1493
b"(needs bzr.dev from before 1.8)\n"),
1494
'breezy.bzr.knitpack_repo',
1608
("Bazaar development format 2 with subtree support "
1609
"(needs bzr.dev from before 1.8)\n"),
1610
'bzrlib.repofmt.knitpack_repo',
1495
1611
'RepositoryFormatPackDevelopment2Subtree',
1497
1613
format_registry.register_lazy(
1498
b'Bazaar development format 8\n',
1499
'breezy.bzr.groupcompress_repo',
1614
'Bazaar development format 8\n',
1615
'bzrlib.repofmt.groupcompress_repo',
1500
1616
'RepositoryFormat2aSubtree',
1525
1642
:param revision_id: Only copy the content needed to construct
1526
1643
revision_id and its parents.
1528
with self.lock_write():
1530
self.target.set_make_working_trees(
1531
self.source.make_working_trees())
1532
except (NotImplementedError, errors.RepositoryUpgradeRequired):
1534
self.target.fetch(self.source, revision_id=revision_id)
1646
self.target.set_make_working_trees(self.source.make_working_trees())
1647
except NotImplementedError:
1649
self.target.fetch(self.source, revision_id=revision_id)
1536
def fetch(self, revision_id=None, find_ghosts=False, lossy=False):
1652
def fetch(self, revision_id=None, find_ghosts=False):
1537
1653
"""Fetch the content required to construct revision_id.
1539
1655
The content is copied from self.source to self.target.
1541
1657
:param revision_id: if None all content is copied, if NULL_REVISION no
1542
1658
content is copied.
1543
:return: FetchResult
1545
1661
raise NotImplementedError(self.fetch)
1547
def search_missing_revision_ids(
1548
self, find_ghosts=True, revision_ids=None, if_present_ids=None,
1664
def search_missing_revision_ids(self,
1665
revision_id=symbol_versioning.DEPRECATED_PARAMETER,
1666
find_ghosts=True, revision_ids=None, if_present_ids=None,
1550
1668
"""Return the revision ids that source has that target does not.
1670
:param revision_id: only return revision ids included by this
1552
1672
:param revision_ids: return revision ids included by these
1553
1673
revision_ids. NoSuchRevision will be raised if any of these
1554
1674
revisions are not present.
1608
1728
:param to_convert: The disk object to convert.
1609
1729
:param pb: a progress bar to use for progress information.
1611
with ui.ui_factory.nested_progress_bar() as pb:
1614
# this is only useful with metadir layouts - separated repo content.
1615
# trigger an assertion if not such
1616
repo._format.get_format_string()
1617
self.repo_dir = repo.controldir
1618
pb.update(gettext('Moving repository to repository.backup'))
1619
self.repo_dir.transport.move('repository', 'repository.backup')
1620
backup_transport = self.repo_dir.transport.clone(
1621
'repository.backup')
1622
repo._format.check_conversion_target(self.target_format)
1623
self.source_repo = repo._format.open(self.repo_dir,
1625
_override_transport=backup_transport)
1626
pb.update(gettext('Creating new repository'))
1627
converted = self.target_format.initialize(self.repo_dir,
1628
self.source_repo.is_shared())
1629
with converted.lock_write():
1630
pb.update(gettext('Copying content'))
1631
self.source_repo.copy_content_into(converted)
1632
pb.update(gettext('Deleting old repository content'))
1633
self.repo_dir.transport.delete_tree('repository.backup')
1634
ui.ui_factory.note(gettext('repository converted'))
1731
pb = ui.ui_factory.nested_progress_bar()
1734
# this is only useful with metadir layouts - separated repo content.
1735
# trigger an assertion if not such
1736
repo._format.get_format_string()
1737
self.repo_dir = repo.bzrdir
1738
pb.update(gettext('Moving repository to repository.backup'))
1739
self.repo_dir.transport.move('repository', 'repository.backup')
1740
backup_transport = self.repo_dir.transport.clone('repository.backup')
1741
repo._format.check_conversion_target(self.target_format)
1742
self.source_repo = repo._format.open(self.repo_dir,
1744
_override_transport=backup_transport)
1745
pb.update(gettext('Creating new repository'))
1746
converted = self.target_format.initialize(self.repo_dir,
1747
self.source_repo.is_shared())
1748
converted.lock_write()
1750
pb.update(gettext('Copying content'))
1751
self.source_repo.copy_content_into(converted)
1754
pb.update(gettext('Deleting old repository content'))
1755
self.repo_dir.transport.delete_tree('repository.backup')
1756
ui.ui_factory.note(gettext('repository converted'))
1637
1760
def _strip_NULL_ghosts(revision_graph):