~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/controldir.py

(gz) Change minimum required testtools version for selftest to 0.9.5 for
 unicode fixes (Martin [gz])

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2010, 2011 Canonical Ltd
 
1
# Copyright (C) 2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
28
28
 
29
29
from bzrlib import (
30
30
    errors,
 
31
    graph,
 
32
    registry,
31
33
    revision as _mod_revision,
32
 
    transport as _mod_transport,
33
 
    ui,
 
34
    symbol_versioning,
 
35
    urlutils,
34
36
    )
35
37
from bzrlib.push import (
36
38
    PushResult,
37
39
    )
 
40
from bzrlib.trace import (
 
41
    mutter,
 
42
    )
 
43
from bzrlib.transport import (
 
44
    get_transport,
 
45
    local,
 
46
    )
38
47
 
39
48
""")
40
49
 
41
 
from bzrlib import registry
42
 
 
43
50
 
44
51
class ControlComponent(object):
45
52
    """Abstract base class for control directory components.
74
81
        return self.user_transport.base
75
82
 
76
83
 
77
 
 
78
84
class ControlDir(ControlComponent):
79
85
    """A control directory.
80
86
 
133
139
        """
134
140
        raise NotImplementedError(self.needs_format_conversion)
135
141
 
136
 
    def create_repository(self, shared=False):
137
 
        """Create a new repository in this control directory.
138
 
 
139
 
        :param shared: If a shared repository should be created
140
 
        :return: The newly created repository
141
 
        """
142
 
        raise NotImplementedError(self.create_repository)
143
 
 
144
142
    def destroy_repository(self):
145
143
        """Destroy the repository in this ControlDir."""
146
144
        raise NotImplementedError(self.destroy_repository)
147
145
 
148
 
    def create_branch(self, name=None, repository=None):
 
146
    def create_branch(self, name=None):
149
147
        """Create a branch in this ControlDir.
150
148
 
151
149
        :param name: Name of the colocated branch to create, None for
207
205
            raise errors.NoColocatedBranchSupport(self)
208
206
        return None
209
207
 
 
208
    def get_branch_transport(self, branch_format, name=None):
 
209
        """Get the transport for use by branch format in this ControlDir.
 
210
 
 
211
        Note that bzr dirs that do not support format strings will raise
 
212
        IncompatibleFormat if the branch format they are given has
 
213
        a format string, and vice versa.
 
214
 
 
215
        If branch_format is None, the transport is returned with no
 
216
        checking. If it is not None, then the returned transport is
 
217
        guaranteed to point to an existing directory ready for use.
 
218
        """
 
219
        raise NotImplementedError(self.get_branch_transport)
 
220
 
 
221
    def get_repository_transport(self, repository_format):
 
222
        """Get the transport for use by repository format in this ControlDir.
 
223
 
 
224
        Note that bzr dirs that do not support format strings will raise
 
225
        IncompatibleFormat if the repository format they are given has
 
226
        a format string, and vice versa.
 
227
 
 
228
        If repository_format is None, the transport is returned with no
 
229
        checking. If it is not None, then the returned transport is
 
230
        guaranteed to point to an existing directory ready for use.
 
231
        """
 
232
        raise NotImplementedError(self.get_repository_transport)
 
233
 
 
234
    def get_workingtree_transport(self, tree_format):
 
235
        """Get the transport for use by workingtree format in this ControlDir.
 
236
 
 
237
        Note that bzr dirs that do not support format strings will raise
 
238
        IncompatibleFormat if the workingtree format they are given has a
 
239
        format string, and vice versa.
 
240
 
 
241
        If workingtree_format is None, the transport is returned with no
 
242
        checking. If it is not None, then the returned transport is
 
243
        guaranteed to point to an existing directory ready for use.
 
244
        """
 
245
        raise NotImplementedError(self.get_workingtree_transport)
 
246
 
210
247
    def open_branch(self, name=None, unsupported=False,
211
248
                    ignore_fallbacks=False):
212
249
        """Open the branch object at this ControlDir if one is present.
327
364
        :param create_tree_if_local: If true, a working-tree will be created
