[PATCH] mq: add --setuser and --user options to qnew and qrefresh

Peter Arrenbrecht peter.arrenbrecht at gmail.com
Thu Dec 13 15:56:38 CST 2007


# HG changeset patch
# User peter.arrenbrecht at gmail.com
# Date 1197582765 -3600
# Node ID c6892532ed83816be689469794c5409cfdd9f280
# Parent  812dbb08d59a6ccfdb873bb50f752c4e0272c518
mq: add --setuser and --user options to qnew and qrefresh

These options make qnew and qrefresh add/update the "From:" header (or, if present,
the "# User" header). This allows proper attribution of patches in patch queues
with multiple contributors.

diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -603,6 +603,7 @@ class queue:
     def new(self, repo, patch, *pats, **opts):
         msg = opts.get('msg')
         force = opts.get('force')
+        user = opts.get('user')
         if os.path.exists(self.join(patch)):
             raise util.Abort(_('patch "%s" already exists') % patch)
         if opts.get('include') or opts.get('exclude') or pats:
@@ -617,7 +618,7 @@ class queue:
         try:
             insert = self.full_series_end()
             commitmsg = msg and msg or ("[mq]: %s" % patch)
-            n = repo.commit(commitfiles, commitmsg, match=match, force=True)
+            n = repo.commit(commitfiles, commitmsg, user, match=match, force=True)
             if n == None:
                 raise util.Abort(_("repo commit failed"))
             self.full_series[insert:insert] = [patch]
@@ -626,6 +627,8 @@ class queue:
             self.series_dirty = 1
             self.applied_dirty = 1
             p = self.opener(patch, "w")
+            if user:
+                p.write("From: " + user + "\n\n")
             if msg:
                 msg = msg + "\n"
                 p.write(msg)
@@ -945,6 +948,22 @@ class queue:
                     while message[mi] != comments[ci]:
                         ci += 1
                     del comments[ci]
+
+            newuser = opts.get('user')
+            if newuser:
+                # Update all references to a user in the patch header.
+                # If none found, add "From: " header.
+                needfrom = True
+                for prefix in ['# User ', 'From: ']:
+                    for i in xrange(len(comments)):
+                        if comments[i].startswith(prefix):
+                            comments[i] = prefix + newuser
+                            needfrom = False
+                            break
+                if needfrom:
+                    comments = ['From: ' + newuser, ''] + comments
+                user = newuser
+
             if msg:
                 comments.append(msg)
 
@@ -1070,9 +1089,12 @@ class queue:
                 else:
                     message = msg
 
+                if not user:
+                    user = changes[1]
+
                 self.strip(repo, top, update=False,
                            backup='strip')
