diff options
Diffstat (limited to 'bzrlib/push.py')
-rw-r--r-- | bzrlib/push.py | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/bzrlib/push.py b/bzrlib/push.py new file mode 100644 index 0000000..ccab830 --- /dev/null +++ b/bzrlib/push.py @@ -0,0 +1,177 @@ +# Copyright (C) 2008-2012 Canonical Ltd +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +"""UI helper for the push command.""" + +from __future__ import absolute_import + +from bzrlib import ( + controldir, + errors, + revision as _mod_revision, + transport, + ) +from bzrlib.trace import ( + note, + warning, + ) +from bzrlib.i18n import gettext + + +class PushResult(object): + """Result of a push operation. + + :ivar branch_push_result: Result of a push between branches + :ivar target_branch: The target branch + :ivar stacked_on: URL of the branch on which the result is stacked + :ivar workingtree_updated: Whether or not the target workingtree was updated. + """ + + def __init__(self): + self.branch_push_result = None + self.stacked_on = None + self.workingtree_updated = None + self.target_branch = None + + def report(self, to_file): + """Write a human-readable description of the result.""" + if self.branch_push_result is None: + if self.stacked_on is not None: + note(gettext('Created new stacked branch referring to %s.') % + self.stacked_on) + else: + note(gettext('Created new branch.')) + else: + self.branch_push_result.report(to_file) + + +def _show_push_branch(br_from, revision_id, location, to_file, verbose=False, + overwrite=False, remember=False, stacked_on=None, create_prefix=False, + use_existing_dir=False, no_tree=False): + """Push a branch to a location. + + :param br_from: the source branch + :param revision_id: the revision-id to push up to + :param location: the url of the destination + :param to_file: the output stream + :param verbose: if True, display more output than normal + :param overwrite: list of things to overwrite ("history", "tags") + or boolean indicating for everything + :param remember: if True, store the location as the push location for + the source branch + :param stacked_on: the url of the branch, if any, to stack on; + if set, only the revisions not in that branch are pushed + :param create_prefix: if True, create the necessary parent directories + at the destination if they don't already exist + :param use_existing_dir: if True, proceed even if the destination + directory exists without a current .bzr directory in it + """ + to_transport = transport.get_transport(location) + try: + dir_to = controldir.ControlDir.open_from_transport(to_transport) + except errors.NotBranchError: + # Didn't find anything + dir_to = None + + if dir_to is None: + try: + br_to = br_from.create_clone_on_transport(to_transport, + revision_id=revision_id, stacked_on=stacked_on, + create_prefix=create_prefix, use_existing_dir=use_existing_dir, + no_tree=no_tree) + except errors.AlreadyControlDirError, err: + raise errors.BzrCommandError(gettext( + "Target directory %s already contains a .bzr directory, " + "but it is not valid.") % (location,)) + except errors.FileExists, err: + if not use_existing_dir: + raise errors.BzrCommandError(gettext("Target directory %s" + " already exists, but does not have a .bzr" + " directory. Supply --use-existing-dir to push" + " there anyway.") % location) + # This shouldn't occur, but if it does the FileExists error will be + # more informative than an UnboundLocalError for br_to. + raise + except errors.NoSuchFile: + if not create_prefix: + raise errors.BzrCommandError(gettext("Parent directory of %s" + " does not exist." + "\nYou may supply --create-prefix to create all" + " leading parent directories.") + % location) + # This shouldn't occur (because create_prefix is true, so + # create_clone_on_transport should be catching NoSuchFile and + # creating the missing directories) but if it does the original + # NoSuchFile error will be more informative than an + # UnboundLocalError for br_to. + raise + except errors.TooManyRedirections: + raise errors.BzrCommandError(gettext("Too many redirections trying " + "to make %s.") % location) + push_result = PushResult() + # TODO: Some more useful message about what was copied + try: + push_result.stacked_on = br_to.get_stacked_on_url() + except (errors.UnstackableBranchFormat, + errors.UnstackableRepositoryFormat, + errors.NotStacked): + push_result.stacked_on = None + push_result.target_branch = br_to + push_result.old_revid = _mod_revision.NULL_REVISION + push_result.old_revno = 0 + # Remembers if asked explicitly or no previous location is set + if (remember + or (remember is None and br_from.get_push_location() is None)): + # FIXME: Should be done only if we succeed ? -- vila 2012-01-18 + br_from.set_push_location(br_to.base) + else: + if stacked_on is not None: + warning("Ignoring request for a stacked branch as repository " + "already exists at the destination location.") + try: + push_result = dir_to.push_branch(br_from, revision_id, overwrite, + remember, create_prefix) + except errors.DivergedBranches: + raise errors.BzrCommandError(gettext('These branches have diverged.' + ' See "bzr help diverged-branches"' + ' for more information.')) + except errors.NoRoundtrippingSupport, e: + raise errors.BzrCommandError(gettext("It is not possible to losslessly " + "push to %s. You may want to use dpush instead.") % + e.target_branch.mapping.vcs.abbreviation) + except errors.NoRepositoryPresent: + # we have a controldir but no branch or repository + # XXX: Figure out what to do other than complain. + raise errors.BzrCommandError(gettext("At %s you have a valid .bzr" + " control directory, but not a branch or repository. This" + " is an unsupported configuration. Please move the target" + " directory out of the way and try again.") % location) + if push_result.workingtree_updated == False: + warning("This transport does not update the working " + "tree of: %s. See 'bzr help working-trees' for " + "more information." % push_result.target_branch.base) + push_result.report(to_file) + if verbose: + br_to = push_result.target_branch + br_to.lock_read() + try: + from bzrlib.log import show_branch_change + show_branch_change(br_to, to_file, push_result.old_revno, + push_result.old_revid) + finally: + br_to.unlock() + + |