328
365
            when working locally.
329
366
        """
330
 
        raise NotImplementedError(self.sprout)
 
367
        target_transport = get_transport(url, possible_transports)
 
368
        target_transport.ensure_base()
 
369
        cloning_format = self.cloning_metadir(stacked)
 
370
        # Create/update the result branch
 
371
        result = cloning_format.initialize_on_transport(target_transport)
 
372
        # if a stacked branch wasn't requested, we don't create one
 
373
        # even if the origin was stacked
 
374
        stacked_branch_url = None
 
375
        if source_branch is not None:
 
376
            if stacked:
 
377
                stacked_branch_url = self.root_transport.base
 
378
            source_repository = source_branch.repository
 
379
        else:
 
380
            try:
 
381
                source_branch = self.open_branch()
 
382
                source_repository = source_branch.repository
 
383
                if stacked:
 
384
                    stacked_branch_url = self.root_transport.base
 
385
            except errors.NotBranchError:
 
386
                source_branch = None
 
387
                try:
 
388
                    source_repository = self.open_repository()
 
389
                except errors.NoRepositoryPresent:
 
390
                    source_repository = None
 
391
        repository_policy = result.determine_repository_policy(
 
392
            force_new_repo, stacked_branch_url, require_stacking=stacked)
 
393
        result_repo, is_new_repo = repository_policy.acquire_repository()
 
394
        is_stacked = stacked or (len(result_repo._fallback_repositories) != 0)
 
395
        if is_new_repo and revision_id is not None and not is_stacked:
 
396
            fetch_spec = graph.PendingAncestryResult(
 
397
                [revision_id], source_repository)
 
398
        else:
 
399
            fetch_spec = None
 
400
        if source_repository is not None:
 
401
            # Fetch while stacked to prevent unstacked fetch from
 
402
            # Branch.sprout.
 
403
            if fetch_spec is None:
 
404
                result_repo.fetch(source_repository, revision_id=revision_id)
 
405
            else:
 
406
                result_repo.fetch(source_repository, fetch_spec=fetch_spec)
 
407
 
 
408
        if source_branch is None:
 
409
            # this is for sprouting a controldir without a branch; is that
 
410
            # actually useful?
 
411
            # Not especially, but it's part of the contract.
 
412
            result_branch = result.create_branch()
 
413
        else:
 
414
            result_branch = source_branch.sprout(result,
 
415
                revision_id=revision_id, repository_policy=repository_policy)
 
416
        mutter("created new branch %r" % (result_branch,))
 
417
 
 
418
        # Create/update the result working tree
 
419
        if (create_tree_if_local and
 
420
            isinstance(target_transport, local.LocalTransport) and
 
421
            (result_repo is None or result_repo.make_working_trees())):
 
422
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
 
423
                hardlink=hardlink)
 
424
            wt.lock_write()
 
425
            try:
 
426
                if wt.path2id('') is None:
 
427
                    try:
 
428
                        wt.set_root_id(self.open_workingtree.get_root_id())
 
429
                    except errors.NoWorkingTree:
 
430
                        pass
 
431
            finally:
 
432
                wt.unlock()
 
433
        else:
 
434
            wt = None
 
435
        if recurse == 'down':
 
436
            if wt is not None:
 
437
                basis = wt.basis_tree()
 
438
                basis.lock_read()
 
439
                subtrees = basis.iter_references()
 
440
            elif result_branch is not None:
 
441
                basis = result_branch.basis_tree()
 
442
                basis.lock_read()
 
443
                subtrees = basis.iter_references()
 
444
            elif source_branch is not None:
 
445
                basis = source_branch.basis_tree()
 
446
                basis.lock_read()
 
447
                subtrees = basis.iter_references()
 
448
            else:
 
449
                subtrees = []
 
450
                basis = None
 
451
            try:
 
452
                for path, file_id in subtrees:
 
453
                    target = urlutils.join(url, urlutils.escape(path))
 
454
                    sublocation = source_branch.reference_parent(file_id, path)
 
455
                    sublocation.bzrdir.sprout(target,
 
456
                        basis.get_reference_revision(file_id, path),
 
457
                        force_new_repo=force_new_repo, recurse=recurse,
 
458
                        stacked=stacked)
 
459
            finally:
 
460
                if basis is not None:
 
461
                    basis.unlock()
 
462
        return result
331
463
 
332
464
    def push_branch(self, source, revision_id=None, overwrite=False, 
333
465
        remember=False, create_prefix=False):
349
481
        if br_to is None:
350
482
            # We have a repository but no branch, copy the revisions, and then
351
483
            # create a branch.
352
 
            if revision_id is None:
353
 
                # No revision supplied by the user, default to the branch
354
 
                # revision
355
 
                revision_id = source.last_revision()
356
484
            repository_to.fetch(source.repository, revision_id=revision_id)
357
485
            br_to = source.clone(self, revision_id=revision_id)
358
486
            if source.get_push_location() is None or remember:
436
564
        :param preserve_stacking: When cloning a stacked branch, stack the
437
565
            new branch on top of the other branch's stacked-on branch.
438
566
        """
