/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 bzrlib/foreign.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2008 Canonical Ltd
 
1
# Copyright (C) 2008, 2009, 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
18
18
"""Foreign branch utilities."""
19
19
 
20
20
 
21
 
from bzrlib.branch import Branch
 
21
from bzrlib.branch import (
 
22
    Branch,
 
23
    InterBranch,
 
24
    )
22
25
from bzrlib.commands import Command, Option
23
26
from bzrlib.repository import Repository
24
27
from bzrlib.revision import Revision
33
36
""")
34
37
 
35
38
class VcsMapping(object):
36
 
    """Describes the mapping between the semantics of Bazaar and a foreign vcs.
 
39
    """Describes the mapping between the semantics of Bazaar and a foreign VCS.
37
40
 
38
41
    """
39
42
    # Whether this is an experimental mapping that is still open to changes.
42
45
    # Whether this mapping supports exporting and importing all bzr semantics.
43
46
    roundtripping = False
44
47
 
45
 
    # Prefix used when importing native foreign revisions (not roundtripped)
46
 
    # using this mapping.
 
48
    # Prefix used when importing revisions native to the foreign VCS (as
 
49
    # opposed to roundtripping bzr-native revisions) using this mapping.
47
50
    revid_prefix = None
48
51
 
49
52
    def __init__(self, vcs):
116
119
        self.mapping = mapping
117
120
 
118
121
 
119
 
def show_foreign_properties(rev):
120
 
    """Custom log displayer for foreign revision identifiers.
121
 
 
122
 
    :param rev: Revision object.
123
 
    """
124
 
    # Revision comes directly from a foreign repository
125
 
    if isinstance(rev, ForeignRevision):
126
 
        return rev.mapping.vcs.show_foreign_revid(rev.foreign_revid)
127
 
 
128
 
    # Revision was once imported from a foreign repository
129
 
    try:
130
 
        foreign_revid, mapping = \
131
 
            foreign_vcs_registry.parse_revision_id(rev.revision_id)
132
 
    except errors.InvalidRevisionId:
133
 
        return {}
134
 
 
135
 
    return mapping.vcs.show_foreign_revid(foreign_revid)
136
 
 
137
 
 
138
122
class ForeignVcs(object):
139
123
    """A foreign version control system."""
140
124
 
141
 
    def __init__(self, mapping_registry):
 
125
    branch_format = None
 
126
 
 
127
    repository_format = None
 
128
 
 
129
    def __init__(self, mapping_registry, abbreviation=None):
 
130
        """Create a new foreign vcs instance.
 
131
 
 
132
        :param mapping_registry: Registry with mappings for this VCS.
 
133
        :param abbreviation: Optional abbreviation ('bzr', 'svn', 'git', etc)
 
134
        """
 
135
        self.abbreviation = abbreviation
142
136
        self.mapping_registry = mapping_registry
143
137
 
144
138
    def show_foreign_revid(self, foreign_revid):
149
143
        """
150
144
        return { }
151
145
 
 
146
    def serialize_foreign_revid(self, foreign_revid):
 
147
        """Serialize a foreign revision id for this VCS.
 
148
 
 
149
        :param foreign_revid: Foreign revision id
 
150
        :return: Bytestring with serialized revid, will not contain any 
 
151
            newlines.
 
152
        """
 
153
        raise NotImplementedError(self.serialize_foreign_revid)
 
154
 
152
155
 
153
156
class ForeignVcsRegistry(registry.Registry):
154
157
    """Registry for Foreign VCSes.
176
179
        :param revid: The bzr revision id
177
180
        :return: tuple with foreign revid and vcs mapping
178
181
        """
179
 
        if not "-" in revid:
 
182
        if not ":" in revid or not "-" in revid:
180
183
            raise errors.InvalidRevisionId(revid, None)
181
184
        try:
182
185
            foreign_vcs = self.get(revid.split("-")[0])
222
225
        """Get the default mapping for this repository."""
223
226
        raise NotImplementedError(self.get_default_mapping)
224
227
 
225
 
    def get_inventory_xml(self, revision_id):
226
 
        """See Repository.get_inventory_xml()."""
227
 
        return self.serialise_inventory(self.get_inventory(revision_id))
228
 
 
229
 
    def get_inventory_sha1(self, revision_id):
230
 
        """Get the sha1 for the XML representation of an inventory.
231
 
 
232
 
        :param revision_id: Revision id of the inventory for which to return
233
 
         the SHA1.
234
 
        :return: XML string
235
 
        """
236
 
 
237
 
        return osutils.sha_string(self.get_inventory_xml(revision_id))
238
 
 
239
 
    def get_revision_xml(self, revision_id):
240
 
        """Return the XML representation of a revision.
241
 
 
242
 
        :param revision_id: Revision for which to return the XML.
243
 
        :return: XML string
244
 
        """
245
 
        return self._serializer.write_revision_to_string(
246
 
            self.get_revision(revision_id))
247
 
 
248
228
 
249
229
class ForeignBranch(Branch):
250
230
    """Branch that exists in a foreign version control system."""
253
233
        self.mapping = mapping
254
234
        super(ForeignBranch, self).__init__()
255
235
 
256
 
    def dpull(self, source, stop_revision=None):
257
 
        """Pull deltas from another branch.
