--- a/hgext/record.py Fri Mar 30 14:35:06 2012 -0500
+++ b/hgext/record.py Fri Mar 30 22:08:46 2012 +0100
@@ -261,7 +261,7 @@
def filterpatch(ui, headers):
"""Interactively filter patch chunks into applied-only chunks"""
- def prompt(skipfile, skipall, query):
+ def prompt(skipfile, skipall, query, chunk):
"""prompt query, and process base inputs
- y/n for the rest of file
@@ -271,14 +271,16 @@
Return True/False and possibly updated skipfile and skipall.
"""
+ newpatches = None
if skipall is not None:
- return skipall, skipfile, skipall
+ return skipall, skipfile, skipall, newpatches
if skipfile is not None:
- return skipfile, skipfile, skipall
+ return skipfile, skipfile, skipall, newpatches
while True:
- resps = _('[Ynsfdaq?]')
+ resps = _('[Ynesfdaq?]')
choices = (_('&Yes, record this change'),
_('&No, skip this change'),
+ _('&Edit the change manually'),
_('&Skip remaining changes to this file'),
_('Record remaining changes to this &file'),
_('&Done, skip remaining changes and files'),
@@ -287,7 +289,7 @@
_('&?'))
r = ui.promptchoice("%s %s" % (query, resps), choices)
ui.write("\n")
- if r == 7: # ?
+ if r == 8: # ?
doc = gettext(record.__doc__)
c = doc.find('::') + 2
for l in doc[c:].splitlines():
@@ -298,17 +300,69 @@
ret = True
elif r == 1: # no
ret = False
- elif r == 2: # Skip
+ elif r == 2: # Edit patch
+ if chunk is None:
+ ui.write(_('cannot edit patch for whole file'))
+ ui.write("\n")
+ continue
+ if chunk.header.binary():
+ ui.write(_('cannot edit patch for binary file'))
+ ui.write("\n")
+ continue
+ # Patch comment based on the Git one (based on comment at end of
+ # http://mercurial.selenic.com/wiki/RecordExtension)
+ phelp = '---' + _("""
+To remove '-' lines, make them ' ' lines (context).
+To remove '+' lines, delete them.
+Lines starting with # will be removed from the patch.
+
+If the patch applies cleanly, the edited hunk will immediately be
+added to the record list. If it does not apply cleanly, a rejects
+file will be generated: you can use that when you try again. If
+all lines of the hunk are removed, then the edit is aborted and
+the hunk is left unchanged.
+""")
+ (patchfd, patchfn) = tempfile.mkstemp(prefix="hg-editor-",
+ suffix=".diff", text=True)
+ try:
+ # Write the initial patch
+ f = os.fdopen(patchfd, "w")
+ chunk.header.write(f)
+ chunk.write(f)
+ f.write('\n'.join(['# ' + i for i in phelp.splitlines()]))
+ f.close()
+ # Start the editor and wait for it to complete
+ editor = ui.geteditor()
+ util.system("%s \"%s\"" % (editor, patchfn),
+ environ={'HGUSER': ui.username()},
+ onerr=util.Abort, errprefix=_("edit failed"),
+ out=ui.fout)
+ # Remove comment lines
+ patchfp = open(patchfn)
+ ncpatchfp = cStringIO.StringIO()
+ for line in patchfp:
+ if not line.startswith('#'):
+ ncpatchfp.write(line)
+ patchfp.close()
+ ncpatchfp.seek(0)
+ newpatches = parsepatch(ncpatchfp)
+ finally:
+ os.unlink(patchfn)
+ del ncpatchfp
+ # Signal that the chunk shouldn't be applied as-is, but
+ # provide the new patch to be used instead.
+ ret = False
+ elif r == 3: # Skip
ret = skipfile = False
- elif r == 3: # file (Record remaining)
+ elif r == 4: # file (Record remaining)
ret = skipfile = True
- elif r == 4: # done, skip remaining
+ elif r == 5: # done, skip remaining
ret = skipall = False
- elif r == 5: # all
+ elif r == 6: # all
ret = skipall = True
- elif r == 6: # quit
+ elif r == 7: # quit
raise util.Abort(_('user quit'))
- return ret, skipfile, skipall
+ return ret, skipfile, skipall, newpatches
seen = set()
applied = {} # 'filename' -> [] of chunks
@@ -326,7 +380,7 @@
h.pretty(ui)
msg = (_('examine changes to %s?') %
_(' and ').join(map(repr, h.files())))
- r, skipfile, skipall = prompt(skipfile, skipall, msg)
+ r, skipfile, skipall, np = prompt(skipfile, skipall, msg, None)
if not r:
continue
applied[h.filename()] = [h]
@@ -342,12 +396,19 @@
idx = pos - len(h.hunks) + i
msg = _('record change %d/%d to %r?') % (idx, total,
chunk.filename())
- r, skipfile, skipall = prompt(skipfile, skipall, msg)
+ r, skipfile, skipall, newpatches = prompt(skipfile,
+ skipall, msg, chunk)
if r:
if fixoffset:
chunk = copy.copy(chunk)
chunk.toline += fixoffset
applied[chunk.filename()].append(chunk)
+ elif newpatches is not None:
+ for newpatch in newpatches:
+ for newhunk in newpatch.hunks:
+ if fixoffset:
+ newhunk.toline += fixoffset
+ applied[newhunk.filename()].append(newhunk)
else:
fixoffset += chunk.removed - chunk.added
return sum([h for h in applied.itervalues()
@@ -372,6 +433,7 @@
y - record this change
n - skip this change
+ e - edit this change manually
s - skip remaining changes to this file
f - record remaining changes to this file