439
 
        return self.clone_on_transport(_mod_transport.get_transport(url),
 
567
        return self.clone_on_transport(get_transport(url),
440
568
                                       revision_id=revision_id,
441
569
                                       force_new_repo=force_new_repo,
442
570
                                       preserve_stacking=preserve_stacking)
443
571
 
444
572
    def clone_on_transport(self, transport, revision_id=None,
445
573
        force_new_repo=False, preserve_stacking=False, stacked_on=None,
446
 
        create_prefix=False, use_existing_dir=True, no_tree=False):
 
574
        create_prefix=False, use_existing_dir=True):
447
575
        """Clone this bzrdir and its contents to transport verbatim.
448
576
 
449
577
        :param transport: The transport for the location to produce the clone
458
586
        :param create_prefix: Create any missing directories leading up to
459
587
            to_transport.
460
588
        :param use_existing_dir: Use an existing directory if one exists.
461
 
        :param no_tree: If set to true prevents creation of a working tree.
462
589
        """
463
590
        raise NotImplementedError(self.clone_on_transport)
464
591
 
465
592
 
466
 
class ControlComponentFormat(object):
467
 
    """A component that can live inside of a .bzr meta directory."""
468
 
 
469
 
    upgrade_recommended = False
470
 
 
471
 
    def get_format_string(self):
472
 
        """Return the format of this format, if usable in meta directories."""
473
 
        raise NotImplementedError(self.get_format_string)
474
 
 
475
 
    def get_format_description(self):
476
 
        """Return the short description for this format."""
477
 
        raise NotImplementedError(self.get_format_description)
478
 
 
479
 
    def is_supported(self):
480
 
        """Is this format supported?
481
 
 
482
 
        Supported formats must be initializable and openable.
483
 
        Unsupported formats may not support initialization or committing or
484
 
        some other features depending on the reason for not being supported.
485
 
        """
486
 
        return True
487
 
 
488
 
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
489
 
        basedir=None):
490
 
        """Give an error or warning on old formats.
491
 
 
492
 
        :param allow_unsupported: If true, allow opening
493
 
            formats that are strongly deprecated, and which may
494
 
            have limited functionality.
495
 
 
496
 
        :param recommend_upgrade: If true (default), warn
497
 
            the user through the ui object that they may wish
498
 
            to upgrade the object.
499
 
        """
500
 
        if not allow_unsupported and not self.is_supported():
501
 
            # see open_downlevel to open legacy branches.
502
 
            raise errors.UnsupportedFormatError(format=self)
503
 
        if recommend_upgrade and self.upgrade_recommended:
504
 
            ui.ui_factory.recommend_upgrade(
505
 
                self.get_format_description(), basedir)
506
 
 
507
 
 
508
 
class ControlComponentFormatRegistry(registry.FormatRegistry):
509
 
    """A registry for control components (branch, workingtree, repository)."""
510
 
 
511
 
    def __init__(self, other_registry=None):
512
 
        super(ControlComponentFormatRegistry, self).__init__(other_registry)
513
 
        self._extra_formats = []
514
 
 
515
 
    def register(self, format):
