175 # (first pick I could think off, update as needed |
175 # (first pick I could think off, update as needed |
176 'log.topic': 'green_background', |
176 'log.topic': 'green_background', |
177 'topic.active': 'green', |
177 'topic.active': 'green', |
178 } |
178 } |
179 |
179 |
180 __version__ = '0.12.3.dev' |
180 __version__ = '0.13.0.dev' |
181 |
181 |
182 testedwith = '4.3.3 4.4.2 4.5.2 4.6.2 4.7' |
182 testedwith = '4.4.2 4.5.2 4.6.2 4.7 4.8' |
183 minimumhgversion = '4.3' |
183 minimumhgversion = '4.4' |
184 buglink = 'https://bz.mercurial-scm.org/' |
184 buglink = 'https://bz.mercurial-scm.org/' |
185 |
185 |
186 if util.safehasattr(registrar, 'configitem'): |
186 if util.safehasattr(registrar, 'configitem'): |
187 |
187 |
188 from mercurial import configitems |
188 from mercurial import configitems |
678 wl = repo.wlock() |
678 wl = repo.wlock() |
679 lock = repo.lock() |
679 lock = repo.lock() |
680 txn = repo.transaction('rewrite-topics') |
680 txn = repo.transaction('rewrite-topics') |
681 rewrote = _changetopics(ui, repo, touchedrevs, topic) |
681 rewrote = _changetopics(ui, repo, touchedrevs, topic) |
682 txn.close() |
682 txn.close() |
683 ui.status('changed topic on %d changes\n' % rewrote) |
683 if topic is None: |
|
684 ui.status('cleared topic on %d changesets\n' % rewrote) |
|
685 else: |
|
686 ui.status('changed topic on %d changesets to "%s"\n' % (rewrote, |
|
687 topic)) |
684 finally: |
688 finally: |
685 lockmod.release(txn, lock, wl) |
689 lockmod.release(txn, lock, wl) |
686 repo.invalidate() |
690 repo.invalidate() |
687 return |
691 return |
688 |
692 |
715 else: |
719 else: |
716 _listtopics(ui, repo, opts) |
720 _listtopics(ui, repo, opts) |
717 return ret |
721 return ret |
718 |
722 |
719 @command('stack', [ |
723 @command('stack', [ |
|
724 ('c', 'children', None, |
|
725 _('display data about children outside of the stack')) |
720 ] + commands.formatteropts, |
726 ] + commands.formatteropts, |
721 _('hg stack [TOPIC]')) |
727 _('hg stack [TOPIC]')) |
722 def cmdstack(ui, repo, topic='', **opts): |
728 def cmdstack(ui, repo, topic='', **opts): |
723 """list all changesets in a topic and other information |
729 """list all changesets in a topic and other information |
724 |
730 |
948 hg.update(repo, newid[0], quietempty=True) |
954 hg.update(repo, newid[0], quietempty=True) |
949 return rewrote |
955 return rewrote |
950 |
956 |
951 def _listtopics(ui, repo, opts): |
957 def _listtopics(ui, repo, opts): |
952 fm = ui.formatter('topics', opts) |
958 fm = ui.formatter('topics', opts) |
953 showlast = opts.get('age') |
|
954 if showlast: |
|
955 # we have a new function as plugging logic into existing function is |
|
956 # pretty much difficult |
|
957 return _showlasttouched(repo, fm, opts) |
|
958 activetopic = repo.currenttopic |
959 activetopic = repo.currenttopic |
959 namemask = '%s' |
960 namemask = '%s' |
960 if repo.topics: |
961 if repo.topics: |
961 maxwidth = max(len(t) for t in repo.topics) |
962 maxwidth = max(len(t) for t in repo.topics) |
962 namemask = '%%-%is' % maxwidth |
963 namemask = '%%-%is' % maxwidth |
963 for topic in sorted(repo.topics): |
964 if opts.get('age'): |
|
965 # here we sort by age and topic name |
|
966 topicsdata = sorted(_getlasttouched(repo, repo.topics)) |
|
967 else: |
|
968 # here we sort by topic name only |
|
969 topicsdata = ( |
|
970 (None, topic, None, None) |
|
971 for topic in sorted(repo.topics) |
|
972 ) |
|
973 for age, topic, date, user in topicsdata: |
964 fm.startitem() |
974 fm.startitem() |
965 marker = ' ' |
975 marker = ' ' |
966 label = 'topic' |
976 label = 'topic' |
967 active = (topic == activetopic) |
977 active = (topic == activetopic) |
968 if active: |
978 if active: |
975 fm.data(active=active) |
985 fm.data(active=active) |
976 |
986 |
977 if ui.quiet: |
987 if ui.quiet: |
978 fm.plain('\n') |
988 fm.plain('\n') |
979 continue |
989 continue |
|
990 fm.plain(' (') |
|
991 if date: |
|
992 if age == -1: |
|
993 timestr = 'empty and active' |
|
994 else: |
|
995 timestr = templatefilters.age(date) |
|
996 fm.write('lasttouched', '%s', timestr, label='topic.list.time') |
|
997 if user: |
|
998 fm.write('usertouched', ' by %s', user, label='topic.list.user') |
|
999 if date: |
|
1000 fm.plain(', ') |
980 data = stack.stack(repo, topic=topic) |
1001 data = stack.stack(repo, topic=topic) |
981 fm.plain(' (') |
|
982 if ui.verbose: |
1002 if ui.verbose: |
983 fm.write('branches+', 'on branch: %s', |
1003 fm.write('branches+', 'on branch: %s', |
984 '+'.join(data.branches), # XXX use list directly after 4.0 is released |
1004 '+'.join(data.branches), # XXX use list directly after 4.0 is released |
985 label='topic.list.branches') |
1005 label='topic.list.branches') |
986 |
1006 |
1016 _('ambiguous destination: %s') % data.behinderror, |
1036 _('ambiguous destination: %s') % data.behinderror, |
1017 label='topic.list.behinderror') |
1037 label='topic.list.behinderror') |
1018 fm.plain(')\n') |
1038 fm.plain(')\n') |
1019 fm.end() |
1039 fm.end() |
1020 |
1040 |
1021 def _showlasttouched(repo, fm, opts): |
|
1022 topics = repo.topics |
|
1023 timedict = _getlasttouched(repo, topics) |
|
1024 times = timedict.keys() |
|
1025 times.sort() |
|
1026 if topics: |
|
1027 maxwidth = max(len(t) for t in topics) |
|
1028 namemask = '%%-%is' % maxwidth |
|
1029 activetopic = repo.currenttopic |
|
1030 for timevalue in times: |
|
1031 curtopics = sorted(timedict[timevalue][1]) |
|
1032 for topic, user in curtopics: |
|
1033 fm.startitem() |
|
1034 marker = ' ' |
|
1035 label = 'topic' |
|
1036 active = (topic == activetopic) |
|
1037 if active: |
|
1038 marker = '*' |
|
1039 label = 'topic.active' |
|
1040 fm.plain(' %s ' % marker, label=label) |
|
1041 fm.write('topic', namemask, topic, label=label) |
|
1042 fm.data(active=active) |
|
1043 fm.plain(' (') |
|
1044 if timevalue == -1: |
|
1045 timestr = 'empty and active' |
|
1046 else: |
|
1047 timestr = templatefilters.age(timedict[timevalue][0]) |
|
1048 fm.write('lasttouched', '%s', timestr, label='topic.list.time') |
|
1049 if user: |
|
1050 fm.write('usertouched', ' by %s', user, label='topic.list.user') |
|
1051 fm.plain(')') |
|
1052 fm.plain('\n') |
|
1053 fm.end() |
|
1054 |
|
1055 def _getlasttouched(repo, topics): |
1041 def _getlasttouched(repo, topics): |
1056 """ |
1042 """ |
1057 Calculates the last time a topic was used. Returns a dictionary of seconds |
1043 Calculates the last time a topic was used. Returns a generator of 4-tuples: |
1058 passed from current time for a topic as keys and topic name as values. |
1044 (age in seconds, topic name, date, and user who last touched the topic). |
1059 """ |
1045 """ |
1060 topicstime = {} |
|
1061 curtime = time.time() |
1046 curtime = time.time() |
1062 for t in topics: |
1047 for topic in topics: |
1063 secspassed = -1 |
1048 age = -1 |
1064 user = None |
1049 user = None |
1065 maxtime = (0, 0) |
1050 maxtime = (0, 0) |
1066 trevs = repo.revs("topic(%s)", t) |
1051 trevs = repo.revs("topic(%s)", topic) |
1067 # Need to check for the time of all changesets in the topic, whether |
1052 # Need to check for the time of all changesets in the topic, whether |
1068 # they are obsolete of non-heads |
1053 # they are obsolete of non-heads |
1069 # XXX: can we just rely on the max rev number for this |
1054 # XXX: can we just rely on the max rev number for this |
1070 for revs in trevs: |
1055 for revs in trevs: |
1071 rt = repo[revs].date() |
1056 rt = repo[revs].date() |
1082 if rt[0] > maxtime[0]: |
1067 if rt[0] > maxtime[0]: |
1083 user = marker.metadata().get('user', user) |
1068 user = marker.metadata().get('user', user) |
1084 maxtime = rt |
1069 maxtime = rt |
1085 |
1070 |
1086 username = stack.parseusername(user) |
1071 username = stack.parseusername(user) |
1087 topicuser = (t, username) |
|
1088 |
|
1089 if trevs: |
1072 if trevs: |
1090 secspassed = (curtime - maxtime[0]) |
1073 age = curtime - maxtime[0] |
1091 try: |
1074 |
1092 topicstime[secspassed][1].append(topicuser) |
1075 yield (age, topic, maxtime, username) |
1093 except KeyError: |
|
1094 topicstime[secspassed] = (maxtime, [topicuser]) |
|
1095 |
|
1096 return topicstime |
|
1097 |
1076 |
1098 def summaryhook(ui, repo): |
1077 def summaryhook(ui, repo): |
1099 t = getattr(repo, 'currenttopic', '') |
1078 t = getattr(repo, 'currenttopic', '') |
1100 if not t: |
1079 if not t: |
1101 return |
1080 return |