88
94
record_root_entry = True
89
95
# the default CommitBuilder does not manage trees whose root is versioned.
90
96
_versioned_root = False
91
# this commit builder supports the record_entry_contents interface
92
supports_record_entry_contents = True
94
98
def __init__(self, repository, parents, config, timestamp=None,
95
99
timezone=None, committer=None, revprops=None,
96
revision_id=None, lossy=False):
97
101
"""Initiate a CommitBuilder.
99
103
:param repository: Repository to commit to.
100
104
:param parents: Revision ids of the parents of the new revision.
105
:param config: Configuration to use.
101
106
:param timestamp: Optional timestamp recorded for commit.
102
107
:param timezone: Optional timezone for timestamp.
103
108
:param committer: Optional committer to set for commit.
104
109
:param revprops: Optional dictionary of revision properties.
105
110
:param revision_id: Optional revision id.
106
:param lossy: Whether to discard data that can not be natively
107
represented, when pushing to a foreign VCS
109
112
self._config = config
112
114
if committer is None:
113
115
self._committer = self._config.username()
236
238
def revision_tree(self):
237
239
"""Return the tree that was just committed.
239
After calling commit() this can be called to get a
240
InventoryRevisionTree representing the newly committed tree. This is
241
preferred to calling Repository.revision_tree() because that may
242
require deserializing the inventory, while we already have a copy in
241
After calling commit() this can be called to get a RevisionTree
242
representing the newly committed tree. This is preferred to
243
calling Repository.revision_tree() because that may require
244
deserializing the inventory, while we already have a copy in
245
247
if self.new_inventory is None:
246
248
self.new_inventory = self.repository.get_inventory(
247
249
self._new_revision_id)
248
return InventoryRevisionTree(self.repository, self.new_inventory,
250
return RevisionTree(self.repository, self.new_inventory,
249
251
self._new_revision_id)
251
253
def finish_inventory(self):
1163
1165
if config is not None and config.signature_needed():
1164
1166
if inv is None:
1165
1167
inv = self.get_inventory(revision_id)
1166
tree = InventoryRevisionTree(self, inv, revision_id)
1167
testament = Testament(rev, tree)
1168
plaintext = testament.as_short_text()
1168
plaintext = Testament(rev, inv).as_short_text()
1169
1169
self.store_revision_signature(
1170
1170
gpg.GPGStrategy(config), plaintext, revision_id)
1171
1171
# check inventory present
1738
1738
def _resume_write_group(self, tokens):
1739
1739
raise errors.UnsuspendableWriteGroup(self)
1741
def fetch(self, source, revision_id=None, find_ghosts=False,
1741
def fetch(self, source, revision_id=None, pb=None, find_ghosts=False,
1742
1742
fetch_spec=None):
1743
1743
"""Fetch the content required to construct revision_id from source.
1779
1779
self.get_revision(revision_id)
1781
1781
inter = InterRepository.get(source, self)
1782
return inter.fetch(revision_id=revision_id,
1782
return inter.fetch(revision_id=revision_id, pb=pb,
1783
1783
find_ghosts=find_ghosts, fetch_spec=fetch_spec)
1785
1785
def create_bundle(self, target, base, fileobj, format=None):
1788
1788
def get_commit_builder(self, branch, parents, config, timestamp=None,
1789
1789
timezone=None, committer=None, revprops=None,
1790
revision_id=None, lossy=False):
1791
1791
"""Obtain a CommitBuilder for this repository.
1793
1793
:param branch: Branch to commit to.
1798
1798
:param committer: Optional committer to set for commit.
1799
1799
:param revprops: Optional dictionary of revision properties.
1800
1800
:param revision_id: Optional revision id.
1801
:param lossy: Whether to discard data that can not be natively
1802
represented, when pushing to a foreign VCS
1804
1802
if self._fallback_repositories and not self._format.supports_chks:
1805
1803
raise errors.BzrError("Cannot commit directly to a stacked branch"
1806
1804
" in pre-2a formats. See "
1807
1805
"https://bugs.launchpad.net/bzr/+bug/375013 for details.")
1808
1806
result = self._commit_builder_class(self, parents, config,
1809
timestamp, timezone, committer, revprops, revision_id,
1807
timestamp, timezone, committer, revprops, revision_id)
1811
1808
self.start_write_group()
2515
2512
# TODO: refactor this to use an existing revision object
2516
2513
# so we don't need to read it in twice.
2517
2514
if revision_id == _mod_revision.NULL_REVISION:
2518
return InventoryRevisionTree(self,
2519
Inventory(root_id=None), _mod_revision.NULL_REVISION)
2515
return RevisionTree(self, Inventory(root_id=None),
2516
_mod_revision.NULL_REVISION)
2521
2518
inv = self.get_inventory(revision_id)
2522
return InventoryRevisionTree(self, inv, revision_id)
2519
return RevisionTree(self, inv, revision_id)
2524
2521
def revision_trees(self, revision_ids):
2525
2522
"""Return Trees for revisions in this repository.
2530
2527
inventories = self.iter_inventories(revision_ids)
2531
2528
for inv in inventories:
2532
yield InventoryRevisionTree(self, inv, inv.revision_id)
2529
yield RevisionTree(self, inv, inv.revision_id)
2534
2531
def _filtered_revision_trees(self, revision_ids, file_ids):
2535
2532
"""Return Tree for a revision on this branch with only some files.
2545
2542
# Should we introduce a FilteredRevisionTree class rather
2546
2543
# than pre-filter the inventory here?
2547
2544
filtered_inv = inv.filter(file_ids)
2548
yield InventoryRevisionTree(self, filtered_inv, filtered_inv.revision_id)
2545
yield RevisionTree(self, filtered_inv, filtered_inv.revision_id)
2550
2547
@needs_read_lock
2551
2548
def get_ancestry(self, revision_id, topo_sorted=True):
2773
2768
except UnicodeDecodeError:
2774
2769
raise errors.NonAsciiRevisionId(method, self)
2776
def _find_inconsistent_revision_parents(self, revisions_iterator=None):
2777
"""Find revisions with different parent lists in the revision object
2778
and in the index graph.
2771
def revision_graph_can_have_wrong_parents(self):
2772
"""Is it possible for this repository to have a revision graph with
2780
:param revisions_iterator: None, or an iterator of (revid,
2781
Revision-or-None). This iterator controls the revisions checked.
2782
:returns: an iterator yielding tuples of (revison-id, parents-in-index,
2783
parents-in-revision).
2775
If True, then this repository must also implement
2776
_find_inconsistent_revision_parents so that check and reconcile can
2777
check for inconsistencies before proceeding with other checks that may
2778
depend on the revision index being consistent.
2785
if not self.is_locked():
2786
raise AssertionError()
2788
if revisions_iterator is None:
2789
revisions_iterator = self._iter_revisions(None)
2790
for revid, revision in revisions_iterator:
2791
if revision is None:
2793
parent_map = vf.get_parent_map([(revid,)])
2794
parents_according_to_index = tuple(parent[-1] for parent in
2795
parent_map[(revid,)])
2796
parents_according_to_revision = tuple(revision.parent_ids)
2797
if parents_according_to_index != parents_according_to_revision:
2798
yield (revid, parents_according_to_index,
2799
parents_according_to_revision)
2801
def _check_for_inconsistent_revision_parents(self):
2802
inconsistencies = list(self._find_inconsistent_revision_parents())
2804
raise errors.BzrCheckError(
2805
"Revision knit has inconsistent parents.")
2780
raise NotImplementedError(self.revision_graph_can_have_wrong_parents)
2808
2783
def install_revision(repository, rev, revision_tree):
2945
class RepositoryFormatRegistry(controldir.ControlComponentFormatRegistry):
2920
class RepositoryFormatRegistry(registry.FormatRegistry):
2946
2921
"""Repository format registry."""
2923
def __init__(self, other_registry=None):
2924
super(RepositoryFormatRegistry, self).__init__(other_registry)
2925
self._extra_formats = []
2927
def register(self, format):
2928
"""Register a new repository format."""
2929
super(RepositoryFormatRegistry, self).register(
2930
format.get_format_string(), format)
2932
def remove(self, format):
2933
"""Remove a registered repository format."""
2934
super(RepositoryFormatRegistry, self).remove(
2935
format.get_format_string())
2937
def register_extra(self, format):
2938
"""Register a repository format that can not be used in a metadir.
2940
This is mainly useful to allow custom repository formats, such as older
2941
Bazaar formats and foreign formats, to be tested.
2943
self._extra_formats.append(registry._ObjectGetter(format))
2945
def remove_extra(self, format):
2946
"""Remove an extra repository format.
2948
self._extra_formats.remove(registry._ObjectGetter(format))
2950
def register_extra_lazy(self, module_name, member_name):
2951
"""Register a repository format lazily.
2953
self._extra_formats.append(
2954
registry._LazyObjectGetter(module_name, member_name))
2948
2956
def get_default(self):
2949
2957
"""Return the current default format."""
2950
2958
from bzrlib import bzrdir
2951
2959
return bzrdir.format_registry.make_bzrdir('default').repository_format
2961
def _get_extra(self):
2963
for getter in self._extra_formats:
2964
f = getter.get_obj()
2971
"""Return all repository formats, even those not usable in metadirs.
2973
return [self.get(k) for k in self.keys()] + self._get_extra()
2954
2976
network_format_registry = registry.FormatRegistry()
2955
2977
"""Registry of formats indexed by their network name.
3040
3062
experimental = False
3041
3063
# Does this repository format escape funky characters, or does it create files with
3042
3064
# similar names as the versioned files in its contents on disk ?
3043
supports_funky_characters = None
3044
# Does this repository format support leaving locks?
3045
supports_leaving_lock = None
3046
# Does this format support the full VersionedFiles interface?
3047
supports_full_versioned_files = None
3048
# Does this format support signing revision signatures?
3049
supports_revision_signatures = True
3050
# Can the revision graph have incorrect parents?
3051
revision_graph_can_have_wrong_parents = None
3065
supports_funky_characters = True
3053
3067
def __repr__(self):
3054
3068
return "%s()" % self.__class__.__name__
3106
3120
"""Return the short description for this format."""
3107
3121
raise NotImplementedError(self.get_format_description)
3123
# TODO: this shouldn't be in the base class, it's specific to things that
3124
# use weaves or knits -- mbp 20070207
3125
def _get_versioned_file_store(self,
3130
versionedfile_class=None,
3131
versionedfile_kwargs={},
3133
if versionedfile_class is None:
3134
versionedfile_class = self._versionedfile_class
3135
weave_transport = control_files._transport.clone(name)
3136
dir_mode = control_files._dir_mode
3137
file_mode = control_files._file_mode
3138
return VersionedFileStore(weave_transport, prefixed=prefixed,
3140
file_mode=file_mode,
3141
versionedfile_class=versionedfile_class,
3142
versionedfile_kwargs=versionedfile_kwargs,
3109
3145
def initialize(self, a_bzrdir, shared=False):
3110
3146
"""Initialize a repository of this format in a_bzrdir.
3223
3250
return self.get_format_string()
3253
# Pre-0.8 formats that don't have a disk format string (because they are
3254
# versioned by the matching control directory). We use the control directories
3255
# disk format string as a key for the network_name because they meet the
3256
# constraints (simple string, unique, immutable).
3257
network_format_registry.register_lazy(
3258
"Bazaar-NG branch, format 5\n",
3259
'bzrlib.repofmt.weaverepo',
3260
'RepositoryFormat5',
3262
network_format_registry.register_lazy(
3263
"Bazaar-NG branch, format 6\n",
3264
'bzrlib.repofmt.weaverepo',
3265
'RepositoryFormat6',
3268
format_registry.register_extra_lazy(
3269
'bzrlib.repofmt.weaverepo',
3270
'RepositoryFormat4')
3271
format_registry.register_extra_lazy(
3272
'bzrlib.repofmt.weaverepo',
3273
'RepositoryFormat5')
3274
format_registry.register_extra_lazy(
3275
'bzrlib.repofmt.weaverepo',
3276
'RepositoryFormat6')
3226
3278
# formats which have no format string are not discoverable or independently
3227
3279
# creatable on disk, so are not registered in format_registry. They're
3228
# all in bzrlib.repofmt.knitreponow. When an instance of one of these is
3280
# all in bzrlib.repofmt.weaverepo now. When an instance of one of these is
3229
3281
# needed, it's constructed directly by the BzrDir. Non-native formats where
3230
3282
# the repository is not separately opened are similar.
3232
3284
format_registry.register_lazy(
3285
'Bazaar-NG Repository format 7',
3286
'bzrlib.repofmt.weaverepo',
3290
format_registry.register_lazy(
3233
3291
'Bazaar-NG Knit Repository Format 1',
3234
3292
'bzrlib.repofmt.knitrepo',
3235
3293
'RepositoryFormatKnit1',
3252
3310
# NOTE: These are experimental in 0.92. Stable in 1.0 and above
3253
3311
format_registry.register_lazy(
3254
3312
'Bazaar pack repository format 1 (needs bzr 0.92)\n',
3255
'bzrlib.repofmt.knitpack_repo',
3313
'bzrlib.repofmt.pack_repo',
3256
3314
'RepositoryFormatKnitPack1',
3258
3316
format_registry.register_lazy(
3259
3317
'Bazaar pack repository format 1 with subtree support (needs bzr 0.92)\n',
3260
'bzrlib.repofmt.knitpack_repo',
3318
'bzrlib.repofmt.pack_repo',
3261
3319
'RepositoryFormatKnitPack3',
3263
3321
format_registry.register_lazy(
3264
3322
'Bazaar pack repository format 1 with rich root (needs bzr 1.0)\n',
3265
'bzrlib.repofmt.knitpack_repo',
3323
'bzrlib.repofmt.pack_repo',
3266
3324
'RepositoryFormatKnitPack4',
3268
3326
format_registry.register_lazy(
3269
3327
'Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n',
3270
'bzrlib.repofmt.knitpack_repo',
3328
'bzrlib.repofmt.pack_repo',
3271
3329
'RepositoryFormatKnitPack5',
3273
3331
format_registry.register_lazy(
3274
3332
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6.1)\n',
3275
'bzrlib.repofmt.knitpack_repo',
3333
'bzrlib.repofmt.pack_repo',
3276
3334
'RepositoryFormatKnitPack5RichRoot',
3278
3336
format_registry.register_lazy(
3279
3337
'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6)\n',
3280
'bzrlib.repofmt.knitpack_repo',
3338
'bzrlib.repofmt.pack_repo',
3281
3339
'RepositoryFormatKnitPack5RichRootBroken',
3283
3341
format_registry.register_lazy(
3284
3342
'Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n',
3285
'bzrlib.repofmt.knitpack_repo',
3343
'bzrlib.repofmt.pack_repo',
3286
3344
'RepositoryFormatKnitPack6',
3288
3346
format_registry.register_lazy(
3289
3347
'Bazaar RepositoryFormatKnitPack6RichRoot (bzr 1.9)\n',
3290
'bzrlib.repofmt.knitpack_repo',
3348
'bzrlib.repofmt.pack_repo',
3291
3349
'RepositoryFormatKnitPack6RichRoot',
3293
3351
format_registry.register_lazy(
3301
3359
format_registry.register_lazy(
3302
3360
("Bazaar development format 2 with subtree support "
3303
3361
"(needs bzr.dev from before 1.8)\n"),
3304
'bzrlib.repofmt.knitpack_repo',
3362
'bzrlib.repofmt.pack_repo',
3305
3363
'RepositoryFormatPackDevelopment2Subtree',
3307
3365
format_registry.register_lazy(
3344
3402
self.target.fetch(self.source, revision_id=revision_id)
3346
3404
@needs_write_lock
3347
def fetch(self, revision_id=None, find_ghosts=False,
3405
def fetch(self, revision_id=None, pb=None, find_ghosts=False,
3348
3406
fetch_spec=None):
3349
3407
"""Fetch the content required to construct revision_id.
3852
3911
# Walk though all revisions; get inventory deltas, copy referenced
3853
3912
# texts that delta references, insert the delta, revision and
3855
pb = ui.ui_factory.nested_progress_bar()
3915
my_pb = ui.ui_factory.nested_progress_bar()
3918
symbol_versioning.warn(
3919
symbol_versioning.deprecated_in((1, 14, 0))
3920
% "pb parameter to fetch()")
3857
3923
self._fetch_all_revisions(revision_ids, pb)
3925
if my_pb is not None:
3860
3927
return len(revision_ids), 0
3862
3929
def _get_basis(self, first_revision_id):
3998
4065
return wrong_parents, unused_keys
4068
def _old_get_graph(repository, revision_id):
4069
"""DO NOT USE. That is all. I'm serious."""
4070
graph = repository.get_graph()
4071
revision_graph = dict(((key, value) for key, value in
4072
graph.iter_ancestry([revision_id]) if value is not None))
4073
return _strip_NULL_ghosts(revision_graph)
4001
4076
def _strip_NULL_ghosts(revision_graph):
4002
4077
"""Also don't use this. more compatibility code for unmigrated clients."""
4003
4078
# Filter ghosts, and null:
4176
4251
parse_result = deserialiser.parse_text_bytes(
4177
4252
inventory_delta_bytes)
4178
4253
except inventory_delta.IncompatibleInventoryDelta, err:
4179
mutter("Incompatible delta: %s", err.msg)
4254
trace.mutter("Incompatible delta: %s", err.msg)
4180
4255
raise errors.IncompatibleRevision(self.target_repo._format)
4181
4256
basis_id, new_id, rich_root, tree_refs, inv_delta = parse_result
4182
4257
revision_id = new_id