comparison hgext/histedit.py @ 27675:d073f4c70575

histedit: replace @addhisteditaction with @action @action supports verbs, messages, priority, and internal messages should be translated. internal means the action should not be listed. geteditcomment will construct the verbs list based on @actions (prefering priority over non priority, otherwise favoring verbs with short forms over verbs without).
author timeless <timeless@mozdev.org>
date Wed, 23 Dec 2015 21:30:38 +0000
parents 78d86664e3a2
children bb810c8b3eca
comparison
equal deleted inserted replaced
27674:78d86664e3a2 27675:d073f4c70575
212 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should 212 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
213 # be specifying the version(s) of Mercurial they are tested with, or 213 # be specifying the version(s) of Mercurial they are tested with, or
214 # leave the attribute unspecified. 214 # leave the attribute unspecified.
215 testedwith = 'internal' 215 testedwith = 'internal'
216 216
217 actiontable = {}
218 primaryactions = set()
219 secondaryactions = set()
220 tertiaryactions = set()
221 internalactions = set()
222
217 def geteditcomment(first, last): 223 def geteditcomment(first, last):
218 """ construct the editor comment 224 """ construct the editor comment
219 The comment includes:: 225 The comment includes::
220 - an intro 226 - an intro
221 - sorted primary commands 227 - sorted primary commands
222 - sorted short commands 228 - sorted short commands
229 - sorted long commands
223 230
224 Commands are only included once. 231 Commands are only included once.
225 """ 232 """
226 intro = _("""Edit history between %s and %s 233 intro = _("""Edit history between %s and %s
227 234
228 Commits are listed from least to most recent 235 Commits are listed from least to most recent
229 236
230 Commands:""") 237 Commands:
231 # i18n: command names and abbreviations must remain untranslated
232 verbs = _("""
233 e, edit = use commit, but stop for amending
234 m, mess = edit commit message without changing commit content
235 p, pick = use commit
236 d, drop = remove commit from history
237 f, fold = use commit, but combine it with the one above
238 r, roll = like fold, but discard this commit's description
239 """) 238 """)
239 actions = []
240 def addverb(v):
241 a = actiontable[v]
242 lines = a.message.split("\n")
243 if len(a.verbs):
244 v = ', '.join(sorted(a.verbs, key=lambda v: len(v)))
245 actions.append(" %s = %s" % (v, lines[0]))
246 actions.extend([' %s' for l in lines[1:]])
247
248 for v in (
249 sorted(primaryactions) +
250 sorted(secondaryactions) +
251 sorted(tertiaryactions)
252 ):
253 addverb(v)
254 actions.append('')
240 255
241 return ''.join(['# %s\n' % l if l else '#\n' 256 return ''.join(['# %s\n' % l if l else '#\n'
242 for l in ((intro % (first, last) + verbs).split('\n'))]) 257 for l in ((intro % (first, last)).split('\n')) + actions])
243 258
244 class histeditstate(object): 259 class histeditstate(object):
245 def __init__(self, repo, parentctxnode=None, actions=None, keep=None, 260 def __init__(self, repo, parentctxnode=None, actions=None, keep=None,
246 topmost=None, replacements=None, lock=None, wlock=None): 261 topmost=None, replacements=None, lock=None, wlock=None):
247 self.repo = repo 262 self.repo = repo
596 def abortdirty(): 611 def abortdirty():
597 raise error.Abort(_('working copy has pending changes'), 612 raise error.Abort(_('working copy has pending changes'),
598 hint=_('amend, commit, or revert them and run histedit ' 613 hint=_('amend, commit, or revert them and run histedit '
599 '--continue, or abort with histedit --abort')) 614 '--continue, or abort with histedit --abort'))
600 615
601 616 def action(verbs, message, priority=False, internal=False):
602 actiontable = {}
603 actionlist = []
604
605 def addhisteditaction(verbs):
606 def wrap(cls): 617 def wrap(cls):
607 cls.verb = verbs[0] 618 assert not priority or not internal
619 verb = verbs[0]
620 if priority:
621 primaryactions.add(verb)
622 elif internal:
623 internalactions.add(verb)
624 elif len(verbs) > 1:
625 secondaryactions.add(verb)
626 else:
627 tertiaryactions.add(verb)
628
629 cls.verb = verb
630 cls.verbs = verbs
631 cls.message = message
608 for verb in verbs: 632 for verb in verbs:
609 actiontable[verb] = cls 633 actiontable[verb] = cls
610 actionlist.append(cls)
611 return cls 634 return cls
612 return wrap 635 return wrap
613 636
614 637 @action(['pick', 'p'],
615 @addhisteditaction(['pick', 'p']) 638 _('use commit'),
639 priority=True)
616 class pick(histeditaction): 640 class pick(histeditaction):
617 def run(self): 641 def run(self):
618 rulectx = self.repo[self.node] 642 rulectx = self.repo[self.node]
619 if rulectx.parents()[0].node() == self.state.parentctxnode: 643 if rulectx.parents()[0].node() == self.state.parentctxnode:
620 self.repo.ui.debug('node %s unchanged\n' % node.short(self.node)) 644 self.repo.ui.debug('node %s unchanged\n' % node.short(self.node))
621 return rulectx, [] 645 return rulectx, []
622 646
623 return super(pick, self).run() 647 return super(pick, self).run()
624 648
625 @addhisteditaction(['edit', 'e']) 649 @action(['edit', 'e'],
650 _('use commit, but stop for amending'),
651 priority=True)
626 class edit(histeditaction): 652 class edit(histeditaction):
627 def run(self): 653 def run(self):
628 repo = self.repo 654 repo = self.repo
629 rulectx = repo[self.node] 655 rulectx = repo[self.node]
630 hg.update(repo, self.state.parentctxnode, quietempty=True) 656 hg.update(repo, self.state.parentctxnode, quietempty=True)
635 hint=_('hg histedit --continue to resume')) 661 hint=_('hg histedit --continue to resume'))
636 662
637 def commiteditor(self): 663 def commiteditor(self):
638 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit') 664 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit')
639 665
640 @addhisteditaction(['fold', 'f']) 666 @action(['fold', 'f'],
667 _('use commit, but combine it with the one above'))
641 class fold(histeditaction): 668 class fold(histeditaction):
642 def verify(self, prev): 669 def verify(self, prev):
643 """ Verifies semantic correctness of the fold rule""" 670 """ Verifies semantic correctness of the fold rule"""
644 super(fold, self).verify(prev) 671 super(fold, self).verify(prev)
645 repo = self.repo 672 repo = self.repo
761 788
762 def continueclean(self): 789 def continueclean(self):
763 basectx = self.repo['.'] 790 basectx = self.repo['.']
764 return basectx, [] 791 return basectx, []
765 792
766 @addhisteditaction(['_multifold']) 793 @action(['_multifold'],
767 class _multifold(fold): 794 _(
768 """fold subclass used for when multiple folds happen in a row 795 """fold subclass used for when multiple folds happen in a row
769 796
770 We only want to fire the editor for the folded message once when 797 We only want to fire the editor for the folded message once when
771 (say) four changes are folded down into a single change. This is 798 (say) four changes are folded down into a single change. This is
772 similar to rollup, but we should preserve both messages so that 799 similar to rollup, but we should preserve both messages so that
773 when the last fold operation runs we can show the user all the 800 when the last fold operation runs we can show the user all the
774 commit messages in their editor. 801 commit messages in their editor.
775 """ 802 """),
803 internal=True)
804 class _multifold(fold):
776 def skipprompt(self): 805 def skipprompt(self):
777 return True 806 return True
778 807
779 @addhisteditaction(["roll", "r"]) 808 @action(["roll", "r"],
809 _("like fold, but discard this commit's description"))
780 class rollup(fold): 810 class rollup(fold):
781 def mergedescs(self): 811 def mergedescs(self):
782 return False 812 return False
783 813
784 def skipprompt(self): 814 def skipprompt(self):
785 return True 815 return True
786 816
787 @addhisteditaction(["drop", "d"]) 817 @action(["drop", "d"],
818 _('remove commit from history'))
788 class drop(histeditaction): 819 class drop(histeditaction):
789 def run(self): 820 def run(self):
790 parentctx = self.repo[self.state.parentctxnode] 821 parentctx = self.repo[self.state.parentctxnode]
791 return parentctx, [(self.node, tuple())] 822 return parentctx, [(self.node, tuple())]
792 823
793 @addhisteditaction(["mess", "m"]) 824 @action(["mess", "m"],
825 _('edit commit message without changing commit content'),
826 priority=True)
794 class message(histeditaction): 827 class message(histeditaction):
795 def commiteditor(self): 828 def commiteditor(self):
796 return cmdutil.getcommiteditor(edit=True, editform='histedit.mess') 829 return cmdutil.getcommiteditor(edit=True, editform='histedit.mess')
797 830
798 def findoutgoing(ui, repo, remote=None, force=False, opts=None): 831 def findoutgoing(ui, repo, remote=None, force=False, opts=None):
1474 ['histedit-state', False, True, _('histedit in progress'), 1507 ['histedit-state', False, True, _('histedit in progress'),
1475 _("use 'hg histedit --continue' or 'hg histedit --abort'")]) 1508 _("use 'hg histedit --continue' or 'hg histedit --abort'")])
1476 cmdutil.afterresolvedstates.append( 1509 cmdutil.afterresolvedstates.append(
1477 ['histedit-state', _('hg histedit --continue')]) 1510 ['histedit-state', _('hg histedit --continue')])
1478 if ui.configbool("experimental", "histeditng"): 1511 if ui.configbool("experimental", "histeditng"):
1479 globals()['base'] = addhisteditaction(['base', 'b'])(base) 1512 globals()['base'] = action(['base', 'b'],
1513 _('checkout changeset and apply further changesets from there')
1514 )(base)