[PATCH 1 of 4 V3] filemerge: add `summarize()`

Phil Cohen phillco at fb.com
Fri Mar 17 02:17:15 UTC 2017


# HG changeset patch
# User Phil Cohen <phillco at fb.com>
# Date 1489716177 25200
#      Thu Mar 16 19:02:57 2017 -0700
# Node ID ad81d182e88ffd3da20364f18204facf6e7750a3
# Parent  568d80b24b3a3e4e6874ac0d95ddee056fef14e4
filemerge: add `summarize()`

returns a dictionary of each version of a conflict, given the contexts

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -7,6 +7,7 @@
 
 from __future__ import absolute_import
 
+import copy
 import filecmp
 import os
 import re
@@ -567,6 +568,60 @@
         "o": " [%s]" % labels[1],
     }
 
+def summarize(repo, workingfilectx, otherctx, basectx):
+    origfile = None if workingfilectx.isabsent() else \
+        scmutil.origpath(repo.ui, repo, repo.wjoin(workingfilectx.path()))
+
+    def flags(context):
+        if isinstance(context, absentfilectx):
+            return {'exists': False}
+        return {
+            'contents': context.data(),
+            'exists': True,
+            'isexec': context.isexec(),
+            'issymlink': context.islink(),
+        }
+
+    output = flags(workingfilectx)
+
+    if origfile and util.filestat(origfile).stat:
+        # Since you can start a merge with a dirty working copy (either via
+        # `up -n` or `merge -f`), "local" must reflect that, not the underlying
+        # commit. Those contents are available in the .orig version, so we look
+        # there and mock up the schema to look like the other contexts.
+        local = {
+            'contents': util.readfile(origfile),
+            'exists': True,
+            'isexec': util.isexec(origfile),
+            'issymlink': util.statislink(util.filestat(origfile).stat),
+        }
+    else:
+        # No backup file. This happens whenever the merge was esoteric enough
+        # that we didn't launch a merge tool*, and instead prompted the user to
+        # "use (c)hanged version, (d)elete, or leave (u)nresolved".
+        #
+        # The only way to exit that prompt with a conflict is to choose "u",
+        # which leaves the local version in the working copy (with all its
+        # pre-merge properties including any local changes), so we can reuse
+        # that.
+        #
+        # Another alternative might be to use repo['.'][path] but that wouldn't
+        # have any dirty pre-merge changes.
+        #
+        # *If we had, we'd've we would've overwritten the working copy, made a
+        # backup and hit the above case.
+        local = copy.copy(output)
+
+    output['path'] = repo.wjoin(workingfilectx.path())
+
+    return {
+        'base': flags(basectx),
+        'local': local,
+        'other': flags(otherctx),
+        'output': output,
+        'path': workingfilectx.path(),
+    }
+
 def _filemerge(premerge, repo, mynode, orig, fcd, fco, fca, labels=None):
     """perform a 3-way merge in the working directory
 


More information about the Mercurial-devel mailing list