obslog: add a patch option
authorBoris Feld <boris.feld@octobus.net>
Tue, 20 Jun 2017 13:49:40 +0200
changeset 2637 49f2741c4dd7
parent 2636 a788967aa800
child 2638 9290f985868c
obslog: add a patch option Add support for '--patch' option in obslog for a similar effect than "hg log --patch". The patch support is only limited to a few basic cases that will be extended in the future.
hgext3rd/evolve/obshistory.py
tests/test-evolve-obshistory.t
--- a/hgext3rd/evolve/obshistory.py	Mon Jun 19 19:00:31 2017 +0200
+++ b/hgext3rd/evolve/obshistory.py	Tue Jun 20 13:49:40 2017 +0200
@@ -14,6 +14,7 @@
     commands,
     error,
     graphmod,
+    patch,
     obsolete,
     node as nodemod,
     scmutil,
@@ -31,7 +32,8 @@
     'obslog|olog',
     [('G', 'graph', True, _("show the revision DAG")),
      ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
-     ('a', 'all', False, _('show all related changesets, not only precursors'))
+     ('a', 'all', False, _('show all related changesets, not only precursors')),
+     ('p', 'patch', False, _('show the patch between two obs versions'))
     ] + commands.formatteropts,
     _('hg olog [OPTION]... [REV]'))
 def cmdobshistory(ui, repo, *revs, **opts):
@@ -72,7 +74,7 @@
 
     fm = ui.formatter('debugobshistory', opts)
     revs.reverse()
-    _debugobshistoryrevs(fm, repo, revs)
+    _debugobshistoryrevs(fm, repo, revs, opts)
 
     fm.end()
 
@@ -97,11 +99,11 @@
 
             markerfm = fm.nested("debugobshistory.markers")
             for successor in succs:
-                _debugobshistorydisplaymarker(markerfm, successor)
+                _debugobshistorydisplaymarker(markerfm, successor,
+                                              ctx.node(), self.repo, self.diffopts)
             markerfm.end()
 
             markerfm.plain('\n')
-
             self.hunk[ctx.node()] = self.ui.popbuffer()
         else:
             ### graph output is buffered only
