diff mercurial/templatekw.py @ 33670:fb672eac2702 stable

templatekw: choose {latesttag} by len(changes), not date (issue5659) As Augie reported in the bug, the current heuristic of choosing the best tag of a merge commit by taking the one with newest tag (in terms of tagging date) currently fails in the Mercurial repo itself. Copying the example from Yuya: $ hg glog -T '{node|short} {latesttag}+{latesttagdistance}\n' \ -r '4.2.3: & (merge() + parents(merge()) + tag())' o 02a745c20121 4.2.3+5 |\ | o 86aca74a063b 4.2.3+4 | |\ | | o e6d8ee3c9ec3 4.3-rc+109 | | | | | ~ o | a3ce07e2dde5 4.3.1+2 : | o | 3fee7f7d2da0 4.3.1+0 |/ o 98e990bb7330 4.2.3+3 |\ | ~ o 506d7e48fbe6 4.2.3+2 : o 943c91326b23 4.2.3+0 | ~ It seems to me like the best choice is the tag with the smallest number of changes since it (across all paths, not the longest single path). So that's what this patch does, even though it's costly. Best-of-5 timings for Yuya's command above shows a slowdown from 1.293s to 1.610s. We can optimize it later. Differential Revision: https://phab.mercurial-scm.org/D447
author Martin von Zweigbergk <martinvonz@google.com>
date Tue, 15 Aug 2017 23:23:55 -0700
parents c0d8de2724ce
children af20468eb0a4
line wrap: on
line diff
--- a/mercurial/templatekw.py	Fri Aug 18 12:50:26 2017 -0700
+++ b/mercurial/templatekw.py	Tue Aug 15 23:23:55 2017 -0700
@@ -208,10 +208,22 @@
             latesttags[rev] = ctx.date()[0], 0, [t for t in sorted(tags)]
             continue
         try:
-            # The tuples are laid out so the right one can be found by
-            # comparison.
-            pdate, pdist, ptag = max(
-                latesttags[p.rev()] for p in ctx.parents())
+            ptags = [latesttags[p.rev()] for p in ctx.parents()]
+            if len(ptags) > 1:
+                if ptags[0][2] == ptags[1][2]:
+                    # The tuples are laid out so the right one can be found by
+                    # comparison in this case.
+                    pdate, pdist, ptag = max(ptags)
+                else:
+                    def key(x):
+                        changessincetag = len(repo.revs('only(%d, %s)',
+                                                        ctx.rev(), x[2][0]))
+                        # Smallest number of changes since tag wins. Date is
+                        # used as tiebreaker.
+                        return [-changessincetag, x[0]]
+                    pdate, pdist, ptag = max(ptags, key=key)
+            else:
+                pdate, pdist, ptag = ptags[0]
         except KeyError:
             # Cache miss - recurse
             todo.append(rev)