-                n = repo.commit(filelist, message, changes[1], match=matchfn,
+                n = repo.commit(filelist, message, user, match=matchfn,
                                 force=1)
                 self.applied[-1] = statusentry(revlog.hex(n), patchfn)
                 self.applied_dirty = 1
@@ -1605,6 +1627,12 @@ def prev(ui, repo, **opts):
     return q.qseries(repo, start=l-2, length=1, status='A',
                      summary=opts.get('summary'))
 
+def setupheaderopts(ui, opts):
+    def do(opt,val):
+        if not opts[opt] and opts['set' + opt]:
+            opts[opt] = val
+    do('user', ui.username())
+
 def new(ui, repo, patch, *args, **opts):
     """create a new patch
 
@@ -1623,6 +1651,7 @@ def new(ui, repo, patch, *args, **opts):
     if opts['edit']:
         message = ui.edit(message, ui.username())
     opts['msg'] = message
+    setupheaderopts(ui, opts)
     q.new(repo, patch, *args, **opts)
     q.save_dirty()
     return 0
@@ -1648,6 +1677,7 @@ def refresh(ui, repo, *pats, **opts):
         patch = q.applied[-1].name
         (message, comment, user, date, hasdiff) = q.readheaders(patch)
         message = ui.edit('\n'.join(message), user or ui.username())
+    setupheaderopts(ui, opts)
     ret = q.refresh(repo, pats, msg=message, **opts)
     q.save_dirty()
     return ret
@@ -2138,6 +2168,10 @@ def reposetup(ui, repo):
 
 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
 
+headeropts = [
+    ('U', 'setuser', None, _('add "From: <current user>" to patch')),
+    ('u', 'user', '', _('add "From: <given user>" to patch'))]
+
 cmdtable = {
     "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')),
     "qclone":
@@ -2196,7 +2230,7 @@ cmdtable = {
          [('e', 'edit', None, _('edit commit message')),
           ('f', 'force', None, _('import uncommitted changes into patch')),
           ('g', 'git', None, _('use git extended diff format')),
-          ] + commands.walkopts + commands.commitopts,
+          ] + commands.walkopts + commands.commitopts + headeropts,
          _('hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...')),
     "qnext": (next, [] + seriesopts, _('hg qnext [-s]')),
     "qprev": (prev, [] + seriesopts, _('hg qprev [-s]')),
@@ -2219,7 +2253,7 @@ cmdtable = {
          [('e', 'edit', None, _('edit commit message')),
           ('g', 'git', None, _('use git extended diff format')),
           ('s', 'short', None, _('refresh only files already in the patch')),
-          ] + commands.walkopts + commands.commitopts,
+          ] + commands.walkopts + commands.commitopts + headeropts,
          _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')),
     'qrename|qmv':
         (rename, [], _('hg qrename PATCH1 [PATCH2]')),
diff --git a/tests/test-mq-header-from b/tests/test-mq-header-from
new file mode 100755
--- /dev/null
+++ b/tests/test-mq-header-from
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
+echo "[diff]" >> $HGRCPATH
+echo "nodates=true" >> $HGRCPATH
+
+echo ==== init
+hg init a
+cd a
+hg qinit
+
+
+echo ==== qnew -U
+hg qnew -U 1.patch
+cat .hg/patches/1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qref
+echo "1" >1
+hg add
+hg qref
+cat .hg/patches/1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qref -u
+hg qref -u mary
+cat .hg/patches/1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qnew
+hg qnew 2.patch
+echo "2" >2
+hg add
+hg qref
+cat .hg/patches/2.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qref -u
+hg qref -u jane
+cat .hg/patches/2.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+
+echo ==== qnew -U -m
+hg qnew -U -m "Three" 3.patch
+cat .hg/patches/3.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qref
+echo "3" >3
+hg add
+hg qref
+cat .hg/patches/3.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qref -m
+hg qref -m "Drei"
+cat .hg/patches/3.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qref -u
+hg qref -u mary
+cat .hg/patches/3.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qref -u -m
+hg qref -u maria -m "Three (again)"
+cat .hg/patches/3.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qnew -m
+hg qnew -m "Four" 4.patch
+echo "4" >4
+hg add
+hg qref
+cat .hg/patches/4.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== qref -u
+hg qref -u jane
+cat .hg/patches/4.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+
+echo ==== qnew with HG header
+hg qnew 5.patch
+hg qpop
+echo "# HG changeset patch" >>.hg/patches/5.patch
+echo "# User johndoe" >>.hg/patches/5.patch
+hg qpush
+cat .hg/patches/5.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== hg qref
+echo "5" >5
+hg add
+hg qref
+cat .hg/patches/5.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== hg qref -U
+hg qref -U
+cat .hg/patches/5.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+echo ==== hg qref -u
+hg qref -u johndeere
+cat .hg/patches/5.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /"
+hg log --template "{rev}: {desc} - {author}\n"
+
+
+echo ==== "qpop -a / qpush -a"
+hg qpop -a
+hg qpush -a
+hg log --template "{rev}: {desc} - {author}\n"
diff --git a/tests/test-mq-header-from.out b/tests/test-mq-header-from.out
new file mode 100644
--- /dev/null
+++ b/tests/test-mq-header-from.out
@@ -0,0 +1,201 @@
+==== init
+==== qnew -U
+From: test
+
+0: [mq]: 1.patch - test
+==== qref
+adding 1
+From: test
+
+diff -r ... 1
+--- /dev/null
++++ b/1
+@@ -0,0 +1,1 @@
++1
+0: [mq]: 1.patch - test
+==== qref -u
+From: mary
+
+diff -r ... 1
+--- /dev/null
++++ b/1
+@@ -0,0 +1,1 @@
++1
+0: [mq]: 1.patch - mary
+==== qnew
+adding 2
+diff -r ... 2
+--- /dev/null
++++ b/2
+@@ -0,0 +1,1 @@
++2
+1: [mq]: 2.patch - test
+0: [mq]: 1.patch - mary
+==== qref -u
+From: jane
+
+
+diff -r ... 2
+--- /dev/null
++++ b/2
+@@ -0,0 +1,1 @@
++2
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qnew -U -m
+From: test
+
+Three
+2: Three - test
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qref
+adding 3
+From: test
+
+Three
+
+diff -r ... 3
+--- /dev/null
++++ b/3
+@@ -0,0 +1,1 @@
++3
+2: Three - test
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qref -m
+From: test
+
+Drei
+
+diff -r ... 3
+--- /dev/null
++++ b/3
+@@ -0,0 +1,1 @@
++3
+2: Drei - test
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qref -u
+From: mary
+
+Drei
+
+diff -r ... 3
+--- /dev/null
++++ b/3
+@@ -0,0 +1,1 @@
++3
+2: Drei - mary
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qref -u -m
+From: maria
+
+Three (again)
+
+diff -r ... 3
+--- /dev/null
++++ b/3
+@@ -0,0 +1,1 @@
++3
+2: Three (again) - maria
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qnew -m
+adding 4
+Four
+
+diff -r ... 4
+--- /dev/null
++++ b/4
+@@ -0,0 +1,1 @@
++4
+3: Four - test
+2: Three (again) - maria
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qref -u
+From: jane
+
+Four
+
+diff -r ... 4
+--- /dev/null
++++ b/4
+@@ -0,0 +1,1 @@
++4
+3: Four - jane
+2: Three (again) - maria
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qnew with HG header
+Now at: 4.patch
+applying 5.patch
+/usr/bin/patch: **** Only garbage was found in the patch input.
+patch failed, unable to continue (try -v)
+patch 5.patch is empty
+Now at: 5.patch
+# HG changeset patch
+# User johndoe
+4: imported patch 5.patch - johndoe
+3: Four - jane
+2: Three (again) - maria
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== hg qref
+adding 5
+# HG changeset patch
+# User johndoe
+
+diff -r ... 5
+--- /dev/null
++++ b/5
+@@ -0,0 +1,1 @@
++5
+4: [mq]: 5.patch - johndoe
+3: Four - jane
+2: Three (again) - maria
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== hg qref -U
+# HG changeset patch
+# User test
+
+diff -r ... 5
+--- /dev/null
++++ b/5
+@@ -0,0 +1,1 @@
++5
+4: [mq]: 5.patch - test
+3: Four - jane
+2: Three (again) - maria
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== hg qref -u
+# HG changeset patch
+# User johndeere
+
+diff -r ... 5
+--- /dev/null
++++ b/5
+@@ -0,0 +1,1 @@
++5
+4: [mq]: 5.patch - johndeere
+3: Four - jane
+2: Three (again) - maria
+1: [mq]: 2.patch - jane
+0: [mq]: 1.patch - mary
+==== qpop -a / qpush -a
+Patch queue now empty
+applying 1.patch
+applying 2.patch
+applying 3.patch
+applying 4.patch
+applying 5.patch
+Now at: 5.patch
+4: imported patch 5.patch - johndeere
+3: Four - jane
+2: Three (again) - maria
+1: imported patch 2.patch - jane
+0: imported patch 1.patch - mary


More information about the Mercurial-devel mailing list