@@ -114,6 +116,46 @@
         '''
         pass
 
+def patchavailable(node, repo, marker):
+    if node not in repo:
+        return False, "context is not local"
+
+    successors = marker[1]
+
+    if len(successors) == 0:
+        return False, "no successors"
+    elif len(successors) > 1:
+        return False, "too many successors (%d)" % len(successors)
+
+    succ = successors[0]
+
+    if succ not in repo:
+        return False, "succ is unknown locally"
+
+    # Check that both node and succ have the same parents
+    nodep1, nodep2 = repo[node].p1(), repo[node].p2()
+    succp1, succp2 = repo[succ].p1(), repo[succ].p2()
+
+    if nodep1 != succp1 or nodep2 != succp2:
+        return False, "changesets rebased"
+
+    return True, succ
+
+def getmarkerpatch(repo, node, succ):
+    # Todo get the ops from the cmd
+    diffopts = patch.diffallopts(repo.ui, {})
+    matchfn = scmutil.matchall(repo)
+
+    repo.ui.pushbuffer()
+    cmdutil.diffordiffstat(repo.ui, repo, diffopts, node, succ,
+                           match=matchfn, stat=False)
+    buffer = repo.ui.popbuffer()
+
+    # Indent the buffer a little
+    splitted = buffer.splitlines(True)
+    splitted = ['    %s' % line for line in splitted]
+    return "".join(splitted)
+
 class missingchangectx(object):
     ''' a minimal object mimicking changectx for change contexts
     references by obs markers but not available locally '''
@@ -277,12 +319,16 @@
     return sorted(seen), nodesucc, nodeprec
 
 def _debugobshistorygraph(ui, repo, revs, opts):
-    displayer = obsmarker_printer(ui, repo.unfiltered(), None, opts, buffered=True)
+    matchfn = None
+    if opts.get('patch'):
+        matchfn = scmutil.matchall(repo)
+
+    displayer = obsmarker_printer(ui, repo.unfiltered(), matchfn, opts, buffered=True)
     edges = graphmod.asciiedges
     walker = _obshistorywalker(repo.unfiltered(), revs, opts.get('all', False))
     cmdutil.displaygraph(ui, repo, walker, displayer, edges)
 
-def _debugobshistoryrevs(fm, repo, revs):
+def _debugobshistoryrevs(fm, repo, revs, opts):
     """ Display the obsolescence history for revset
     """
     precursors = repo.obsstore.precursors
@@ -302,7 +348,7 @@
 
         markerfm = fm.nested("debugobshistory.markers")
         for successor in sorted(succs):
-            _debugobshistorydisplaymarker(markerfm, successor)
+            _debugobshistorydisplaymarker(markerfm, successor, ctxnode, repo, opts)
         markerfm.end()
 
         precs = precursors.get(ctxnode, ())
@@ -341,7 +387,7 @@
              label="evolve.node evolve.missing_change_ctx")
     fm.plain('\n')
 
-def _debugobshistorydisplaymarker(fm, marker):
+def _debugobshistorydisplaymarker(fm, marker, node, repo, opts):
     succnodes = marker[1]
     date = marker[4]
     metadata = dict(marker[3])
@@ -404,6 +450,19 @@
         fm.write('debugobshistory.succnodes', '%s', nodes,
                  label="evolve.node")
 
+    # Patch display
+    if opts.get('patch'):
+        _patchavailable = patchavailable(node, repo, marker)
+
+        if _patchavailable[0]:
+            patch = getmarkerpatch(repo, node, _patchavailable[1])
+        else:
+            patch = "    (No patch available yet, %s)" % _patchavailable[1]
+        if patch:
+            fm.plain("\n")
+            # should be in json too
+            fm.plain(patch)
+
     fm.plain("\n")
 
 # logic around storing and using effect flags
--- a/tests/test-evolve-obshistory.t	Mon Jun 19 19:00:31 2017 +0200
+++ b/tests/test-evolve-obshistory.t	Tue Jun 20 13:49:40 2017 +0200
@@ -55,11 +55,18 @@
   
 Actual test
 -----------
-  $ hg obslog 4ae3a4151de9
+  $ hg obslog --patch 4ae3a4151de9
   @  4ae3a4151de9 (3) A1
   |
   x  471f378eab4c (1) A0
-       rewritten(description, content) by test (*) as 4ae3a4151de9 (glob)
+       rewritten(description, content) by test (Thu Jan 01 00:00:00 1970 +0000) as 4ae3a4151de9
+         diff -r 471f378eab4c -r 4ae3a4151de9 A0
+         --- a/A0	Thu Jan 01 00:00:00 1970 +0000
+         +++ b/A0	Thu Jan 01 00:00:00 1970 +0000
+         @@ -1,1 +1,2 @@
+          A0
+         +42
+  
   
   $ hg obslog 4ae3a4151de9 --no-graph -Tjson | python -m json.tool
   [
@@ -92,9 +99,16 @@
           "debugobshistory.shortdescription": "A0"
       }
   ]
-  $ hg obslog --hidden 471f378eab4c
+  $ hg obslog --hidden --patch 471f378eab4c
   x  471f378eab4c (1) A0
        rewritten(description, content) by test (*) as 4ae3a4151de9 (glob)
+         diff -r 471f378eab4c -r 4ae3a4151de9 A0
+         --- a/A0	Thu Jan 01 00:00:00 1970 +0000
+         +++ b/A0	Thu Jan 01 00:00:00 1970 +0000
+         @@ -1,1 +1,2 @@
+          A0
+         +42
+  
   
   $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool
   [
@@ -183,9 +197,10 @@
 Actual test
 -----------
 
-  $ hg obslog 'desc(B0)' --hidden
+  $ hg obslog 'desc(B0)' --hidden --patch
   x  0dec01379d3b (2) B0
        pruned by test (*) (glob)
+         (No patch available yet, no successors)
   
   $ hg obslog 'desc(B0)' --hidden --no-graph -Tjson | python -m json.tool
   [
@@ -205,7 +220,7 @@
           "debugobshistory.shortdescription": "B0"
       }
   ]
-  $ hg obslog 'desc(A0)'
+  $ hg obslog 'desc(A0)' --patch
   @  471f378eab4c (1) A0
   
   $ hg obslog 'desc(A0)' --no-graph -Tjson | python -m json.tool
@@ -316,9 +331,10 @@
 -----------
 
 Check that debugobshistory on splitted commit show both targets
-  $ hg obslog 471597cad322 --hidden
+  $ hg obslog 471597cad322 --hidden --patch
   x  471597cad322 (1) A0
        rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
+         (No patch available yet, too many successors (2))
   
   $ hg obslog 471597cad322 --hidden --no-graph -Tjson | python -m json.tool
   [
@@ -348,56 +364,62 @@
   ]
 Check that debugobshistory on the first successor after split show
 the revision plus the splitted one
-  $ hg obslog 337fec4d2edc
+  $ hg obslog 337fec4d2edc --patch
   o  337fec4d2edc (2) A0
   |
   x  471597cad322 (1) A0
        rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
+         (No patch available yet, too many successors (2))
   
 With the all option, it should show the three changesets
-  $ hg obslog --all 337fec4d2edc
+  $ hg obslog --all 337fec4d2edc --patch
   o  337fec4d2edc (2) A0
   |
   | @  f257fde29c7a (3) A0
   |/
   x  471597cad322 (1) A0
        rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
+         (No patch available yet, too many successors (2))
   
 Check that debugobshistory on the second successor after split show
 the revision plus the splitted one
-  $ hg obslog f257fde29c7a
+  $ hg obslog f257fde29c7a --patch
   @  f257fde29c7a (3) A0
   |
   x  471597cad322 (1) A0
        rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
+         (No patch available yet, too many successors (2))
   
 With the all option, it should show the three changesets
-  $ hg obslog f257fde29c7a --all
+  $ hg obslog f257fde29c7a --all --patch
   o  337fec4d2edc (2) A0
   |
   | @  f257fde29c7a (3) A0
   |/
   x  471597cad322 (1) A0
        rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
+         (No patch available yet, too many successors (2))
   
 Obslog with all option all should also works on the splitted commit
-  $ hg obslog -a 471597cad322 --hidden
+  $ hg obslog -a 471597cad322 --hidden --patch
   o  337fec4d2edc (2) A0
   |
   | @  f257fde29c7a (3) A0
   |/
   x  471597cad322 (1) A0
        rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
+         (No patch available yet, too many successors (2))
   
 Check that debugobshistory on both successors after split show
 a coherent graph
-  $ hg obslog 'f257fde29c7a+337fec4d2edc'
+  $ hg obslog 'f257fde29c7a+337fec4d2edc' --patch
   o  337fec4d2edc (2) A0
   |
   | @  f257fde29c7a (3) A0
   |/
   x  471597cad322 (1) A0
        rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
+         (No patch available yet, too many successors (2))
   
   $ hg update 471597cad322
   abort: hidden revision '471597cad322'!
@@ -561,11 +583,12 @@
 Actual test
 -----------
 
-  $ hg obslog de7290d8b885 --hidden
+  $ hg obslog de7290d8b885 --hidden --patch
   x  de7290d8b885 (1) A0
        rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
+         (No patch available yet, too many successors (4))
   
-  $ hg obslog de7290d8b885 --hidden --all
+  $ hg obslog de7290d8b885 --hidden --all --patch
   o  1ae8bc733a14 (4) A0
   |
   | o  337fec4d2edc (2) A0
@@ -576,6 +599,7 @@
   |/
   x  de7290d8b885 (1) A0
        rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
+         (No patch available yet, too many successors (4))
   
   $ hg obslog de7290d8b885 --hidden --no-graph -Tjson | python -m json.tool
   [
@@ -605,11 +629,12 @@
           "debugobshistory.shortdescription": "A0"
       }
   ]
-  $ hg obslog c7f044602e9b
+  $ hg obslog c7f044602e9b --patch
   @  c7f044602e9b (5) A0
   |
   x  de7290d8b885 (1) A0
        rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
+         (No patch available yet, too many successors (4))
   
   $ hg obslog c7f044602e9b --no-graph -Tjson | python -m json.tool
   [
@@ -646,7 +671,7 @@
       }
   ]
 Check that debugobshistory on all heads show a coherent graph
-  $ hg obslog 2::5
+  $ hg obslog 2::5 --patch
   o  1ae8bc733a14 (4) A0
   |
   | o  337fec4d2edc (2) A0
@@ -657,8 +682,9 @@
   |/
   x  de7290d8b885 (1) A0
        rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
+         (No patch available yet, too many successors (4))
   
-  $ hg obslog 5 --all
+  $ hg obslog 5 --all --patch
   o  1ae8bc733a14 (4) A0
   |
   | o  337fec4d2edc (2) A0
@@ -669,6 +695,7 @@
   |/
   x  de7290d8b885 (1) A0
        rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
+         (No patch available yet, too many successors (4))
   
   $ hg update de7290d8b885
   abort: hidden revision 'de7290d8b885'!
@@ -738,46 +765,74 @@
 
 Check that debugobshistory on the first folded revision show only
 the revision with the target
-  $ hg obslog --hidden 471f378eab4c
+  $ hg obslog --hidden 471f378eab4c --patch
   x  471f378eab4c (1) A0
        rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+         diff -r 471f378eab4c -r eb5a0daa2192 B0
+         --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+         +++ b/B0	Thu Jan 01 00:00:00 1970 +0000
+         @@ -0,0 +1,1 @@
+         +B0
+  
   
 Check that with all option, all changesets are shown
-  $ hg obslog --hidden --all 471f378eab4c
+  $ hg obslog --hidden --all 471f378eab4c --patch
   @    eb5a0daa2192 (3) C0
   |\
   x |  0dec01379d3b (2) B0
    /     rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
+  |        (No patch available yet, changesets rebased)
   |
   x  471f378eab4c (1) A0
        rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+         diff -r 471f378eab4c -r eb5a0daa2192 B0
+         --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+         +++ b/B0	Thu Jan 01 00:00:00 1970 +0000
+         @@ -0,0 +1,1 @@
+         +B0
+  
   
 Check that debugobshistory on the second folded revision show only
 the revision with the target
-  $ hg obslog --hidden 0dec01379d3b
+  $ hg obslog --hidden 0dec01379d3b --patch
   x  0dec01379d3b (2) B0
        rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
+         (No patch available yet, changesets rebased)
   
 Check that with all option, all changesets are shown
-  $ hg obslog --hidden --all 0dec01379d3b
+  $ hg obslog --hidden --all 0dec01379d3b --patch
   @    eb5a0daa2192 (3) C0
   |\
   x |  0dec01379d3b (2) B0
    /     rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
+  |        (No patch available yet, changesets rebased)
   |
   x  471f378eab4c (1) A0
        rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+         diff -r 471f378eab4c -r eb5a0daa2192 B0
+         --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+         +++ b/B0	Thu Jan 01 00:00:00 1970 +0000
+         @@ -0,0 +1,1 @@
+         +B0
+  
   
 Check that debugobshistory on the successor revision show a coherent
 graph
-  $ hg obslog eb5a0daa2192
+  $ hg obslog eb5a0daa2192 --patch
   @    eb5a0daa2192 (3) C0
   |\
   x |  0dec01379d3b (2) B0
    /     rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
+  |        (No patch available yet, changesets rebased)
   |
   x  471f378eab4c (1) A0
        rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+         diff -r 471f378eab4c -r eb5a0daa2192 B0
+         --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+         +++ b/B0	Thu Jan 01 00:00:00 1970 +0000
+         @@ -0,0 +1,1 @@
+         +B0
+  
   
   $ hg obslog eb5a0daa2192 --no-graph -Tjson | python -m json.tool
   [
@@ -917,14 +972,14 @@
 -----------
 
 Check that debugobshistory on the divergent revision show both destinations
-  $ hg obslog --hidden 471f378eab4c
+  $ hg obslog --hidden 471f378eab4c --patch
   x  471f378eab4c (1) A0
        rewritten(description) by test (*) as 65b757b745b9 (glob)
        rewritten(description) by test (*) as fdf9bde5129a (glob)
   
 
 Check that with all option, every changeset is shown
-  $ hg obslog --hidden --all 471f378eab4c
+  $ hg obslog --hidden --all 471f378eab4c --patch
   @  65b757b745b9 (3) A2
   |
   | o  fdf9bde5129a (2) A1
@@ -973,7 +1028,7 @@
   ]
 Check that debugobshistory on the first diverged revision show the revision
 and the diverent one
-  $ hg obslog fdf9bde5129a
+  $ hg obslog fdf9bde5129a --patch
   o  fdf9bde5129a (2) A1
   |
   x  471f378eab4c (1) A0
@@ -982,7 +1037,7 @@
   
 
 Check that all option show all of them
-  $ hg obslog fdf9bde5129a -a
+  $ hg obslog fdf9bde5129a -a --patch
   @  65b757b745b9 (3) A2
   |
   | o  fdf9bde5129a (2) A1
@@ -993,7 +1048,7 @@
   
 Check that debugobshistory on the second diverged revision show the revision
 and the diverent one
-  $ hg obslog 65b757b745b9
+  $ hg obslog 65b757b745b9 --patch
   @  65b757b745b9 (3) A2
   |
   x  471f378eab4c (1) A0
@@ -1001,7 +1056,7 @@
        rewritten(description) by test (*) as fdf9bde5129a (glob)
   
 Check that all option show all of them
-  $ hg obslog 65b757b745b9 -a
+  $ hg obslog 65b757b745b9 -a --patch
   @  65b757b745b9 (3) A2
   |
   | o  fdf9bde5129a (2) A1
@@ -1012,7 +1067,7 @@
   
 Check that debugobshistory on the both diverged revision show a coherent
 graph
-  $ hg obslog '65b757b745b9+fdf9bde5129a'
+  $ hg obslog '65b757b745b9+fdf9bde5129a' --patch
   @  65b757b745b9 (3) A2
   |
   | o  fdf9bde5129a (2) A1
@@ -1151,27 +1206,41 @@
  -----------
 
 Check that debugobshistory on head show a coherent graph
-  $ hg obslog eb5a0daa2192
+  $ hg obslog eb5a0daa2192 --patch
   @    eb5a0daa2192 (4) C0
   |\
   x |  471f378eab4c (1) A0
    /     rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+  |        diff -r 471f378eab4c -r eb5a0daa2192 B0
+  |        --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ b/B0	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -0,0 +1,1 @@
+  |        +B0
+  |
   |
   x  b7ea6d14e664 (3) B1
   |    rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
+  |      (No patch available yet, changesets rebased)
   |
   x  0dec01379d3b (2) B0
        rewritten(description) by test (*) as b7ea6d14e664 (glob)
   
 Check that obslog on ROOT with all option show everything
-  $ hg obslog 1 --hidden --all
+  $ hg obslog 1 --hidden --all --patch
   @    eb5a0daa2192 (4) C0
   |\
   x |  471f378eab4c (1) A0
    /     rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+  |        diff -r 471f378eab4c -r eb5a0daa2192 B0
+  |        --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ b/B0	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -0,0 +1,1 @@
+  |        +B0
+  |
   |
   x  b7ea6d14e664 (3) B1
   |    rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
+  |      (No patch available yet, changesets rebased)
   |
   x  0dec01379d3b (2) B0
        rewritten(description) by test (*) as b7ea6d14e664 (glob)
@@ -1340,7 +1409,7 @@
  Actual test
  -----------
 
-  $ hg obslog 7a230b46bf61
+  $ hg obslog 7a230b46bf61 --patch
   @  7a230b46bf61 (3) A2
   |
   x  fdf9bde5129a (2) A1
@@ -1363,21 +1432,25 @@
   (use 'hg evolve' to update to its successor: 7a230b46bf61)
 Check that debugobshistory works with markers pointing to missing local
 changectx
-  $ hg obslog 7a230b46bf61
+  $ hg obslog 7a230b46bf61 --patch
   o  7a230b46bf61 (2) A2
   |
   x  fdf9bde5129a
   |    rewritten(description) by test (*) as 7a230b46bf61 (glob)
+  |      (No patch available yet, context is not local)
   |
   @  471f378eab4c (1) A0
        rewritten(description) by test (*) as fdf9bde5129a (glob)
+         (No patch available yet, succ is unknown locally)
   
-  $ hg obslog 7a230b46bf61 --color=debug
+  $ hg obslog 7a230b46bf61 --color=debug --patch
   o  [evolve.node|7a230b46bf61] [evolve.rev|(2)] [evolve.short_description|A2]
   |
   x  [evolve.node evolve.missing_change_ctx|fdf9bde5129a]
   |    [evolve.verb|rewritten](description) by [evolve.user|test] [evolve.date|(*)] as [evolve.node|7a230b46bf61] (glob)
+  |      (No patch available yet, context is not local)
   |
   @  [evolve.node|471f378eab4c] [evolve.rev|(1)] [evolve.short_description|A0]
        [evolve.verb|rewritten](description) by [evolve.user|test] [evolve.date|(*)] as [evolve.node|fdf9bde5129a] (glob)
+         (No patch available yet, succ is unknown locally)