/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to __init__.py

  • Committer: Jelmer Vernooij
  • Date: 2009-02-08 19:20:14 UTC
  • mto: (0.436.139 foreign)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@samba.org-20090208192014-0g17picqdx7edl92
Import foreign-mapping-upgrade command, fixes for bzr-svn.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2008-2009 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
 
 
19
from bzrlib import errors
 
20
from bzrlib.branch import Branch
 
21
from bzrlib.commands import Command, Option
 
22
 
 
23
 
 
24
class ForeignBranch(Branch):
 
25
    """Branch that exists in a foreign version control system."""
 
26
 
 
27
    def __init__(self, mapping):
 
28
        self.mapping = mapping
 
29
        super(ForeignBranch, self).__init__()
 
30
 
 
31
    def dpull(self, source, stop_revision=None):
 
32
        """Pull deltas from another branch.
 
33
 
 
34
        :note: This does not, like pull, retain the revision ids from 
 
35
            the source branch and will, rather than adding bzr-specific 
 
36
            metadata, push only those semantics of the revision that can be 
 
37
            natively represented in this branch.
 
38
 
 
39
        :param source: Source branch
 
40
        :param stop_revision: Revision to pull, defaults to last revision.
 
41
        :return: Revision id map and file id map
 
42
        """
 
43
        raise NotImplementedError(self.dpull)
 
44
 
 
45
 
 
46
class FakeControlFiles(object):
 
47
    """Dummy implementation of ControlFiles.
 
48
    
 
49
    This is required as some code relies on controlfiles being 
 
50
    available."""
 
51
    def get_utf8(self, name):
 
52
        raise errors.NoSuchFile(name)
 
53
 
 
54
    def get(self, name):
 
55
        raise errors.NoSuchFile(name)
 
56
 
 
57
    def break_lock(self):
 
58
        pass
 
59
 
 
60
 
 
61
class cmd_dpush(Command):
 
62
    """Push diffs into a foreign version control system without any 
 
63
    Bazaar-specific metadata.
 
64
 
 
65
    This will afterwards rebase the local Bazaar branch on the remote
 
66
    branch unless the --no-rebase option is used, in which case 
 
67
    the two branches will be out of sync. 
 
68
    """
 
69
    takes_args = ['location?']
 
70
    takes_options = ['remember', Option('directory',
 
71
            help='Branch to push from, '
 
72
                 'rather than the one containing the working directory.',
 
73
            short_name='d',
 
74
            type=unicode,
 
75
            ),
 
76
            Option('no-rebase', help="Don't rebase after push")]
 
77
 
 
78
    def run(self, location=None, remember=False, directory=None, 
 
79
            no_rebase=False):
 
80
        from bzrlib import urlutils
 
81
        from bzrlib.bzrdir import BzrDir
 
82
        from bzrlib.errors import BzrCommandError, NoWorkingTree
 
83
        from bzrlib.inventory import Inventory
 
84
        from bzrlib.revision import NULL_REVISION
 
85
        from bzrlib.trace import info
 
86
        from bzrlib.workingtree import WorkingTree
 
87
        from upgrade import update_workinginv_fileids
 
88
 
 
89
        def get_inv(wt, revid):
 
90
            if revid == NULL_REVISION:
 
91
                return Inventory()
 
92
            else:
 
93
                return wt.branch.repository.get_inventory(revid)
 
94
 
 
95
        if directory is None:
 
96
            directory = "."
 
97
        try:
 
98
            source_wt = WorkingTree.open_containing(directory)[0]
 
99
            source_branch = source_wt.branch
 
100
        except NoWorkingTree:
 
101
            source_branch = Branch.open_containing(directory)[0]
 
102
            source_wt = None
 
103
        stored_loc = source_branch.get_push_location()
 
104
        if location is None:
 
105
            if stored_loc is None:
 
106
                raise BzrCommandError("No push location known or specified.")
 
107
            else:
 
108
                display_url = urlutils.unescape_for_display(stored_loc,
 
109
                        self.outf.encoding)
 
110
                self.outf.write("Using saved location: %s\n" % display_url)
 
111
                location = stored_loc
 
112
 
 
113
        bzrdir = BzrDir.open(location)
 
114
        target_branch = bzrdir.open_branch()
 
115
        target_branch.lock_write()
 
116
        try:
 
117
            if getattr(target_branch, "dpull", None) is None:
 
118
                info("target branch is not a foreign branch, using regular push.")
 
119
                target_branch.pull(source_branch)
 
120
                no_rebase = True
 
121
            else:
 
122
                revid_map = target_branch.dpull(source_branch)
 
123
            # We successfully created the target, remember it
 
124
            if source_branch.get_push_location() is None or remember:
 
125
                source_branch.set_push_location(target_branch.base)
 
126
            if not no_rebase:
 
127
                _, old_last_revid = source_branch.last_revision_info()
 
128
                new_last_revid = revid_map[old_last_revid]
 
129
                if source_wt is not None:
 
130
                    source_wt.pull(target_branch, overwrite=True, 
 
131
                                   stop_revision=new_last_revid)
 