516
 
        """Register a new format."""
517
 
        super(ControlComponentFormatRegistry, self).register(
518
 
            format.get_format_string(), format)
519
 
 
520
 
    def remove(self, format):
521
 
        """Remove a registered format."""
522
 
        super(ControlComponentFormatRegistry, self).remove(
523
 
            format.get_format_string())
524
 
 
525
 
    def register_extra(self, format):
526
 
        """Register a format that can not be used in a metadir.
527
 
 
528
 
        This is mainly useful to allow custom repository formats, such as older
529
 
        Bazaar formats and foreign formats, to be tested.
530
 
        """
531
 
        self._extra_formats.append(registry._ObjectGetter(format))
532
 
 
533
 
    def remove_extra(self, format):
534
 
        """Remove an extra format.
535
 
        """
536
 
        self._extra_formats.remove(registry._ObjectGetter(format))
537
 
 
538
 
    def register_extra_lazy(self, module_name, member_name):
539
 
        """Register a format lazily.
540
 
        """
541
 
        self._extra_formats.append(
542
 
            registry._LazyObjectGetter(module_name, member_name))
543
 
 
544
 
    def _get_extra(self):
545
 
        """Return all "extra" formats, not usable in meta directories."""
546
 
        result = []
547
 
        for getter in self._extra_formats:
548
 
            f = getter.get_obj()
549
 
            if callable(f):
550
 
                f = f()
551
 
            result.append(f)
552
 
        return result
553
 
 
554
 
    def _get_all(self):
555
 
        """Return all formats, even those not usable in metadirs.
556
 
        """
557
 
        result = []
558
 
        for name in self.keys():
559
 
            fmt = self.get(name)
560
 
            if callable(fmt):
561
 
                fmt = fmt()
562
 
            result.append(fmt)
563
 
        return result + self._get_extra()
564
 
 
565
 
    def _get_all_modules(self):
566
 
        """Return a set of the modules providing objects."""
567
 
        modules = set()
568
 
        for name in self.keys():
569
 
            modules.add(self._get_module(name))
570
 
        for getter in self._extra_formats:
571
 
            modules.add(getter.get_module())
572
 
        return modules
573
 
 
574
 
 
575
 
class Converter(object):
576
 
    """Converts a disk format object from one format to another."""
577
 
 
578
 
    def convert(self, to_convert, pb):
579
 
        """Perform the conversion of to_convert, giving feedback via pb.
580
 
 
581
 
        :param to_convert: The disk object to convert.
582
 
        :param pb: a progress bar to use for progress information.
583
 
        """
584
 
 
585
 
    def step(self, message):
586
 
        """Update the pb by a step."""
587
 
        self.count +=1
588
 
        self.pb.update(message, self.count, self.total)
589
 
 
590
 
 
591
593
class ControlDirFormat(object):
592
594
    """An encapsulation of the initialization and open routines for a format.
593
595
 
612
614
    _default_format = None
613
615
    """The default format used for new control directories."""
614
616
 
 
617
    _formats = []
 
618
    """The registered control formats - .bzr, ....
 
619
 
 
620
    This is a list of ControlDirFormat objects.
 
621
    """
 
622
 
615
623
    _server_probers = []
616
624
    """The registered server format probers, e.g. RemoteBzrProber.
617
625
 
629
637
    """
630
638
 
631
639
    supports_workingtrees = True
632
 
    """Whether working trees can exist in control directories of this format.
633
 
    """
634
 
 
635
 
    fixed_components = False
636
 
    """Whether components can not change format independent of the control dir.
637
 
    """
638
 
 
639
 
    upgrade_recommended = False
640
 
    """Whether an upgrade from this format is recommended."""
641
640
 
642
641
    def get_format_description(self):
643
642
        """Return the short description for this format."""
666
665
        """
667
666
        return True
668
667
 
669
 
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
670
 
        basedir=None):
671
 
        """Give an error or warning on old formats.
672
 
 
673
 
        :param allow_unsupported: If true, allow opening
674
 
            formats that are strongly deprecated, and which may
675
 
            have limited functionality.
676
 
 
677
 
        :param recommend_upgrade: If true (default), warn
678
 
            the user through the ui object that they may wish
679
 
            to upgrade the object.
680
 
        """
