~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Martin Packman
  • Date: 2012-01-05 10:37:58 UTC
  • mto: This revision was merged to the branch mainline in revision 6427.
  • Revision ID: martin.packman@canonical.com-20120105103758-wzftnmsip5iv9n2g
Revert addition of get_message_encoding function

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
    gpg,
36
36
    )
37
37
from bzrlib.bundle import serializer
 
38
from bzrlib.i18n import gettext
38
39
""")
39
40
 
40
41
from bzrlib import (
73
74
    record_root_entry = True
74
75
    # whether this commit builder supports the record_entry_contents interface
75
76
    supports_record_entry_contents = False
 
77
    # whether this commit builder will automatically update the branch that is
 
78
    # being committed to
 
79
    updates_branch = False
76
80
 
77
 
    def __init__(self, repository, parents, config, timestamp=None,
 
81
    def __init__(self, repository, parents, config_stack, timestamp=None,
78
82
                 timezone=None, committer=None, revprops=None,
79
83
                 revision_id=None, lossy=False):
80
84
        """Initiate a CommitBuilder.
89
93
        :param lossy: Whether to discard data that can not be natively
90
94
            represented, when pushing to a foreign VCS 
91
95
        """
92
 
        self._config = config
 
96
        self._config_stack = config_stack
93
97
        self._lossy = lossy
94
98
 
95
99
        if committer is None:
96
 
            self._committer = self._config.username()
 
100
            self._committer = self._config_stack.get('email')
97
101
        elif not isinstance(committer, unicode):
98
102
            self._committer = committer.decode() # throw if non-ascii
99
103
        else:
280
284
                raise
281
285
            mutter('abort_write_group failed')
282
286
            log_exception_quietly()
283
 
            note('bzr: ERROR (ignored): %s', exc)
 
287
            note(gettext('bzr: ERROR (ignored): %s'), exc)
284
288
        self._write_group = None
285
289
 
286
290
    def _abort_write_group(self):
340
344
        """
341
345
        self.control_files.break_lock()
342
346
 
343
 
    @needs_read_lock
344
 
    def _eliminate_revisions_not_present(self, revision_ids):
345
 
        """Check every revision id in revision_ids to see if we have it.
346
 
 
347
 
        Returns a set of the present revisions.
348
 
        """
349
 
        result = []
350
 
        graph = self.get_graph()
351
 
        parent_map = graph.get_parent_map(revision_ids)
352
 
        # The old API returned a list, should this actually be a set?
353
 
        return parent_map.keys()
354
 
 
355
347
    @staticmethod
356
 
    def create(a_bzrdir):
357
 
        """Construct the current default format repository in a_bzrdir."""
358
 
        return RepositoryFormat.get_default_format().initialize(a_bzrdir)
 
348
    def create(controldir):
 
349
        """Construct the current default format repository in controldir."""
 
350
        return RepositoryFormat.get_default_format().initialize(controldir)
359
351
 
360
 
    def __init__(self, _format, a_bzrdir, control_files):
 
352
    def __init__(self, _format, controldir, control_files):
361
353
        """instantiate a Repository.
362
354
 
363
355
        :param _format: The format of the repository on disk.
364
 
        :param a_bzrdir: The BzrDir of the repository.
 
356
        :param controldir: The ControlDir of the repository.
365
357
        :param control_files: Control files to use for locking, etc.
366
358
        """
367
359
        # In the future we will have a single api for all stores for
370
362
        super(Repository, self).__init__()
371
363
        self._format = _format
372
364
        # the following are part of the public API for Repository:
373
 
        self.bzrdir = a_bzrdir
 
365
        self.bzrdir = controldir
374
366
        self.control_files = control_files
375
 
        self._transport = control_files._transport
376
 
        self.base = self._transport.base
377
367
        # for tests
378
368
        self._write_group = None
379
369
        # Additional places to query for data.
417
407
        """
418
408
        if self.__class__ is not other.__class__:
419
409
            return False
420
 
        return (self._transport.base == other._transport.base)
 
410
        return (self.control_url == other.control_url)
421
411
 
422
412
    def is_in_write_group(self):
423
413
        """Return True if there is an open write group.
560
550
            def __init__(self):
561
551
                self.first_call = True
562
552
 
563
 
            def __call__(self, bzrdir):
564
 
                # On the first call, the parameter is always the bzrdir
 
553
            def __call__(self, controldir):
 
554
                # On the first call, the parameter is always the controldir
565
555
                # containing the current repo.
