~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

(gz) Never raise KnownFailure in tests,
 use knownFailure method instead (Martin [gz])

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
39
38
""")
40
39
 
41
40
from bzrlib import (
74
73
    record_root_entry = True
75
74
    # whether this commit builder supports the record_entry_contents interface
76
75
    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
80
76
 
81
77
    def __init__(self, repository, parents, config, timestamp=None,
82
78
                 timezone=None, committer=None, revprops=None,
284
280
                raise
285
281
            mutter('abort_write_group failed')
286
282
            log_exception_quietly()
287
 
            note(gettext('bzr: ERROR (ignored): %s'), exc)
 
283
            note('bzr: ERROR (ignored): %s', exc)
288
284
        self._write_group = None
289
285
 
290
286
    def _abort_write_group(self):
345
341
        self.control_files.break_lock()
346
342
 
347
343
    @staticmethod
348
 
    def create(controldir):
349
 
        """Construct the current default format repository in controldir."""
350
 
        return RepositoryFormat.get_default_format().initialize(controldir)
 
344
    def create(a_bzrdir):
 
345
        """Construct the current default format repository in a_bzrdir."""
 
346
        return RepositoryFormat.get_default_format().initialize(a_bzrdir)
351
347
 
352
 
    def __init__(self, _format, controldir, control_files):
 
348
    def __init__(self, _format, a_bzrdir, control_files):
353
349
        """instantiate a Repository.
354
350
 
355
351
        :param _format: The format of the repository on disk.
356
 
        :param controldir: The ControlDir of the repository.
 
352
        :param a_bzrdir: The BzrDir of the repository.
357
353
        :param control_files: Control files to use for locking, etc.
358
354
        """
359
355
        # In the future we will have a single api for all stores for
362
358
        super(Repository, self).__init__()
363
359
        self._format = _format
364
360
        # the following are part of the public API for Repository:
365
 
        self.bzrdir = controldir
 
361
        self.bzrdir = a_bzrdir
366
362
        self.control_files = control_files
 
363
        self._transport = control_files._transport
 
364
        self.base = self._transport.base
367
365
        # for tests
368
366
        self._write_group = None
369
367
        # Additional places to query for data.
407
405
        """
408
406
        if self.__class__ is not other.__class__:
409
407
            return False
410
 
        return (self.control_url == other.control_url)
 
408
        return (self._transport.base == other._transport.base)
411
409
 
412
410
    def is_in_write_group(self):
413
411
        """Return True if there is an open write group.
550
548
            def __init__(self):
551
549
                self.first_call = True
552
550
 
553
 
            def __call__(self, controldir):
554
 
                # On the first call, the parameter is always the controldir
 
551
            def __call__(self, bzrdir):
 
552
                # On the first call, the parameter is always the bzrdir
555
553
                # containing the current repo.
556
554
                if not self.first_call:
557
555
                    try:
558
 
                        repository = controldir.open_repository()
 
556
                        repository = bzrdir.open_repository()
559
557
                    except errors.NoRepositoryPresent:
560
558
                        pass
561
559
                    else:
562
560
                        return False, ([], repository)
563
561
                self.first_call = False
564
 
                value = (controldir.list_branches(), None)
 
562
                value = (bzrdir.list_branches(), None)
565
563
                return True, value
566
564
 
567
565
        ret = []
568
 
        for branches, repository in controldir.ControlDir.find_bzrdirs(
 
566
        for branches, repository in bzrdir.BzrDir.find_bzrdirs(
569
567
                self.user_transport, evaluate=Evaluator()):
570
568
            if branches is not None:
571
569
                ret.extend(branches)
605
603
        For instance, if the repository is at URL/.bzr/repository,
606
604
        Repository.open(URL) -> a Repository instance.
607
605
        """
608
 
        control = controldir.ControlDir.open(base)
 
606
        control = bzrdir.BzrDir.open(base)
609
607
        return control.open_repository()
610
608
 
611
609
    def copy_content_into(self, destination, revision_id=None):
642
640
        """
643
641
 
644
642
    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
 
        """
