~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/foreign.py

  • Committer: Andrew Bennetts
  • Date: 2009-10-07 08:17:25 UTC
  • mto: This revision was merged to the branch mainline in revision 4734.
  • Revision ID: andrew.bennetts@canonical.com-20091007081725-4t3vkhher69a4k0j
Refactor to reduce duplication.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2008-2012 Canonical Ltd
 
1
# Copyright (C) 2008 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
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
 
17
18
"""Foreign branch utilities."""
18
19
 
19
 
from __future__ import absolute_import
20
 
 
21
20
 
22
21
from bzrlib.branch import (
23
22
    Branch,
 
23
    InterBranch,
24
24
    )
25
25
from bzrlib.commands import Command, Option
26
26
from bzrlib.repository import Repository
29
29
lazy_import(globals(), """
30
30
from bzrlib import (
31
31
    errors,
 
32
    osutils,
32
33
    registry,
33
34
    transform,
34
35
    )
35
 
from bzrlib.i18n import gettext
36
36
""")
37
37
 
38
38
class VcsMapping(object):
39
 
    """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.
40
40
 
41
41
    """
42
42
    # Whether this is an experimental mapping that is still open to changes.
122
122
class ForeignVcs(object):
123
123
    """A foreign version control system."""
124
124
 
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
 
125
    def __init__(self, mapping_registry):
136
126
        self.mapping_registry = mapping_registry
137
127
 
138
128
    def show_foreign_revid(self, foreign_revid):
143
133
        """
144
134
        return { }
145
135
 
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
 
 
155
136
 
156
137
class ForeignVcsRegistry(registry.Registry):
157
138
    """Registry for Foreign VCSes.
225
206
        """Get the default mapping for this repository."""
226
207
        raise NotImplementedError(self.get_default_mapping)
227
208
 
 
209
    def get_inventory_xml(self, revision_id):
 
210
        """See Repository.get_inventory_xml()."""
 
211
        return self.serialise_inventory(self.get_inventory(revision_id))
 
212
 
 
213
    def get_inventory_sha1(self, revision_id):
 
214
        """Get the sha1 for the XML representation of an inventory.
 
215
 
 
216
        :param revision_id: Revision id of the inventory for which to return
 
217
         the SHA1.
 
218
        :return: XML string
 
219
        """
 
220
 
 
221
        return osutils.sha_string(self.get_inventory_xml(revision_id))
 
222
 
 
223
    def get_revision_xml(self, revision_id):
 
224
        """Return the XML representation of a revision.
 
225
 
 
226
        :param revision_id: Revision for which to return the XML.
 
227
        :return: XML string
 
228
        """
 
229
        return self._serializer.write_revision_to_string(
 
230
            self.get_revision(revision_id))
 
231
 
228
232
 
229
233
class ForeignBranch(Branch):
230
234
    """Branch that exists in a foreign version control system."""
259
263
 
260
264
 
261
265
class cmd_dpush(Command):
262
 
    __doc__ = """Push into a different VCS without any custom bzr metadata.
 
266
    """Push into a different VCS without any custom bzr metadata.
263
267
 
264
268
    This will afterwards rebase the local branch on the remote
265
269
    branch unless the --no-rebase option is used, in which case 
266
270
    the two branches will be out of sync after the push. 
