hgext3rd: move 'drophack' as 'evolve.hack.drophack'
Yet another extension migrating. Ideally we would implement stripping
obsolescence marker in code soon and be able to dispose of this extensions
directly. In the mean time this goes into the "hack" namespace.
--- a/MANIFEST.in Tue Nov 01 16:07:28 2016 +0100
+++ b/MANIFEST.in Tue Nov 01 16:11:50 2016 +0100
@@ -1,5 +1,4 @@
exclude contrib/nopushpublish.py
-exclude hgext/drophack.py
exclude hgext/obsolete.py
exclude hgext3rd/evolve/hack/*.py
exclude Makefile
--- a/hgext/drophack.py Tue Nov 01 16:07:28 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2 or any later version.
-'''This extension add a hacky command to drop changeset during review
-
-This extension is intended as a temporary hack to allow Matt Mackall to use
-evolve in the Mercurial review it self. You should probably not use it if your
-name is not Matt Mackall.
-'''
-
-import os
-import time
-import contextlib
-
-from mercurial.i18n import _
-from mercurial import cmdutil
-from mercurial import repair
-from mercurial import scmutil
-from mercurial import lock as lockmod
-from mercurial import util
-from mercurial import commands
-
-cmdtable = {}
-command = cmdutil.command(cmdtable)
-
-
-@contextlib.contextmanager
-def timed(ui, caption):
- ostart = os.times()
- cstart = time.time()
- yield
- cstop = time.time()
- ostop = os.times()
- wall = cstop - cstart
- user = ostop[0] - ostart[0]
- sys = ostop[1] - ostart[1]
- comb = user + sys
- ui.write("%s: wall %f comb %f user %f sys %f\n"
- % (caption, wall, comb, user, sys))
-
-def obsmarkerchainfrom(obsstore, nodes):
- """return all marker chain starting from node
-
- Starting from mean "use as successors"."""
- # XXX need something smarter for descendant of bumped changeset
- seennodes = set(nodes)
- seenmarkers = set()
- pendingnodes = set(nodes)
- precursorsmarkers = obsstore.precursors
- while pendingnodes:
- current = pendingnodes.pop()
- new = set()
- for precmark in precursorsmarkers.get(current, ()):
- if precmark in seenmarkers:
- continue
- seenmarkers.add(precmark)
- new.add(precmark[0])
- yield precmark
- new -= seennodes
- pendingnodes |= new
-
-def stripmarker(ui, repo, markers):
- """remove <markers> from the repo obsstore
-
- The old obsstore content is saved in a `obsstore.prestrip` file
- """
- repo = repo.unfiltered()
- repo.destroying()
- oldmarkers = list(repo.obsstore._all)
- util.rename(repo.sjoin('obsstore'),
- repo.join('obsstore.prestrip'))
- del repo.obsstore # drop the cache
- newstore = repo.obsstore
- assert not newstore # should be empty after rename
- newmarkers = [m for m in oldmarkers if m not in markers]
- tr = repo.transaction('drophack')
- try:
- newstore.add(tr, newmarkers)
- tr.close()
- finally:
- tr.release()
- repo.destroyed()
-
-
-@command('drop', [('r', 'rev', [], 'revision to update')], _('[-r] revs'))
-def cmddrop(ui, repo, *revs, **opts):
- """I'm hacky do not use me!
-
- This command strip a changeset, its precursors and all obsolescence marker
- associated to its chain.
-
- There is no way to limit the extend of the purge yet. You may have to
- repull from other source to get some changeset and obsolescence marker
- back.
-
- This intended for Matt Mackall usage only. do not use me.
- """
- revs = list(revs)
- revs.extend(opts['rev'])
- if not revs:
- revs = ['.']
- # get the changeset
- revs = scmutil.revrange(repo, revs)
- if not revs:
- ui.write_err('no revision to drop\n')
- return 1
- # lock from the beginning to prevent race
- wlock = lock = None
- try:
- wlock = repo.wlock()
- lock = repo.lock()
- # check they have no children
- if repo.revs('%ld and public()', revs):
- ui.write_err('cannot drop public revision')
- return 1
- if repo.revs('children(%ld) - %ld', revs, revs):
- ui.write_err('cannot drop revision with children')
- return 1
- if repo.revs('. and %ld', revs):
- newrevs = repo.revs('max(::. - %ld)', revs)
- if newrevs:
- assert len(newrevs) == 1
- newrev = newrevs.first()
- else:
- newrev = -1
- commands.update(ui, repo, newrev)
- ui.status(_('working directory now at %s\n') % repo[newrev])
- # get all markers and successors up to root
- nodes = [repo[r].node() for r in revs]
- with timed(ui, 'search obsmarker'):
- markers = set(obsmarkerchainfrom(repo.obsstore, nodes))
- ui.write('%i obsmarkers found\n' % len(markers))
- cl = repo.unfiltered().changelog
- with timed(ui, 'search nodes'):
- allnodes = set(nodes)
- allnodes.update(m[0] for m in markers if cl.hasnode(m[0]))
- ui.write('%i nodes found\n' % len(allnodes))
- cl = repo.changelog
- visiblenodes = set(n for n in allnodes if cl.hasnode(n))
- # check constraint again
- if repo.revs('%ln and public()', visiblenodes):
- ui.write_err('cannot drop public revision')
- return 1
- if repo.revs('children(%ln) - %ln', visiblenodes, visiblenodes):
- ui.write_err('cannot drop revision with children')
- return 1
-
- if markers:
- # strip them
- with timed(ui, 'strip obsmarker'):
- stripmarker(ui, repo, markers)
- # strip the changeset
- with timed(ui, 'strip nodes'):
- repair.strip(ui, repo, list(allnodes), backup="all",
- topic='drophack')
-
- finally:
- lockmod.release(lock, wlock)
-
- # rewrite the whole file.
- # print data.
- # - time to compute the chain
- # - time to strip the changeset
- # - time to strip the obs marker.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext3rd/evolve/hack/drophack.py Tue Nov 01 16:11:50 2016 +0100
@@ -0,0 +1,163 @@
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+'''This extension add a hacky command to drop changeset during review
+
+This extension is intended as a temporary hack to allow Matt Mackall to use
+evolve in the Mercurial review it self. You should probably not use it if your
+name is not Matt Mackall.
+'''
+
+import os
+import time
+import contextlib
+
+from mercurial.i18n import _
+from mercurial import cmdutil
+from mercurial import repair
+from mercurial import scmutil
+from mercurial import lock as lockmod
+from mercurial import util
+from mercurial import commands
+
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+
+
+@contextlib.contextmanager
+def timed(ui, caption):
+ ostart = os.times()
+ cstart = time.time()
+ yield
+ cstop = time.time()
+ ostop = os.times()
+ wall = cstop - cstart
+ user = ostop[0] - ostart[0]
+ sys = ostop[1] - ostart[1]
+ comb = user + sys
+ ui.write("%s: wall %f comb %f user %f sys %f\n"
+ % (caption, wall, comb, user, sys))
+
+def obsmarkerchainfrom(obsstore, nodes):
+ """return all marker chain starting from node
+
+ Starting from mean "use as successors"."""
+ # XXX need something smarter for descendant of bumped changeset
+ seennodes = set(nodes)
+ seenmarkers = set()
+ pendingnodes = set(nodes)
+ precursorsmarkers = obsstore.precursors
+ while pendingnodes:
+ current = pendingnodes.pop()
+ new = set()
+ for precmark in precursorsmarkers.get(current, ()):
+ if precmark in seenmarkers:
+ continue
+ seenmarkers.add(precmark)
+ new.add(precmark[0])
+ yield precmark
+ new -= seennodes
+ pendingnodes |= new
+
+def stripmarker(ui, repo, markers):
+ """remove <markers> from the repo obsstore
+
+ The old obsstore content is saved in a `obsstore.prestrip` file
+ """
+ repo = repo.unfiltered()
+ repo.destroying()
+ oldmarkers = list(repo.obsstore._all)
+ util.rename(repo.sjoin('obsstore'),
+ repo.join('obsstore.prestrip'))
+ del repo.obsstore # drop the cache
+ newstore = repo.obsstore
+ assert not newstore # should be empty after rename
+ newmarkers = [m for m in oldmarkers if m not in markers]
+ tr = repo.transaction('drophack')
+ try:
+ newstore.add(tr, newmarkers)
+ tr.close()
+ finally:
+ tr.release()
+ repo.destroyed()
+
+
+@command('drop', [('r', 'rev', [], 'revision to update')], _('[-r] revs'))
+def cmddrop(ui, repo, *revs, **opts):
+ """I'm hacky do not use me!
+
+ This command strip a changeset, its precursors and all obsolescence marker
+ associated to its chain.
+
+ There is no way to limit the extend of the purge yet. You may have to
+ repull from other source to get some changeset and obsolescence marker
+ back.
+
+ This intended for Matt Mackall usage only. do not use me.
+ """
+ revs = list(revs)
+ revs.extend(opts['rev'])
+ if not revs:
+ revs = ['.']
+ # get the changeset
+ revs = scmutil.revrange(repo, revs)
+ if not revs:
+ ui.write_err('no revision to drop\n')
+ return 1
+ # lock from the beginning to prevent race
+ wlock = lock = None
+ try:
+ wlock = repo.wlock()
+ lock = repo.lock()
+ # check they have no children
+ if repo.revs('%ld and public()', revs):
+ ui.write_err('cannot drop public revision')
+ return 1
+ if repo.revs('children(%ld) - %ld', revs, revs):
+ ui.write_err('cannot drop revision with children')
+ return 1
+ if repo.revs('. and %ld', revs):
+ newrevs = repo.revs('max(::. - %ld)', revs)
+ if newrevs:
+ assert len(newrevs) == 1
+ newrev = newrevs.first()
+ else:
+ newrev = -1
+ commands.update(ui, repo, newrev)
+ ui.status(_('working directory now at %s\n') % repo[newrev])
+ # get all markers and successors up to root
+ nodes = [repo[r].node() for r in revs]
+ with timed(ui, 'search obsmarker'):
+ markers = set(obsmarkerchainfrom(repo.obsstore, nodes))
+ ui.write('%i obsmarkers found\n' % len(markers))
+ cl = repo.unfiltered().changelog
+ with timed(ui, 'search nodes'):
+ allnodes = set(nodes)
+ allnodes.update(m[0] for m in markers if cl.hasnode(m[0]))
+ ui.write('%i nodes found\n' % len(allnodes))
+ cl = repo.changelog
+ visiblenodes = set(n for n in allnodes if cl.hasnode(n))
+ # check constraint again
+ if repo.revs('%ln and public()', visiblenodes):
+ ui.write_err('cannot drop public revision')
+ return 1
+ if repo.revs('children(%ln) - %ln', visiblenodes, visiblenodes):
+ ui.write_err('cannot drop revision with children')
+ return 1
+
+ if markers:
+ # strip them
+ with timed(ui, 'strip obsmarker'):
+ stripmarker(ui, repo, markers)
+ # strip the changeset
+ with timed(ui, 'strip nodes'):
+ repair.strip(ui, repo, list(allnodes), backup="all",
+ topic='drophack')
+
+ finally:
+ lockmod.release(lock, wlock)
+
+ # rewrite the whole file.
+ # print data.
+ # - time to compute the chain
+ # - time to strip the changeset
+ # - time to strip the obs marker.
--- a/tests/test-drop.t Tue Nov 01 16:07:28 2016 +0100
+++ b/tests/test-drop.t Tue Nov 01 16:11:50 2016 +0100
@@ -3,7 +3,7 @@
> [extensions]
> hgext.graphlog=
> EOF
- $ echo "drophack=$(echo $(dirname $TESTDIR))/hgext/drophack.py" >> $HGRCPATH
+ $ echo "drophack=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/drophack.py" >> $HGRCPATH
$ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
$ mkcommit() {
> echo "$1" > "$1"