hgext3rd/topic/__init__.py
changeset 2731 d39942773163
parent 2718 b6fa7b3e13d4
child 2733 adfbb984ebbb
equal deleted inserted replaced
2730:7fbb7a5d359f 2731:d39942773163
    51 """
    51 """
    52 
    52 
    53 from __future__ import absolute_import
    53 from __future__ import absolute_import
    54 
    54 
    55 import re
    55 import re
       
    56 import time
    56 
    57 
    57 from mercurial.i18n import _
    58 from mercurial.i18n import _
    58 from mercurial import (
    59 from mercurial import (
    59     cmdutil,
    60     cmdutil,
    60     commands,
    61     commands,
    66     lock,
    67     lock,
    67     merge,
    68     merge,
    68     namespaces,
    69     namespaces,
    69     node,
    70     node,
    70     obsolete,
    71     obsolete,
       
    72     obsutil,
    71     patch,
    73     patch,
    72     phases,
    74     phases,
    73     registrar,
    75     registrar,
       
    76     templatefilters,
    74     util,
    77     util,
    75 )
    78 )
    76 
    79 
    77 from . import (
    80 from . import (
    78     constants,
    81     constants,
   295 
   298 
   296 @command('topics [TOPIC]', [
   299 @command('topics [TOPIC]', [
   297         ('', 'clear', False, 'clear active topic if any'),
   300         ('', 'clear', False, 'clear active topic if any'),
   298         ('r', 'rev', '', 'revset of existing revisions', _('REV')),
   301         ('r', 'rev', '', 'revset of existing revisions', _('REV')),
   299         ('l', 'list', False, 'show the stack of changeset in the topic'),
   302         ('l', 'list', False, 'show the stack of changeset in the topic'),
       
   303         ('', 'age', False, 'show when you last touched the topics')
   300     ] + commands.formatteropts)
   304     ] + commands.formatteropts)
   301 def topics(ui, repo, topic='', clear=False, rev=None, list=False, **opts):
   305 def topics(ui, repo, topic='', clear=False, rev=None, list=False, **opts):
   302     """View current topic, set current topic, change topic for a set of revisions, or see all topics.
   306     """View current topic, set current topic, change topic for a set of revisions, or see all topics.
   303 
   307 
   304     Clear topic on existing topiced revisions:
   308     Clear topic on existing topiced revisions:
   313     Set current topic:
   317     Set current topic:
   314         `hg topic <topicname>`
   318         `hg topic <topicname>`
   315 
   319 
   316     List of topics:
   320     List of topics:
   317         `hg topics`
   321         `hg topics`
       
   322 
       
   323     List of topics with their last touched time sorted according to it:
       
   324         `hg topic --age`
   318 
   325 
   319     The active topic (if any) will be prepended with a "*".
   326     The active topic (if any) will be prepended with a "*".
   320 
   327 
   321     The --verbose version of this command display various information on the state of each topic."""
   328     The --verbose version of this command display various information on the state of each topic."""
   322     if list:
   329     if list:
   440         repo.invalidate()
   447         repo.invalidate()
   441     ui.status('changed topic on %d changes\n' % rewrote)
   448     ui.status('changed topic on %d changes\n' % rewrote)
   442 
   449 
   443 def _listtopics(ui, repo, opts):
   450 def _listtopics(ui, repo, opts):
   444     fm = ui.formatter('topics', opts)
   451     fm = ui.formatter('topics', opts)
       
   452     showlast = opts.get('age')
       
   453     if showlast:
       
   454         # we have a new function as plugging logic into existing function is
       
   455         # pretty much difficult
       
   456         return _showlasttouched(repo, fm, opts)
   445     activetopic = repo.currenttopic
   457     activetopic = repo.currenttopic
   446     namemask = '%s'
   458     namemask = '%s'
   447     if repo.topics and ui.verbose:
   459     if repo.topics and ui.verbose:
   448         maxwidth = max(len(t) for t in repo.topics)
   460         maxwidth = max(len(t) for t in repo.topics)
   449         namemask = '%%-%is' % maxwidth
   461         namemask = '%%-%is' % maxwidth
   492                          label='topic.list.behinderror')
   504                          label='topic.list.behinderror')
   493             fm.plain(')')
   505             fm.plain(')')
   494         fm.plain('\n')
   506         fm.plain('\n')
   495     fm.end()
   507     fm.end()
   496 
   508 
       
   509 def _showlasttouched(repo, fm, opts):
       
   510     topics = repo.topics
       
   511     timedict = _getlasttouched(repo, topics)
       
   512     times = timedict.keys()
       
   513     times.sort()
       
   514     if topics:
       
   515         maxwidth = max(len(t) for t in topics)
       
   516         namemask = '%%-%is' % maxwidth
       
   517     activetopic = repo.currenttopic
       
   518     for timevalue in times:
       
   519         curtopics = timedict[timevalue][1]
       
   520         for topic in curtopics:
       
   521             fm.startitem()
       
   522             marker = ' '
       
   523             label = 'topic'
       
   524             active = (topic == activetopic)
       
   525             if active:
       
   526                 marker = '*'
       
   527                 label = 'topic.active'
       
   528             fm.plain(' %s ' % marker, label=label)
       
   529             fm.write('topic', namemask, topic, label=label)
       
   530             fm.data(active=active)
       
   531             fm.plain(' (')
       
   532             if timevalue == -1:
       
   533                 timestr = 'not yet touched'
       
   534             else:
       
   535                 timestr = templatefilters.age(timedict[timevalue][0])
       
   536             fm.write('lasttouched', '%s', timestr, label='topic.list.time')
       
   537             fm.plain(')')
       
   538             fm.plain('\n')
       
   539     fm.end()
       
   540 
       
   541 def _getlasttouched(repo, topics):
       
   542     """
       
   543     Calculates the last time a topic was used. Returns a dictionary of seconds
       
   544     passed from current time for a topic as keys and topic name as values.
       
   545     """
       
   546     topicstime = {}
       
   547     curtime = time.time()
       
   548     for t in topics:
       
   549         maxtime = (0, 0)
       
   550         trevs = repo.revs("topic(%s)", t)
       
   551         # Need to check for the time of all changesets in the topic, whether
       
   552         # they are obsolete of non-heads
       
   553         # XXX: can we just rely on the max rev number for this
       
   554         for revs in trevs:
       
   555             rt = repo[revs].date()
       
   556             if rt[0] > maxtime[0]:
       
   557                 # Can store the rev to gather more info
       
   558                 # latesthead = revs
       
   559                 maxtime = rt
       
   560             # looking on the markers also to get more information and accurate
       
   561             # last touch time.
       
   562             obsmarkers = obsutil.getmarkers(repo, [repo[revs].node()])
       
   563             for marker in obsmarkers:
       
   564                 rt = marker.date()
       
   565                 if rt[0] > maxtime[0]:
       
   566                     maxtime = rt
       
   567         # is the topic still yet untouched
       
   568         if not trevs:
       
   569             secspassed = -1
       
   570         else:
       
   571             secspassed = (curtime - maxtime[0])
       
   572         try:
       
   573             topicstime[secspassed][1].append(t)
       
   574         except KeyError:
       
   575             topicstime[secspassed] = (maxtime, [t])
       
   576 
       
   577     return topicstime
       
   578 
   497 def panicforuntopicedcommit():
   579 def panicforuntopicedcommit():
   498     msg = _("no active topic")
   580     msg = _("no active topic")
   499     hint = _("set a current topic or use '--config " +
   581     hint = _("set a current topic or use '--config " +
   500              "experimental.enforce-topic=no' to commit without a topic")
   582              "experimental.enforce-topic=no' to commit without a topic")
   501     raise error.Abort(msg, hint=hint)
   583     raise error.Abort(msg, hint=hint)