Rev 6094: (jelmer) Remove tags in `bzr uncommit`. (Jelmer Vernooij) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Wed Aug 24 17:13:49 UTC 2011


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 6094 [merge]
revision-id: pqm at pqm.ubuntu.com-20110824171334-rmma92i0w6umipi6
parent: pqm at pqm.ubuntu.com-20110823131455-25rwamcvm0il00ps
parent: jelmer at samba.org-20110824093118-ewjpuuc9onlkn3la
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2011-08-24 17:13:34 +0000
message:
  (jelmer) Remove tags in `bzr uncommit`. (Jelmer Vernooij)
modified:
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/tests/blackbox/test_uncommit.py test_uncommit.py-20051027212835-84944b63adae51be
  bzrlib/tests/test_uncommit.py  test_uncommit.py-20080316104338-y3gxu67g5m2qih10-1
  bzrlib/uncommit.py             uncommit.py-20050626215513-5ec509fa425b305c
  bzrlib/vf_repository.py        vf_repository.py-20110502151858-yh9nnoxpokg86unk-1
  doc/en/release-notes/bzr-2.5.txt bzr2.5.txt-20110708125756-587p0hpw7oke4h05-1
  doc/en/user-guide/undoing_mistakes.txt undoing_mistakes.txt-20071121092300-8fyacngt1w98e5mp-1
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2011-08-19 22:26:03 +0000
+++ b/bzrlib/builtins.py	2011-08-24 09:28:57 +0000
@@ -4979,6 +4979,8 @@
     takes_options = ['verbose', 'revision',
                     Option('dry-run', help='Don\'t actually make changes.'),
                     Option('force', help='Say yes to all questions.'),
+                    Option('keep-tags',
+                           help='Keep tags that point to removed revisions.'),
                     Option('local',
                            help="Only remove the commits from the local branch"
                                 " when in a checkout."
@@ -4988,9 +4990,8 @@
     aliases = []
     encoding_type = 'replace'
 
-    def run(self, location=None,
-            dry_run=False, verbose=False,
-            revision=None, force=False, local=False):
+    def run(self, location=None, dry_run=False, verbose=False,
+            revision=None, force=False, local=False, keep_tags=False):
         if location is None:
             location = u'.'
         control, relpath = bzrdir.BzrDir.open_containing(location)
@@ -5005,9 +5006,11 @@
             self.add_cleanup(tree.lock_write().unlock)
         else:
             self.add_cleanup(b.lock_write().unlock)
-        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
+        return self._run(b, tree, dry_run, verbose, revision, force,
+                         local, keep_tags)
 
-    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
+    def _run(self, b, tree, dry_run, verbose, revision, force, local,
+             keep_tags):
         from bzrlib.log import log_formatter, show_log
         from bzrlib.uncommit import uncommit
 
@@ -5059,7 +5062,7 @@
         mutter('Uncommitting from {%s} to {%s}',
                last_rev_id, rev_id)
         uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
-                 revno=revno, local=local)
+                 revno=revno, local=local, keep_tags=keep_tags)
         self.outf.write('You can restore the old tip by running:\n'
              '  bzr pull . -r revid:%s\n' % last_rev_id)
 

=== modified file 'bzrlib/tests/blackbox/test_uncommit.py'
--- a/bzrlib/tests/blackbox/test_uncommit.py	2010-09-15 09:35:42 +0000
+++ b/bzrlib/tests/blackbox/test_uncommit.py	2011-08-22 10:44:29 +0000
@@ -18,9 +18,9 @@
 
 import os
 
-from bzrlib import uncommit, workingtree
+from bzrlib import uncommit
 from bzrlib.bzrdir import BzrDirMetaFormat1
