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 __future__ import absolute_import
19
17
from bzrlib.lazy_import import lazy_import
20
18
lazy_import(globals(), """
24
22
from bzrlib import (
76
74
record_root_entry = True
77
75
# whether this commit builder supports the record_entry_contents interface
78
76
supports_record_entry_contents = False
79
# whether this commit builder will automatically update the branch that is
81
updates_branch = False
83
def __init__(self, repository, parents, config_stack, timestamp=None,
78
def __init__(self, repository, parents, config, timestamp=None,
84
79
timezone=None, committer=None, revprops=None,
85
80
revision_id=None, lossy=False):
86
81
"""Initiate a CommitBuilder.
95
90
:param lossy: Whether to discard data that can not be natively
96
91
represented, when pushing to a foreign VCS
98
self._config_stack = config_stack
99
94
self._lossy = lossy
101
96
if committer is None:
102
self._committer = self._config_stack.get('email')
97
self._committer = self._config.username()
103
98
elif not isinstance(committer, unicode):
104
99
self._committer = committer.decode() # throw if non-ascii
347
342
self.control_files.break_lock()
350
def create(controldir):
351
"""Construct the current default format repository in controldir."""
352
return RepositoryFormat.get_default_format().initialize(controldir)
345
def create(a_bzrdir):
346
"""Construct the current default format repository in a_bzrdir."""
347
return RepositoryFormat.get_default_format().initialize(a_bzrdir)
354
def __init__(self, _format, controldir, control_files):
349
def __init__(self, _format, a_bzrdir, control_files):
355
350
"""instantiate a Repository.
357
352
:param _format: The format of the repository on disk.
358
:param controldir: The ControlDir of the repository.
353
:param a_bzrdir: The BzrDir of the repository.
359
354
:param control_files: Control files to use for locking, etc.
361
356
# In the future we will have a single api for all stores for
552
547
def __init__(self):
553
548
self.first_call = True
555
def __call__(self, controldir):
556
# On the first call, the parameter is always the controldir
550
def __call__(self, bzrdir):
551
# On the first call, the parameter is always the bzrdir
557
552
# containing the current repo.
558
553
if not self.first_call:
560
repository = controldir.open_repository()
555
repository = bzrdir.open_repository()
561
556
except errors.NoRepositoryPresent:
564
559
return False, ([], repository)
565
560
self.first_call = False
566
value = (controldir.list_branches(), None)
561
value = (bzrdir.list_branches(), None)
567
562
return True, value
570
for branches, repository in controldir.ControlDir.find_bzrdirs(
565
for branches, repository in bzrdir.BzrDir.find_bzrdirs(
571
566
self.user_transport, evaluate=Evaluator()):
572
567
if branches is not None:
573
568
ret.extend(branches)
607
602
For instance, if the repository is at URL/.bzr/repository,
608
603
Repository.open(URL) -> a Repository instance.
610
control = controldir.ControlDir.open(base)
605
control = bzrdir.BzrDir.open(base)
611
606
return control.open_repository()
613
608
def copy_content_into(self, destination, revision_id=None):
677
666
def _resume_write_group(self, tokens):
678
667
raise errors.UnsuspendableWriteGroup(self)
680
def fetch(self, source, revision_id=None, find_ghosts=False):
669
def fetch(self, source, revision_id=None, find_ghosts=False,
681
671
"""Fetch the content required to construct revision_id from source.
683
If revision_id is None, then all content is copied.
673
If revision_id is None and fetch_spec is None, then all content is
685
676
fetch() may not be used when the repository is in a write group -
686
677
either finish the current write group before using fetch, or use
692
683
:param revision_id: If specified, all the content needed for this
693
684
revision ID will be copied to the target. Fetch will determine for
694
685
itself which content needs to be copied.
686
:param fetch_spec: If specified, a SearchResult or
687
PendingAncestryResult that describes which revisions to copy. This
688
allows copying multiple heads at once. Mutually exclusive with
691
if fetch_spec is not None and revision_id is not None:
692
raise AssertionError(
693
"fetch_spec and revision_id are mutually exclusive.")
696
694
if self.is_in_write_group():
697
695
raise errors.InternalBzrError(
698
696
"May not fetch while in a write group.")
700
698
# TODO: lift out to somewhere common with RemoteRepository
701
699
# <https://bugs.launchpad.net/bzr/+bug/401646>
702
700
if (self.has_same_location(source)
701
and fetch_spec is None
703
702
and self._has_same_fallbacks(source)):
704
703
# check that last_revision is in 'from' and then return a
708
707
self.get_revision(revision_id)
710
709
inter = InterRepository.get(source, self)
711
return inter.fetch(revision_id=revision_id, find_ghosts=find_ghosts)
710
return inter.fetch(revision_id=revision_id,
711
find_ghosts=find_ghosts, fetch_spec=fetch_spec)
713
713
def create_bundle(self, target, base, fileobj, format=None):
714
714
return serializer.write_bundle(self, target, base, fileobj, format)
716
def get_commit_builder(self, branch, parents, config_stack, timestamp=None,
716
def get_commit_builder(self, branch, parents, config, timestamp=None,
717
717
timezone=None, committer=None, revprops=None,
718
718
revision_id=None, lossy=False):
719
719
"""Obtain a CommitBuilder for this repository.
721
721
:param branch: Branch to commit to.
722
722
:param parents: Revision ids of the parents of the new revision.
723
:param config_stack: Configuration stack to use.
723
:param config: Configuration to use.
724
724
:param timestamp: Optional timestamp recorded for commit.
725
725
:param timezone: Optional timezone for timestamp.
726
726
:param committer: Optional committer to set for commit.
749
def clone(self, controldir, revision_id=None):
750
"""Clone this repository into controldir using the current format.
749
def clone(self, a_bzrdir, revision_id=None):
750
"""Clone this repository into a_bzrdir using the current format.
752
752
Currently no check is made that the format of this repository and
753
753
the bzrdir format are compatible. FIXME RBC 20060201.
757
757
# TODO: deprecate after 0.16; cloning this with all its settings is
758
758
# probably not very useful -- mbp 20070423
759
dest_repo = self._create_sprouting_repo(
760
controldir, shared=self.is_shared())
759
dest_repo = self._create_sprouting_repo(a_bzrdir, shared=self.is_shared())
761
760
self.copy_content_into(dest_repo, revision_id)
930
929
parent_ids.discard(_mod_revision.NULL_REVISION)
931
930
return parent_ids
932
def fileids_altered_by_revision_ids(self, revision_ids):
933
"""Find the file ids and versions affected by revisions.
935
:param revisions: an iterable containing revision ids.
936
:return: a dictionary mapping altered file-ids to an iterable of
937
revision_ids. Each altered file-ids has the exact revision_ids
938
that altered it listed explicitly.
940
raise NotImplementedError(self.fileids_altered_by_revision_ids)
933
942
def iter_files_bytes(self, desired_files):
934
943
"""Iterate through file versions.
1149
1158
[parents_provider, other_repository._make_parents_provider()])
1150
1159
return graph.Graph(parents_provider)
1161
def revision_ids_to_search_result(self, result_set):
1162
"""Convert a set of revision ids to a graph SearchResult."""
1163
result_parents = set()
1164
for parents in self.get_graph().get_parent_map(
1165
result_set).itervalues():
1166
result_parents.update(parents)
1167
included_keys = result_set.intersection(result_parents)
1168
start_keys = result_set.difference(included_keys)
1169
exclude_keys = result_parents.difference(result_set)
1170
result = graph.SearchResult(start_keys, exclude_keys,
1171
len(result_set), result_set)
1152
1174
@needs_write_lock
1153
1175
def set_make_working_trees(self, new_value):
1154
1176
"""Set the policy flag for making working trees when creating branches.
1172
1194
self.store_revision_signature(gpg_strategy, plaintext, revision_id)
1174
1196
@needs_read_lock
1175
def verify_revision_signature(self, revision_id, gpg_strategy):
1197
def verify_revision(self, revision_id, gpg_strategy):
1176
1198
"""Verify the signature on a revision.
1178
1200
:param revision_id: the revision to verify
1226
1248
if branch is None:
1227
conf = config.GlobalStack()
1249
conf = config.GlobalConfig()
1229
conf = branch.get_config_stack()
1230
if 'format_deprecation' in conf.get('suppress_warnings'):
1251
conf = branch.get_config()
1252
if conf.suppress_warning('format_deprecation'):
1232
1254
warning("Format %s for %s is deprecated -"
1233
1255
" please use 'bzr upgrade' to get better performance"
1293
1315
"""Returns the policy for making working trees on new branches."""
1294
1316
return not self._transport.has('no-working-trees')
1297
def update_feature_flags(self, updated_flags):
1298
"""Update the feature flags for this branch.
1300
:param updated_flags: Dictionary mapping feature names to necessities
1301
A necessity can be None to indicate the feature should be removed
1303
self._format._update_feature_flags(updated_flags)
1304
self.control_transport.put_bytes('format', self._format.as_string())
1307
1319
class RepositoryFormatRegistry(controldir.ControlComponentFormatRegistry):
1308
1320
"""Repository format registry."""
1310
1322
def get_default(self):
1311
1323
"""Return the current default format."""
1312
return controldir.format_registry.make_bzrdir('default').repository_format
1324
from bzrlib import bzrdir
1325
return bzrdir.format_registry.make_bzrdir('default').repository_format
1315
1328
network_format_registry = registry.FormatRegistry()
1360
1373
Common instance attributes:
1361
_matchingbzrdir - the controldir format that the repository format was
1374
_matchingbzrdir - the bzrdir format that the repository format was
1362
1375
originally written to work with. This can be used if manually
1363
1376
constructing a bzrdir and repository, or more commonly for test suite
1364
1377
parameterization.
1406
1419
supports_versioned_directories = None
1407
1420
# Can other repositories be nested into one of this format?
1408
1421
supports_nesting_repositories = None
1409
# Is it possible for revisions to be present without being referenced
1411
supports_unreferenced_revisions = None
1413
1423
def __repr__(self):
1414
1424
return "%s()" % self.__class__.__name__
1421
1431
return not self == other
1434
def find_format(klass, a_bzrdir):
1435
"""Return the format for the repository object in a_bzrdir.
1437
This is used by bzr native formats that have a "format" file in
1438
the repository. Other methods may be used by different types of
1442
transport = a_bzrdir.get_repository_transport(None)
1443
format_string = transport.get_bytes("format")
1444
return format_registry.get(format_string)
1445
except errors.NoSuchFile:
1446
raise errors.NoRepositoryPresent(a_bzrdir)
1448
raise errors.UnknownFormatError(format=format_string,
1424
1452
@symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1425
1453
def register_format(klass, format):
1426
1454
format_registry.register(format)
1436
1464
"""Return the current default format."""
1437
1465
return format_registry.get_default()
1467
def get_format_string(self):
1468
"""Return the ASCII format string that identifies this format.
1470
Note that in pre format ?? repositories the format string is
1471
not permitted nor written to disk.
1473
raise NotImplementedError(self.get_format_string)
1439
1475
def get_format_description(self):
1440
1476
"""Return the short description for this format."""
1441
1477
raise NotImplementedError(self.get_format_description)
1443
def initialize(self, controldir, shared=False):
1444
"""Initialize a repository of this format in controldir.
1479
def initialize(self, a_bzrdir, shared=False):
1480
"""Initialize a repository of this format in a_bzrdir.
1446
:param controldir: The controldir to put the new repository in it.
1482
:param a_bzrdir: The bzrdir to put the new repository in it.
1447
1483
:param shared: The repository should be initialized as a sharable one.
1448
1484
:returns: The new repository object.
1450
1486
This may raise UninitializableFormat if shared repository are not
1451
compatible the controldir.
1487
compatible the a_bzrdir.
1453
1489
raise NotImplementedError(self.initialize)
1490
1526
'Does not support nested trees', target_format,
1491
1527
from_format=self)
1493
def open(self, controldir, _found=False):
1494
"""Return an instance of this format for a controldir.
1529
def open(self, a_bzrdir, _found=False):
1530
"""Return an instance of this format for the bzrdir a_bzrdir.
1496
1532
_found is a private parameter, do not use it.
1498
1534
raise NotImplementedError(self.open)
1500
def _run_post_repo_init_hooks(self, repository, controldir, shared):
1501
from bzrlib.controldir import ControlDir, RepoInitHookParams
1502
hooks = ControlDir.hooks['post_repo_init']
1536
def _run_post_repo_init_hooks(self, repository, a_bzrdir, shared):
1537
from bzrlib.bzrdir import BzrDir, RepoInitHookParams
1538
hooks = BzrDir.hooks['post_repo_init']
1505
params = RepoInitHookParams(repository, self, controldir, shared)
1541
params = RepoInitHookParams(repository, self, a_bzrdir, shared)
1506
1542
for hook in hooks:
1510
class RepositoryFormatMetaDir(bzrdir.BzrFormat, RepositoryFormat):
1546
class MetaDirRepositoryFormat(RepositoryFormat):
1511
1547
"""Common base class for the new repositories using the metadir layout."""
1513
1549
rich_root_data = False
1523
1559
return matching
1525
1561
def __init__(self):
1526
RepositoryFormat.__init__(self)
1527
bzrdir.BzrFormat.__init__(self)
1562
super(MetaDirRepositoryFormat, self).__init__()
1529
1564
def _create_control_files(self, a_bzrdir):
1530
1565
"""Create the required files and the initial control_files object."""
1555
1590
control_files.unlock()
1558
def find_format(klass, a_bzrdir):
1559
"""Return the format for the repository object in a_bzrdir.
1561
This is used by bzr native formats that have a "format" file in
1562
the repository. Other methods may be used by different types of
1566
transport = a_bzrdir.get_repository_transport(None)
1567
format_string = transport.get_bytes("format")
1568
except errors.NoSuchFile:
1569
raise errors.NoRepositoryPresent(a_bzrdir)
1570
return klass._find_format(format_registry, 'repository', format_string)
1572
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
1574
RepositoryFormat.check_support_status(self,
1575
allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
1577
bzrdir.BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
1578
recommend_upgrade=recommend_upgrade, basedir=basedir)
1592
def network_name(self):
1593
"""Metadir formats have matching disk and network format strings."""
1594
return self.get_format_string()
1581
1597
# formats which have no format string are not discoverable or independently
1582
1598
# creatable on disk, so are not registered in format_registry. They're
1583
1599
# all in bzrlib.repofmt.knitreponow. When an instance of one of these is
1584
# needed, it's constructed directly by the ControlDir. Non-native formats where
1600
# needed, it's constructed directly by the BzrDir. Non-native formats where
1585
1601
# the repository is not separately opened are similar.
1587
1603
format_registry.register_lazy(
1698
1714
self.target.fetch(self.source, revision_id=revision_id)
1700
1716
@needs_write_lock
1701
def fetch(self, revision_id=None, find_ghosts=False):
1717
def fetch(self, revision_id=None, find_ghosts=False,
1702
1719
"""Fetch the content required to construct revision_id.
1704
1721
The content is copied from self.source to self.target.