651
643
        raise errors.UnsuspendableWriteGroup(self)
652
644
 
653
645
    def refresh_data(self):
675
667
    def _resume_write_group(self, tokens):
676
668
        raise errors.UnsuspendableWriteGroup(self)
677
669
 
678
 
    def fetch(self, source, revision_id=None, find_ghosts=False):
 
670
    def fetch(self, source, revision_id=None, find_ghosts=False,
 
671
            fetch_spec=None):
679
672
        """Fetch the content required to construct revision_id from source.
680
673
 
681
 
        If revision_id is None, then all content is copied.
 
674
        If revision_id is None and fetch_spec is None, then all content is
 
675
        copied.
682
676
 
683
677
        fetch() may not be used when the repository is in a write group -
684
678
        either finish the current write group before using fetch, or use
690
684
        :param revision_id: If specified, all the content needed for this
691
685
            revision ID will be copied to the target.  Fetch will determine for
692
686
            itself which content needs to be copied.
 
687
        :param fetch_spec: If specified, a SearchResult or
 
688
            PendingAncestryResult that describes which revisions to copy.  This
 
689
            allows copying multiple heads at once.  Mutually exclusive with
 
690
            revision_id.
693
691
        """
 
692
        if fetch_spec is not None and revision_id is not None:
 
693
            raise AssertionError(
 
694
                "fetch_spec and revision_id are mutually exclusive.")
694
695
        if self.is_in_write_group():
695
696
            raise errors.InternalBzrError(
696
697
                "May not fetch while in a write group.")
698
699
        # TODO: lift out to somewhere common with RemoteRepository
699
700
        # <https://bugs.launchpad.net/bzr/+bug/401646>
700
701
        if (self.has_same_location(source)
 
702
            and fetch_spec is None
701
703
            and self._has_same_fallbacks(source)):
702
704
            # check that last_revision is in 'from' and then return a
703
705
            # no-operation.
706
708
                self.get_revision(revision_id)
707
709
            return 0, []
708
710
        inter = InterRepository.get(source, self)
709
 
        return inter.fetch(revision_id=revision_id, find_ghosts=find_ghosts)
 
711
        return inter.fetch(revision_id=revision_id,
 
712
            find_ghosts=find_ghosts, fetch_spec=fetch_spec)
710
713
 
711
714
    def create_bundle(self, target, base, fileobj, format=None):
712
715
        return serializer.write_bundle(self, target, base, fileobj, format)
744
747
                repo.unlock()
745
748
 
746
749
    @needs_read_lock
747
 
    def clone(self, controldir, revision_id=None):
748
 
        """Clone this repository into controldir using the current format.
 
750
    def clone(self, a_bzrdir, revision_id=None):
 
751
        """Clone this repository into a_bzrdir using the current format.
749
752
 
750
753
        Currently no check is made that the format of this repository and
751
754
        the bzrdir format are compatible. FIXME RBC 20060201.
754
757
        """
755
758
        # TODO: deprecate after 0.16; cloning this with all its settings is
756
759
        # probably not very useful -- mbp 20070423
757
 
        dest_repo = self._create_sprouting_repo(
758
 
            controldir, shared=self.is_shared())
 
760
        dest_repo = self._create_sprouting_repo(a_bzrdir, shared=self.is_shared())
759
761
        self.copy_content_into(dest_repo, revision_id)
760
762
        return dest_repo
761
763
 
928
930
        parent_ids.discard(_mod_revision.NULL_REVISION)
929
931
        return parent_ids
930
932
 
 
933
    def fileids_altered_by_revision_ids(self, revision_ids):
 
934
        """Find the file ids and versions affected by revisions.
 
935
 
 
936
        :param revisions: an iterable containing revision ids.
 
937
        :return: a dictionary mapping altered file-ids to an iterable of
 
938
            revision_ids. Each altered file-ids has the exact revision_ids
 
939
            that altered it listed explicitly.
 
940
        """
 
941
        raise NotImplementedError(self.fileids_altered_by_revision_ids)
 
942
 
931
943
    def iter_files_bytes(self, desired_files):
932
944
        """Iterate through file versions.
