Patchwork [10,of,11,RFC] histedit: add -x/--exec flag

login
register
mail settings
Submitter Olle Lundberg
Date March 5, 2014, 4:15 p.m.
Message ID <675c70c708d124506fbb.1394036121@SE-C02KQ0DADR55>
Download mbox | patch
Permalink /patch/3861/
State Changes Requested
Headers show

Comments

Olle Lundberg - March 5, 2014, 4:15 p.m.
# HG changeset patch
# User Olle Lundberg <geek@nerd.sh>
# Date 1394020502 -3600
#      Wed Mar 05 12:55:02 2014 +0100
# Node ID 675c70c708d124506fbbc2b720763024f4b0384a
# Parent  24a57c88dacd922d9891b421d769d8ca51644d2c
histedit: add -x/--exec flag
Olle Lundberg - March 5, 2014, 10:44 p.m.
On Wed, Mar 5, 2014 at 5:15 PM, Olle Lundberg <olle.lundberg@gmail.com>wrote:

> # HG changeset patch
> # User Olle Lundberg <geek@nerd.sh>
> # Date 1394020502 -3600
> #      Wed Mar 05 12:55:02 2014 +0100
> # Node ID 675c70c708d124506fbbc2b720763024f4b0384a
> # Parent  24a57c88dacd922d9891b421d769d8ca51644d2c
> histedit: add -x/--exec flag
>
> diff --git a/hgext/histedit.py b/hgext/histedit.py
> --- a/hgext/histedit.py
> +++ b/hgext/histedit.py
> @@ -147,10 +147,11 @@
>  try:
>      import cPickle as pickle
>      pickle.dump # import now
>  except ImportError:
>      import pickle
> +import itertools
>  import os
>  import sys
>
>  from mercurial import cmdutil
>  from mercurial import discovery
> @@ -488,10 +489,13 @@
>        _("don't strip old nodes after edit is complete")),
>       ('', 'abort', False, _('abort an edit in progress')),
>       ('o', 'outgoing', False, _('changesets not found in destination')),
>       ('f', 'force', False,
>        _('force outgoing even for unrelated repositories')),
> +     ('x', 'exec', '',
> +      _('append an exec line after each commit in the list containing
> CMD'),
> +      _('CMD')),
>       ('r', 'rev', [], _('first revision to be edited'))],
>       _("ANCESTOR | --outgoing [URL]"))
>  def histedit(ui, repo, *freeargs, **opts):
>      """interactively edit changeset history
>
> @@ -533,10 +537,11 @@
>      # basic argument incompatibility processing
>      outg = opts.get('outgoing')
>      cont = opts.get('continue')
>      abort = opts.get('abort')
>      force = opts.get('force')
> +    execute_ = opts.get('exec')
>      rules = opts.get('commands', '')
>      revs = opts.get('rev', [])
>      goal = 'new' # This invocation goal, in new, continue, abort
>      if force and not outg:
>          raise util.Abort(_('--force only allowed with --outgoing'))
> @@ -546,10 +551,12 @@
>          goal = 'continue'
>      elif abort:
>          if util.any((outg, revs, freeargs, rules)):
>              raise util.Abort(_('no arguments allowed with --abort'))
>          goal = 'abort'
> +    elif execute_ and util.any((outg, cont, abort, force, rules)):
> +        raise util.Abort(_('no arguments except --rev allowed with
> --exec'))
>      else:
>          if os.path.exists(os.path.join(repo.path, 'histedit-state')):
>              raise util.Abort(_('history edit already in progress, try '
>                                 '--continue or --abort'))
>          if outg:
> @@ -607,11 +614,15 @@
>              raise util.Abort(_('%s is not an ancestor of working
> directory') %
>                               node.short(root))
>
>          ctxs = [repo[r] for r in revs]
>          if not rules:
> -            rules = '\n'.join([makedesc(c) for c in ctxs])
> +            nodes = [makedesc(c) for c in ctxs]
> +            if execute_:
> +                execline = "%s %s" % ('exec', execute_)
> +                nodes = itertools.chain(*zip(nodes,[execline] *
> len(nodes)))
> +            rules = '\n'.join(nodes)
>              rules += '\n\n'
>              rules += editcomment % (node.short(root), node.short(topmost))
>              rules = ui.edit(rules, ui.username())
>              # Save edit rules in .hg/histedit-last-edit.txt in case
>              # the user needs to ask for help after something
>


The reason behind this patch is compatibility with gits rebase x/exec and
the corresponding flags -x/--exec, for which this change was modeled after.
Olle Lundberg - March 6, 2014, 10:32 a.m.
On Wed, Mar 5, 2014 at 11:44 PM, Olle <olle.lundberg@gmail.com> wrote:

>
>
> On Wed, Mar 5, 2014 at 5:15 PM, Olle Lundberg <olle.lundberg@gmail.com>wrote:
>
>> # HG changeset patch
>> # User Olle Lundberg <geek@nerd.sh>
>> # Date 1394020502 -3600
>> #      Wed Mar 05 12:55:02 2014 +0100
>> # Node ID 675c70c708d124506fbbc2b720763024f4b0384a
>> # Parent  24a57c88dacd922d9891b421d769d8ca51644d2c
>> histedit: add -x/--exec flag
>>
>> diff --git a/hgext/histedit.py b/hgext/histedit.py
>> --- a/hgext/histedit.py
>> +++ b/hgext/histedit.py
>> @@ -147,10 +147,11 @@
>>  try:
>>      import cPickle as pickle
>>      pickle.dump # import now
>>  except ImportError:
>>      import pickle
>> +import itertools
>>  import os
>>  import sys
>>
>>  from mercurial import cmdutil
>>  from mercurial import discovery
>> @@ -488,10 +489,13 @@
>>        _("don't strip old nodes after edit is complete")),
>>       ('', 'abort', False, _('abort an edit in progress')),
>>       ('o', 'outgoing', False, _('changesets not found in destination')),
>>       ('f', 'force', False,
>>        _('force outgoing even for unrelated repositories')),
>> +     ('x', 'exec', '',
>> +      _('append an exec line after each commit in the list containing
>> CMD'),
>> +      _('CMD')),
>>       ('r', 'rev', [], _('first revision to be edited'))],
>>       _("ANCESTOR | --outgoing [URL]"))
>>  def histedit(ui, repo, *freeargs, **opts):
>>      """interactively edit changeset history
>>
>> @@ -533,10 +537,11 @@
>>      # basic argument incompatibility processing
>>      outg = opts.get('outgoing')
>>      cont = opts.get('continue')
>>      abort = opts.get('abort')
>>      force = opts.get('force')
>> +    execute_ = opts.get('exec')
>>      rules = opts.get('commands', '')
>>      revs = opts.get('rev', [])
>>      goal = 'new' # This invocation goal, in new, continue, abort
>>      if force and not outg:
>>          raise util.Abort(_('--force only allowed with --outgoing'))
>> @@ -546,10 +551,12 @@
>>          goal = 'continue'
>>      elif abort:
>>          if util.any((outg, revs, freeargs, rules)):
>>              raise util.Abort(_('no arguments allowed with --abort'))
>>          goal = 'abort'
>> +    elif execute_ and util.any((outg, cont, abort, force, rules)):
>> +        raise util.Abort(_('no arguments except --rev allowed with
>> --exec'))
>>      else:
>>          if os.path.exists(os.path.join(repo.path, 'histedit-state')):
>>              raise util.Abort(_('history edit already in progress, try '
>>                                 '--continue or --abort'))
>>          if outg:
>> @@ -607,11 +614,15 @@
>>              raise util.Abort(_('%s is not an ancestor of working
>> directory') %
>>                               node.short(root))
>>
>>          ctxs = [repo[r] for r in revs]
>>          if not rules:
>> -            rules = '\n'.join([makedesc(c) for c in ctxs])
>> +            nodes = [makedesc(c) for c in ctxs]
>> +            if execute_:
>> +                execline = "%s %s" % ('exec', execute_)
>> +                nodes = itertools.chain(*zip(nodes,[execline] *
>> len(nodes)))
>> +            rules = '\n'.join(nodes)
>>              rules += '\n\n'
>>              rules += editcomment % (node.short(root),
>> node.short(topmost))
>>              rules = ui.edit(rules, ui.username())
>>              # Save edit rules in .hg/histedit-last-edit.txt in case
>>              # the user needs to ask for help after something
>>
>
>
> The reason behind this patch is compatibility with gits rebase x/exec and
> the corresponding flags -x/--exec, for which this change was modeled after.
>

I also found this really useful when doing development and wanted to inject
a test run after each change, after restructuring my patches i ran this:
lhg histedit --exec "python run-tests.py test-check-code*
test-check-pyflakes.t test-histedit*"

Which allows me to re-run relevant part of the test suite after each change
i made.


> --
> Olle
>

Patch

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -147,10 +147,11 @@ 
 try:
     import cPickle as pickle
     pickle.dump # import now
 except ImportError:
     import pickle
+import itertools
 import os
 import sys
 
 from mercurial import cmdutil
 from mercurial import discovery
@@ -488,10 +489,13 @@ 
       _("don't strip old nodes after edit is complete")),
      ('', 'abort', False, _('abort an edit in progress')),
      ('o', 'outgoing', False, _('changesets not found in destination')),
      ('f', 'force', False,
       _('force outgoing even for unrelated repositories')),
+     ('x', 'exec', '',
+      _('append an exec line after each commit in the list containing CMD'),
+      _('CMD')),
      ('r', 'rev', [], _('first revision to be edited'))],
      _("ANCESTOR | --outgoing [URL]"))
 def histedit(ui, repo, *freeargs, **opts):
     """interactively edit changeset history
 
@@ -533,10 +537,11 @@ 
     # basic argument incompatibility processing
     outg = opts.get('outgoing')
     cont = opts.get('continue')
     abort = opts.get('abort')
     force = opts.get('force')
+    execute_ = opts.get('exec')
     rules = opts.get('commands', '')
     revs = opts.get('rev', [])
     goal = 'new' # This invocation goal, in new, continue, abort
     if force and not outg:
         raise util.Abort(_('--force only allowed with --outgoing'))
@@ -546,10 +551,12 @@ 
         goal = 'continue'
     elif abort:
         if util.any((outg, revs, freeargs, rules)):
             raise util.Abort(_('no arguments allowed with --abort'))
         goal = 'abort'
+    elif execute_ and util.any((outg, cont, abort, force, rules)):
+        raise util.Abort(_('no arguments except --rev allowed with --exec'))
     else:
         if os.path.exists(os.path.join(repo.path, 'histedit-state')):
             raise util.Abort(_('history edit already in progress, try '
                                '--continue or --abort'))
         if outg:
@@ -607,11 +614,15 @@ 
             raise util.Abort(_('%s is not an ancestor of working directory') %
                              node.short(root))
 
         ctxs = [repo[r] for r in revs]
         if not rules:
-            rules = '\n'.join([makedesc(c) for c in ctxs])
+            nodes = [makedesc(c) for c in ctxs]
+            if execute_:
+                execline = "%s %s" % ('exec', execute_)
+                nodes = itertools.chain(*zip(nodes,[execline] * len(nodes)))
+            rules = '\n'.join(nodes)
             rules += '\n\n'
             rules += editcomment % (node.short(root), node.short(topmost))
             rules = ui.edit(rules, ui.username())
             # Save edit rules in .hg/histedit-last-edit.txt in case
             # the user needs to ask for help after something