diff -r 7fbb7a5d359f -r d39942773163 hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Tue Jul 11 11:24:43 2017 +0200 +++ b/hgext3rd/topic/__init__.py Tue Jul 11 21:39:39 2017 +0530 @@ -53,6 +53,7 @@ from __future__ import absolute_import import re +import time from mercurial.i18n import _ from mercurial import ( @@ -68,9 +69,11 @@ namespaces, node, obsolete, + obsutil, patch, phases, registrar, + templatefilters, util, ) @@ -297,6 +300,7 @@ ('', 'clear', False, 'clear active topic if any'), ('r', 'rev', '', 'revset of existing revisions', _('REV')), ('l', 'list', False, 'show the stack of changeset in the topic'), + ('', 'age', False, 'show when you last touched the topics') ] + commands.formatteropts) def topics(ui, repo, topic='', clear=False, rev=None, list=False, **opts): """View current topic, set current topic, change topic for a set of revisions, or see all topics. @@ -316,6 +320,9 @@ List of topics: `hg topics` + List of topics with their last touched time sorted according to it: + `hg topic --age` + The active topic (if any) will be prepended with a "*". The --verbose version of this command display various information on the state of each topic.""" @@ -442,6 +449,11 @@ def _listtopics(ui, repo, opts): fm = ui.formatter('topics', opts) + showlast = opts.get('age') + if showlast: + # we have a new function as plugging logic into existing function is + # pretty much difficult + return _showlasttouched(repo, fm, opts) activetopic = repo.currenttopic namemask = '%s' if repo.topics and ui.verbose: @@ -494,6 +506,76 @@ fm.plain('\n') fm.end() +def _showlasttouched(repo, fm, opts): + topics = repo.topics + timedict = _getlasttouched(repo, topics) + times = timedict.keys() + times.sort() + if topics: + maxwidth = max(len(t) for t in topics) + namemask = '%%-%is' % maxwidth + activetopic = repo.currenttopic + for timevalue in times: + curtopics = timedict[timevalue][1] + for topic in curtopics: + fm.startitem() + marker = ' ' + label = 'topic' + active = (topic == activetopic) + if active: + marker = '*' + label = 'topic.active' + fm.plain(' %s ' % marker, label=label) + fm.write('topic', namemask, topic, label=label) + fm.data(active=active) + fm.plain(' (') + if timevalue == -1: + timestr = 'not yet touched' + else: + timestr = templatefilters.age(timedict[timevalue][0]) + fm.write('lasttouched', '%s', timestr, label='topic.list.time') + fm.plain(')') + fm.plain('\n') + fm.end() + +def _getlasttouched(repo, topics): + """ + Calculates the last time a topic was used. Returns a dictionary of seconds + passed from current time for a topic as keys and topic name as values. + """ + topicstime = {} + curtime = time.time() + for t in topics: + maxtime = (0, 0) + trevs = repo.revs("topic(%s)", t) + # Need to check for the time of all changesets in the topic, whether + # they are obsolete of non-heads + # XXX: can we just rely on the max rev number for this + for revs in trevs: + rt = repo[revs].date() + if rt[0] > maxtime[0]: + # Can store the rev to gather more info + # latesthead = revs + maxtime = rt + # looking on the markers also to get more information and accurate + # last touch time. + obsmarkers = obsutil.getmarkers(repo, [repo[revs].node()]) + for marker in obsmarkers: + rt = marker.date() + if rt[0] > maxtime[0]: + maxtime = rt + # is the topic still yet untouched + if not trevs: + secspassed = -1 + else: + secspassed = (curtime - maxtime[0]) + try: + topicstime[secspassed][1].append(t) + except KeyError: + topicstime[secspassed] = (maxtime, [t]) + + return topicstime + def panicforuntopicedcommit(): msg = _("no active topic") hint = _("set a current topic or use '--config " +