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: |
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) |