def get_ancestry(repository, revision_id): """Return a list of revision-ids integrated by a revision. The first element of the list is always None, indicating the origin revision. This might change when we have history horizons, or perhaps we should have a new API. This is topologically sorted. """ if is_null(revision_id): return set() if not repository.has_revision(revision_id): raise NoSuchRevision(repository, revision_id) repository.lock_read() try: graph = repository.get_graph() keys = set() search = graph._make_breadth_first_searcher([revision_id]) while True: try: found, ghosts = search.next_with_ghosts() except StopIteration: break keys.update(found) if NULL_REVISION in keys: keys.remove(NULL_REVISION) finally: repository.unlock() return keys
def run(self, location=None, committer=None, dry_run=False): if location is None: bzrdir = controldir.ControlDir.open_containing('.')[0] else: # Passed in locations should be exact bzrdir = controldir.ControlDir.open(location) branch = bzrdir.open_branch() repo = branch.repository branch_config = branch.get_config_stack() if committer is None: committer = branch_config.get('email') gpg_strategy = gpg.GPGStrategy(branch_config) count = 0 repo.lock_write() try: graph = repo.get_graph() repo.start_write_group() try: 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 if repo.has_signature_for_revision_id(rev_id): continue rev = repo.get_revision(rev_id) if rev.committer != committer: continue # We have a revision without a signature who has a # matching committer, start signing self.outf.write("%s\n" % rev_id) count += 1 if not dry_run: repo.sign_revision(rev_id, gpg_strategy) except: repo.abort_write_group() raise else: repo.commit_write_group() finally: repo.unlock() self.outf.write( ngettext('Signed %d revision.\n', 'Signed %d revisions.\n', count) % count)
def initialize(self, a_bzrdir, revision_id=None, from_branch=None, accelerator_tree=None, hardlink=False): """See WorkingTreeFormat.initialize().""" if not isinstance(a_bzrdir.transport, LocalTransport): raise errors.NotLocalUrl(a_bzrdir.transport.base) if from_branch is not None: branch = from_branch else: branch = a_bzrdir.open_branch() if revision_id is None: revision_id = _mod_revision.ensure_null(branch.last_revision()) branch.lock_write() try: branch.generate_revision_history(revision_id) finally: branch.unlock() inv = inventory.Inventory() wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'), branch, inv, _internal=True, _format=self, _bzrdir=a_bzrdir, _control_files=branch.control_files) basis_tree = branch.repository.revision_tree(revision_id) if basis_tree.get_root_id() is not None: wt.set_root_id(basis_tree.get_root_id()) # set the parent list and cache the basis tree. if _mod_revision.is_null(revision_id): parent_trees = [] else: parent_trees = [(revision_id, basis_tree)] wt.set_parent_trees(parent_trees) transform.build_tree(basis_tree, wt) for hook in MutableTree.hooks['post_build_tree']: hook(wt) return wt
def test_sprout_bzrdir_repository(self): tree = self.make_branch_and_tree('commit_tree') self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..')) tree.add('foo') tree.commit('revision 1', rev_id='1') dir = self.make_bzrdir('source') repo = dir.create_repository() repo.fetch(tree.branch.repository) self.assertTrue(repo.has_revision('1')) try: self.assertTrue( _mod_revision.is_null(_mod_revision.ensure_null( dir.open_branch().last_revision()))) except errors.NotBranchError: pass target = dir.sprout(self.get_url('target')) self.assertNotEqual(dir.transport.base, target.transport.base) # testing inventory isn't reasonable for repositories self.assertDirectoriesEqual(dir.root_transport, target.root_transport, [ './.bzr/branch', './.bzr/checkout', './.bzr/inventory', './.bzr/parent', './.bzr/repository/inventory.knit', ]) try: local_inventory = dir.transport.local_abspath('inventory') except errors.NotLocalUrl: return try: # If we happen to have a tree, we'll guarantee everything # except for the tree root is the same. inventory_f = file(local_inventory, 'rb') self.addCleanup(inventory_f.close) self.assertContainsRe(inventory_f.read(), '<inventory format="5">\n</inventory>\n') except IOError, e: if e.errno != errno.ENOENT: raise
def uncommit(branch, dry_run=False, verbose=False, revno=None, tree=None, local=False): """Remove the last revision from the supplied branch. :param dry_run: Don't actually change anything :param verbose: Print each step as you do it :param revno: Remove back to this revision :param local: If this branch is bound, only remove the revisions from the local branch. If this branch is not bound, it is an error to pass local=True. """ unlockable = [] try: if tree is not None: tree.lock_write() unlockable.append(tree) branch.lock_write() unlockable.append(branch) pending_merges = [] if tree is not None: pending_merges = tree.get_parent_ids()[1:] if local: master = None if branch.get_bound_location() is None: raise errors.LocalRequiresBoundBranch() else: master = branch.get_master_branch() if master is not None: master.lock_write() unlockable.append(master) old_revno, old_tip = branch.last_revision_info() if master is not None and old_tip != master.last_revision(): raise BoundBranchOutOfDate(branch, master) if revno is None: revno = old_revno new_revno = revno - 1 revid_iterator = branch.repository.iter_reverse_revision_history( old_tip) cur_revno = old_revno new_revision_id = old_tip graph = branch.repository.get_graph() for rev_id in revid_iterator: if cur_revno == new_revno: new_revision_id = rev_id break if verbose: print 'Removing revno %d: %s' % (cur_revno, rev_id) cur_revno -= 1 parents = graph.get_parent_map([rev_id]).get(rev_id, None) if not parents: continue # When we finish popping off the pending merges, we want # them to stay in the order that they used to be. # but we pop from the end, so reverse the order, and # then get the order right at the end pending_merges.extend(reversed(parents[1:])) else: # We ran off the end of revisions, which means we should be trying # to get to NULL_REVISION new_revision_id = _mod_revision.NULL_REVISION if not dry_run: if master is not None: master.set_last_revision_info(new_revno, new_revision_id) branch.set_last_revision_info(new_revno, new_revision_id) if master is None: hook_local = None hook_master = branch else: hook_local = branch hook_master = master for hook in Branch.hooks['post_uncommit']: hook_new_tip = new_revision_id if hook_new_tip == _mod_revision.NULL_REVISION: hook_new_tip = None hook(hook_local, hook_master, old_revno, old_tip, new_revno, hook_new_tip) if tree is not None: if not _mod_revision.is_null(new_revision_id): parents = [new_revision_id] else: parents = [] parents.extend(reversed(pending_merges)) tree.set_parent_ids(parents) finally: for item in reversed(unlockable): item.unlock()
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 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 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: write(gpg.verbose_valid_message(result)) 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