/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.205.1 by Jelmer Vernooij
Import utility functions for foreign branches.
1
# Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Foreign branch utilities."""
18
0.205.6 by Jelmer Vernooij
Import FakeControlFiles.
19
from bzrlib import errors, registry
0.207.1 by Jelmer Vernooij
Add ForeignBranch class, make dpush fallback to regular push.
20
from bzrlib.branch import Branch
0.205.7 by Jelmer Vernooij
Import dpush.
21
from bzrlib.commands import Command, Option
0.207.1 by Jelmer Vernooij
Add ForeignBranch class, make dpush fallback to regular push.
22
from bzrlib.trace import info
0.205.3 by Jelmer Vernooij
Fix import.
23
24
0.205.1 by Jelmer Vernooij
Import utility functions for foreign branches.
25
class VcsMapping(object):
26
    """Describes the mapping between the semantics of Bazaar and a foreign vcs.
27
28
    """
29
    experimental = False
30
    roundtripping = False
31
    revid_prefix = None
32
0.205.9 by Jelmer Vernooij
Add abstract functions for converting revision ids between bzr and foreign vcses.
33
    def revision_id_bzr_to_foreign(self, bzr_revid):
34
        """Parse a bzr revision id and convert it to a foreign revid.
35
36
        :param bzr_revid: The bzr revision id (a string).
37
        :return: A foreign revision id, can be any sort of object.
38
        """
39
        raise NotImplementedError(self.revision_id_bzr_to_foreign)
40
41
    def revision_id_foreign_to_bzr(self, foreign_revid):
42
        """Parse a foreign revision id and convert it to a bzr revid.
43
44
        :param foreign_revid: Foreign revision id, can be any sort of object.
45
        :return: A bzr revision id.
46
        """
47
        raise NotImplementedError(self.revision_id_foreign_to_bzr)
48
0.205.1 by Jelmer Vernooij
Import utility functions for foreign branches.
49
50
class VcsMappingRegistry(registry.Registry):
51
    """Registry for Bazaar<->foreign VCS mappings.
52
    
53
    There should be one instance of this registry for every foreign VCS.
54
    """
55
56
    def register(self, key, factory, help):
57
        """Register a mapping between Bazaar and foreign VCS semantics.
58
59
        The factory must be a callable that takes one parameter: the key.
60
        It must produce an instance of VcsMapping when called.
61
        """
62
        registry.Registry.register(self, key, factory, help)
63
64
    def set_default(self, key):
65
        """Set the 'default' key to be a clone of the supplied key.
66
67
        This method must be called once and only once.
68
        """
69
        self._set_default_key(key)
70
71
    def get_default(self):
72
        """Convenience function for obtaining the default mapping to use."""
73
        return self.get(self._get_default_key())
74
0.205.6 by Jelmer Vernooij
Import FakeControlFiles.
75
0.207.1 by Jelmer Vernooij
Add ForeignBranch class, make dpush fallback to regular push.
76
class ForeignBranch(Branch):
77
78
    def __init__(self, mapping):
79
        super(ForeignBranch, self).__init__()
80
        self.mapping = mapping
81
82
    def dpull(self, source, stop_revision=None):
83
        raise NotImplementedError(self.pull)
84
85
0.205.6 by Jelmer Vernooij
Import FakeControlFiles.
86
class FakeControlFiles(object):
87
    """Dummy implementation of ControlFiles.
88
    
89
    This is required as some code relies on controlfiles being 
90
    available."""
91
    def get_utf8(self, name):
92
        raise errors.NoSuchFile(name)
93
94
    def get(self, name):
95
        raise errors.NoSuchFile(name)
96
97
    def break_lock(self):
98
        pass
99
0.205.7 by Jelmer Vernooij
Import dpush.
100
101
class cmd_dpush(Command):
0.205.8 by Jelmer Vernooij
Remove references to svn.
102
    """Push diffs into a foreign version control system without any 
103
    Bazaar-specific metadata.
0.205.7 by Jelmer Vernooij
Import dpush.
104
0.205.8 by Jelmer Vernooij
Remove references to svn.
105
    This will afterwards rebase the local Bazaar branch on the remote
0.205.7 by Jelmer Vernooij
Import dpush.
106
    branch unless the --no-rebase option is used, in which case 
107
    the two branches will be out of sync. 
108
    """