933
945
 
1147
1159
                [parents_provider, other_repository._make_parents_provider()])
1148
1160
        return graph.Graph(parents_provider)
1149
1161
 
 
1162
    def revision_ids_to_search_result(self, result_set):
 
1163
        """Convert a set of revision ids to a graph SearchResult."""
 
1164
        result_parents = set()
 
1165
        for parents in self.get_graph().get_parent_map(
 
1166
            result_set).itervalues():
 
1167
            result_parents.update(parents)
 
1168
        included_keys = result_set.intersection(result_parents)
 
1169
        start_keys = result_set.difference(included_keys)
 
1170
        exclude_keys = result_parents.difference(result_set)
 
1171
        result = graph.SearchResult(start_keys, exclude_keys,
 
1172
            len(result_set), result_set)
 
1173
        return result
 
1174
 
1150
1175
    @needs_write_lock
1151
1176
    def set_make_working_trees(self, new_value):
1152
1177
        """Set the policy flag for making working trees when creating branches.
1170
1195
        self.store_revision_signature(gpg_strategy, plaintext, revision_id)
1171
1196
 
1172
1197
    @needs_read_lock
1173
 
    def verify_revision_signature(self, revision_id, gpg_strategy):
 
1198
    def verify_revision(self, revision_id, gpg_strategy):
1174
1199
        """Verify the signature on a revision.
1175
1200
        
1176
1201
        :param revision_id: the revision to verify
1297
1322
 
1298
1323
    def get_default(self):
1299
1324
        """Return the current default format."""
1300
 
        return controldir.format_registry.make_bzrdir('default').repository_format
 
1325
        from bzrlib import bzrdir
 
1326
        return bzrdir.format_registry.make_bzrdir('default').repository_format
1301
1327
 
1302
1328
 
1303
1329
network_format_registry = registry.FormatRegistry()
1346
1372
    created.
1347
1373
 
1348
1374
    Common instance attributes:
1349
 
    _matchingbzrdir - the controldir format that the repository format was
 
1375
    _matchingbzrdir - the bzrdir format that the repository format was
1350
1376
    originally written to work with. This can be used if manually
1351
1377
    constructing a bzrdir and repository, or more commonly for test suite
1352
1378
    parameterization.
1392
1418
    rich_root_data = None
1393
1419
    # Does this format support explicitly versioned directories?
1394
1420
    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
1400
1421
 
1401
1422
    def __repr__(self):
1402
1423
        return "%s()" % self.__class__.__name__
1454
1475
        """Return the short description for this format."""
1455
1476
        raise NotImplementedError(self.get_format_description)
1456
1477
 
1457
 
    def initialize(self, controldir, shared=False):
1458
 
        """Initialize a repository of this format in controldir.
 
1478
    def initialize(self, a_bzrdir, shared=False):
 
1479
        """Initialize a repository of this format in a_bzrdir.
1459
1480
 
1460
 
        :param controldir: The controldir to put the new repository in it.
 
1481
        :param a_bzrdir: The bzrdir to put the new repository in it.
1461
1482
        :param shared: The repository should be initialized as a sharable one.
1462
1483
        :returns: The new repository object.
1463
1484
 
1464
1485
        This may raise UninitializableFormat if shared repository are not
1465
 
        compatible the controldir.
 
1486
        compatible the a_bzrdir.
1466
1487
        """
1467
1488
        raise NotImplementedError(self.initialize)
1468
1489
 
1504
1525
                'Does not support nested trees', target_format,
1505
1526
                from_format=self)
1506
1527
 
1507
 
    def open(self, controldir, _found=False):
1508
 
        """Return an instance of this format for a controldir.
 
1528
    def open(self, a_bzrdir, _found=False):
 
1529
        """Return an instance of this format for the bzrdir a_bzrdir.
1509
1530
 
1510
1531
        _found is a private parameter, do not use it.
1511
1532
        """
1512
1533
        raise NotImplementedError(self.open)
