Show More
@@ -745,6 +745,9 b' class changeset_templater(changeset_prin' | |||||
745 | 'parent': '{rev}:{node|formatnode} ', |
|
745 | 'parent': '{rev}:{node|formatnode} ', | |
746 | 'manifest': '{rev}:{node|formatnode}', |
|
746 | 'manifest': '{rev}:{node|formatnode}', | |
747 | 'filecopy': '{name} ({source})'}) |
|
747 | 'filecopy': '{name} ({source})'}) | |
|
748 | # Cache mapping from rev to a tuple with tag date, tag | |||
|
749 | # distance and tag name | |||
|
750 | self._latesttagcache = {-1: (0, 0, 'null')} | |||
748 |
|
751 | |||
749 | def use_template(self, t): |
|
752 | def use_template(self, t): | |
750 | '''set template string to use''' |
|
753 | '''set template string to use''' | |
@@ -762,6 +765,30 b' class changeset_templater(changeset_prin' | |||||
762 | return [] |
|
765 | return [] | |
763 | return parents |
|
766 | return parents | |
764 |
|
767 | |||
|
768 | def _latesttaginfo(self, rev): | |||
|
769 | '''return date, distance and name for the latest tag of rev''' | |||
|
770 | todo = [rev] | |||
|
771 | while todo: | |||
|
772 | rev = todo.pop() | |||
|
773 | if rev in self._latesttagcache: | |||
|
774 | continue | |||
|
775 | ctx = self.repo[rev] | |||
|
776 | tags = [t for t in ctx.tags() if self.repo.tagtype(t) == 'global'] | |||
|
777 | if tags: | |||
|
778 | self._latesttagcache[rev] = ctx.date()[0], 0, ':'.join(sorted(tags)) | |||
|
779 | continue | |||
|
780 | try: | |||
|
781 | # The tuples are laid out so the right one can be found by comparison. | |||
|
782 | pdate, pdist, ptag = max( | |||
|
783 | self._latesttagcache[p.rev()] for p in ctx.parents()) | |||
|
784 | except KeyError: | |||
|
785 | # Cache miss - recurse | |||
|
786 | todo.append(rev) | |||
|
787 | todo.extend(p.rev() for p in ctx.parents()) | |||
|
788 | continue | |||
|
789 | self._latesttagcache[rev] = pdate, pdist + 1, ptag | |||
|
790 | return self._latesttagcache[rev] | |||
|
791 | ||||
765 | def _show(self, ctx, copies, props): |
|
792 | def _show(self, ctx, copies, props): | |
766 | '''show a single changeset or file revision''' |
|
793 | '''show a single changeset or file revision''' | |
767 |
|
794 | |||
@@ -879,6 +906,11 b' class changeset_templater(changeset_prin' | |||||
879 | removes += i[2] |
|
906 | removes += i[2] | |
880 | return '%s: +%s/-%s' % (files, adds, removes) |
|
907 | return '%s: +%s/-%s' % (files, adds, removes) | |
881 |
|
908 | |||
|
909 | def showlatesttag(**args): | |||
|
910 | return self._latesttaginfo(ctx.rev())[2] | |||
|
911 | def showlatesttagdistance(**args): | |||
|
912 | return self._latesttaginfo(ctx.rev())[1] | |||
|
913 | ||||
882 | defprops = { |
|
914 | defprops = { | |
883 | 'author': ctx.user(), |
|
915 | 'author': ctx.user(), | |
884 | 'branches': showbranches, |
|
916 | 'branches': showbranches, | |
@@ -896,6 +928,8 b' class changeset_templater(changeset_prin' | |||||
896 | 'tags': showtags, |
|
928 | 'tags': showtags, | |
897 | 'extras': showextras, |
|
929 | 'extras': showextras, | |
898 | 'diffstat': showdiffstat, |
|
930 | 'diffstat': showdiffstat, | |
|
931 | 'latesttag': showlatesttag, | |||
|
932 | 'latesttagdistance': showlatesttagdistance, | |||
899 | } |
|
933 | } | |
900 | props = props.copy() |
|
934 | props = props.copy() | |
901 | props.update(defprops) |
|
935 | props.update(defprops) |
@@ -393,6 +393,9 b' PYTHONPATH' | |||||
393 | number. |
|
393 | number. | |
394 | :tags: List of strings. Any tags associated with the |
|
394 | :tags: List of strings. Any tags associated with the | |
395 | changeset. |
|
395 | changeset. | |
|
396 | :latesttag: String. Most recent global tag in the ancestors of this | |||
|
397 | changeset. | |||
|
398 | :latesttagdistance: Integer. Longest path to the latest tag. | |||
396 |
|
399 | |||
397 | The "date" keyword does not produce human-readable output. If you |
|
400 | The "date" keyword does not produce human-readable output. If you | |
398 | want to use a date in your output, you can use a filter to process |
|
401 | want to use a date in your output, you can use a filter to process |
@@ -127,4 +127,49 b" echo '# error on syntax'" | |||||
127 | echo 'x = "f' >> t |
|
127 | echo 'x = "f' >> t | |
128 | hg log |
|
128 | hg log | |
129 |
|
129 | |||
|
130 | cd .. | |||
|
131 | ||||
|
132 | echo '# latesttag' | |||
|
133 | hg init latesttag | |||
|
134 | cd latesttag | |||
|
135 | ||||
|
136 | echo a > file | |||
|
137 | hg ci -Am a -d '0 0' | |||
|
138 | ||||
|
139 | echo b >> file | |||
|
140 | hg ci -m b -d '1 0' | |||
|
141 | ||||
|
142 | echo c >> head1 | |||
|
143 | hg ci -Am h1c -d '2 0' | |||
|
144 | ||||
|
145 | hg update -q 1 | |||
|
146 | echo d >> head2 | |||
|
147 | hg ci -Am h2d -d '3 0' | |||
|
148 | ||||
|
149 | echo e >> head2 | |||
|
150 | hg ci -m h2e -d '4 0' | |||
|
151 | ||||
|
152 | hg merge -q | |||
|
153 | hg ci -m merge -d '5 0' | |||
|
154 | ||||
|
155 | echo '# No tag set' | |||
|
156 | hg log --template '{rev}: {latesttag}+{latesttagdistance}\n' | |||
|
157 | ||||
|
158 | echo '# one common tag: longuest path wins' | |||
|
159 | hg tag -r 1 -m t1 -d '6 0' t1 | |||
|
160 | hg log --template '{rev}: {latesttag}+{latesttagdistance}\n' | |||
|
161 | ||||
|
162 | echo '# one ancestor tag: more recent wins' | |||
|
163 | hg tag -r 2 -m t2 -d '7 0' t2 | |||
|
164 | hg log --template '{rev}: {latesttag}+{latesttagdistance}\n' | |||
|
165 | ||||
|
166 | echo '# two branch tags: more recent wins' | |||
|
167 | hg tag -r 3 -m t3 -d '8 0' t3 | |||
|
168 | hg log --template '{rev}: {latesttag}+{latesttagdistance}\n' | |||
|
169 | ||||
|
170 | echo '# merged tag overrides' | |||
|
171 | hg tag -r 5 -m t5 -d '9 0' t5 | |||
|
172 | hg tag -r 3 -m at3 -d '10 0' at3 | |||
|
173 | hg log --template '{rev}: {latesttag}+{latesttagdistance}\n' | |||
|
174 | ||||
130 | echo '# done' |
|
175 | echo '# done' |
@@ -672,4 +672,55 b' 1e4e1b8f71e0' | |||||
672 | 1e4e1b8f71e05681d422154f5421e385fec3454f |
|
672 | 1e4e1b8f71e05681d422154f5421e385fec3454f | |
673 | # error on syntax |
|
673 | # error on syntax | |
674 | abort: t:3: unmatched quotes |
|
674 | abort: t:3: unmatched quotes | |
|
675 | # latesttag | |||
|
676 | adding file | |||
|
677 | adding head1 | |||
|
678 | adding head2 | |||
|
679 | created new head | |||
|
680 | # No tag set | |||
|
681 | 5: null+5 | |||
|
682 | 4: null+4 | |||
|
683 | 3: null+3 | |||
|
684 | 2: null+3 | |||
|
685 | 1: null+2 | |||
|
686 | 0: null+1 | |||
|
687 | # one common tag: longuest path wins | |||
|
688 | 6: t1+4 | |||
|
689 | 5: t1+3 | |||
|
690 | 4: t1+2 | |||
|
691 | 3: t1+1 | |||
|
692 | 2: t1+1 | |||
|
693 | 1: t1+0 | |||
|
694 | 0: null+1 | |||
|
695 | # one ancestor tag: more recent wins | |||
|
696 | 7: t2+3 | |||
|
697 | 6: t2+2 | |||
|
698 | 5: t2+1 | |||
|
699 | 4: t1+2 | |||
|
700 | 3: t1+1 | |||
|
701 | 2: t2+0 | |||
|
702 | 1: t1+0 | |||
|
703 | 0: null+1 | |||
|
704 | # two branch tags: more recent wins | |||
|
705 | 8: t3+5 | |||
|
706 | 7: t3+4 | |||
|
707 | 6: t3+3 | |||
|
708 | 5: t3+2 | |||
|
709 | 4: t3+1 | |||
|
710 | 3: t3+0 | |||
|
711 | 2: t2+0 | |||
|
712 | 1: t1+0 | |||
|
713 | 0: null+1 | |||
|
714 | # merged tag overrides | |||
|
715 | 10: t5+5 | |||
|
716 | 9: t5+4 | |||
|
717 | 8: t5+3 | |||
|
718 | 7: t5+2 | |||
|
719 | 6: t5+1 | |||
|
720 | 5: t5+0 | |||
|
721 | 4: at3:t3+1 | |||
|
722 | 3: at3:t3+0 | |||
|
723 | 2: t2+0 | |||
|
724 | 1: t1+0 | |||
|
725 | 0: null+1 | |||
675 | # done |
|
726 | # done |
General Comments 0
You need to be logged in to leave comments.
Login now