-from bzrlib.errors import BzrError, BoundBranchOutOfDate
+from bzrlib.errors import BoundBranchOutOfDate
 from bzrlib.tests import TestCaseWithTransport
 from bzrlib.tests.script import (
     run_script,
@@ -280,3 +280,17 @@
         tree.commit(u'\u1234 message')
         out, err = self.run_bzr('uncommit --force tree', encoding='ascii')
         self.assertContainsRe(out, r'\? message')
+
+    def test_uncommit_removes_tags(self):
+        tree = self.make_branch_and_tree('tree')
+        revid = tree.commit('message')
+        tree.branch.tags.set_tag("atag", revid)
+        out, err = self.run_bzr('uncommit --force tree')
+        self.assertEquals({}, tree.branch.tags.get_tag_dict())
+
+    def test_uncommit_keep_tags(self):
+        tree = self.make_branch_and_tree('tree')
+        revid = tree.commit('message')
+        tree.branch.tags.set_tag("atag", revid)
+        out, err = self.run_bzr('uncommit --keep-tags --force tree')
+        self.assertEquals({"atag": revid}, tree.branch.tags.get_tag_dict())

=== modified file 'bzrlib/tests/test_uncommit.py'
--- a/bzrlib/tests/test_uncommit.py	2011-05-13 12:51:05 +0000
+++ b/bzrlib/tests/test_uncommit.py	2011-08-22 10:44:29 +0000
@@ -96,3 +96,30 @@
         # If this tree isn't bound, local=True raises an exception
         self.assertRaises(errors.LocalRequiresBoundBranch,
             uncommit.uncommit, tree.branch, tree=tree, local=True)
+
+    def test_uncommit_remove_tags(self):
+        tree, history = self.make_linear_tree()
+        self.assertEqual(history[1], tree.last_revision())
+        self.assertEqual((2, history[1]), tree.branch.last_revision_info())
+        tree.branch.tags.set_tag(u"pointsatexisting", history[0])
+        tree.branch.tags.set_tag(u"pointsatremoved", history[1])
+        uncommit.uncommit(tree.branch, tree=tree)
+        self.assertEqual(history[0], tree.last_revision())
+        self.assertEqual((1, history[0]), tree.branch.last_revision_info())
+        self.assertEqual({
+            "pointsatexisting": history[0]
+            }, tree.branch.tags.get_tag_dict())
+
+    def test_uncommit_keep_tags(self):
+        tree, history = self.make_linear_tree()
+        self.assertEqual(history[1], tree.last_revision())
+        self.assertEqual((2, history[1]), tree.branch.last_revision_info())
+        tree.branch.tags.set_tag(u"pointsatexisting", history[0])
+        tree.branch.tags.set_tag(u"pointsatremoved", history[1])
+        uncommit.uncommit(tree.branch, tree=tree, keep_tags=True)
+        self.assertEqual(history[0], tree.last_revision())
+        self.assertEqual((1, history[0]), tree.branch.last_revision_info())
+        self.assertEqual({
+            "pointsatexisting": history[0],
+            "pointsatremoved": history[1],
+            }, tree.branch.tags.get_tag_dict())

=== modified file 'bzrlib/uncommit.py'
--- a/bzrlib/uncommit.py	2011-06-16 12:50:32 +0000
+++ b/bzrlib/uncommit.py	2011-08-22 10:53:21 +0000
@@ -26,8 +26,29 @@
 from bzrlib.errors import BoundBranchOutOfDate
 
 
+def remove_tags(branch, graph, old_tip, new_tip):
+    """Remove tags on revisions between old_tip and new_tip.
+
+    :param branch: Branch to remove tags from
+    :param graph: Graph object for branch repository
+    :param old_tip: Old branch tip
+    :param new_tip: New branch tip
+    :return: Names of the removed tags
+    """
+    reverse_tags = branch.tags.get_reverse_tag_dict()
+    ancestors = graph.find_unique_ancestors(old_tip, [new_tip])
+    removed_tags = []
+    for revid, tags in reverse_tags.iteritems():
+        if not revid in ancestors:
+            continue
+        for tag in tags:
+            branch.tags.delete_tag(tag)
+            removed_tags.append(tag)
+    return removed_tags
+
+
 def uncommit(branch, dry_run=False, verbose=False, revno=None, tree=None,
-             local=False):
+             local=False, keep_tags=False):
     """Remove the last revision from the supplied branch.
 
     :param dry_run: Don't actually change anything
@@ -36,6 +57,8 @@
     :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.
+    :param keep_tags: Whether to keep tags pointing at the removed revisions
+        around.
     """
     unlockable = []
     try:
