~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Andrew Starr-Bochicchio
  • Date: 2014-03-30 17:59:29 UTC
  • mto: This revision was merged to the branch mainline in revision 6592.
  • Revision ID: a.starr.b@gmail.com-20140330175929-rd97jstcbau2j1gy
Use LooseVersion from distutils to check Cython version in order to handle non-integers in the version string.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
16
16
 
 
17
from __future__ import absolute_import
 
18
 
17
19
from bzrlib.lazy_import import lazy_import
18
20
lazy_import(globals(), """
19
21
import itertools
20
22
import time
21
23
 
22
24
from bzrlib import (
23
 
    bzrdir,
24
25
    config,
25
26
    controldir,
26
27
    debug,
39
40
""")
40
41
 
41
42
from bzrlib import (
 
43
    bzrdir,
42
44
    errors,
43
45
    registry,
44
46
    symbol_versioning,
78
80
    # being committed to
79
81
    updates_branch = False
80
82
 
81
 
    def __init__(self, repository, parents, config, timestamp=None,
 
83
    def __init__(self, repository, parents, config_stack, timestamp=None,
82
84
                 timezone=None, committer=None, revprops=None,
83
85
                 revision_id=None, lossy=False):
84
86
        """Initiate a CommitBuilder.
93
95
        :param lossy: Whether to discard data that can not be natively
94
96
            represented, when pushing to a foreign VCS 
95
97
        """
96
 
        self._config = config
 
98
        self._config_stack = config_stack
97
99
        self._lossy = lossy
98
100
 
99
101
        if committer is None:
100
 
            self._committer = self._config.username()
 
102
            self._committer = self._config_stack.get('email')
101
103
        elif not isinstance(committer, unicode):
102
104
            self._committer = committer.decode() # throw if non-ascii
103
105
        else:
711
713
    def create_bundle(self, target, base, fileobj, format=None):
712
714
        return serializer.write_bundle(self, target, base, fileobj, format)
713
715
 
714
 
    def get_commit_builder(self, branch, parents, config, timestamp=None,
 
716
    def get_commit_builder(self, branch, parents, config_stack, timestamp=None,
715
717
                           timezone=None, committer=None, revprops=None,
716
718
                           revision_id=None, lossy=False):
717
719
        """Obtain a CommitBuilder for this repository.
718
720
 
719
721
        :param branch: Branch to commit to.
720
722
        :param parents: Revision ids of the parents of the new revision.
721
 
        :param config: Configuration to use.
 
723
        :param config_stack: Configuration stack to use.
722
724
        :param timestamp: Optional timestamp recorded for commit.
723
725
        :param timezone: Optional timezone for timestamp.
724
726
        :param committer: Optional committer to set for commit.
979
981
            raise AssertionError('_iter_for_revno returned too much history')
980
982
        return (True, partial_history[-1])
981
983
 
982
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
983
 
    def iter_reverse_revision_history(self, revision_id):
984
 
        """Iterate backwards through revision ids in the lefthand history
985
 
 
986
 
        :param revision_id: The revision id to start with.  All its lefthand
987
 
            ancestors will be traversed.
988
 
        """
989
 
        graph = self.get_graph()
990
 
        stop_revisions = (None, _mod_revision.NULL_REVISION)
991
 
        return graph.iter_lefthand_ancestry(revision_id, stop_revisions)
992
 
 
993
984
    def is_shared(self):
994
985
        """Return True if this repository is flagged as a shared repository."""
995
986
        raise NotImplementedError(self.is_shared)
1032
1023
        """
1033
1024
        raise NotImplementedError(self.revision_trees)
1034
1025
 
1035
 
    @needs_read_lock
1036
 
    @symbol_versioning.deprecated_method(
1037
 
        symbol_versioning.deprecated_in((2, 4, 0)))
1038
 
    def get_ancestry(self, revision_id, topo_sorted=True):
1039
 
        """Return a list of revision-ids integrated by a revision.
1040
 
 
1041
 
        The first element of the list is always None, indicating the origin
1042
 
        revision.  This might change when we have history horizons, or
1043
 
        perhaps we should have a new API.
1044
 
 
1045
 
        This is topologically sorted.
1046
 
        """
1047
 
        if 'evil' in debug.debug_flags:
1048
 
            mutter_callsite(2, "get_ancestry is linear with history.")
1049
 
        if _mod_revision.is_null(revision_id):
1050
 
            return [None]
1051
 
        if not self.has_revision(revision_id):
1052
 
            raise errors.NoSuchRevision(self, revision_id)
1053
 
        graph = self.get_graph()
1054
 
        keys = set()
1055
 
        search = graph._make_breadth_first_searcher([revision_id])
1056
 
        while True:
1057
 
            try:
1058
 
                found, ghosts = search.next_with_ghosts()
1059
 
            except StopIteration:
1060
 
                break
1061
 
            keys.update(found)
1062
 
        if _mod_revision.NULL_REVISION in keys:
1063
 
            keys.remove(_mod_revision.NULL_REVISION)
1064
 
        if topo_sorted:
1065
 
            parent_map = graph.get_parent_map(keys)
1066
 
            keys = tsort.topo_sort(parent_map)
1067
 
        return [None] + list(keys)
1068
 
 
1069
1026
    def pack(self, hint=None, clean_obsolete_packs=False):
1070
1027
        """Compress the data within the repository.
1071
1028
 
1172
1129
    @needs_read_lock
1173
1130
    def verify_revision_signature(self, revision_id, gpg_strategy):
1174
1131
        """Verify the signature on a revision.
1175
 
        
 
1132
 
1176
1133
        :param revision_id: the revision to verify
1177
1134
        :gpg_strategy: the GPGStrategy object to used
1178
 
        
 
1135
 
1179
1136
        :return: gpg.SIGNATURE_VALID or a failed SIGNATURE_ value
1180
1137
        """
1181
1138
        if not self.has_signature_for_revision_id(revision_id):
1187
1144
 
1188
1145
        return gpg_strategy.verify(signature, plaintext)
1189
1146
 
 
1147
    @needs_read_lock
 
1148
    def verify_revision_signatures(self, revision_ids, gpg_strategy):
 
1149
        """Verify revision signatures for a number of revisions.
 
1150
 
 
1151
        :param revision_id: the revision to verify
 
1152
        :gpg_strategy: the GPGStrategy object to used
 
1153
        :return: Iterator over tuples with revision id, result and keys
 
1154
        """
 
1155
        for revid in revision_ids:
 
1156
            (result, key) = self.verify_revision_signature(revid, gpg_strategy)
 
1157
            yield revid, result, key
 
1158
 
1190
1159
    def has_signature_for_revision_id(self, revision_id):
1191
1160
        """Query for a revision signature for revision_id in the repository."""
1192
1161
        raise NotImplementedError(self.has_signature_for_revision_id)
1222
1191
            return
1223
1192
        try:
1224
1193
            if branch is None:
1225
 
                conf = config.GlobalConfig()
 
1194
                conf = config.GlobalStack()
1226
1195
            else:
1227
 
                conf = branch.get_config()
1228
 
            if conf.suppress_warning('format_deprecation'):
 
1196
                conf = branch.get_config_stack()
 
1197
            if 'format_deprecation' in conf.get('suppress_warnings'):
1229
1198
                return
1230
1199
            warning("Format %s for %s is deprecated -"
1231
1200
                    " please use 'bzr upgrade' to get better performance"
1291
1260
        """Returns the policy for making working trees on new branches."""
1292
1261
        return not self._transport.has('no-working-trees')
1293
1262
 
 
1263
    @needs_write_lock
 
1264
    def update_feature_flags(self, updated_flags):
 
1265
        """Update the feature flags for this branch.
 
1266
 
 
1267
        :param updated_flags: Dictionary mapping feature names to necessities
 
1268
            A necessity can be None to indicate the feature should be removed
 
1269
        """
 
1270
        self._format._update_feature_flags(updated_flags)
 
1271
        self.control_transport.put_bytes('format', self._format.as_string())
 
1272
 
1294
1273
 
1295
1274
class RepositoryFormatRegistry(controldir.ControlComponentFormatRegistry):
1296
1275
    """Repository format registry."""
1408
1387
    def __ne__(self, other):
1409
1388
        return not self == other
1410
1389
 
1411
 
    @classmethod
1412
 
    def find_format(klass, a_bzrdir):
1413
 
        """Return the format for the repository object in a_bzrdir.
1414
 
 
1415
 
        This is used by bzr native formats that have a "format" file in
1416
 
        the repository.  Other methods may be used by different types of
1417
 
        control directory.
1418
 
        """
1419
 
        try:
1420
 
            transport = a_bzrdir.get_repository_transport(None)
1421
 
            format_string = transport.get_bytes("format")
1422
 
            return format_registry.get(format_string)
1423
 
        except errors.NoSuchFile:
1424
 
            raise errors.NoRepositoryPresent(a_bzrdir)
1425
 
        except KeyError:
1426
 
            raise errors.UnknownFormatError(format=format_string,
1427
 
                                            kind='repository')
1428
 
 
1429
 
    @classmethod
1430
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1431
 
    def register_format(klass, format):
1432
 
        format_registry.register(format)
1433
 
 
1434
 
    @classmethod
1435
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1436
 
    def unregister_format(klass, format):
1437
 
        format_registry.remove(format)
1438
 
 
1439
 
    @classmethod
1440
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1441
 
    def get_default_format(klass):
1442
 
        """Return the current default format."""
1443
 
        return format_registry.get_default()
1444
 
 
1445
 
    def get_format_string(self):
1446
 
        """Return the ASCII format string that identifies this format.
1447
 
 
1448
 
        Note that in pre format ?? repositories the format string is
1449
 
        not permitted nor written to disk.
1450
 
        """
1451
 
        raise NotImplementedError(self.get_format_string)
1452
 
 
1453
1390
    def get_format_description(self):
1454
1391
        """Return the short description for this format."""
1455
1392
        raise NotImplementedError(self.get_format_description)
1521
1458
            hook(params)
1522
1459
 
1523
1460
 
1524
 
class MetaDirRepositoryFormat(RepositoryFormat):
 
1461
class RepositoryFormatMetaDir(bzrdir.BzrFormat, RepositoryFormat):
1525
1462
    """Common base class for the new repositories using the metadir layout."""
1526
1463
 
1527
1464
    rich_root_data = False
1537
1474
        return matching
1538
1475
 
1539
1476
    def __init__(self):
1540
 
        super(MetaDirRepositoryFormat, self).__init__()
 
1477
        RepositoryFormat.__init__(self)
 
1478
        bzrdir.BzrFormat.__init__(self)
1541
1479
 
1542
1480
    def _create_control_files(self, a_bzrdir):
1543
1481
        """Create the required files and the initial control_files object."""
1567
1505
        finally:
1568
1506
            control_files.unlock()
1569
1507
 
1570
 
    def network_name(self):
1571
 
        """Metadir formats have matching disk and network format strings."""
1572
 
        return self.get_format_string()
 
1508
    @classmethod
 
1509
    def find_format(klass, a_bzrdir):
 
1510
        """Return the format for the repository object in a_bzrdir.
 
1511
 
 
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
 
1514
        control directory.
 
1515
        """
 
1516
        try:
 
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)
 
1522
 
 
1523
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
 
1524
            basedir=None):
 
1525
        RepositoryFormat.check_support_status(self,
 
1526
            allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
 
1527
            basedir=basedir)
 
1528
        bzrdir.BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
 
1529
            recommend_upgrade=recommend_upgrade, basedir=basedir)
1573
1530
 
1574
1531
 
1575
1532
# formats which have no format string are not discoverable or independently