def _set_branch_location(control, to_branch, force=False): """Set location value of a branch reference. :param control: BzrDir of the checkout to change :param to_branch: branch that the checkout is to reference :param force: skip the check for local commits in a heavy checkout """ branch_format = control.find_branch_format() if branch_format.get_reference(control) is not None: # Lightweight checkout: update the branch reference branch_format.set_reference(control, to_branch) else: b = control.open_branch() bound_branch = b.get_bound_location() if bound_branch is not None: # Heavyweight checkout: check all local commits # have been pushed to the current bound branch then # synchronise the local branch with the new remote branch # and bind to it possible_transports = [] if not force and _any_local_commits(b, possible_transports): raise errors.BzrCommandError( 'Cannot switch as local commits found in the checkout. ' 'Commit these to the bound branch or use --force to ' 'throw them away.') b.set_bound_location(None) b.pull(to_branch, overwrite=True, possible_transports=possible_transports) b.set_bound_location(to_branch.base) else: raise errors.BzrCommandError('Cannot switch a branch, ' 'only a checkout.')
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
def get_branch(repo, relpath, format=None): """Return existing branch in destination repo. Create new if don't exist. @param format: force create new branch in specified format. """ repo_trans = repo.bzrdir.root_transport try: br_dir = BzrDir.open(repo_trans.abspath(relpath)) branch = br_dir.open_branch() except errors.NotBranchError: # create destination branch directory, creating parents as needed. needed = [relpath] while needed: try: repo_trans.mkdir(needed[-1]) needed.pop() except errors.NoSuchFile: parent = urlutils.dirname(needed[-1]) if parent == '': raise errors.BzrCommandError('Could not create branch dir') needed.append(parent) br_dir = BzrDir.create(repo_trans.abspath(relpath)) if format is None: format = BranchFormat.get_default_format() branch = format.initialize(br_dir) note('Created destination branch %s' % relpath) if branch.repository.bzrdir.root_transport.base != repo_trans.base: raise errors.BzrCommandError('Branch %s does not use repository %s' % (relpath, repo_trans.base)) # XXX: hack to make sure the branch is using the same repository # instance, for locking purposes branch.repository = repo return branch
def check_proposal(self): """Check that the submission is sensible.""" if self.source_branch.lp.self_link == self.target_branch.lp.self_link: raise errors.BzrCommandError( 'Source and target branches must be different.') for mp in self.source_branch.lp.landing_targets: if mp.queue_status in ('Merged', 'Rejected'): continue if mp.target_branch.self_link == self.target_branch.lp.self_link: raise errors.BzrCommandError(gettext( 'There is already a branch merge proposal: %s') % lp_api.canonical_url(mp))
def run(self, file_list=None, revision=None, using=None, diff_options=None, prefix=None): """ Run the external diff tool. """ # Get an instance of this tool: assert using is not None tool = find_diff_tool(using) tool.add_options(diff_options) # Default to current working directory: if (not file_list or len(file_list) == 0): file_list = [ osutils.getcwd() ] # Pick the right comparison to perform: if revision: if (len(revision) == 1) or (revision[1].spec is None): result = compare_using(tool, file_list, revision[0]) elif len(revision) == 2: result = compare_using(tool, file_list, revision[0], revision[1]) else: raise errors.BzrCommandError( '--revision takes exactly one or two revision specifiers') else: # Just diff against the current base tree: result = compare_using(tool, file_list) return result
def _send_0_9(branch, revision_id, submit_branch, public_branch, no_patch, no_bundle, message, base_revision_id, local_target_branch=None): if not no_bundle: if not no_patch: patch_type = 'bundle' else: raise errors.BzrCommandError( gettext('Format 0.9 does not' ' permit bundle with no patch')) else: if not no_patch: patch_type = 'diff' else: patch_type = None from bzrlib import merge_directive return merge_directive.MergeDirective.from_objects( branch.repository, revision_id, time.time(), osutils.local_time_offset(), submit_branch, public_branch=public_branch, patch_type=patch_type, message=message, local_target_branch=local_target_branch)
def run(self, destination=None, remember=False, overwrite=False): from repopush import repo_push # get the repository for the branch we're currently in bzrdir = BzrDir.open_containing('.')[0] try: branch = bzrdir.open_branch() src_repo = branch.repository except errors.NotBranchError: src_repo = bzrdir.open_repository() repo_config = LocationConfig(src_repo.bzrdir.root_transport.base) if destination is None: destination = repo_config.get_user_option('public_repository') if destination is None: raise errors.BzrCommandError('No destination specified') dst_repo = BzrDir.open(destination).open_repository() if remember or (repo_config.get_user_option('public_repository') is None): repo_config.set_user_option('public_repository', dst_repo.bzrdir.root_transport.base) pb = ui_factory.nested_progress_bar() try: repo_push(src_repo, dst_repo, pb=pb, overwrite=overwrite) finally: pb.finished()
def _qbzr_run(self, selected_list=None, message=None, file=None, local=False, ui_mode=False, file_encoding=None): if message is not None and file: raise errors.BzrCommandError( "please specify either --message or --file") if file: f = open(file) try: message = f.read().decode(file_encoding or osutils.get_user_encoding()) finally: f.close() tree, selected_list = WorkingTree.open_containing_paths(selected_list) if selected_list == ['']: selected_list = None self.main_window = CommitWindow(tree, selected_list, dialog=False, message=message, local=local, ui_mode=ui_mode) self.main_window.show() self._application.exec_()
def _load_branch(self, filename, revision): """To assist in getting a UI up as soon as possible, the UI calls back to this function to process the command-line args and convert them into the branch and tree etc needed by the UI. """ wt, branch, relpath = \ BzrDir.open_containing_tree_or_branch(filename) if wt is not None: wt.lock_read() else: branch.lock_read() try: if revision is None: if wt is not None: tree = wt else: tree = branch.repository.revision_tree( branch.last_revision()) elif len(revision) != 1: raise errors.BzrCommandError( 'bzr qannotate --revision takes exactly 1 argument') else: tree = branch.repository.revision_tree( revision_id=revision[0].in_history(branch).rev_id) file_id = tree.path2id(relpath) if file_id is None: raise errors.NotVersionedError(filename) [(path, entry) ] = list(tree.iter_entries_by_dir(specific_file_ids=[file_id])) if entry.kind != 'file': raise errors.BzrCommandError( 'bzr qannotate only works for files (got %r)' % entry.kind) #repo = branch.repository #w = repo.weave_store.get_weave(file_id, repo.get_transaction()) #content = list(w.annotate_iter(entry.revision)) #revision_ids = set(o for o, t in content) #revision_ids = [o for o in revision_ids if repo.has_revision(o)] #revisions = branch.repository.get_revisions(revision_ids) finally: if wt is not None: wt.unlock() else: branch.unlock() return branch, tree, wt, relpath, file_id
def _qbzr_run(self, ui_mode=False, execute=False): from bzrlib.plugins.qbzr.lib.unbind import QBzrUnbindDialog branch = Branch.open_containing(CUR_DIR)[0] if branch.get_bound_location() == None: raise errors.BzrCommandError("This branch is not bound.") self.main_window = QBzrUnbindDialog(branch, ui_mode, execute) self.main_window.show() self._application.exec_()
def from_args(klass, shelf_id=None, action='apply', directory='.', write_diff_to=None): """Create an unshelver from commandline arguments. The returned shelver will have a tree that is locked and should be unlocked. :param shelf_id: Integer id of the shelf, as a string. :param action: action to perform. May be 'apply', 'dry-run', 'delete', 'preview'. :param directory: The directory to unshelve changes into. :param write_diff_to: See Unshelver.__init__(). """ tree, path = workingtree.WorkingTree.open_containing(directory) tree.lock_tree_write() try: manager = tree.get_shelf_manager() if shelf_id is not None: try: shelf_id = int(shelf_id) except ValueError: raise errors.InvalidShelfId(shelf_id) else: shelf_id = manager.last_shelf() if shelf_id is None: raise errors.BzrCommandError( gettext('No changes are shelved.')) apply_changes = True delete_shelf = True read_shelf = True show_diff = False if action == 'dry-run': apply_changes = False delete_shelf = False elif action == 'preview': apply_changes = False delete_shelf = False show_diff = True elif action == 'delete-only': apply_changes = False read_shelf = False elif action == 'keep': apply_changes = True delete_shelf = False except: tree.unlock() raise return klass(tree, manager, shelf_id, apply_changes, delete_shelf, read_shelf, show_diff, write_diff_to)
def repo_push(src_repo, dst_repo, pb, overwrite=False): src_repo.lock_read() try: dst_repo.lock_write() try: src_repo_trans = src_repo.bzrdir.root_transport dst_repo_trans = dst_repo.bzrdir.root_transport pb.update('Getting list of branches', 0, 1) branches = list_branches(src_repo) note('Pushing %d branches from %s to %s' % (len(branches), src_repo_trans.base, dst_repo_trans.base)) # XXX: ideally this would only fetch the tips of the # branches we found previously. pb.update('Fetching entire repo', 0, 1) dst_repo.fetch(src_repo, pb=pb) # Now synchronise the revision histories of the local and # remote branches. The previous fetch() call has made # sure that the corresponding revisions exist in dst_repo. for index, src_branch in enumerate(branches): pb.update('Updating branches', index, len(branches)) relpath = src_repo_trans.relpath( src_branch.bzrdir.root_transport.base) format = BranchFormat.find_format(src_branch.bzrdir) dst_branch = get_branch(dst_repo, relpath, format) src_history = src_branch.revision_history() dst_history = dst_branch.revision_history() # If we aren't overwriting and the destination history # is not a subset of the source history, error out. # XXX this implementation is buggy in some cases if not overwrite and (src_history[:len(dst_history)] != dst_history): raise errors.BzrCommandError('Branch %s has diverged' % relpath) # push tags src_branch.tags.merge_to(dst_branch.tags) if src_history != dst_history: dst_branch.set_revision_history(src_history) note('%d revision(s) pushed to %s' % (len(src_history) - len(dst_history), relpath)) finally: dst_repo.unlock() finally: src_repo.unlock()
def _authenticate(self): """If necessary authenticate yourself to the server.""" if self._smtp_username is None: return if self._smtp_password is None: self._smtp_password = ui.ui_factory.get_password( 'Please enter the SMTP password: %(user)s@%(host)s', user=self._smtp_username, host=self._smtp_server) try: self._connection.login(self._smtp_username, self._smtp_password) except smtplib.SMTPHeloError, e: raise errors.BzrCommandError('SMTP server refused HELO: %d %s' % (e.smtp_code, e.smtp_error))
def load(self): self.throbber.show() self.processEvents() try: if not self.tree: branch, relpath = Branch.open_containing(self.filename) self.branch = branch self.encoding = get_set_encoding(self.encoding, branch) self.encoding_selector.encoding = self.encoding if self.revision is None: self.tree = branch.basis_tree() else: revision_id = self.revision[0].in_branch(branch).rev_id self.tree = branch.repository.revision_tree(revision_id) self.file_id = self.tree.path2id(relpath) if not self.file_id: self.file_id = self.tree.path2id(self.filename) if not self.file_id: raise errors.BzrCommandError( "%r is not present in revision %s" % ( self.filename, self.tree.get_revision_id())) self.tree.lock_read() try: kind = self.tree.kind(self.file_id) if kind == 'file': text = self.tree.get_file_text(self.file_id) elif kind == 'symlink': text = self.tree.get_symlink_target(self.file_id) else: text = '' finally: self.tree.unlock() self.processEvents() self.text = text self.kind = kind self._create_and_show_browser(self.filename, text, kind) finally: self.throbber.hide()
def _qbzr_run(self, filename, revision=None, encoding=None, native=None): if revision is not None and len(revision) != 1: raise errors.BzrCommandError("bzr qcat --revision takes exactly" " one revision specifier") if native: branch, relpath = Branch.open_containing(filename) if revision is None: tree = branch.basis_tree() else: revision_id = revision[0].in_branch(branch).rev_id tree = branch.repository.revision_tree(revision_id) result = cat_to_native_app(tree, relpath) return int(not result) window = QBzrCatWindow(filename=filename, revision=revision, encoding=encoding) window.show() self._application.exec_()
def _qbzr_run(self, revision=None, file_list=None, complete=False, encoding=None, ignore_whitespace=False, added=None, deleted=None, modified=None, renamed=None, old=None, new=None, ui_mode=False): if revision and len(revision) > 2: raise errors.BzrCommandError('bzr qdiff --revision takes exactly' ' one or two revision specifiers') # changes filter filter_options = FilterOptions(added=added, deleted=deleted, modified=modified, renamed=renamed) if not (added or deleted or modified or renamed): # if no filter option used then turn all on filter_options.all_enable() self.revision = revision self.file_list = file_list self.old = old self.new = new self.ignore_whitespace = ignore_whitespace window = DiffWindow(self, complete=complete, encoding=encoding, filter_options=filter_options, ui_mode=ui_mode) window.show() self._application.exec_()
def test_format_unicode_error(self): try: raise errors.BzrCommandError(u'argument foo\xb5 does not exist') except errors.BzrCommandError: pass msg = _format_exception()
if self._smtp_username is None: return if self._smtp_password is None: self._smtp_password = ui.ui_factory.get_password( 'Please enter the SMTP password: %(user)s@%(host)s', user=self._smtp_username, host=self._smtp_server) try: self._connection.login(self._smtp_username, self._smtp_password) except smtplib.SMTPHeloError, e: raise errors.BzrCommandError('SMTP server refused HELO: %d %s' % (e.smtp_code, e.smtp_error)) except smtplib.SMTPAuthenticationError, e: raise errors.BzrCommandError( 'SMTP server refused authentication: %d %s' % (e.smtp_code, e.smtp_error)) except smtplib.SMTPException, e: raise errors.BzrCommandError(str(e)) @staticmethod def _split_address(address): """Split an username + email address into its parts. This takes "Joe Foo <*****@*****.**>" and returns "Joe Foo", "*****@*****.**". :param address: A combined username :return: (username, email) """ return parseaddr(address)
def show_tree_status(wt, show_unchanged=None, specific_files=None, show_ids=False, to_file=None, show_pending=True, revision=None, short=False, versioned=False): """Display summary of changes. By default this compares the working tree to a previous revision. If the revision argument is given, summarizes changes between the working tree and another, or between two revisions. The result is written out as Unicode and to_file should be able to encode that. If showing the status of a working tree, extra information is included about unknown files, conflicts, and pending merges. :param show_unchanged: Deprecated parameter. If set, includes unchanged files. :param specific_files: If set, a list of filenames whose status should be shown. It is an error to give a filename that is not in the working tree, or in the working inventory or in the basis inventory. :param show_ids: If set, includes each file's id. :param to_file: If set, write to this file (default stdout.) :param show_pending: If set, write pending merges. :param revision: If None, compare latest revision with working tree If not None, it must be a RevisionSpec list. If one revision, compare with working tree. If two revisions, show status between first and second. :param short: If True, gives short SVN-style status lines. :param versioned: If True, only shows versioned files. """ if show_unchanged is not None: warn( "show_tree_status with show_unchanged has been deprecated " "since bzrlib 0.9", DeprecationWarning, stacklevel=2) if to_file is None: to_file = sys.stdout wt.lock_read() try: new_is_working_tree = True if revision is None: if wt.last_revision() != wt.branch.last_revision(): warning("working tree is out of date, run 'bzr update'") new = wt old = new.basis_tree() elif len(revision) > 0: try: rev_id = revision[0].as_revision_id(wt.branch) old = wt.branch.repository.revision_tree(rev_id) except errors.NoSuchRevision, e: raise errors.BzrCommandError(str(e)) if (len(revision) > 1) and (revision[1].spec is not None): try: rev_id = revision[1].as_revision_id(wt.branch) new = wt.branch.repository.revision_tree(rev_id) new_is_working_tree = False except errors.NoSuchRevision, e: raise errors.BzrCommandError(str(e)) else:
def run(self, acceptable_keys=None, revision=None, verbose=None, location=u'.'): bzrdir = controldir.ControlDir.open_containing(location)[0] branch = bzrdir.open_branch() repo = branch.repository branch_config = branch.get_config_stack() gpg_strategy = gpg.GPGStrategy(branch_config) gpg_strategy.set_acceptable_keys(acceptable_keys) def write(string): self.outf.write(string + "\n") def write_verbose(string): self.outf.write(" " + string + "\n") self.add_cleanup(repo.lock_read().unlock) #get our list of revisions revisions = [] if revision is not None: if len(revision) == 1: revno, rev_id = revision[0].in_history(branch) revisions.append(rev_id) elif len(revision) == 2: from_revno, from_revid = revision[0].in_history(branch) to_revno, to_revid = revision[1].in_history(branch) if to_revid is None: to_revno = branch.revno() if from_revno is None or to_revno is None: raise errors.BzrCommandError( gettext( 'Cannot verify a range of non-revision-history revisions' )) for revno in range(from_revno, to_revno + 1): revisions.append(branch.get_rev_id(revno)) else: #all revisions by default including merges graph = repo.get_graph() revisions = [] for rev_id, parents in graph.iter_ancestry( [branch.last_revision()]): if _mod_revision.is_null(rev_id): continue if parents is None: # Ignore ghosts continue revisions.append(rev_id) count, result, all_verifiable = gpg.bulk_verify_signatures( repo, revisions, gpg_strategy) if all_verifiable: write(gettext("All commits signed with verifiable keys")) if verbose: for message in gpg.verbose_valid_message(result): write_verbose(message) return 0 else: write(gpg.valid_commits_message(count)) if verbose: for message in gpg.verbose_valid_message(result): write_verbose(message) write(gpg.expired_commit_message(count)) if verbose: for message in gpg.verbose_expired_key_message(result, repo): write_verbose(message) write(gpg.unknown_key_message(count)) if verbose: for message in gpg.verbose_missing_key_message(result): write_verbose(message) write(gpg.commit_not_valid_message(count)) if verbose: for message in gpg.verbose_not_valid_message(result, repo): write_verbose(message) write(gpg.commit_not_signed_message(count)) if verbose: for message in gpg.verbose_not_signed_message(result, repo): write_verbose(message) return 1
def _parse_levels(s): try: return int(s) except ValueError: msg = "The levels argument must be an integer." raise errors.BzrCommandError(msg)
def run(self, verbose=False, ignore_case=False, no_recursive=False, from_root=False, null=False, levels=None, line_number=False, path_list=None, revision=None, pattern=None, include=None, exclude=None, fixed_string=False, files_with_matches=False, files_without_match=False, color=None, diff=False): from bzrlib import _termcolor from bzrlib.plugins.grep import ( grep, ) import re if path_list is None: path_list = ['.'] else: if from_root: raise errors.BzrCommandError( 'cannot specify both --from-root and PATH.') if files_with_matches and files_without_match: raise errors.BzrCommandError( 'cannot specify both ' '-l/--files-with-matches and -L/--files-without-matches.') global_config = GlobalConfig() if color is None: color = global_config.get_user_option('grep_color') if color is None: color = 'never' if color not in ['always', 'never', 'auto']: raise errors.BzrCommandError('Valid values for --color are ' '"always", "never" or "auto".') if levels == None: levels = 1 print_revno = False if revision != None or levels == 0: # print revision numbers as we may be showing multiple revisions print_revno = True eol_marker = '\n' if null: eol_marker = '\0' if not ignore_case and grep.is_fixed_string(pattern): # if the pattern isalnum, implicitly use to -F for faster grep fixed_string = True elif ignore_case and fixed_string: # GZ 2010-06-02: Fall back to regexp rather than lowercasing # pattern and text which will cause pain later fixed_string = False pattern = re.escape(pattern) patternc = None re_flags = re.MULTILINE if ignore_case: re_flags |= re.IGNORECASE if not fixed_string: patternc = grep.compile_pattern(pattern, re_flags) if color == 'always': show_color = True elif color == 'never': show_color = False elif color == 'auto': show_color = _termcolor.allow_color() GrepOptions.verbose = verbose GrepOptions.ignore_case = ignore_case GrepOptions.no_recursive = no_recursive GrepOptions.from_root = from_root GrepOptions.null = null GrepOptions.levels = levels GrepOptions.line_number = line_number GrepOptions.path_list = path_list GrepOptions.revision = revision GrepOptions.pattern = pattern GrepOptions.include = include GrepOptions.exclude = exclude GrepOptions.fixed_string = fixed_string GrepOptions.files_with_matches = files_with_matches GrepOptions.files_without_match = files_without_match GrepOptions.color = color GrepOptions.diff = False GrepOptions.eol_marker = eol_marker GrepOptions.print_revno = print_revno GrepOptions.patternc = patternc GrepOptions.recursive = not no_recursive GrepOptions.fixed_string = fixed_string GrepOptions.outf = self.outf GrepOptions.show_color = show_color if diff: # options not used: # files_with_matches, files_without_match # levels(?), line_number, from_root # include, exclude # These are silently ignored. grep.grep_diff(GrepOptions) elif revision is None: grep.workingtree_grep(GrepOptions) else: grep.versioned_grep(GrepOptions)
def show_missing_xml(self, other_branch=None, reverse=False, mine_only=False, theirs_only=False, log_format=None, long=False, short=False, line=False, show_ids=False, verbose=False, this=False, other=False): """output missing info as xml""" if this: mine_only = this if other: theirs_only = other local_branch = Branch.open_containing(u".")[0] parent = local_branch.get_parent() if other_branch is None: other_branch = parent if other_branch is None: raise errors.BzrCommandError("No peer location known" " or specified.") display_url = urlutils.unescape_for_display(other_branch, self.outf.encoding) remote_branch = Branch.open(other_branch) if remote_branch.base == local_branch.base: remote_branch = local_branch local_branch.lock_read() try: remote_branch.lock_read() self.outf.write('<?xml version="1.0" encoding="%s"?>' % \ osutils.get_user_encoding()) self.outf.write('<missing>') try: self.outf.write('<last_location>' + display_url + \ '</last_location>') local_extra, remote_extra = find_unmerged(local_branch, remote_branch) if log_format is None: registry = log_formatter_registry log_format = registry.get_default(local_branch) if reverse is False: local_extra.reverse() remote_extra.reverse() if local_extra and not theirs_only: self.outf.write('<extra_revisions size="%d">' % len(local_extra)) if local_extra > 0: lf = log_format(to_file=self.outf, show_ids=show_ids, show_timezone='original') showlogs( self, iter_log_revisions(local_extra, local_branch.repository, verbose), lf) self.outf.write('</extra_revisions>') if remote_extra and not mine_only: self.outf.write('<missing_revisions size="%d">' % len(remote_extra)) if remote_extra > 0: lf = log_format(to_file=self.outf, show_ids=show_ids, show_timezone='original') showlogs( self, iter_log_revisions(remote_extra, remote_branch.repository, verbose), lf) self.outf.write('</missing_revisions>') if not remote_extra and not local_extra: status_code = 0 # self.outf.write("Branches are up to date.\n") else: status_code = 1 finally: remote_branch.unlock() finally: self.outf.write('</missing>') local_branch.unlock() if not status_code and parent is None and other_branch is not None: local_branch.lock_write() try: # handle race conditions - a parent might be set while we run. if local_branch.get_parent() is None: local_branch.set_parent(remote_branch.base) finally: local_branch.unlock() return status_code
:param control: BzrDir of the branch to check """ try: tree = control.open_workingtree() except errors.NotBranchError, ex: # Lightweight checkout and branch is no longer there if force: return else: raise ex # XXX: Should the tree be locked for get_parent_ids? existing_pending_merges = tree.get_parent_ids()[1:] if len(existing_pending_merges) > 0: raise errors.BzrCommandError( 'Pending merges must be ' 'committed or reverted before using switch.') def _set_branch_location(control, to_branch, force=False): """Set location value of a branch reference. :param control: BzrDir of the checkout to change :param to_branch: branch that the checkout is to reference :param force: skip the check for local commits in a heavy checkout """ branch_format = control.find_branch_format() if branch_format.get_reference(control) is not None: # Lightweight checkout: update the branch reference branch_format.set_reference(control, to_branch) else:
def compare_using(tool, file_list=None, rev1=None, rev2=None): """ Compare two branches or revisions using an external tool. Determine which revisions of the file to compare, extract them if necessary, and run the comparison. Handle repository branches and non-local branches (see get_tree_files). """ tmp_prefix = 'bzr_diff-' # Find the tree(s) and the files associated with each: (b1, work_tree1, file_ids1, remainder) = get_tree_files(file_list) trees_to_lock = [work_tree1] if (len(remainder) > 0): (b2, work_tree2, file_ids2, remainder) = get_tree_files(remainder) b2_in_working_tree = isinstance(work_tree2, workingtree.WorkingTree) trees_to_lock.append(work_tree2) if (len(remainder) > 0): raise errors.BzrCommandError("Cannot compare more than two branches") if rev1 or rev2: raise errors.BzrCommandError("Cannot specify -r with multiple branches") else: b2 = None b2_in_working_tree = False get_read_locks(trees_to_lock) try: kind = work_tree1.inventory.get_file_kind(file_ids1[0]) in_subdir = (kind == 'directory' or kind == 'root_directory') in_working_tree = isinstance(work_tree1, workingtree.WorkingTree) # Decide which mode (tree or files) to use when writing to tmpdir: if (len(file_list) == 1 and not in_subdir): use_tree = False elif (b2 and not in_subdir): use_tree = False else: use_tree = True # Check if we need to adjust our tmpdir paths: if (len(file_list) == 1) or b2: if in_subdir: adjust_path = work_tree1.inventory.id2path(file_ids1[0]) else: adjust_path = osutils.basename(file_list[0]) else: adjust_path = '' cleanup = tool.supports('cleanup') finally: release_read_locks(trees_to_lock) try: # Use the 1st revision as the old version (basis_tree is the default): if rev1: old_tree = b1.repository.revision_tree(rev1.in_history(b1).rev_id) old_hint = "-rev%s" % rev1.in_history(b1).revno elif b2: old_tree = work_tree1 old_hint = '-' + b1.nick else: old_tree = b1.basis_tree() old_hint = "-basis" get_read_locks(trees_to_lock) try: # Use the 2nd revision as the new version (working_tree is the default): if rev2: new_tree = b1.repository.revision_tree(rev2.in_history(b1).rev_id) delta = get_diffs_or_stop(old_tree, new_tree, file_ids1) new_hint = "-rev%s" % rev2.in_history(b1).revno new_tmp_dir = NamedTemporaryDir(tmp_prefix, new_hint, cleanup) new_tmp_dir.write_stuff(new_tree, file_ids1, use_tree) new_path = osutils.pathjoin(new_tmp_dir.path, adjust_path) elif b2_in_working_tree: # Files from two different branches, branch2 has a working tree: delta = get_diffs_or_stop(old_tree, work_tree2, file_ids2) if (len(file_list) == 1): new_path = work_tree2.id2abspath(file_ids2[0]) else: new_path = work_tree2.abspath('') elif b2: # Files from two different branches, branch2 has no working tree: delta = get_diffs_or_stop(old_tree, work_tree2, file_ids2) new_hint = '-' + b2.nick new_tmp_dir = NamedTemporaryDir(tmp_prefix, new_hint, cleanup) new_tmp_dir.write_stuff(work_tree2, file_ids2, use_tree) new_path = osutils.pathjoin(new_tmp_dir.path, adjust_path) elif not in_working_tree: # Repository branch or remote branch, but only one revision: new_tree = b1.basis_tree() delta = get_diffs_or_stop(old_tree, new_tree, file_ids1) new_hint = "-basis" new_tmp_dir = NamedTemporaryDir(tmp_prefix, new_hint, cleanup) new_tmp_dir.write_stuff(new_tree, file_ids1, use_tree) new_path = osutils.pathjoin(new_tmp_dir.path, adjust_path) else: # Item(s) in working tree, just diff it in place: delta = get_diffs_or_stop(old_tree, work_tree1, file_ids1) if (len(file_list) == 1): new_path = work_tree1.id2abspath(file_ids1[0]) else: new_path = work_tree1.abspath('') # No exceptions yet, so we really do need to extract the old version: if b2 and in_working_tree: if (len(file_list) == 1): old_path = work_tree1.id2abspath(file_ids1[0]) else: old_path = work_tree1.abspath('') else: old_tmp_dir = NamedTemporaryDir(tmp_prefix, old_hint, cleanup) old_tmp_dir.write_stuff(old_tree, file_ids1, use_tree) old_path = osutils.pathjoin(old_tmp_dir.path, adjust_path) finally: # Release the locks before we start any interactive tools: release_read_locks(trees_to_lock) # Run the comparison: if (tool.supports('recursive')): result = tool.run(old_path, new_path) elif (len(file_list) == 1 and not in_subdir): result = tool.run(old_path, new_path) else: # Iterative diff: if adjust_path != '': path_list = [path.replace(adjust_path, '.', 1) for (path, file_id, kind, text_mods, meta_mods) in delta.modified if text_mods] else: path_list = [path for (path, file_id, kind, text_mods, meta_mods) in delta.modified if text_mods] result = tool.run(old_path, new_path, path_list) # Set the result, since external tools cannot be trusted to do so: result = 1 except NoDifferencesFound: result = 0 return result
def refresh_view(self): """get the revisions wanted by the user, do the verifications and popular the tree widget with the results""" self.throbber.show() bzrdir = _mod_bzrdir.BzrDir.open_containing(self.location)[0] branch = bzrdir.open_branch() repo = branch.repository branch_config = branch.get_config() gpg_strategy = gpg.GPGStrategy(branch_config) gpg_strategy.set_acceptable_keys(self.acceptable_keys) if branch.name is None: header = branch.user_url else: header = branch.name self.ui.treeWidget.setHeaderLabels([str(header)]) #get our list of revisions revisions = [] if self.revision is not None: if len(self.revision) == 1: revno, rev_id = self.revision[0].in_history(branch) revisions.append(rev_id) elif len(sel.revision) == 2: from_revno, from_revid = self.revision[0].in_history(branch) to_revno, to_revid = self.revision[1].in_history(branch) if to_revid is None: to_revno = branch.revno() if from_revno is None or to_revno is None: raise errors.BzrCommandError('Cannot verify a range of '\ 'non-revision-history revisions') for revno in range(from_revno, to_revno + 1): revisions.append(branch.get_rev_id(revno)) else: #all revisions by default including merges graph = repo.get_graph() revisions = [] repo.lock_read() for rev_id, parents in graph.iter_ancestry( [branch.last_revision()]): if _mod_revision.is_null(rev_id): continue if parents is None: # Ignore ghosts continue revisions.append(rev_id) repo.unlock() count, result, all_verifiable =\ gpg_strategy.do_verifications(revisions, repo, QApplication.processEvents) if all_verifiable: message = QTreeWidgetItem( [gettext("All commits signed with verifiable keys")]) self.ui.treeWidget.addTopLevelItem(message) for verbose_message in gpg_strategy.verbose_valid_message(result): QTreeWidgetItem(message, [verbose_message]) else: valid_commit_message = QTreeWidgetItem( [gpg_strategy.valid_commits_message(count)]) self.ui.treeWidget.addTopLevelItem(valid_commit_message) for verbose_message in gpg_strategy.verbose_valid_message(result): QTreeWidgetItem(valid_commit_message, [verbose_message]) expired_key_message = QTreeWidgetItem( [gpg_strategy.expired_commit_message(count)]) self.ui.treeWidget.addTopLevelItem(expired_key_message) for verbose_message in \ gpg_strategy.verbose_expired_key_message(result, repo): QTreeWidgetItem(expired_key_message, [verbose_message]) unknown_key_message = QTreeWidgetItem( [gpg_strategy.unknown_key_message(count)]) self.ui.treeWidget.addTopLevelItem(unknown_key_message) for verbose_message in gpg_strategy.verbose_missing_key_message( result): QTreeWidgetItem(unknown_key_message, [verbose_message]) commit_not_valid_message = QTreeWidgetItem( [gpg_strategy.commit_not_valid_message(count)]) self.ui.treeWidget.addTopLevelItem(commit_not_valid_message) for verbose_message in gpg_strategy.verbose_not_valid_message( result, repo): QTreeWidgetItem(commit_not_valid_message, [verbose_message]) commit_not_signed_message = QTreeWidgetItem( [gpg_strategy.commit_not_signed_message(count)]) self.ui.treeWidget.addTopLevelItem(commit_not_signed_message) for verbose_message in gpg_strategy.verbose_not_signed_message( result, repo): QTreeWidgetItem(commit_not_signed_message, [verbose_message]) self.throbber.hide()
def send(target_branch, revision, public_branch, remember, format, no_bundle, no_patch, output, from_, mail_to, message, body, to_file, strict=None): possible_transports = [] tree, branch = controldir.ControlDir.open_containing_tree_or_branch( from_, possible_transports=possible_transports)[:2] # we may need to write data into branch's repository to calculate # the data to send. branch.lock_write() try: if output is None: config_stack = branch.get_config_stack() if mail_to is None: mail_to = config_stack.get('submit_to') mail_client = config_stack.get('mail_client')(config_stack) if (not getattr(mail_client, 'supports_body', False) and body is not None): raise errors.BzrCommandError( gettext( 'Mail client "%s" does not support specifying body') % mail_client.__class__.__name__) if remember and target_branch is None: raise errors.BzrCommandError( gettext('--remember requires a branch to be specified.')) stored_target_branch = branch.get_submit_branch() remembered_target_branch = None if target_branch is None: target_branch = stored_target_branch remembered_target_branch = "submit" else: # Remembers if asked explicitly or no previous location is set if remember or (remember is None and stored_target_branch is None): branch.set_submit_branch(target_branch) if target_branch is None: target_branch = branch.get_parent() remembered_target_branch = "parent" if target_branch is None: raise errors.BzrCommandError( gettext('No submit branch known or' ' specified')) if remembered_target_branch is not None: trace.note( gettext('Using saved {0} location "{1}" to determine ' 'what changes to submit.').format( remembered_target_branch, target_branch)) submit_branch = Branch.open(target_branch, possible_transports=possible_transports) possible_transports.append(submit_branch.bzrdir.root_transport) if mail_to is None or format is None: if mail_to is None: mail_to = submit_branch.get_config_stack().get( 'child_submit_to') if format is None: formatname = submit_branch.get_child_submit_format() try: format = format_registry.get(formatname) except KeyError: raise errors.BzrCommandError( gettext("No such send format '%s'.") % formatname) stored_public_branch = branch.get_public_branch() if public_branch is None: public_branch = stored_public_branch # Remembers if asked explicitly or no previous location is set elif (remember or (remember is None and stored_public_branch is None)): branch.set_public_branch(public_branch) if no_bundle and public_branch is None: raise errors.BzrCommandError( gettext('No public branch specified or' ' known')) base_revision_id = None revision_id = None if revision is not None: if len(revision) > 2: raise errors.BzrCommandError( gettext('bzr send takes ' 'at most two one revision identifiers')) revision_id = revision[-1].as_revision_id(branch) if len(revision) == 2: base_revision_id = revision[0].as_revision_id(branch) if revision_id is None: if tree is not None: tree.check_changed_or_out_of_date( strict, 'send_strict', more_error='Use --no-strict to force the send.', more_warning='Uncommitted changes will not be sent.') revision_id = branch.last_revision() if revision_id == NULL_REVISION: raise errors.BzrCommandError(gettext('No revisions to submit.')) if format is None: format = format_registry.get() directive = format(branch, revision_id, target_branch, public_branch, no_patch, no_bundle, message, base_revision_id, submit_branch) if output is None: directive.compose_merge_request(mail_client, mail_to, body, branch, tree) else: if directive.multiple_output_files: if output == '-': raise errors.BzrCommandError( gettext( '- not supported for ' 'merge directives that use more than one output file.' )) if not os.path.exists(output): os.mkdir(output, 0755) for (filename, lines) in directive.to_files(): path = os.path.join(output, filename) outfile = open(path, 'wb') try: outfile.writelines(lines) finally: outfile.close() else: if output == '-': outfile = to_file else: outfile = open(output, 'wb') try: outfile.writelines(directive.to_lines()) finally: if outfile is not to_file: outfile.close() finally: branch.unlock()
"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:
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): """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: if False, a current branch at the destination may not have diverged from the source, otherwise the push fails :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) br_to = repository_to = dir_to = None try: dir_to = bzrdir.BzrDir.open_from_transport(to_transport) except errors.NotBranchError: pass # Didn't find anything else: # If we can open a branch, use its direct repository, otherwise see # if there is a repository without a branch. try: br_to = dir_to.open_branch() except errors.NotBranchError: # Didn't find a branch, can we find a repository? try: repository_to = dir_to.find_repository() except errors.NoRepositoryPresent: pass else: # Found a branch, so we must have found a repository repository_to = br_to.repository push_result = None if verbose: old_rh = [] if dir_to is None: # The destination doesn't exist; create it. # XXX: Refactor the create_prefix/no_create_prefix code into a # common helper function def make_directory(transport): transport.mkdir('.') return transport def redirected(redirected_transport, e, redirection_notice): return transport.get_transport(e.get_target_url()) try: to_transport = transport.do_catching_redirections( make_directory, to_transport, redirected) except errors.FileExists: if not use_existing_dir: raise errors.BzrCommandError( "Target directory %s" " already exists, but does not have a valid .bzr" " directory. Supply --use-existing-dir to push" " there anyway." % location) except errors.NoSuchFile: if not create_prefix: raise errors.BzrCommandError( "Parent directory of %s" " does not exist." "\nYou may supply --create-prefix to create all" " leading parent directories." % location) builtins._create_prefix(to_transport) except errors.TooManyRedirections: raise errors.BzrCommandError("Too many redirections trying " "to make %s." % location) # Now the target directory exists, but doesn't have a .bzr # directory. So we need to create it, along with any work to create # all of the dependent branches, etc. if stacked_on is not None: # This should be buried in the clone method itself. TODO. try: # if the from format is stackable, this will either work or # trigger NotStacked. If it's not, an error will be given to # the user. br_from.get_stacked_on_url() except errors.NotStacked: pass # now we need to sprout the repository, dir_to = br_from.bzrdir._format.initialize_on_transport( to_transport) br_from.repository._format.initialize(dir_to) br_to = br_from._format.initialize(dir_to) br_to.set_stacked_on_url(stacked_on) # and copy the data up. br_from.push(br_to) else: dir_to = br_from.bzrdir.clone_on_transport(to_transport, revision_id=revision_id) br_to = dir_to.open_branch() # TODO: Some more useful message about what was copied if stacked_on is not None: note('Created new stacked branch referring to %s.' % stacked_on) else: note('Created new branch.') # We successfully created the target, remember it if br_from.get_push_location() is None or remember: br_from.set_push_location(br_to.base) elif repository_to is None: # we have a bzrdir but no branch or repository # XXX: Figure out what to do other than complain. raise errors.BzrCommandError( "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) elif br_to is None: # We have a repository but no branch, copy the revisions, and then # create a branch. if stacked_on is not None: warning("Ignoring request for a stacked branch as repository " "already exists at the destination location.") repository_to.fetch(br_from.repository, revision_id=revision_id) br_to = br_from.clone(dir_to, revision_id=revision_id) note('Created new branch.') if br_from.get_push_location() is None or remember: br_from.set_push_location(br_to.base) else: # We have a valid to branch if stacked_on is not None: warning("Ignoring request for a stacked branch as branch " "already exists at the destination location.") # We were able to connect to the remote location, so remember it. # (We don't need to successfully push because of possible divergence.) if br_from.get_push_location() is None or remember: br_from.set_push_location(br_to.base) if verbose: old_rh = br_to.revision_history() try: try: tree_to = dir_to.open_workingtree() except errors.NotLocalUrl: warning("This transport does not update the working " "tree of: %s. See 'bzr help working-trees' for " "more information." % br_to.base) push_result = br_from.push(br_to, overwrite, stop_revision=revision_id) except errors.NoWorkingTree: push_result = br_from.push(br_to, overwrite, stop_revision=revision_id) else: tree_to.lock_write() try: push_result = br_from.push(tree_to.branch, overwrite, stop_revision=revision_id) tree_to.update() finally: tree_to.unlock() except errors.DivergedBranches: raise errors.BzrCommandError( 'These branches have diverged.' ' Try using "merge" and then "push".') if push_result is not None: push_result.report(to_file) elif verbose: new_rh = br_to.revision_history() if old_rh != new_rh: # Something changed from bzrlib.log import show_changed_revisions show_changed_revisions(br_to, old_rh, new_rh, to_file=to_file) else: # we probably did a clone rather than a push, so a message was # emitted above pass