132
                    source_wt.lock_write()
 
133
                    try:
 
134
                        update_workinginv_fileids(source_wt, 
 
135
                            get_inv(source_wt, old_last_revid), 
 
136
                            get_inv(source_wt, new_last_revid))
 
137
                    finally:
 
138
                        source_wt.unlock()
 
139
                else:
 
140
                    source_branch.pull(target_branch, overwrite=True, 
 
141
                                       stop_revision=new_last_revid)
 
142
        finally:
 
143
            target_branch.unlock()
 
144
 
 
145
 
 
146
class cmd_foreign_mapping_upgrade(Command):
 
147
    """Upgrade revisions mapped from a foreign version control system 
 
148
    in a Bazaar branch.
 
149
    
 
150
    This will change the identity of revisions whose parents 
 
151
    were mapped from revisions in the other version control system.
 
152
 
 
153
    You are recommended to run "bzr check" in the local repository 
 
154
    after running this command.
 
155
    """
 
156
    aliases = ['svn-upgrade']
 
157
    takes_args = ['from_repository?']
 
158
    takes_options = ['verbose', 
 
159
            Option("idmap-file", help="Write map with old and new revision ids.", type=str)]
 
160
 
 
161
    def run(self, from_repository=None, verbose=False, idmap_file=None):
 
162
        from upgrade import upgrade_branch, upgrade_workingtree
 
163
        from bzrlib.branch import Branch
 
164
        from bzrlib.errors import NoWorkingTree, BzrCommandError
 
165
        from bzrlib.repository import Repository
 
166
        from bzrlib.trace import info
 
167
        from bzrlib.workingtree import WorkingTree
 
168
        try:
 
169
            wt_to = WorkingTree.open(".")
 
170
            branch_to = wt_to.branch
 
171
        except NoWorkingTree:
 
172
            wt_to = None
 
173
            branch_to = Branch.open(".")
 
174
 
 
175
        stored_loc = branch_to.get_parent()
 
176
        if from_repository is None:
 
177
            if stored_loc is None:
 
178
                raise BzrCommandError("No pull location known or"
 
179
                                             " specified.")
 
180
            else:
 
181
                import bzrlib.urlutils as urlutils
 
182
                display_url = urlutils.unescape_for_display(stored_loc,
 
183
                        self.outf.encoding)
 
184
                self.outf.write("Using saved location: %s\n" % display_url)
 
185
                from_repository = Branch.open(stored_loc).repository
 
186
        else:
 
187
            from_repository = Repository.open(from_repository)
 
188
 
 
189
        vcs = getattr(from_repository, "vcs", None)
 
190
        if vcs is None:
 
191
            raise BzrCommandError("Repository at %s is not a foreign repository.a" % from_repository.base)
 
192
 
 
193
        new_mapping = from_repository.get_mapping()
 
194
 
 
195
        if wt_to is not None:
 
196
            renames = upgrade_workingtree(wt_to, from_repository, 
 
197
                                          new_mapping=new_mapping,
 
198
                                          allow_changes=True, verbose=verbose)
 
199
        else:
 
200
            renames = upgrade_branch(branch_to, from_repository, 
 
201
                                     new_mapping=new_mapping,
 
202
                                     allow_changes=True, verbose=verbose)
 
203
 
 
204
        if renames == {}:
 
205
            info("Nothing to do.")
 
206
 
 
207
        if idmap_file is not None:
 
208
            f = open(idmap_file, 'w')
 
209
            try:
 
210
                for oldid, newid in renames.iteritems():
 
211
                    f.write("%s\t%s\n" % (oldid, newid))
 
212
            finally:
 
213
                f.close()
 
214
 
 
215
        if wt_to is not None:
 
216
            wt_to.set_last_revision(branch_to.last_revision())
 
217
 
 
218
 
 
219
def test_suite():
 
220
    from unittest import TestSuite
 
221
    from bzrlib.tests import TestUtil
 
222
    loader = TestUtil.TestLoader()
 
223
    suite = TestSuite()
 
224
    testmod_names = ['test_versionedfiles', ]
 
225
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
226
    return suite
 
227
 
 
228
 
 
229
def escape_commit_message(message):
 
230
    """Replace xml-incompatible control characters."""
 
231
    if message is None:
 
232
        return None
 
233
    import re
 
234
    # FIXME: RBC 20060419 this should be done by the revision
 
235
    # serialiser not by commit. Then we can also add an unescaper
 
236
    # in the deserializer and start roundtripping revision messages
 
237
    # precisely. See repository_implementations/test_repository.py
 
238
    
 
239
    # Python strings can include characters that can't be
 
240
    # represented in well-formed XML; escape characters that
 
241
    # aren't listed in the XML specification
 
242
    # (http://www.w3.org/TR/REC-xml/#NT-Char).
 
243
    message, _ = re.subn(
 
244
        u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD]+',
 
245
        lambda match: match.group(0).encode('unicode_escape'),
 
246
        message)
 
247
    return message
 
248
 
 
249