1513
1534
 
1514
 
    def _run_post_repo_init_hooks(self, repository, controldir, shared):
1515
 
        from bzrlib.controldir import ControlDir, RepoInitHookParams
1516
 
        hooks = ControlDir.hooks['post_repo_init']
 
1535
    def _run_post_repo_init_hooks(self, repository, a_bzrdir, shared):
 
1536
        from bzrlib.bzrdir import BzrDir, RepoInitHookParams
 
1537
        hooks = BzrDir.hooks['post_repo_init']
1517
1538
        if not hooks:
1518
1539
            return
1519
 
        params = RepoInitHookParams(repository, self, controldir, shared)
 
1540
        params = RepoInitHookParams(repository, self, a_bzrdir, shared)
1520
1541
        for hook in hooks:
1521
1542
            hook(params)
1522
1543
 
1528
1549
    supports_tree_reference = False
1529
1550
    supports_external_lookups = False
1530
1551
    supports_leaving_lock = True
1531
 
    supports_nesting_repositories = True
1532
1552
 
1533
1553
    @property
1534
1554
    def _matchingbzrdir(self):
1575
1595
# formats which have no format string are not discoverable or independently
1576
1596
# creatable on disk, so are not registered in format_registry.  They're
1577
1597
# all in bzrlib.repofmt.knitreponow.  When an instance of one of these is
1578
 
# needed, it's constructed directly by the ControlDir.  Non-native formats where
 
1598
# needed, it's constructed directly by the BzrDir.  Non-native formats where
1579
1599
# the repository is not separately opened are similar.
1580
1600
 
1581
1601
format_registry.register_lazy(
1692
1712
        self.target.fetch(self.source, revision_id=revision_id)
1693
1713
 
1694
1714
    @needs_write_lock
1695
 
    def fetch(self, revision_id=None, find_ghosts=False):
 
1715
    def fetch(self, revision_id=None, find_ghosts=False,
 
1716
            fetch_spec=None):
1696
1717
        """Fetch the content required to construct revision_id.
1697
1718
 
1698
1719
        The content is copied from self.source to self.target.
1778
1799
        # trigger an assertion if not such
1779
1800
        repo._format.get_format_string()
1780
1801
        self.repo_dir = repo.bzrdir
1781
 
        pb.update(gettext('Moving repository to repository.backup'))
 
1802
        pb.update('Moving repository to repository.backup')
1782
1803
        self.repo_dir.transport.move('repository', 'repository.backup')
1783
1804
        backup_transport =  self.repo_dir.transport.clone('repository.backup')
1784
1805
        repo._format.check_conversion_target(self.target_format)
1785
1806
        self.source_repo = repo._format.open(self.repo_dir,
1786
1807
            _found=True,
1787
1808
            _override_transport=backup_transport)
1788
 
        pb.update(gettext('Creating new repository'))
 
1809
        pb.update('Creating new repository')
1789
1810
        converted = self.target_format.initialize(self.repo_dir,
1790
1811
                                                  self.source_repo.is_shared())
1791
1812
        converted.lock_write()
1792
1813
        try:
1793
 
            pb.update(gettext('Copying content'))
 
1814
            pb.update('Copying content')
1794
1815
            self.source_repo.copy_content_into(converted)
1795
1816
        finally:
1796
1817
            converted.unlock()
1797
 
        pb.update(gettext('Deleting old repository content'))
 
1818
        pb.update('Deleting old repository content')
1798
1819
        self.repo_dir.transport.delete_tree('repository.backup')
1799
 
        ui.ui_factory.note(gettext('repository converted'))
 
1820
        ui.ui_factory.note('repository converted')
1800
1821
        pb.finished()
1801
1822
 
1802
1823
 
1868
1889
        for list_part in self.list_parts:
1869
1890
            full_list.extend(list_part)
1870
1891
        return iter(full_list)
1871
 
 
1872
 
    def __repr__(self):
1873
 
        return "%s.%s(%s)" % (self.__module__, self.__class__.__name__,
1874
 
                              self.list_parts)