changeset 715:070bbbb0e6f2 stable

prune: add strip-like bookmark This prune changesets pointed by the specified bookmark only (and removes the bookmarks)
author Levi Bard <levi@unity3d.com>
date Mon, 11 Feb 2013 09:21:11 +0000
parents 3867f7b1fe6e
children 4c0f6d555032
files README hgext/evolve.py tests/test-prune.t
diffstat 3 files changed, 89 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/README	Sun Feb 10 16:17:01 2013 +0100
+++ b/README	Mon Feb 11 09:21:11 2013 +0000
@@ -46,12 +46,13 @@
 
 3.1.0 --
 
-- prune: various minor improvements
 - amend: drop deprecated --change option for amend
 - alias: add a grab aliast to be used instead of graft -O
 - touch: add a --duplicate option to *not* obsolete the old version
 - touch: fix touching multiple revision at the same time
 - evolve: add a --all option
+- prune: various minor improvements
+- prune: add option to prune a specific bookmark
 
 3.0.0 -- 2013-02-02
 
--- a/hgext/evolve.py	Sun Feb 10 16:17:01 2013 +0100
+++ b/hgext/evolve.py	Mon Feb 11 09:21:11 2013 +0000
@@ -1242,10 +1242,42 @@
         ui.warn(_('Multiple non-obsolete children, explicitly update to one\n'))
         return 1
 
+def _reachablefrombookmark(repo, revs, mark):
+    """filter revisions and bookmarks reachable from the given bookmark
+    yoinked from mq.py
+    """
+    marks = repo._bookmarks
+    if mark not in marks:
+        raise util.Abort(_("bookmark '%s' not found") % mark)
+
+    # If the requested bookmark is not the only one pointing to a
+    # a revision we have to only delete the bookmark and not strip
+    # anything. revsets cannot detect that case.
+    uniquebm = True
+    for m, n in marks.iteritems():
+        if m != mark and n == repo[mark].node():
+            uniquebm = False
+            break
+    if uniquebm:
+        rsrevs = repo.revs("ancestors(bookmark(%s)) - "
+                           "ancestors(head() and not bookmark(%s)) - "
+                           "ancestors(bookmark() and not bookmark(%s)) - "
+                           "obsolete()",
+                           mark, mark, mark)
+        revs.update(set(rsrevs))
+    return marks,revs
+
+def _deletebookmark(ui, marks, mark):
+    del marks[mark]
+    marks.write()
+    ui.write(_("bookmark '%s' deleted\n") % mark)
+
 @command('^prune|obsolete|kill',
     [('n', 'new', [], _("successor changeset (DEPRECATED)")),
      ('s', 'succ', [], _("successor changeset")),
-     ('r', 'rev', [], _("revisions to prune"))],
+     ('r', 'rev', [], _("revisions to prune")),
+     ('B', 'bookmark', '', _("remove revs only reachable from given"
+                             " bookmark"))],
     _('[OPTION] [-r] REV...'))
     # -d --date
     # -u --user
@@ -1263,12 +1295,20 @@
 
     you can use the ``--succ`` option to informs mercurial that a newer version
     of the pruned changeset exists.
+    """
+    revs = set(scmutil.revrange(repo, list(revs) + opts.get('rev')))
+    succs = opts['new'] + opts['succ']
+    bookmark = opts.get('bookmark')
 
-    XXX this commands needs bookmarks support.
-    """
-    revs = list(revs)
-    revs.extend(opts['rev'])
-    succs = opts['new'] + opts['succ']
+    if bookmark:
+        marks,revs = _reachablefrombookmark(repo, revs, bookmark)
+        if not revs:
+            # no revisions to prune - delete bookmark immediately
+            _deletebookmark(ui, marks, bookmark)
+
+    if not revs:
+        raise util.Abort(_('nothing to prune'))
+
     wlock = lock = None
     wlock = repo.wlock()
     sortedrevs = lambda specs: sorted(set(scmutil.revrange(repo, specs)))
@@ -1303,16 +1343,15 @@
         if newnode.node() != wdp.node():
             commands.update(ui, repo, newnode.rev())
             ui.status(_('working directory now at %s\n') % newnode)
-        # upVdate bookmarks
+        # update bookmarks
+        if bookmark:
+            _deletebookmark(ui, marks, bookmark)
         for ctx in repo.unfiltered().set('bookmark() and %ld', precs):
             ldest = list(repo.set('max((::%d) - obsolete())', ctx))
             if ldest:
                 dest = ldest[0]
                 updatebookmarks = _bookmarksupdater(repo, ctx.node())
                 updatebookmarks(dest.node())
-            else:
-                # delete bookmarks
-                pass
     finally:
         lockmod.release(lock, wlock)
 
--- a/tests/test-prune.t	Sun Feb 10 16:17:01 2013 +0100
+++ b/tests/test-prune.t	Mon Feb 11 09:21:11 2013 +0000
@@ -194,3 +194,41 @@
   00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 {'date': '**', 'user': 'test'} (glob)
   814c38b95e72dfe2cbf675b1649ea9d780c89a80 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 {'date': '*', 'user': 'test'} (glob)
   354011cd103f58bbbd9091a3cee6d6a6bd0dddf7 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 {'date': '*', 'user': 'test'} (glob)
+
+test hg prune -B bookmark
+yoinked from test-mq-strip.t
+
+  $ cd ..
+  $ hg init bookmarks
+  $ cd bookmarks
+  $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b'
+  $ hg bookmark -r 'a' 'todelete'
+  $ hg bookmark -r 'b' 'B'
+  $ hg bookmark -r 'b' 'nostrip'
+  $ hg bookmark -r 'c' 'delete'
+  $ hg up -C todelete
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg prune -B nostrip
+  bookmark 'nostrip' deleted
+  abort: nothing to prune
+  [255]
+  $ hg prune -B todelete
+  1 changesets pruned
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  working directory now at d62d843c9a01
+  bookmark 'todelete' deleted
+  $ hg id -ir dcbb326fdec2
+  abort: 00changelog.i@dcbb326fdec2*: no node! (glob)
+  [255]
+  $ hg id -ir d62d843c9a01
+  d62d843c9a01
+  $ hg bookmarks
+     B                         10:ff43616e5d0f
+     delete                    6:2702dd0c91e7
+  $ hg prune -B delete
+  3 changesets pruned
+  bookmark 'delete' deleted
+  $ hg id -ir 6:2702dd0c91e7
+  abort: 00changelog.i@2702dd0c91e7*: no node! (glob)
+  [255]
+