template: add successors template
authorBoris Feld <boris.feld@octobus.net>
Fri, 26 May 2017 10:05:37 +0200
changeset 2487 590da9c523ae
parent 2486 cd4290f923b7
child 2488 1bdbe8f55339
template: add successors template The successors templates display the closest visible successors of each changeset, we may have gap, like in this case: A -> B -> C -> D If we display A, C and D but not B, we can't display than B is the closest successor of A because it's not displayed. We display C as the closest successor of A instead.
README
hgext3rd/evolve/templatekw.py
tests/test-evolve-templates.t
--- a/README	Fri May 26 10:05:27 2017 +0200
+++ b/README	Fri May 26 10:05:37 2017 +0200
@@ -118,6 +118,7 @@
  - olog: add an 'obslog' alias
  - olog: add an '--all' option to show the whole obsolescence history tree.
  - template: add a 'precursors' template that display the closests precursors of changesets
+ - template: add a 'successors' template that display the closests successors of changesets
 
 6.2.2 - in progress
 -------------------
--- a/hgext3rd/evolve/templatekw.py	Fri May 26 10:05:27 2017 +0200
+++ b/hgext3rd/evolve/templatekw.py	Fri May 26 10:05:37 2017 +0200
@@ -74,3 +74,107 @@
     # XXX: I think we could returns something close to a "changectx" that would allow template to alter the way we render this.
     shortnodes = map(node.short, sorted(closestprecursors(repo, ctx.node())))
     return ', '.join(shortnodes)
+
+def closestsuccessors(repo, nodeid):
+    """ returns the closest visible successors sets instead.
+    """
+    return directsuccessorssets(repo, nodeid)
+
+@eh.templatekw("successors")
+def shownextvisiblesuccessors(repo, ctx, templ, **args):
+    """Returns a string of sets of successors for a changectx in this format:
+    [ctx1, ctx2], [ctx3] if ctx has been splitted into ctx1 and ctx2 while
+    also diverged into ctx3"""
+    if not ctx.obsolete():
+        return ''
+
+    ssets = closestsuccessors(repo, ctx.node())
+
+    final = []
+    for ss in ssets:
+        final.append('[%s]' % ', '.join(map(node.short, ss)))
+
+    return ', '.join(final)
+
+# copy from mercurial.obsolete with a small change to stop at first known changeset.
+
+def directsuccessorssets(repo, initialnode, cache=None):
+    """return set of all direct successors of initial nodes
+    """
+
+    succmarkers = repo.obsstore.successors
+
+    # Stack of nodes we search successors sets for
+    toproceed = [initialnode]
+    # set version of above list for fast loop detection
+    # element added to "toproceed" must be added here
+    stackedset = set(toproceed)
+    if cache is None:
+        cache = {}
+    while toproceed:
+        current = toproceed[-1]
+        if current in cache:
+            stackedset.remove(toproceed.pop())
+        elif current != initialnode and current in repo:
+            # We have a valid direct successors.
+            cache[current] = [(current,)]
+        elif current not in succmarkers:
+            if current in repo:
+                # We have a valid last successors.
+                cache[current] = [(current,)]
+            else:
+                # Final obsolete version is unknown locally.
+                # Do not count that as a valid successors
+                cache[current] = []
+        else:
+            for mark in sorted(succmarkers[current]):
+                for suc in mark[1]:
+                    if suc not in cache:
+                        if suc in stackedset:
+                            # cycle breaking
+                            cache[suc] = []
+                        else:
+                            # case (3) If we have not computed successors sets
+                            # of one of those successors we add it to the
+                            # `toproceed` stack and stop all work for this
+                            # iteration.
+                            toproceed.append(suc)
+                            stackedset.add(suc)
+                            break
+                else:
+                    continue
+                break
+            else:
+                succssets = []
+                for mark in sorted(succmarkers[current]):
+                    # successors sets contributed by this marker
+                    markss = [[]]
+                    for suc in mark[1]:
+                        # cardinal product with previous successors
+                        productresult = []
+                        for prefix in markss:
+                            for suffix in cache[suc]:
+                                newss = list(prefix)
+                                for part in suffix:
+                                    # do not duplicated entry in successors set
+                                    # first entry wins.
+                                    if part not in newss:
+                                        newss.append(part)
+                                productresult.append(newss)
+                        markss = productresult
+                    succssets.extend(markss)
+                # remove duplicated and subset
+                seen = []
+                final = []
+                candidate = sorted(((set(s), s) for s in succssets if s),
+                                   key=lambda x: len(x[1]), reverse=True)
+                for setversion, listversion in candidate:
+                    for seenset in seen:
+                        if setversion.issubset(seenset):
+                            break
+                    else:
+                        final.append(listversion)
+                        seen.append(setversion)
+                final.reverse() # put small successors set first
+                cache[current] = final
+    return cache[initialnode]
--- a/tests/test-evolve-templates.t	Fri May 26 10:05:27 2017 +0200
+++ b/tests/test-evolve-templates.t	Fri May 26 10:05:37 2017 +0200
@@ -12,7 +12,7 @@
   > [extensions]
   > evolve =
   > [alias]
