Patchwork D2889: filemerge: make the 'local' path match the format that 'base' and 'other' use

login
register
mail settings
Submitter phabricator
Date March 21, 2018, 8:48 p.m.
Message ID <e886f36a7a697593a4ed68346c1f515d@localhost.localdomain>
Download mbox | patch
Permalink /patch/29715/
State Not Applicable
Headers show

Comments

phabricator - March 21, 2018, 8:48 p.m.
spectral updated this revision to Diff 7189.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2889?vs=7087&id=7189

REVISION DETAIL
  https://phab.mercurial-scm.org/D2889

AFFECTED FILES
  mercurial/filemerge.py
  tests/test-merge-tools.t

CHANGE DETAILS




To: spectral, #hg-reviewers, yuja
Cc: yuja, mercurial-devel

Patch

diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
--- a/tests/test-merge-tools.t
+++ b/tests/test-merge-tools.t
@@ -1585,7 +1585,7 @@ 
   $ hg update -q -C 2
   $ hg merge -y -r tip --tool echo --config merge-tools.echo.args='$base $local $other $output'
   merging f and f.txt to f.txt
-  */f~base.* $TESTTMP/f.txt.orig */f~other.*.txt $TESTTMP/f.txt (glob)
+  */f~base.* */f~local.*.txt */f~other.*.txt $TESTTMP/f.txt (glob)
   0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
@@ -1600,7 +1600,7 @@ 
   >    --config merge-tools.echo.args='$base $local $other $output' \
   >    --config experimental.mergetempdirprefix=$TESTTMP/hgmerge.
   merging f and f.txt to f.txt
-  $TESTTMP/hgmerge.*/f~base $TESTTMP/f.txt.orig $TESTTMP/hgmerge.*/f~other.txt $TESTTMP/f.txt (glob)
+  $TESTTMP/hgmerge.*/f~base $TESTTMP/hgmerge.*/f~local.txt $TESTTMP/hgmerge.*/f~other.txt $TESTTMP/f.txt (glob)
   0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -512,8 +512,11 @@ 
         return False, 1, None
     unused, unused, unused, back = files
     localpath = _workingpath(repo, fcd)
-    with _maketempfiles(repo, fco, fca) as temppaths:
-        basepath, otherpath = temppaths
+    args = _toolstr(repo.ui, tool, "args")
+
+    with _maketempfiles(repo, fco, fca, repo.wvfs.join(back.path()),
+                        "$output" in args) as temppaths:
+        basepath, otherpath, localoutputpath = temppaths
         outpath = ""
         mylabel, otherlabel = labels[:2]
         if len(labels) >= 3:
@@ -533,11 +536,10 @@ 
                }
         ui = repo.ui
 
-        args = _toolstr(ui, tool, "args")
         if "$output" in args:
             # read input from backup, write to original
             outpath = localpath
-            localpath = repo.wvfs.join(back.path())
+            localpath = localoutputpath
         replace = {'local': localpath, 'base': basepath, 'other': otherpath,
                    'output': outpath, 'labellocal': mylabel,
                    'labelother': otherlabel, 'labelbase': baselabel}
@@ -665,41 +667,61 @@ 
         return context.arbitraryfilectx(back, repo=repo)
 
 @contextlib.contextmanager
-def _maketempfiles(repo, fco, fca):
-    """Writes out `fco` and `fca` as temporary files, so an external merge
-    tool may use them.
+def _maketempfiles(repo, fco, fca, localpath, uselocalpath):
+    """Writes out `fco` and `fca` as temporary files, and (if uselocalpath)
+    copies `localpath` to another temporary file, so an external merge tool may
+    use them.
     """
     tmproot = None
     tmprootprefix = repo.ui.config('experimental', 'mergetempdirprefix')
     if tmprootprefix:
         tmproot = tempfile.mkdtemp(prefix=tmprootprefix)
 
-    def temp(prefix, ctx):
-        fullbase, ext = os.path.splitext(ctx.path())
+    def maketempfrompath(prefix, path):
+        fullbase, ext = os.path.splitext(path)
         pre = "%s~%s" % (os.path.basename(fullbase), prefix)
         if tmproot:
             name = os.path.join(tmproot, pre)
             if ext:
                 name += ext
             f = open(name, r"wb")
         else:
-            (fd, name) = tempfile.mkstemp(prefix=pre + '.', suffix=ext)
+            fd, name = tempfile.mkstemp(prefix=pre + '.', suffix=ext)
             f = os.fdopen(fd, r"wb")
+        return f, name
+
+    def tempfromcontext(prefix, ctx):
+        f, name = maketempfrompath(prefix, ctx.path())
         data = repo.wwritedata(ctx.path(), ctx.data())
         f.write(data)
         f.close()
         return name
 
-    b = temp("base", fca)
-    c = temp("other", fco)
+    b = tempfromcontext("base", fca)
+    c = tempfromcontext("other", fco)
+    d = localpath
+    if uselocalpath:
+        # We start off with this being the backup filename, so remove the .orig
+        # to make syntax-highlighting more likely.
+        if d.endswith('.orig'):
+            d, _ = os.path.splitext(d)
+        f, d = maketempfrompath("local", d)
+        with open(localpath, 'rb') as src:
+            f.write(src.read())
+        f.close()
+
     try:
-        yield b, c
+        yield b, c, d
     finally:
         if tmproot:
             shutil.rmtree(tmproot)
         else:
             util.unlink(b)
             util.unlink(c)
+            # if not uselocalpath, d is the 'orig'/backup file which we
+            # shouldn't delete.
+            if d and uselocalpath:
+                util.unlink(d)
 
 def _filemerge(premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=None):
     """perform a 3-way merge in the working directory