[PATCH] mq: Add mechanism for setting patch header contents

Peter Williams pwil3058 at bigpond.net.au
Mon Aug 24 18:53:45 CDT 2009


# HG changeset patch
# User Peter Williams <pwil3058 at bigpond.net.au>
# Date 1251157881 -36000
# Node ID 9576c70b3b56b305c6ece781190c95947fc7c427
# Parent  37042e8b3b342b2e380d8be3e3f7692584c92d33
mq: Add mechanism for setting patch header contents

Modify 'qheader' by adding options rather than creating a new command.
Make sure that users will not be surprised by changes to 'qheader'.
Modification may be made to both applied and unapplied patches but
the '-f/--force' option is required for changes to applied patch
headers.
If the patch is applied, the change is not propagated into the change
set representing the patch but the user is warned that a refresh is
required for the propagation to occur.

diff -r 37042e8b3b34 -r 9576c70b3b56 hgext/mq.py
--- a/hgext/mq.py	Mon Jun 29 01:33:26 2009 +0900
+++ b/hgext/mq.py	Tue Aug 25 09:51:21 2009 +1000
@@ -2084,8 +2084,38 @@ def guard(ui, repo, *args, **opts):
     else:
         status(q.series.index(q.lookup(patch)))
 
-def header(ui, repo, patch=None):
-    """print the header of the topmost or specified patch"""
+def header(ui, repo, patch=None, **opts):
+    """print or modify the header of the specified (or topmost) patch
+
+    When run without options, the header of the patch is printed.
+
+    -e/--edit, -m/--message or -l/--logfile set the patch header. This
+    will become the commit message the next time the patch is refreshed
+    or pushed.
+
+    -u/--user and -d/--date can be used to set the (specified) user and
+    date, respectively. -U/--currentuser and -D/--currentdate set user
+    to current user and date to current date.
+
+    Modifications to the headers of applied patches will be refused
+    unless -f/--force is specified.
+    """
+    def get_patch_diff(patch):
+        patchf = q.opener(patch, 'r')
+
+        lines = patchf.readlines()
+        patchf.close()
+
+        bd = 0
+        while bd < len(lines):
+            if lines[bd].startswith('diff --git'):
+                break
+            elif lines[bd].startswith('--- '):
+                if bd + 1 < len(lines) and lines[bd + 1].startswith('+++ '):
+                    break
+            bd += 1
+        return ''.join(lines[bd:])
+
     q = repo.mq
 
     if patch:
@@ -2095,6 +2125,55 @@ def header(ui, repo, patch=None):
             ui.write('no patches applied\n')
             return 1
         patch = q.lookup('qtip')
+
+    if [val for val in opts.values() if val]: # any options supplied?
+        if q.isapplied(patch) and not opts.get('force'):
+            raise util.Abort(_('%s is applied (use -f to force)') % patch)
+        setupheaderopts(ui, opts)
+        newuser = opts.get('user')
+        newdate = opts.get('date')
+        if newdate:
+            newdate = '%d %d' % util.parsedate(newdate)
+        if opts.get('edit'):
+            if opts.get('message') or opts.get('logfile'):
+                raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
+            msg = '\n'.join(patchheader(q.join(patch)).message)
+            msg = ui.edit(msg, ui.username())
+        else:
+            msg = cmdutil.logmessage(opts)
+        wlock = repo.wlock()
+        try:
+            ph = patchheader(q.join(patch))
+            if msg:
+                ph.setmessage(msg)
+            if newuser:
+                ph.setuser(newuser)
+            if newdate:
+                ph.setdate(newdate)
+            comments = str(ph)
+
+            pdiff = get_patch_diff(patch)
+
+            patchf = q.opener(patch, 'w', atomictemp=True)
+            patchf.seek(0)
+            patchf.truncate()
+
+            if comments:
+                patchf.write(comments)
+            if pdiff:
+                patchf.write(pdiff)
+
+            patchf.rename()
+            patchf.close()
+
+            if q.isapplied(patch):
+                ui.warn(_('%s requires refresh to update commit message\n') % patch)
+        except:
+            raise util.Abort(_('write "%s" header failed') % patch)
+        finally:
+            wlock.release()
+        return
+
     ph = patchheader(repo.mq.join(patch))
 
     ui.write('\n'.join(ph.message) + '\n')
@@ -2520,6 +2599,11 @@ def uisetup(ui):
     extensions.wrapcommand(commands.table, 'import', mqimport)
 
 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
+userdateopts = \
+    [('U', 'currentuser', None, _('add "From: <current user>" to patch')),
+     ('u', 'user', '', _('add "From: <given user>" to patch')),
+     ('D', 'currentdate', None, _('add "Date: <current date>" to patch')),
+     ('d', 'date', '', _('add "Date: <given date>" to patch'))]
 
 cmdtable = {
     "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')),
@@ -2560,7 +2644,12 @@ cmdtable = {
          [('l', 'list', None, _('list all patches and guards')),
           ('n', 'none', None, _('drop all guards'))],
          _('hg qguard [-l] [-n] -- [PATCH] [+GUARD]... [-GUARD]...')),
-    'qheader': (header, [], _('hg qheader [PATCH]')),
+    'qheader':
+        (header,
+         [('e', 'edit', None, _('edit commit message')),
+          ('f', 'force', None, _('modify applied patch header')),
+         ] + userdateopts + commands.commitopts,
+         _('hg qheader [[-e] | [-m TEXT] | [-l FILE]] [PATCH]')),
     "^qimport":
         (qimport,
          [('e', 'existing', None, _('import file in patch directory')),
@@ -2579,11 +2668,7 @@ cmdtable = {
          [('e', 'edit', None, _('edit commit message')),
           ('f', 'force', None, _('import uncommitted changes into patch')),
           ('g', 'git', None, _('use git extended diff format')),
-          ('U', 'currentuser', None, _('add "From: <current user>" to patch')),
-          ('u', 'user', '', _('add "From: <given user>" to patch')),
-          ('D', 'currentdate', None, _('add "Date: <current date>" to patch')),
-          ('d', 'date', '', _('add "Date: <given date>" to patch'))
-          ] + commands.walkopts + commands.commitopts,
+          ] + userdateopts + commands.walkopts + commands.commitopts,
          _('hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...')),
     "qnext": (next, [] + seriesopts, _('hg qnext [-s]')),
     "qprev": (prev, [] + seriesopts, _('hg qprev [-s]')),


More information about the Mercurial-devel mailing list