1
# Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
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.
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.
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
17
"""Foreign branch utilities."""
19
from bzrlib import errors, registry
20
from bzrlib.commands import Command, Option
23
class VcsMapping(object):
24
"""Describes the mapping between the semantics of Bazaar and a foreign vcs.
31
def revision_id_bzr_to_foreign(self, bzr_revid):
32
"""Parse a bzr revision id and convert it to a foreign revid.
34
:param bzr_revid: The bzr revision id (a string).
35
:return: A foreign revision id, can be any sort of object.
37
raise NotImplementedError(self.revision_id_bzr_to_foreign)
39
def revision_id_foreign_to_bzr(self, foreign_revid):
40
"""Parse a foreign revision id and convert it to a bzr revid.
42
:param foreign_revid: Foreign revision id, can be any sort of object.
43
:return: A bzr revision id.
45
raise NotImplementedError(self.revision_id_foreign_to_bzr)
48
class VcsMappingRegistry(registry.Registry):
49
"""Registry for Bazaar<->foreign VCS mappings.
51
There should be one instance of this registry for every foreign VCS.
54
def register(self, key, factory, help):
55
"""Register a mapping between Bazaar and foreign VCS semantics.
57
The factory must be a callable that takes one parameter: the key.
58
It must produce an instance of VcsMapping when called.
60
registry.Registry.register(self, key, factory, help)
62
def set_default(self, key):
63
"""Set the 'default' key to be a clone of the supplied key.
65
This method must be called once and only once.
67
self._set_default_key(key)
69
def get_default(self):
70
"""Convenience function for obtaining the default mapping to use."""
71
return self.get(self._get_default_key())
74
class FakeControlFiles(object):
75
"""Dummy implementation of ControlFiles.
77
This is required as some code relies on controlfiles being
79
def get_utf8(self, name):
80
raise errors.NoSuchFile(name)
83
raise errors.NoSuchFile(name)
89
class cmd_dpush(Command):
90
"""Push diffs into a foreign version control system without any
91
Bazaar-specific metadata.
93
This will afterwards rebase the local Bazaar branch on the remote
94
branch unless the --no-rebase option is used, in which case
95
the two branches will be out of sync.
97
takes_args = ['location?']
98
takes_options = ['remember', Option('directory',
99
help='Branch to push from, '
100
'rather than the one containing the working directory.',
104
Option('no-rebase', help="Don't rebase after push")]
106
def run(self, location=None, remember=False, directory=None,
108
from bzrlib import urlutils
109
from bzrlib.bzrdir import BzrDir
110
from bzrlib.branch import Branch
111
from bzrlib.errors import BzrCommandError, NoWorkingTree
112
from bzrlib.workingtree import WorkingTree
114
if directory is None:
117
source_wt = WorkingTree.open_containing(directory)[0]
118
source_branch = source_wt.branch
119
except NoWorkingTree:
120
source_branch = Branch.open_containing(directory)[0]
122
stored_loc = source_branch.get_push_location()
124
if stored_loc is None:
125
raise BzrCommandError("No push location known or specified.")
127
display_url = urlutils.unescape_for_display(stored_loc,
129
self.outf.write("Using saved location: %s\n" % display_url)
130
location = stored_loc
132
bzrdir = BzrDir.open(location)
133
target_branch = bzrdir.open_branch()
134
target_branch.lock_write()
135
revid_map = source_branch.dpush(target_branch)
136
# We successfully created the target, remember it
137
if source_branch.get_push_location() is None or remember:
138
source_branch.set_push_location(target_branch.base)
140
_, old_last_revid = source_branch.last_revision_info()
141
new_last_revid = revid_map[old_last_revid]
142
if source_wt is not None:
143
source_wt.pull(target_branch, overwrite=True,
144
stop_revision=new_last_revid)
146
source_branch.pull(target_branch, overwrite=True,
147
stop_revision=new_last_revid)