-  > tlog = log -G -T '{node|short} Precursors: {precursors}\n'
+  > tlog = log -G -T '{node|short} Precursors: {precursors} | Successors: {successors}\n'
   > EOF
 
 Test templates on amended commit
@@ -26,16 +26,21 @@
   $ mkcommit ROOT
   $ mkcommit A0
   $ echo 42 >> A0
-  $ hg amend -m "A1
-  > 
-  > Better commit message"
+  $ hg amend -m "A1"
+  $ hg amend -m "A2"
   $ hg log --hidden -G
-  @  changeset:   3:4ae3a4151de9
+  @  changeset:   4:d004c8f274b9
   |  tag:         tip
   |  parent:      0:ea207398892e
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     A1
+  |  summary:     A2
+  |
+  | x  changeset:   3:a468dc9b3633
+  |/   parent:      0:ea207398892e
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     A1
   |
   | x  changeset:   2:f137d23bb3e1
   | |  user:        test
@@ -57,36 +62,60 @@
   $ hg up 'desc(A0)' --hidden
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory parent is obsolete! (471f378eab4c)
-  (use 'hg evolve' to update to its successor: 4ae3a4151de9)
+  (use 'hg evolve' to update to its successor: d004c8f274b9)
+
+Precursors template should show current revision as it is the working copy
+  $ hg tlog
+  o  d004c8f274b9 Precursors: 471f378eab4c | Successors:
+  |
+  | @  471f378eab4c Precursors:  | Successors: [d004c8f274b9]
+  |/
+  o  ea207398892e Precursors:  | Successors:
+  
+  $ hg up 'desc(A1)' --hidden
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  working directory parent is obsolete! (a468dc9b3633)
+  (use 'hg evolve' to update to its successor: d004c8f274b9)
 
 Precursors template should show current revision as it is the working copy
   $ hg tlog
-  o  4ae3a4151de9 Precursors: 471f378eab4c
+  o  d004c8f274b9 Precursors: a468dc9b3633 | Successors:
   |
-  | @  471f378eab4c Precursors:
+  | @  a468dc9b3633 Precursors:  | Successors: [d004c8f274b9]
   |/
-  o  ea207398892e Precursors:
-  
-  $ hg up 'desc(A1)'
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-Precursors template should not show a precursor as it's not displayed in the
-log
-  $ hg tlog
-  @  4ae3a4151de9 Precursors:
-  |
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
 Precursors template should show the precursor as we force its display with
---hidden
+--hidden  
   $ hg tlog --hidden
-  @  4ae3a4151de9 Precursors: 471f378eab4c
+  o  d004c8f274b9 Precursors: a468dc9b3633 | Successors:
   |
-  | x  f137d23bb3e1 Precursors:
+  | @  a468dc9b3633 Precursors: 471f378eab4c | Successors: [d004c8f274b9]
+  |/
+  | x  f137d23bb3e1 Precursors:  | Successors:
   | |
-  | x  471f378eab4c Precursors:
+  | x  471f378eab4c Precursors:  | Successors: [a468dc9b3633]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
+  
+
+  $ hg up 'desc(A2)'
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg tlog
+  @  d004c8f274b9 Precursors:  | Successors:
+  |
+  o  ea207398892e Precursors:  | Successors:
+  
+  $ hg tlog --hidden
+  @  d004c8f274b9 Precursors: a468dc9b3633 | Successors:
+  |
+  | x  a468dc9b3633 Precursors: 471f378eab4c | Successors: [d004c8f274b9]
+  |/
+  | x  f137d23bb3e1 Precursors:  | Successors:
+  | |
+  | x  471f378eab4c Precursors:  | Successors: [a468dc9b3633]
+  |/
+  o  ea207398892e Precursors:  | Successors:
   
 
 Test templates with splitted commit
@@ -181,13 +210,13 @@
 
 Precursors template should show current revision as it is the working copy
   $ hg tlog