267
271
    """
 
272
    hidden = True
268
273
    takes_args = ['location?']
269
274
    takes_options = [
270
275
        'remember',
283
288
    def run(self, location=None, remember=False, directory=None,
284
289
            no_rebase=False, strict=None):
285
290
        from bzrlib import urlutils
286
 
        from bzrlib.controldir import ControlDir
 
291
        from bzrlib.bzrdir import BzrDir
287
292
        from bzrlib.errors import BzrCommandError, NoWorkingTree
288
293
        from bzrlib.workingtree import WorkingTree
289
294
 
295
300
        except NoWorkingTree:
296
301
            source_branch = Branch.open(directory)
297
302
            source_wt = None
298
 
        if source_wt is not None:
299
 
            source_wt.check_changed_or_out_of_date(
300
 
                strict, 'dpush_strict',
301
 
                more_error='Use --no-strict to force the push.',
302
 
                more_warning='Uncommitted changes will not be pushed.')
 
303
        if strict is None:
 
304
            strict = source_branch.get_config(
 
305
                ).get_user_option_as_bool('dpush_strict')
 
306
        if strict is None: strict = True # default value
 
307
        if strict and source_wt is not None:
 
308
            if (source_wt.has_changes()):
 
309
                raise errors.UncommittedChanges(
 
310
                    source_wt, more='Use --no-strict to force the push.')
 
311
            if source_wt.last_revision() != source_wt.branch.last_revision():
 
312
                # The tree has lost sync with its branch, there is little
 
313
                # chance that the user is aware of it but he can still force
 
314
                # the push with --no-strict
 
315
                raise errors.OutOfDateTree(
 
316
                    source_wt, more='Use --no-strict to force the push.')
303
317
        stored_loc = source_branch.get_push_location()
304
318
        if location is None:
305
319
            if stored_loc is None:
306
 
                raise BzrCommandError(gettext("No push location known or specified."))
 
320
                raise BzrCommandError("No push location known or specified.")
307
321
            else:
308
322
                display_url = urlutils.unescape_for_display(stored_loc,
309
323
                        self.outf.encoding)
310
 
                self.outf.write(
311
 
                       gettext("Using saved location: %s\n") % display_url)
 
324
                self.outf.write("Using saved location: %s\n" % display_url)
312
325
                location = stored_loc
313
326
 
314
 
        controldir = ControlDir.open(location)
315
 
        target_branch = controldir.open_branch()
 
327
        bzrdir = BzrDir.open(location)
 
328
        target_branch = bzrdir.open_branch()
316
329
        target_branch.lock_write()
317
330
        try:
318
331
            try:
319
 
                push_result = source_branch.push(target_branch, lossy=True)
 
332
                push_result = source_branch.lossy_push(target_branch)
320
333
            except errors.LossyPushToSameVCS:
321
 
                raise BzrCommandError(gettext("{0!r} and {1!r} are in the same VCS, lossy "
322
 
                    "push not necessary. Please use regular push.").format(
323
 
                    source_branch, target_branch))
 
334
                raise BzrCommandError("%r and %r are in the same VCS, lossy "
 
335
                    "push not necessary. Please use regular push." %
 
336
                    (source_branch, target_branch))
324
337
            # We successfully created the target, remember it
325
338
            if source_branch.get_push_location() is None or remember:
326
 
                # FIXME: Should be done only if we succeed ? -- vila 2012-01-18
327
339
                source_branch.set_push_location(target_branch.base)
328
340
            if not no_rebase:
329
341
                old_last_revid = source_branch.last_revision()
340
352
            push_result.report(self.outf)
341
353
        finally:
342
354
            target_branch.unlock()
 
355
 
 
356
 
 
357
class InterToForeignBranch(InterBranch):
 
358
 
 
359
    def lossy_push(self, stop_revision=None):
 
360
        """Push deltas into another branch.
 
361
 
 
362
        :note: This does not, like push, retain the revision ids from 
 
363
            the source branch and will, rather than adding bzr-specific 
 
364
            metadata, push only those semantics of the revision that can be 
 
365
            natively represented by this branch' VCS.
 
366
 
 
367
        :param target: Target branch
 
368
        :param stop_revision: Revision to push, defaults to last revision.
 
369
        :return: BranchPushResult with an extra member revidmap: 
 
370
            A dictionary mapping revision ids from the target branch 
 
371
            to new revision ids in the target branch, for each 
 
372
            revision that was pushed.
 
373
        """
 
374
        raise NotImplementedError(self.lossy_push)