Patchwork [3,of,4,V3] commands: add --tool=internal:dumpjson to resolve

login
register
mail settings
Submitter Phillip Cohen
Date March 17, 2017, 2:17 a.m.
Message ID <36d378ac43dbbf559655.1489717037@phillco-mbp.dhcp.thefacebook.com>
Download mbox | patch
Permalink /patch/19416/
State Changes Requested
Headers show

Comments

Phillip Cohen - March 17, 2017, 2:17 a.m.
# HG changeset patch
# User Phil Cohen <phillco@fb.com>
# Date 1489716587 25200
#      Thu Mar 16 19:09:47 2017 -0700
# Node ID 36d378ac43dbbf559655c70b7cad873768a0e794
# Parent  864def5028681cdffeaf5b440ff4753e1389f453
commands: add --tool=internal:dumpjson to resolve

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -33,6 +33,7 @@ 
     error,
     exchange,
     extensions,
+    formatter,
     graphmod,
     hbisect,
     help,
@@ -4287,6 +4288,26 @@ 
         fm.end()
         return 0
 
+    if opts.get('tool', '') == "internal:dumpjson":
+        formatter = ui.formatter('resolve', {'template': 'json'})
+        mergestate = mergemod.mergestate.read(repo)
+        matcher = scmutil.match(repo[None], pats, opts)
+        workingctx = repo[None]
+
+        paths = []
+        for filename in mergestate:
+            if not matcher(filename):
+                continue
+
+            val = mergestate.summarizeconflicts(filename, workingctx)
+            if val is not None:
+                paths.append(val)
+
+        formatter.startitem()
+        formatter.write('conflicts', '%s\n', paths)
+        formatter.end()
+        return 0
+
     with repo.wlock():
         ms = mergemod.mergestate.read(repo)
 
diff --git a/tests/test-resolve-dumpjson.t b/tests/test-resolve-dumpjson.t
new file mode 100644
--- /dev/null
+++ b/tests/test-resolve-dumpjson.t
@@ -0,0 +1,83 @@ 
+1) Make the repo
+  $ hg init
+
+2) Can't run dumpjson outside a conflict
+  $ hg resolve --tool internal:dumpjson
+  abort: no files or directories specified
+  (use --all to re-merge all unresolved files)
+  [255]
+
+3) Make a simple conflict
+  $ echo "Unconflicted base, F1" > F1
+  $ echo "Unconflicted base, F2" > F2
+  $ hg commit -Aqm "initial commit"
+  $ echo "First conflicted version, F1" > F1
+  $ echo "First conflicted version, F2" > F2
+  $ hg commit -m "first version, a"
+  $ hg bookmark a
+  $ hg checkout .~1
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (leaving bookmark a)
+  $ echo "Second conflicted version, F1" > F1
+  $ echo "Second conflicted version, F2" > F2
+  $ hg commit -m "second version, b"
+  created new head
+  $ hg bookmark b 
+  $ hg log -G -T '({rev}) {desc}\nbookmark: {bookmarks}\nfiles: {files}\n\n'
+  @  (2) second version, b
+  |  bookmark: b
+  |  files: F1 F2
+  |
+  | o  (1) first version, a
+  |/   bookmark: a
+  |    files: F1 F2
+  |
+  o  (0) initial commit
+     bookmark:
+     files: F1 F2
+  
+
+
+  $ hg merge a
+  merging F1
+  merging F2
+  warning: conflicts while merging F1! (edit, then use 'hg resolve --mark')
+  warning: conflicts while merging F2! (edit, then use 'hg resolve --mark')
+  0 files updated, 0 files merged, 0 files removed, 2 files unresolved
+  use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
+  [1]
+
+5) Get the paths:
+  $ hg resolve --tool internal:dumpjson --all
+  [
+   {
+    "conflicts": [{"base": {"contents": "Unconflicted base, F1\n", "isexec": false, "issymlink": false}, "local": {"contents": "Second conflicted version, F1\n", "isexec": false, "issymlink": false}, "other": {"contents": "First conflicted version, F1\n", "isexec": false, "issymlink": false}, "output": {"contents": "<<<<<<< working copy: 13124abb51b9 b - test: second version, b\nSecond conflicted version, F1\n=======\nFirst conflicted version, F1\n>>>>>>> merge rev:    6dd692b7db4a a - test: first version, a\n", "isexec": false, "issymlink": false, "path": "$TESTTMP/F1"}, "path": "F1"}, {"base": {"contents": "Unconflicted base, F2\n", "isexec": false, "issymlink": false}, "local": {"contents": "Second conflicted version, F2\n", "isexec": false, "issymlink": false}, "other": {"contents": "First conflicted version, F2\n", "isexec": false, "issymlink": false}, "output": {"contents": "<<<<<<< working copy: 13124abb51b9 b - test: second version, b\nSecond conflicted version, F2\n=======\nFirst conflicted version, F2\n>>>>>>> merge rev:    6dd692b7db4a a - test: first version, a\n", "isexec": false, "issymlink": false, "path": "$TESTTMP/F2"}, "path": "F2"}]
+   }
+  ]
+
+6) Only requested paths get dumped
+  $ hg resolve --tool internal:dumpjson F2
+  [
+   {
+    "conflicts": [{"base": {"contents": "Unconflicted base, F2\n", "isexec": false, "issymlink": false}, "local": {"contents": "Second conflicted version, F2\n", "isexec": false, "issymlink": false}, "other": {"contents": "First conflicted version, F2\n", "isexec": false, "issymlink": false}, "output": {"contents": "<<<<<<< working copy: 13124abb51b9 b - test: second version, b\nSecond conflicted version, F2\n=======\nFirst conflicted version, F2\n>>>>>>> merge rev:    6dd692b7db4a a - test: first version, a\n", "isexec": false, "issymlink": false, "path": "$TESTTMP/F2"}, "path": "F2"}]
+   }
+  ]
+
+7) Ensure the paths point to the right contents:
+  $ getcontents() { # Usage: getcontents <path> <version>
+  >  local script="import sys, json; print json.load(sys.stdin)[0][\"conflicts\"][$1][\"$2\"][\"contents\"]"
+  >  local result=$(hg resolve --tool internal:dumpjson --all | python -c "$script")
+  >  echo "$result"
+  > }
+  $ echo $(getcontents 0 "base")
+  Unconflicted base, F1
+  $ echo $(getcontents 0 "other")
+  First conflicted version, F1
+  $ echo $(getcontents 0 "local")
+  Second conflicted version, F1
+  $ echo $(getcontents 1 "base")
+  Unconflicted base, F2
+  $ echo $(getcontents 1 "other")
+  First conflicted version, F2
+  $ echo $(getcontents 1 "local")
+  Second conflicted version, F2