D401: filemerge: reduce creation of tempfiles until needed

phillco (Phil Cohen) phabricator at mercurial-scm.org
Tue Aug 15 05:28:18 UTC 2017


phillco created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/filemerge.py

CHANGE DETAILS

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -483,8 +483,8 @@
     This implies permerge. Therefore, files aren't dumped, if premerge
     runs successfully. Use :forcedump to forcibly write files out.
     """
-    a, b, c, back = files
 
+    a = _workingpath(repo, fcd)
     fd = fcd.path()
 
     util.copyfile(a, a + ".local")
@@ -507,33 +507,39 @@
         repo.ui.warn(_('warning: %s cannot merge change/delete conflict '
                        'for %s\n') % (tool, fcd.path()))
         return False, 1, None
-    a, b, c, back = files
-    out = ""
-    env = {'HG_FILE': fcd.path(),
-           'HG_MY_NODE': short(mynode),
-           'HG_OTHER_NODE': str(fco.changectx()),
-           'HG_BASE_NODE': str(fca.changectx()),
-           'HG_MY_ISLINK': 'l' in fcd.flags(),
-           'HG_OTHER_ISLINK': 'l' in fco.flags(),
-           'HG_BASE_ISLINK': 'l' in fca.flags(),
-           }
+    unused, unused, unused, back = files
+    a = _workingpath(repo, fcd)
+    b, c = _maketempfiles(repo, fco, fca)
+    try:
+        out = ""
+        env = {'HG_FILE': fcd.path(),
+               'HG_MY_NODE': short(mynode),
+               'HG_OTHER_NODE': str(fco.changectx()),
+               'HG_BASE_NODE': str(fca.changectx()),
+               'HG_MY_ISLINK': 'l' in fcd.flags(),
+               'HG_OTHER_ISLINK': 'l' in fco.flags(),
+               'HG_BASE_ISLINK': 'l' in fca.flags(),
+               }
 
-    ui = repo.ui
+        ui = repo.ui
 
-    args = _toolstr(ui, tool, "args", '$local $base $other')
-    if "$output" in args:
-        out, a = a, back # read input from backup, write to original
-    replace = {'local': a, 'base': b, 'other': c, 'output': out}
-    args = util.interpolate(r'\$', replace, args,
-                            lambda s: util.shellquote(util.localpath(s)))
-    cmd = toolpath + ' ' + args
-    if _toolbool(ui, tool, "gui"):
-        repo.ui.status(_('running merge tool %s for file %s\n') %
-                       (tool, fcd.path()))
-    repo.ui.debug('launching merge tool: %s\n' % cmd)
-    r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool')
-    repo.ui.debug('merge tool returned: %s\n' % r)
-    return True, r, False
+        args = _toolstr(ui, tool, "args", '$local $base $other')
+        if "$output" in args:
+            out, a = a, back # read input from backup, write to original
+        replace = {'local': a, 'base': b, 'other': c, 'output': out}
+        args = util.interpolate(r'\$', replace, args,
+                                lambda s: util.shellquote(util.localpath(s)))
+        cmd = toolpath + ' ' + args
+        if _toolbool(ui, tool, "gui"):
+            repo.ui.status(_('running merge tool %s for file %s\n') %
+                           (tool, fcd.path()))
+        repo.ui.debug('launching merge tool: %s\n' % cmd)
+        r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool')
+        repo.ui.debug('merge tool returned: %s\n' % r)
+        return True, r, False
+    finally:
+        util.unlink(b)
+        util.unlink(c)
 
 def _formatconflictmarker(repo, ctx, template, label, pad):
     """Applies the given template to the ctx, prefixed by the label.
@@ -609,13 +615,13 @@
     if fcd.isabsent():
         return None
 
-    a = repo.wjoin(fcd.path())
+    a = _workingpath(repo, fcd)
     back = scmutil.origpath(ui, repo, a)
     if premerge:
         util.copyfile(a, back)
     return back
 
-def _maketempfiles(repo, fcd, fco, fca):
+def _maketempfiles(repo, fco, fca):
     """Writes out `fco` and `fca` as temporary files, so an external merge
     tool may use them.
 
@@ -632,11 +638,10 @@
         f.close()
         return name
 
-    a = repo.wjoin(fcd.path())
     b = temp("base", fca)
     c = temp("other", fco)
 
-    return a, b, c
+    return b, c
 
 def _filemerge(premerge, repo, mynode, orig, fcd, fco, fca, labels=None):
     """perform a 3-way merge in the working directory
@@ -699,7 +704,7 @@
         return True, 1, False
 
     back = _makebackup(repo, ui, fcd, premerge)
-    files = _maketempfiles(repo, fcd, fco, fca) + (back,)
+    files = (None, None, None, back)
     r = 1
     try:
         markerstyle = ui.config('ui', 'mergemarkers')
@@ -717,7 +722,7 @@
                                      toolconf, files, labels=labels)
 
         if needcheck:
-            r = _check(r, ui, tool, fcd, files)
+            r = _check(repo, r, ui, tool, fcd, files)
 
         if r:
             if onfailure:
@@ -727,12 +732,10 @@
     finally:
         if not r and back is not None:
             util.unlink(back)
-        util.unlink(files[1])
-        util.unlink(files[2])
 
-def _check(r, ui, tool, fcd, files):
+def _check(repo, r, ui, tool, fcd, files):
     fd = fcd.path()
-    a, unused, unused, back = files
+    unused, unused, unused, back = files
 
     if not r and (_toolbool(ui, tool, "checkconflicts") or
                   'conflicts' in _toollist(ui, tool, "check")):
@@ -750,17 +753,20 @@
     if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
                                   'changed' in
                                   _toollist(ui, tool, "check")):
-        if back is not None and filecmp.cmp(a, back):
+        if back is not None and filecmp.cmp(_workingpath(repo, fcd), back):
             if ui.promptchoice(_(" output file %s appears unchanged\n"
                                  "was merge successful (yn)?"
                                  "$$ &Yes $$ &No") % fd, 1):
                 r = 1
 
     if back is not None and _toolbool(ui, tool, "fixeol"):
-        _matcheol(a, back)
+        _matcheol(_workingpath(repo, fcd), back)
 
     return r
 
+def _workingpath(repo, ctx):
+    return repo.wjoin(ctx.path())
+
 def premerge(repo, mynode, orig, fcd, fco, fca, labels=None):
     return _filemerge(True, repo, mynode, orig, fcd, fco, fca, labels=labels)
 



To: phillco, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list