258
 
 
259
 
        :note: This does not, like pull, retain the revision ids from 
260
 
            the source branch and will, rather than adding bzr-specific 
261
 
            metadata, push only those semantics of the revision that can be 
262
 
            natively represented by this branch' VCS.
263
 
 
264
 
        :param source: Source branch
265
 
        :param stop_revision: Revision to pull, defaults to last revision.
266
 
        :return: Dictionary mapping revision ids from the source branch 
267
 
            to new revision ids in the target branch, for each 
268
 
            revision that was pull.
269
 
        """
270
 
        raise NotImplementedError(self.dpull)
271
 
 
272
236
 
273
237
def update_workingtree_fileids(wt, target_tree):
274
238
    """Update the file ids in a working tree based on another tree.
295
259
 
296
260
 
297
261
class cmd_dpush(Command):
298
 
    """Push diffs into a foreign version control system without any 
299
 
    Bazaar-specific metadata.
 
262
    __doc__ = """Push into a different VCS without any custom bzr metadata.
300
263
 
301
 
    This will afterwards rebase the local Bazaar branch on the remote
 
264
    This will afterwards rebase the local branch on the remote
302
265
    branch unless the --no-rebase option is used, in which case 
303
 
    the two branches will be out of sync. 
 
266
    the two branches will be out of sync after the push. 
304
267
    """
305
268
    hidden = True
306
269
    takes_args = ['location?']
307
 
    takes_options = ['remember', Option('directory',
308
 
            help='Branch to push from, '
309
 
                 'rather than the one containing the working directory.',
310
 
            short_name='d',
311
 
            type=unicode,
312
 
            ),
313
 
            Option('no-rebase', help="Do not rebase after push.")]
 
270
    takes_options = [
 
271
        'remember',
 
272
        Option('directory',
 
273
               help='Branch to push from, '
 
274
               'rather than the one containing the working directory.',
 
275
               short_name='d',
 
276
               type=unicode,
 
277
               ),
 
278
        Option('no-rebase', help="Do not rebase after push."),
 
279
        Option('strict',
 
280
               help='Refuse to push if there are uncommitted changes in'
 
281
               ' the working tree, --no-strict disables the check.'),
 
282
        ]
314
283
 
315
 
    def run(self, location=None, remember=False, directory=None, 
316
 
            no_rebase=False):
 
284
    def run(self, location=None, remember=False, directory=None,
 
285
            no_rebase=False, strict=None):
317
286
        from bzrlib import urlutils
318
287
        from bzrlib.bzrdir import BzrDir
319
288
        from bzrlib.errors import BzrCommandError, NoWorkingTree
320
 
        from bzrlib.trace import info
321
289
        from bzrlib.workingtree import WorkingTree
322
290
 
323
291
        if directory is None:
328
296
        except NoWorkingTree:
329
297
            source_branch = Branch.open(directory)
330
298
            source_wt = None
 
299
        if source_wt is not None:
 
300
            source_wt.check_changed_or_out_of_date(
 
301
                strict, 'dpush_strict',
 
302
                more_error='Use --no-strict to force the push.',
 
303
                more_warning='Uncommitted changes will not be pushed.')
331
304
        stored_loc = source_branch.get_push_location()
332
305
        if location is None:
333
306
            if stored_loc is None:
340
313
 
341
314
        bzrdir = BzrDir.open(location)
342
315
        target_branch = bzrdir.open_branch()
343
 
        dpull = getattr(target_branch, "dpull", None)
344
 
        if dpull is None:
345
 
            raise BzrCommandError("%r is not a foreign branch, use "
346
 
                                  "regular push." % target_branch)
347
316
        target_branch.lock_write()
348
317
        try:
349
 
            revid_map = dpull(source_branch)
 
318
            try:
 
319
                push_result = source_branch.lossy_push(target_branch)
 
320
            except errors.LossyPushToSameVCS:
 
321
                raise BzrCommandError("%r and %r are in the same VCS, lossy "
 
322
                    "push not necessary. Please use regular push." %
 
323
                    (source_branch, target_branch))
350
324
            # We successfully created the target, remember it
351
325
            if source_branch.get_push_location() is None or remember:
352
326
                source_branch.set_push_location(target_branch.base)
362
336
                        update_workingtree_fileids(source_wt, target)
363
337
                    finally:
364
338
                        source_wt.unlock()
 
339
            push_result.report(self.outf)
365
340
        finally:
366
341
            target_branch.unlock()
 
342
 
 
343
 
 
344
class InterToForeignBranch(InterBranch):
 
345
 
 
346
    def lossy_push(self, stop_revision=None):
 
347
        """Push deltas into another branch.
 
348
 
 
349
        :note: This does not, like push, retain the revision ids from 
 
350
            the source branch and will, rather than adding bzr-specific 
 
351
            metadata, push only those semantics of the revision that can be 
 
352
            natively represented by this branch' VCS.
 
353
 
 
354
        :param target: Target branch
 
355
        :param stop_revision: Revision to push, defaults to last revision.
 
356
        :return: BranchPushResult with an extra member revidmap: 
 
357
            A dictionary mapping revision ids from the target branch 
 
358
            to new revision ids in the target branch, for each 
 
359
            revision that was pushed.
 
360
        """
 
361
        raise NotImplementedError(self.lossy_push)