# HG changeset patch # User peter.arrenbrecht@gmail.com # Date 2007-12-19 21:36:18 # Node ID dd3ce7515f4dbe80093735eed4101b2dd6313cf4 # Parent 1b35bc1c19688248b90a617d1a4d3ef05ef022d6 mq: add --currentuser 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['current' + 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', 'currentuser', None, _('add "From: " to patch')), + ('u', 'user', '', _('add "From: " 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,108 @@ +#!/bin/sh + +echo "[extensions]" >> $HGRCPATH +echo "mq=" >> $HGRCPATH +echo "[diff]" >> $HGRCPATH +echo "nodates=true" >> $HGRCPATH + + +catlog() { + cat .hg/patches/$1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /" + hg log --template "{rev}: {desc} - {author}\n" +} + + +echo ==== init +hg init a +cd a +hg qinit + + +echo ==== qnew -U +hg qnew -U 1.patch +catlog 1 + +echo ==== qref +echo "1" >1 +hg add +hg qref +catlog 1 + +echo ==== qref -u +hg qref -u mary +catlog 1 + +echo ==== qnew +hg qnew 2.patch +echo "2" >2 +hg add +hg qref +catlog 2 + +echo ==== qref -u +hg qref -u jane +catlog 2 + + +echo ==== qnew -U -m +hg qnew -U -m "Three" 3.patch +catlog 3 + +echo ==== qref +echo "3" >3 +hg add +hg qref +catlog 3 + +echo ==== qref -m +hg qref -m "Drei" +catlog 3 + +echo ==== qref -u +hg qref -u mary +catlog 3 + +echo ==== qref -u -m +hg qref -u maria -m "Three (again)" +catlog 3 + +echo ==== qnew -m +hg qnew -m "Four" 4.patch +echo "4" >4 +hg add +hg qref +catlog 4 + +echo ==== qref -u +hg qref -u jane +catlog 4 + + +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 +# Drop patch specific error line +hg qpush 2>&1 | grep -v garbage +catlog 5 + +echo ==== hg qref +echo "5" >5 +hg add +hg qref +catlog 5 + +echo ==== hg qref -U +hg qref -U +catlog 5 + +echo ==== hg qref -u +hg qref -u johndeere +catlog 5 + + +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,200 @@ +==== 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 +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