566
556
                if not self.first_call:
567
557
                    try:
568
 
                        repository = bzrdir.open_repository()
 
558
                        repository = controldir.open_repository()
569
559
                    except errors.NoRepositoryPresent:
570
560
                        pass
571
561
                    else:
572
562
                        return False, ([], repository)
573
563
                self.first_call = False
574
 
                value = (bzrdir.list_branches(), None)
 
564
                value = (controldir.list_branches(), None)
575
565
                return True, value
576
566
 
577
567
        ret = []
578
 
        for branches, repository in bzrdir.BzrDir.find_bzrdirs(
 
568
        for branches, repository in controldir.ControlDir.find_bzrdirs(
579
569
                self.user_transport, evaluate=Evaluator()):
580
570
            if branches is not None:
581
571
                ret.extend(branches)
615
605
        For instance, if the repository is at URL/.bzr/repository,
616
606
        Repository.open(URL) -> a Repository instance.
617
607
        """
618
 
        control = bzrdir.BzrDir.open(base)
 
608
        control = controldir.ControlDir.open(base)
619
609
        return control.open_repository()
620
610
 
621
611
    def copy_content_into(self, destination, revision_id=None):
652
642
        """
653
643
 
654
644
    def suspend_write_group(self):
 
645
        """Suspend a write group.
 
646
 
 
647
        :raise UnsuspendableWriteGroup: If the write group can not be
 
648
            suspended.
 
649
        :return: List of tokens
 
650
        """
655
651
        raise errors.UnsuspendableWriteGroup(self)
656
652
 
657
653
    def refresh_data(self):
679
675
    def _resume_write_group(self, tokens):
680
676
        raise errors.UnsuspendableWriteGroup(self)
681
677
 
682
 
    def fetch(self, source, revision_id=None, find_ghosts=False,
683
 
            fetch_spec=None):
 
678
    def fetch(self, source, revision_id=None, find_ghosts=False):
684
679
        """Fetch the content required to construct revision_id from source.
685
680
 
686
 
        If revision_id is None and fetch_spec is None, then all content is
687
 
        copied.
 
681
        If revision_id is None, then all content is copied.
688
682
 
689
683
        fetch() may not be used when the repository is in a write group -
690
684
        either finish the current write group before using fetch, or use
696
690
        :param revision_id: If specified, all the content needed for this
697
691
            revision ID will be copied to the target.  Fetch will determine for
698
692
            itself which content needs to be copied.
699
 
        :param fetch_spec: If specified, a SearchResult or
700
 
            PendingAncestryResult that describes which revisions to copy.  This
701
 
            allows copying multiple heads at once.  Mutually exclusive with
702
 
            revision_id.
703
693
        """
704
 
        if fetch_spec is not None and revision_id is not None:
705
 
            raise AssertionError(
706
 
                "fetch_spec and revision_id are mutually exclusive.")
707
694
        if self.is_in_write_group():
708
695
            raise errors.InternalBzrError(
709
696
                "May not fetch while in a write group.")
711
698
        # TODO: lift out to somewhere common with RemoteRepository
712
699
        # <https://bugs.launchpad.net/bzr/+bug/401646>
713
700
        if (self.has_same_location(source)
714
 
            and fetch_spec is None
715
701
            and self._has_same_fallbacks(source)):
716
702
            # check that last_revision is in 'from' and then return a
717
703
            # no-operation.
720
706
                self.get_revision(revision_id)
721
707
            return 0, []
722
708
        inter = InterRepository.get(source, self)
723
 
        return inter.fetch(revision_id=revision_id,
724
 
            find_ghosts=find_ghosts, fetch_spec=fetch_spec)
 
709
        return inter.fetch(revision_id=revision_id, find_ghosts=find_ghosts)
725
710
 
726
711
    def create_bundle(self, target, base, fileobj, format=None):
727
712
        return serializer.write_bundle(self, target, base, fileobj, format)
728
713
 
729
 
    def get_commit_builder(self, branch, parents, config, timestamp=None,
 
714
    def get_commit_builder(self, branch, parents, config_stack, timestamp=None,
730
715
                           timezone=None, committer=None, revprops=None,
731
716
                           revision_id=None, lossy=False):
732
717
        """Obtain a CommitBuilder for this repository.
733
718
 
734
719
        :param branch: Branch to commit to.
735
720
        :param parents: Revision ids of the parents of the new revision.
736
 
        :param config: Configuration to use.
 
721
        :param config_stack: Configuration stack to use.
737
722
        :param timestamp: Optional timestamp recorded for commit.
738
723
        :param timezone: Optional timezone for timestamp.
739
724
        :param committer: Optional committer to set for commit.
759
744
                repo.unlock()
760
745
 
761
746
    @needs_read_lock
762
 
    def clone(self, a_bzrdir, revision_id=None):
763
 
        """Clone this repository into a_bzrdir using the current format.
 
747
    def clone(self, controldir, revision_id=None):
 
748
        """Clone this repository into controldir using the current format.
764
749
 
765
750
        Currently no check is made that the format of this repository and
766
751
        the bzrdir format are compatible. FIXME RBC 20060201.
769
754
        """
770
755
        # TODO: deprecate after 0.16; cloning this with all its settings is
771
756
        # probably not very useful -- mbp 20070423
772
 
        dest_repo = self._create_sprouting_repo(a_bzrdir, shared=self.is_shared())
 
757
        dest_repo = self._create_sprouting_repo(
 
758
            controldir, shared=self.is_shared())
773
759
        self.copy_content_into(dest_repo, revision_id)
774
760
        return dest_repo
775
761
 
942
928
        parent_ids.discard(_mod_revision.NULL_REVISION)
943
929
        return parent_ids
944
930
 
945
 
    def fileids_altered_by_revision_ids(self, revision_ids):
946
 
        """Find the file ids and versions affected by revisions.
947
 
 
948
 
        :param revisions: an iterable containing revision ids.
949
 
        :return: a dictionary mapping altered file-ids to an iterable of
950
 
            revision_ids. Each altered file-ids has the exact revision_ids
951
 
            that altered it listed explicitly.
952
 
        """
953
 
        raise NotImplementedError(self.fileids_altered_by_revision_ids)
954
 
 
955
931
    def iter_files_bytes(self, desired_files):
956
932
        """Iterate through file versions.
957
933
 
1171
1147
                [parents_provider, other_repository._make_parents_provider()])
1172
1148
        return graph.Graph(parents_provider)
1173
1149
 
1174
 
    def revision_ids_to_search_result(self, result_set):
1175
 
        """Convert a set of revision ids to a graph SearchResult."""
1176
 
        result_parents = set()
1177
 
        for parents in self.get_graph().get_parent_map(
1178
 
            result_set).itervalues():
1179
 
            result_parents.update(parents)
1180
 
        included_keys = result_set.intersection(result_parents)
1181
 
        start_keys = result_set.difference(included_keys)
1182
 
        exclude_keys = result_parents.difference(result_set)
1183
 
        result = graph.SearchResult(start_keys, exclude_keys,
1184
 
            len(result_set), result_set)
1185
 
        return result
1186
 
 
1187
1150
    @needs_write_lock
1188
1151
    def set_make_working_trees(self, new_value):
1189
1152
        """Set the policy flag for making working trees when creating branches.
1207
1170
        self.store_revision_signature(gpg_strategy, plaintext, revision_id)
1208
1171
 
1209
1172
    @needs_read_lock
1210
 
    def verify_revision(self, revision_id, gpg_strategy):
 
1173
    def verify_revision_signature(self, revision_id, gpg_strategy):
1211
1174
        """Verify the signature on a revision.
1212
1175
        
1213
1176
        :param revision_id: the revision to verify
1334
1297
 
1335
1298
    def get_default(self):
1336
1299
        """Return the current default format."""
1337
 
        from bzrlib import bzrdir
1338
 
        return bzrdir.format_registry.make_bzrdir('default').repository_format
 
1300
        return controldir.format_registry.make_bzrdir('default').repository_format
1339
1301
 
1340
1302
 
1341
1303
network_format_registry = registry.FormatRegistry()
1384
1346
    created.
1385
1347
 
1386
1348
    Common instance attributes:
1387
 
    _matchingbzrdir - the bzrdir format that the repository format was
 
1349
    _matchingbzrdir - the controldir format that the repository format was
1388
1350
    originally written to work with. This can be used if manually
1389
1351
    constructing a bzrdir and repository, or more commonly for test suite
1390
1352
    parameterization.
1430
1392
    rich_root_data = None
1431
1393
    # Does this format support explicitly versioned directories?
1432
1394
    supports_versioned_directories = None
 
1395
    # Can other repositories be nested into one of this format?
 
1396
    supports_nesting_repositories = None
 
1397
    # Is it possible for revisions to be present without being referenced
 
1398
    # somewhere ?
 
1399
    supports_unreferenced_revisions = None
1433
1400
 
1434
1401
    def __repr__(self):
1435
1402
        return "%s()" % self.__class__.__name__
1442
1409
        return not self == other
1443
1410
 
1444
1411
    @classmethod
1445
 
    def find_format(klass, a_bzrdir):
1446
 
        """Return the format for the repository object in a_bzrdir.
1447
 
 
1448
 
        This is used by bzr native formats that have a "format" file in
1449
 
        the repository.  Other methods may be used by different types of
1450
 
        control directory.
1451
 
        """
1452
 
        try:
1453
 
            transport = a_bzrdir.get_repository_transport(None)
1454
 
            format_string = transport.get_bytes("format")
1455
 
            return format_registry.get(format_string)
1456
 
        except errors.NoSuchFile:
1457
 
            raise errors.NoRepositoryPresent(a_bzrdir)
1458
 
        except KeyError:
1459
 
            raise errors.UnknownFormatError(format=format_string,
1460
 
                                            kind='repository')
1461
 
 
1462
 
    @classmethod
1463
1412
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
1464
1413
    def register_format(klass, format):
1465
1414
        format_registry.register(format)
1475
1424
        """Return the current default format."""
1476
1425
        return format_registry.get_default()
1477
1426
 
1478
 
    def get_format_string(self):
1479
 
        """Return the ASCII format string that identifies this format.
1480
 
 
1481
 
        Note that in pre format ?? repositories the format string is
1482
 
        not permitted nor written to disk.
1483
 
        """
1484
 
        raise NotImplementedError(self.get_format_string)
1485
 
 
1486
1427
    def get_format_description(self):
1487
1428
        """Return the short description for this format."""
1488
1429
        raise NotImplementedError(self.get_format_description)
1489
1430
 
1490
 
    def initialize(self, a_bzrdir, shared=False):
1491
 
        """Initialize a repository of this format in a_bzrdir.
 
1431
    def initialize(self, controldir, shared=False):
 
1432
        """Initialize a repository of this format in controldir.
1492
1433
 
1493
 
        :param a_bzrdir: The bzrdir to put the new repository in it.
 
1434
        :param controldir: The controldir to put the new repository in it.
1494
1435
        :param shared: The repository should be initialized as a sharable one.
1495
1436
        :returns: The new repository object.
1496
1437
 
1497
1438
        This may raise UninitializableFormat if shared repository are not
1498
 
        compatible the a_bzrdir.
 
1439
        compatible the controldir.
1499
1440
        """
1500
1441
        raise NotImplementedError(self.initialize)
1501
1442
 
1537
1478
                'Does not support nested trees', target_format,
1538
1479
                from_format=self)
1539
1480
 
1540
 
    def open(self, a_bzrdir, _found=False):
1541
 
        """Return an instance of this format for the bzrdir a_bzrdir.
 
1481
    def open(self, controldir, _found=False):
 
1482
        """Return an instance of this format for a controldir.
1542
1483
 
1543
1484
        _found is a private parameter, do not use it.
1544
1485
        """
1545
1486
        raise NotImplementedError(self.open)
1546
1487
 
1547
 
    def _run_post_repo_init_hooks(self, repository, a_bzrdir, shared):
1548
 
        from bzrlib.bzrdir import BzrDir, RepoInitHookParams
1549
 
        hooks = BzrDir.hooks['post_repo_init']
 
1488
    def _run_post_repo_init_hooks(self, repository, controldir, shared):
 
1489
        from bzrlib.controldir import ControlDir, RepoInitHookParams
 
1490
        hooks = ControlDir.hooks['post_repo_init']
1550
1491
        if not hooks:
1551
1492
            return
1552
 
        params = RepoInitHookParams(repository, self, a_bzrdir, shared)
 
1493
        params = RepoInitHookParams(repository, self, controldir, shared)
1553
1494
        for hook in hooks:
1554
1495
            hook(params)
1555
1496
 
1556
1497
 
1557
 
class MetaDirRepositoryFormat(RepositoryFormat):
 
1498
class RepositoryFormatMetaDir(bzrdir.BzrDirMetaComponentFormat, RepositoryFormat):
1558
1499
    """Common base class for the new repositories using the metadir layout."""
1559
1500
 
1560
1501
    rich_root_data = False
1561
1502
    supports_tree_reference = False
1562
1503
    supports_external_lookups = False
1563
1504
    supports_leaving_lock = True
 
1505
    supports_nesting_repositories = True
1564
1506
 
1565
1507
    @property
1566
1508
    def _matchingbzrdir(self):
1569
1511
        return matching
1570
1512
 
1571
1513
    def __init__(self):
1572
 
        super(MetaDirRepositoryFormat, self).__init__()
 
1514
        RepositoryFormat.__init__(self)
 
1515
        bzrdir.BzrDirMetaComponentFormat.__init__(self)
1573
1516
 
1574
1517
    def _create_control_files(self, a_bzrdir):
1575
1518
        """Create the required files and the initial control_files object."""
1599
1542
        finally:
1600
1543
            control_files.unlock()
1601
1544
 
1602
 
    def network_name(self):
1603
 
        """Metadir formats have matching disk and network format strings."""
1604
 
        return self.get_format_string()
 
1545
    @classmethod
 
1546
    def find_format(klass, a_bzrdir):
 
1547
        """Return the format for the repository object in a_bzrdir.
 
1548
 
 
1549
        This is used by bzr native formats that have a "format" file in
 
1550
        the repository.  Other methods may be used by different types of
 
1551
        control directory.
 
1552
        """
 
1553
        try:
 
1554
            transport = a_bzrdir.get_repository_transport(None)
 
1555
            format_string = transport.get_bytes("format")
 
1556
        except errors.NoSuchFile:
 
1557
            raise errors.NoRepositoryPresent(a_bzrdir)
 
1558
        return klass._find_format(format_registry, 'repository', format_string)
1605
1559
 
1606
1560
 
1607
1561
# formats which have no format string are not discoverable or independently
1608
1562
# creatable on disk, so are not registered in format_registry.  They're
1609
1563
# all in bzrlib.repofmt.knitreponow.  When an instance of one of these is
1610
 
# needed, it's constructed directly by the BzrDir.  Non-native formats where
 
1564
# needed, it's constructed directly by the ControlDir.  Non-native formats where
1611
1565
# the repository is not separately opened are similar.
1612
1566
 
1613
1567
format_registry.register_lazy(
1724
1678
        self.target.fetch(self.source, revision_id=revision_id)
1725
1679
 
1726
1680
    @needs_write_lock
1727
 
    def fetch(self, revision_id=None, find_ghosts=False,
1728
 
            fetch_spec=None):
 
1681
    def fetch(self, revision_id=None, find_ghosts=False):
1729
1682
        """Fetch the content required to construct revision_id.
1730
1683
 
1731
1684
        The content is copied from self.source to self.target.
1811
1764
        # trigger an assertion if not such
1812
1765
        repo._format.get_format_string()
1813
1766
        self.repo_dir = repo.bzrdir
1814
 
        pb.update('Moving repository to repository.backup')
 
1767
        pb.update(gettext('Moving repository to repository.backup'))
1815
1768
        self.repo_dir.transport.move('repository', 'repository.backup')
1816
1769
        backup_transport =  self.repo_dir.transport.clone('repository.backup')
1817
1770
        repo._format.check_conversion_target(self.target_format)
1818
1771
        self.source_repo = repo._format.open(self.repo_dir,
1819
1772
            _found=True,
1820
1773
            _override_transport=backup_transport)
1821
 
        pb.update('Creating new repository')
 
1774
        pb.update(gettext('Creating new repository'))
1822
1775
        converted = self.target_format.initialize(self.repo_dir,
1823
1776
                                                  self.source_repo.is_shared())
1824
1777
        converted.lock_write()
1825
1778
        try:
1826
 
            pb.update('Copying content')
 
1779
            pb.update(gettext('Copying content'))
1827
1780
            self.source_repo.copy_content_into(converted)
1828
1781
        finally:
1829
1782
            converted.unlock()
1830
 
        pb.update('Deleting old repository content')
 
1783
        pb.update(gettext('Deleting old repository content'))
1831
1784
        self.repo_dir.transport.delete_tree('repository.backup')
1832
 
        ui.ui_factory.note('repository converted')
 
1785
        ui.ui_factory.note(gettext('repository converted'))
1833
1786
        pb.finished()
1834
1787
 
1835
1788
 
1901
1854
        for list_part in self.list_parts:
1902
1855
            full_list.extend(list_part)
1903
1856
        return iter(full_list)
 
1857
 
 
1858
    def __repr__(self):
 
1859
        return "%s.%s(%s)" % (self.__module__, self.__class__.__name__,
 
1860
                              self.list_parts)