-  o  f257fde29c7a Precursors: 471597cad322
+  o  f257fde29c7a Precursors: 471597cad322 | Successors:
   |
-  o  337fec4d2edc Precursors: 471597cad322
+  o  337fec4d2edc Precursors: 471597cad322 | Successors:
   |
-  | @  471597cad322 Precursors:
+  | @  471597cad322 Precursors:  | Successors: [337fec4d2edc, f257fde29c7a]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg up f257fde29c7a
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -195,22 +224,22 @@
 Precursors template should not show a precursor as it's not displayed in the
 log
   $ hg tlog
-  @  f257fde29c7a Precursors:
+  @  f257fde29c7a Precursors:  | Successors:
   |
-  o  337fec4d2edc Precursors:
+  o  337fec4d2edc Precursors:  | Successors:
   |
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
 Precursors template should show the precursor as we force its display with
 --hidden
   $ hg tlog --hidden
-  @  f257fde29c7a Precursors: 471597cad322
+  @  f257fde29c7a Precursors: 471597cad322 | Successors:
   |
-  o  337fec4d2edc Precursors: 471597cad322
+  o  337fec4d2edc Precursors: 471597cad322 | Successors:
   |
-  | x  471597cad322 Precursors:
+  | x  471597cad322 Precursors:  | Successors: [337fec4d2edc, f257fde29c7a]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
 Test templates with folded commit
 ==============================
@@ -276,11 +305,11 @@
 
 Precursors template should show current revision as it is the working copy
   $ hg tlog
-  o  eb5a0daa2192 Precursors: 471f378eab4c
+  o  eb5a0daa2192 Precursors: 471f378eab4c | Successors:
   |
-  | @  471f378eab4c Precursors:
+  | @  471f378eab4c Precursors:  | Successors: [eb5a0daa2192]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg up 'desc(B0)' --hidden
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -290,13 +319,13 @@
 Precursors template should show both precursors as they should be both
 displayed
   $ hg tlog
-  o  eb5a0daa2192 Precursors: 0dec01379d3b, 471f378eab4c
+  o  eb5a0daa2192 Precursors: 0dec01379d3b, 471f378eab4c | Successors:
   |
-  | @  0dec01379d3b Precursors:
+  | @  0dec01379d3b Precursors:  | Successors: [eb5a0daa2192]
   | |
-  | x  471f378eab4c Precursors:
+  | x  471f378eab4c Precursors:  | Successors: [eb5a0daa2192]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg up 'desc(C0)'
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -304,20 +333,20 @@
 Precursors template should not show precursors as it's not displayed in the
 log
   $ hg tlog
-  @  eb5a0daa2192 Precursors:
+  @  eb5a0daa2192 Precursors:  | Successors:
   |
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
 Precursors template should show both precursors as we force its display with
 --hidden
   $ hg tlog --hidden
-  @  eb5a0daa2192 Precursors: 0dec01379d3b, 471f378eab4c
+  @  eb5a0daa2192 Precursors: 0dec01379d3b, 471f378eab4c | Successors:
   |
-  | x  0dec01379d3b Precursors:
+  | x  0dec01379d3b Precursors:  | Successors: [eb5a0daa2192]
   | |
-  | x  471f378eab4c Precursors:
+  | x  471f378eab4c Precursors:  | Successors: [eb5a0daa2192]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
 
 Test templates with divergence
@@ -381,6 +410,8 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     ROOT
   
+  $ hg amend -m 'A3'
+
 Check templates
 ---------------
 
@@ -391,34 +422,36 @@
 
 Precursors template should show current revision as it is the working copy
   $ hg tlog
-  o  65b757b745b9 Precursors: 471f378eab4c
+  o  019fadeab383 Precursors: 471f378eab4c | Successors:
   |
-  | o  fdf9bde5129a Precursors: 471f378eab4c
+  | o  fdf9bde5129a Precursors: 471f378eab4c | Successors:
   |/
-  | @  471f378eab4c Precursors:
+  | @  471f378eab4c Precursors:  | Successors: [fdf9bde5129a], [019fadeab383]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg up 'desc(A1)'
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 Precursors template should not show precursors as it's not displayed in the
 log
   $ hg tlog
-  o  65b757b745b9 Precursors:
+  o  019fadeab383 Precursors:  | Successors:
   |
-  | @  fdf9bde5129a Precursors:
+  | @  fdf9bde5129a Precursors:  | Successors:
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
 Precursors template should a precursor as we force its display with --hidden
   $ hg tlog --hidden