@@ -105,6 +128,8 @@
                     hook_new_tip = None
                 hook(hook_local, hook_master, old_revno, old_tip, new_revno,
                      hook_new_tip)
+            if branch.supports_tags() and not keep_tags:
+                remove_tags(branch, graph, old_tip, new_revision_id)
             if tree is not None:
                 if not _mod_revision.is_null(new_revision_id):
                     parents = [new_revision_id]

=== modified file 'bzrlib/vf_repository.py'
--- a/bzrlib/vf_repository.py	2011-08-02 11:18:43 +0000
+++ b/bzrlib/vf_repository.py	2011-08-21 21:03:57 +0000
@@ -419,8 +419,8 @@
                 return None, False, None
         # XXX: Friction: parent_candidates should return a list not a dict
         #      so that we don't have to walk the inventories again.
-        parent_candiate_entries = ie.parent_candidates(parent_invs)
-        head_set = self._heads(ie.file_id, parent_candiate_entries.keys())
+        parent_candidate_entries = ie.parent_candidates(parent_invs)
+        head_set = self._heads(ie.file_id, parent_candidate_entries.keys())
         heads = []
         for inv in parent_invs:
             if inv.has_id(ie.file_id):
@@ -441,7 +441,7 @@
             store = True
         if not store:
             # There is a single head, look it up for comparison
-            parent_entry = parent_candiate_entries[heads[0]]
+            parent_entry = parent_candidate_entries[heads[0]]
             # if the non-content specific data has changed, we'll be writing a
             # node:
             if (parent_entry.parent_id != ie.parent_id or
@@ -559,7 +559,7 @@
         :param iter_changes: An iter_changes iterator with the changes to apply
             to basis_revision_id. The iterator must not include any items with
             a current kind of None - missing items must be either filtered out
-            or errored-on beefore record_iter_changes sees the item.
+            or errored-on before record_iter_changes sees the item.
         :param _entry_factory: Private method to bind entry_factory locally for
             performance.
         :return: A generator of (file_id, relpath, fs_hash) tuples for use with

=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- a/doc/en/release-notes/bzr-2.5.txt	2011-08-23 10:27:54 +0000
+++ b/doc/en/release-notes/bzr-2.5.txt	2011-08-24 17:13:34 +0000
@@ -100,6 +100,10 @@
   Entering an empty commit message in the message editor still triggers
   an error. (Jelmer Vernooij)
 
+* ``bzr uncommit`` will now remove tags that refer to removed revisions.
+  The ``--keep-tags`` option can be used to prevent this behaviour.
+  (Jelmer Vernooij, #605814)
+
 * Locations printed by ``bzr upgrade`` are now formatted before display.
   (Jelmer Vernooij)
 

=== modified file 'doc/en/user-guide/undoing_mistakes.txt'
--- a/doc/en/user-guide/undoing_mistakes.txt	2009-11-23 15:29:24 +0000
+++ b/doc/en/user-guide/undoing_mistakes.txt	2011-08-24 09:31:18 +0000
@@ -93,6 +93,9 @@
 one or more files. Some users like to alias ``commit`` to ``commit --strict``
 so that commits fail if unknown files are found in the tree.
 
+Tags for uncommitted revisions are removed from the branch unless
+``--keep-tags`` was specified.
+
 Note: While the ``merge`` command is not introduced until the next
 chapter, it is worth noting now that ``uncommit`` restores any pending
 merges. (Running ``bzr status`` after ``uncommit`` will show these.)




More information about the bazaar-commits mailing list