Mercurial > hg
comparison hgext/mq.py @ 5673:dd3ce7515f4d
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.
author | peter.arrenbrecht@gmail.com |
---|---|
date | Wed, 19 Dec 2007 22:36:18 +0100 |
parents | 1f044b04fa0a |
children | 4107e823dc2c |
comparison
equal
deleted
inserted
replaced
5653:1b35bc1c1968 | 5673:dd3ce7515f4d |
---|---|
601 return m, a, r, d | 601 return m, a, r, d |
602 | 602 |
603 def new(self, repo, patch, *pats, **opts): | 603 def new(self, repo, patch, *pats, **opts): |
604 msg = opts.get('msg') | 604 msg = opts.get('msg') |
605 force = opts.get('force') | 605 force = opts.get('force') |
606 user = opts.get('user') | |
606 if os.path.exists(self.join(patch)): | 607 if os.path.exists(self.join(patch)): |
607 raise util.Abort(_('patch "%s" already exists') % patch) | 608 raise util.Abort(_('patch "%s" already exists') % patch) |
608 if opts.get('include') or opts.get('exclude') or pats: | 609 if opts.get('include') or opts.get('exclude') or pats: |
609 fns, match, anypats = cmdutil.matchpats(repo, pats, opts) | 610 fns, match, anypats = cmdutil.matchpats(repo, pats, opts) |
610 m, a, r, d = repo.status(files=fns, match=match)[:4] | 611 m, a, r, d = repo.status(files=fns, match=match)[:4] |
615 self.check_toppatch(repo) | 616 self.check_toppatch(repo) |
616 wlock = repo.wlock() | 617 wlock = repo.wlock() |
617 try: | 618 try: |
618 insert = self.full_series_end() | 619 insert = self.full_series_end() |
619 commitmsg = msg and msg or ("[mq]: %s" % patch) | 620 commitmsg = msg and msg or ("[mq]: %s" % patch) |
620 n = repo.commit(commitfiles, commitmsg, match=match, force=True) | 621 n = repo.commit(commitfiles, commitmsg, user, match=match, force=True) |
621 if n == None: | 622 if n == None: |
622 raise util.Abort(_("repo commit failed")) | 623 raise util.Abort(_("repo commit failed")) |
623 self.full_series[insert:insert] = [patch] | 624 self.full_series[insert:insert] = [patch] |
624 self.applied.append(statusentry(revlog.hex(n), patch)) | 625 self.applied.append(statusentry(revlog.hex(n), patch)) |
625 self.parse_series() | 626 self.parse_series() |
626 self.series_dirty = 1 | 627 self.series_dirty = 1 |
627 self.applied_dirty = 1 | 628 self.applied_dirty = 1 |
628 p = self.opener(patch, "w") | 629 p = self.opener(patch, "w") |
630 if user: | |
631 p.write("From: " + user + "\n\n") | |
629 if msg: | 632 if msg: |
630 msg = msg + "\n" | 633 msg = msg + "\n" |
631 p.write(msg) | 634 p.write(msg) |
632 p.close() | 635 p.close() |
633 wlock = None | 636 wlock = None |
943 ci = 0 | 946 ci = 0 |
944 for mi in xrange(len(message)): | 947 for mi in xrange(len(message)): |
945 while message[mi] != comments[ci]: | 948 while message[mi] != comments[ci]: |
946 ci += 1 | 949 ci += 1 |
947 del comments[ci] | 950 del comments[ci] |
951 | |
952 newuser = opts.get('user') | |
953 if newuser: | |
954 # Update all references to a user in the patch header. | |
955 # If none found, add "From: " header. | |
956 needfrom = True | |
957 for prefix in ['# User ', 'From: ']: | |
958 for i in xrange(len(comments)): | |
959 if comments[i].startswith(prefix): | |
960 comments[i] = prefix + newuser | |
961 needfrom = False | |
962 break | |
963 if needfrom: | |
964 comments = ['From: ' + newuser, ''] + comments | |
965 user = newuser | |
966 | |
948 if msg: | 967 if msg: |
949 comments.append(msg) | 968 comments.append(msg) |
950 | 969 |
951 patchf.seek(0) | 970 patchf.seek(0) |
952 patchf.truncate() | 971 patchf.truncate() |
1068 else: | 1087 else: |
1069 message = "\n".join(message) | 1088 message = "\n".join(message) |
1070 else: | 1089 else: |
1071 message = msg | 1090 message = msg |
1072 | 1091 |
1092 if not user: | |
1093 user = changes[1] | |
1094 | |
1073 self.strip(repo, top, update=False, | 1095 self.strip(repo, top, update=False, |
1074 backup='strip') | 1096 backup='strip') |
1075 n = repo.commit(filelist, message, changes[1], match=matchfn, | 1097 n = repo.commit(filelist, message, user, match=matchfn, |
1076 force=1) | 1098 force=1) |
1077 self.applied[-1] = statusentry(revlog.hex(n), patchfn) | 1099 self.applied[-1] = statusentry(revlog.hex(n), patchfn) |
1078 self.applied_dirty = 1 | 1100 self.applied_dirty = 1 |
1079 self.removeundo(repo) | 1101 self.removeundo(repo) |
1080 else: | 1102 else: |
1603 ui.write("No patches applied\n") | 1625 ui.write("No patches applied\n") |
1604 return 1 | 1626 return 1 |
1605 return q.qseries(repo, start=l-2, length=1, status='A', | 1627 return q.qseries(repo, start=l-2, length=1, status='A', |
1606 summary=opts.get('summary')) | 1628 summary=opts.get('summary')) |
1607 | 1629 |
1630 def setupheaderopts(ui, opts): | |
1631 def do(opt,val): | |
1632 if not opts[opt] and opts['current' + opt]: | |
1633 opts[opt] = val | |
1634 do('user', ui.username()) | |
1635 | |
1608 def new(ui, repo, patch, *args, **opts): | 1636 def new(ui, repo, patch, *args, **opts): |
1609 """create a new patch | 1637 """create a new patch |
1610 | 1638 |
1611 qnew creates a new patch on top of the currently-applied patch | 1639 qnew creates a new patch on top of the currently-applied patch |
1612 (if any). It will refuse to run if there are any outstanding | 1640 (if any). It will refuse to run if there are any outstanding |
1621 q = repo.mq | 1649 q = repo.mq |
1622 message = cmdutil.logmessage(opts) | 1650 message = cmdutil.logmessage(opts) |
1623 if opts['edit']: | 1651 if opts['edit']: |
1624 message = ui.edit(message, ui.username()) | 1652 message = ui.edit(message, ui.username()) |
1625 opts['msg'] = message | 1653 opts['msg'] = message |
1654 setupheaderopts(ui, opts) | |
1626 q.new(repo, patch, *args, **opts) | 1655 q.new(repo, patch, *args, **opts) |
1627 q.save_dirty() | 1656 q.save_dirty() |
1628 return 0 | 1657 return 0 |
1629 | 1658 |
1630 def refresh(ui, repo, *pats, **opts): | 1659 def refresh(ui, repo, *pats, **opts): |
1646 if message: | 1675 if message: |
1647 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) | 1676 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
1648 patch = q.applied[-1].name | 1677 patch = q.applied[-1].name |
1649 (message, comment, user, date, hasdiff) = q.readheaders(patch) | 1678 (message, comment, user, date, hasdiff) = q.readheaders(patch) |
1650 message = ui.edit('\n'.join(message), user or ui.username()) | 1679 message = ui.edit('\n'.join(message), user or ui.username()) |
1680 setupheaderopts(ui, opts) | |
1651 ret = q.refresh(repo, pats, msg=message, **opts) | 1681 ret = q.refresh(repo, pats, msg=message, **opts) |
1652 q.save_dirty() | 1682 q.save_dirty() |
1653 return ret | 1683 return ret |
1654 | 1684 |
1655 def diff(ui, repo, *pats, **opts): | 1685 def diff(ui, repo, *pats, **opts): |
2136 repo.__class__ = mqrepo | 2166 repo.__class__ = mqrepo |
2137 repo.mq = queue(ui, repo.join("")) | 2167 repo.mq = queue(ui, repo.join("")) |
2138 | 2168 |
2139 seriesopts = [('s', 'summary', None, _('print first line of patch header'))] | 2169 seriesopts = [('s', 'summary', None, _('print first line of patch header'))] |
2140 | 2170 |
2171 headeropts = [ | |
2172 ('U', 'currentuser', None, _('add "From: <current user>" to patch')), | |
2173 ('u', 'user', '', _('add "From: <given user>" to patch'))] | |
2174 | |
2141 cmdtable = { | 2175 cmdtable = { |
2142 "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')), | 2176 "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')), |
2143 "qclone": | 2177 "qclone": |
2144 (clone, | 2178 (clone, |
2145 [('', 'pull', None, _('use pull protocol to copy metadata')), | 2179 [('', 'pull', None, _('use pull protocol to copy metadata')), |
2194 "qnew": | 2228 "qnew": |
2195 (new, | 2229 (new, |
2196 [('e', 'edit', None, _('edit commit message')), | 2230 [('e', 'edit', None, _('edit commit message')), |
2197 ('f', 'force', None, _('import uncommitted changes into patch')), | 2231 ('f', 'force', None, _('import uncommitted changes into patch')), |
2198 ('g', 'git', None, _('use git extended diff format')), | 2232 ('g', 'git', None, _('use git extended diff format')), |
2199 ] + commands.walkopts + commands.commitopts, | 2233 ] + commands.walkopts + commands.commitopts + headeropts, |
2200 _('hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...')), | 2234 _('hg qnew [-e] [-m TEXT] [-l FILE] [-f] PATCH [FILE]...')), |
2201 "qnext": (next, [] + seriesopts, _('hg qnext [-s]')), | 2235 "qnext": (next, [] + seriesopts, _('hg qnext [-s]')), |
2202 "qprev": (prev, [] + seriesopts, _('hg qprev [-s]')), | 2236 "qprev": (prev, [] + seriesopts, _('hg qprev [-s]')), |
2203 "^qpop": | 2237 "^qpop": |
2204 (pop, | 2238 (pop, |
2217 "^qrefresh": | 2251 "^qrefresh": |
2218 (refresh, | 2252 (refresh, |
2219 [('e', 'edit', None, _('edit commit message')), | 2253 [('e', 'edit', None, _('edit commit message')), |
2220 ('g', 'git', None, _('use git extended diff format')), | 2254 ('g', 'git', None, _('use git extended diff format')), |
2221 ('s', 'short', None, _('refresh only files already in the patch')), | 2255 ('s', 'short', None, _('refresh only files already in the patch')), |
2222 ] + commands.walkopts + commands.commitopts, | 2256 ] + commands.walkopts + commands.commitopts + headeropts, |
2223 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')), | 2257 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...')), |
2224 'qrename|qmv': | 2258 'qrename|qmv': |
2225 (rename, [], _('hg qrename PATCH1 [PATCH2]')), | 2259 (rename, [], _('hg qrename PATCH1 [PATCH2]')), |
2226 "qrestore": | 2260 "qrestore": |
2227 (restore, | 2261 (restore, |