681
 
        if not allow_unsupported and not self.is_supported():
682
 
            # see open_downlevel to open legacy branches.
683
 
            raise errors.UnsupportedFormatError(format=self)
684
 
        if recommend_upgrade and self.upgrade_recommended:
685
 
            ui.ui_factory.recommend_upgrade(
686
 
                self.get_format_description(), basedir)
687
 
 
688
668
    def same_model(self, target_format):
689
669
        return (self.repository_format.rich_root_data ==
690
670
            target_format.rich_root_data)
694
674
        """Register a format that does not use '.bzr' for its control dir.
695
675
 
696
676
        """
697
 
        raise errors.BzrError("ControlDirFormat.register_format() has been "
698
 
            "removed in Bazaar 2.4. Please upgrade your plugins.")
 
677
        klass._formats.append(format)
699
678
 
700
679
    @classmethod
701
680
    def register_prober(klass, prober):
727
706
        return self.get_format_description().rstrip()
728
707
 
729
708
    @classmethod
 
709
    def unregister_format(klass, format):
 
710
        klass._formats.remove(format)
 
711
 
 
712
    @classmethod
730
713
    def known_formats(klass):
731
714
        """Return all the known formats.
732
715
        """
733
 
        result = set()
734
 
        for prober_kls in klass._probers + klass._server_probers:
735
 
            result.update(prober_kls.known_formats())
736
 
        return result
 
716
        return set(klass._formats)
737
717
 
738
718
    @classmethod
739
719
    def find_format(klass, transport, _server_formats=True):
761
741
        Subclasses should typically override initialize_on_transport
762
742
        instead of this method.
763
743
        """
764
 
        return self.initialize_on_transport(
765
 
            _mod_transport.get_transport(url, possible_transports))
766
 
 
 
744
        return self.initialize_on_transport(get_transport(url,
 
745
                                                          possible_transports))
767
746
    def initialize_on_transport(self, transport):
768
747
        """Initialize a new controldir in the base directory of a Transport."""
769
748
        raise NotImplementedError(self.initialize_on_transport)
829
808
 
830
809
 
831
810
class Prober(object):
832
 
    """Abstract class that can be used to detect a particular kind of
 
811
    """Abstract class that can be used to detect a particular kind of 
833
812
    control directory.
834
813
 
835
 
    At the moment this just contains a single method to probe a particular
836
 
    transport, but it may be extended in the future to e.g. avoid
 
814
    At the moment this just contains a single method to probe a particular 
 
815
    transport, but it may be extended in the future to e.g. avoid 
837
816
    multiple levels of probing for Subversion repositories.
838
 
 
839
 
    See BzrProber and RemoteBzrProber in bzrlib.bzrdir for the
840
 
    probers that detect .bzr/ directories and Bazaar smart servers,
841
 
    respectively.
842
 
 
843
 
    Probers should be registered using the register_server_prober or
844
 
    register_prober methods on ControlDirFormat.
845
817
    """
846
818
 
847
819
    def probe_transport(self, transport):
854
826
        """
855
827
        raise NotImplementedError(self.probe_transport)
856
828
 
857
 
    @classmethod
858
 
    def known_formats(cls):
859
 
        """Return the control dir formats known by this prober.
860
 
 
861
 
        Multiple probers can return the same formats, so this should
862
 
        return a set.
863
 
 
864
 
        :return: A set of known formats.
865
 
        """
866
 
        raise NotImplementedError(cls.known_formats)
867
 
 
868
829
 
869
830
class ControlDirFormatInfo(object):
870
831
 
879
840
    """Registry of user-selectable ControlDir subformats.
880
841
 
881
842
    Differs from ControlDirFormat._formats in that it provides sub-formats,
882
 
    e.g. BzrDirMeta1 with weave repository.  Also, it's more user-oriented.
 
843
    e.g. ControlDirMeta1 with weave repository.  Also, it's more user-oriented.
883
844
    """
884
845
 
885
846
    def __init__(self):