109
    takes_args = ['location?']
110
    takes_options = ['remember', Option('directory',
111
            help='Branch to push from, '
112
                 'rather than the one containing the working directory.',
113
            short_name='d',
114
            type=unicode,
115
            ),
116
            Option('no-rebase', help="Don't rebase after push")]
117
118
    def run(self, location=None, remember=False, directory=None, 
119
            no_rebase=False):
120
        from bzrlib import urlutils
121
        from bzrlib.bzrdir import BzrDir
122
        from bzrlib.branch import Branch
123
        from bzrlib.errors import BzrCommandError, NoWorkingTree
124
        from bzrlib.workingtree import WorkingTree
125
126
        if directory is None:
127
            directory = "."
128
        try:
129
            source_wt = WorkingTree.open_containing(directory)[0]
130
            source_branch = source_wt.branch
131
        except NoWorkingTree:
132
            source_branch = Branch.open_containing(directory)[0]
133
            source_wt = None
134
        stored_loc = source_branch.get_push_location()
135
        if location is None:
136
            if stored_loc is None:
137
                raise BzrCommandError("No push location known or specified.")
138
            else:
139
                display_url = urlutils.unescape_for_display(stored_loc,
140
                        self.outf.encoding)
141
                self.outf.write("Using saved location: %s\n" % display_url)
142
                location = stored_loc
143
144
        bzrdir = BzrDir.open(location)
145
        target_branch = bzrdir.open_branch()
146
        target_branch.lock_write()
0.207.1 by Jelmer Vernooij
Add ForeignBranch class, make dpush fallback to regular push.
147
        if not isinstance(target_branch, ForeignBranch):
148
            info("target branch is not a foreign branch, using regular push.")
149
            target_branch.pull(source_branch)
150
            no_rebase = True
151
        else:
152
            revid_map = target_branch.dpull(source_branch)
0.205.7 by Jelmer Vernooij
Import dpush.
153
        # We successfully created the target, remember it
154
        if source_branch.get_push_location() is None or remember:
155
            source_branch.set_push_location(target_branch.base)
156
        if not no_rebase:
157
            _, old_last_revid = source_branch.last_revision_info()
158
            new_last_revid = revid_map[old_last_revid]
159
            if source_wt is not None:
160
                source_wt.pull(target_branch, overwrite=True, 
161
                               stop_revision=new_last_revid)
162
            else:
163
                source_branch.pull(target_branch, overwrite=True, 
164
                                   stop_revision=new_last_revid)
165
0.205.15 by Jelmer Vernooij
Add test_suite function.
166
def test_suite():
167
    from unittest import TestSuite
168
    from bzrlib.tests import TestUtil
169
    loader = TestUtil.TestLoader()
170
    suite = TestSuite()
171
    testmod_names = ['test_versionedfiles',]
172
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
173
    return suite
0.205.7 by Jelmer Vernooij
Import dpush.
174
0.207.2 by Jelmer Vernooij
Import escape commit message function.
175
def escape_commit_message(message):
176
    """Replace xml-incompatible control characters."""
177
    if message is None:
178
        return None
179
    import re
180
    # FIXME: RBC 20060419 this should be done by the revision
181
    # serialiser not by commit. Then we can also add an unescaper
182
    # in the deserializer and start roundtripping revision messages
183
    # precisely. See repository_implementations/test_repository.py
184
    
185
    # Python strings can include characters that can't be
186
    # represented in well-formed XML; escape characters that
187
    # aren't listed in the XML specification
188
    # (http://www.w3.org/TR/REC-xml/#NT-Char).
189
    message, _ = re.subn(
190
        u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD]+',
191
        lambda match: match.group(0).encode('unicode_escape'),
192
        message)
193
    return message
194
195
196