-  o  65b757b745b9 Precursors: 471f378eab4c
+  o  019fadeab383 Precursors: 65b757b745b9 | Successors:
   |
-  | @  fdf9bde5129a Precursors: 471f378eab4c
+  | x  65b757b745b9 Precursors: 471f378eab4c | Successors: [019fadeab383]
   |/
-  | x  471f378eab4c Precursors:
+  | @  fdf9bde5129a Precursors: 471f378eab4c | Successors:
   |/
-  o  ea207398892e Precursors:
+  | x  471f378eab4c Precursors:  | Successors: [fdf9bde5129a], [65b757b745b9]
+  |/
+  o  ea207398892e Precursors:  | Successors:
   
 Test templates with amended + folded commit
 ===========================================
@@ -495,55 +528,55 @@
   working directory parent is obsolete! (471f378eab4c)
   (use 'hg evolve' to update to its successor: eb5a0daa2192)
   $ hg tlog
-  o  eb5a0daa2192 Precursors: 471f378eab4c
+  o  eb5a0daa2192 Precursors: 471f378eab4c | Successors:
   |
-  | @  471f378eab4c Precursors:
+  | @  471f378eab4c Precursors:  | Successors: [eb5a0daa2192]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg up 'desc(B0)' --hidden
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory parent is obsolete! (0dec01379d3b)
   (use 'hg evolve' to update to its successor: eb5a0daa2192)
   $ hg tlog
-  o  eb5a0daa2192 Precursors: 0dec01379d3b, 471f378eab4c
+  o  eb5a0daa2192 Precursors: 0dec01379d3b, 471f378eab4c | Successors:
   |
-  | @  0dec01379d3b Precursors:
+  | @  0dec01379d3b Precursors:  | Successors: [eb5a0daa2192]
   | |
-  | x  471f378eab4c Precursors:
+  | x  471f378eab4c Precursors:  | Successors: [eb5a0daa2192]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg up 'desc(B1)' --hidden
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory parent is obsolete! (b7ea6d14e664)
   (use 'hg evolve' to update to its successor: eb5a0daa2192)
   $ hg tlog
-  o  eb5a0daa2192 Precursors: 471f378eab4c, b7ea6d14e664
+  o  eb5a0daa2192 Precursors: 471f378eab4c, b7ea6d14e664 | Successors:
   |
-  | @  b7ea6d14e664 Precursors:
+  | @  b7ea6d14e664 Precursors:  | Successors: [eb5a0daa2192]
   | |
-  | x  471f378eab4c Precursors:
+  | x  471f378eab4c Precursors:  | Successors: [eb5a0daa2192]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg up 'desc(C0)'
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg tlog
-  @  eb5a0daa2192 Precursors:
+  @  eb5a0daa2192 Precursors:  | Successors:
   |
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg tlog --hidden
-  @  eb5a0daa2192 Precursors: 471f378eab4c, b7ea6d14e664
+  @  eb5a0daa2192 Precursors: 471f378eab4c, b7ea6d14e664 | Successors:
   |
-  | x  b7ea6d14e664 Precursors: 0dec01379d3b
+  | x  b7ea6d14e664 Precursors: 0dec01379d3b | Successors: [eb5a0daa2192]
   | |
-  | | x  0dec01379d3b Precursors:
+  | | x  0dec01379d3b Precursors:  | Successors: [b7ea6d14e664]
   | |/
-  | x  471f378eab4c Precursors:
+  | x  471f378eab4c Precursors:  | Successors: [eb5a0daa2192]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
 
 Test template with pushed and pulled obs markers
@@ -634,23 +667,23 @@
 ---------------
 
   $ hg tlog
-  o  7a230b46bf61 Precursors: 471f378eab4c
+  o  7a230b46bf61 Precursors: 471f378eab4c | Successors:
   |
-  | @  471f378eab4c Precursors:
+  | @  471f378eab4c Precursors:  | Successors: [7a230b46bf61]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg up 'desc(A2)'
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg tlog
-  @  7a230b46bf61 Precursors:
+  @  7a230b46bf61 Precursors:  | Successors:
   |
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors:
   
   $ hg tlog --hidden
-  @  7a230b46bf61 Precursors: 471f378eab4c
+  @  7a230b46bf61 Precursors: 471f378eab4c | Successors:
   |
-  | x  471f378eab4c Precursors:
+  | x  471f378eab4c Precursors:  | Successors: [7a230b46bf61]
   |/
-  o  ea207398892e Precursors:
+  o  ea207398892e Precursors:  | Successors: