diff hgext/evolve.py @ 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
line wrap: on
line diff
--- 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)