Details
Details
- Reviewers
yuja - Group Reviewers
hg-reviewers - Commits
- rHG3723b42ff953: filemerge: move temp file unlinks to _maketempfiles
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Lint Skipped - Unit
Unit Tests Skipped
| yuja |
| hg-reviewers |
| Lint Skipped |
| Unit Tests Skipped |
| Path | Packages | |||
|---|---|---|---|---|
| M | mercurial/filemerge.py (16 lines) |
| # filemerge.py - file-level merge handling for Mercurial | # filemerge.py - file-level merge handling for Mercurial | ||||
| # | # | ||||
| # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com> | # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com> | ||||
| # | # | ||||
| # This software may be used and distributed according to the terms of the | # This software may be used and distributed according to the terms of the | ||||
| # GNU General Public License version 2 or any later version. | # GNU General Public License version 2 or any later version. | ||||
| from __future__ import absolute_import | from __future__ import absolute_import | ||||
| import contextlib | |||||
| import os | import os | ||||
| import re | import re | ||||
| import tempfile | import tempfile | ||||
| from .i18n import _ | from .i18n import _ | ||||
| from .node import nullid, short | from .node import nullid, short | ||||
| from . import ( | from . import ( | ||||
| def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): | def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): | ||||
| tool, toolpath, binary, symlink = toolconf | tool, toolpath, binary, symlink = toolconf | ||||
| if fcd.isabsent() or fco.isabsent(): | if fcd.isabsent() or fco.isabsent(): | ||||
| repo.ui.warn(_('warning: %s cannot merge change/delete conflict ' | repo.ui.warn(_('warning: %s cannot merge change/delete conflict ' | ||||
| 'for %s\n') % (tool, fcd.path())) | 'for %s\n') % (tool, fcd.path())) | ||||
| return False, 1, None | return False, 1, None | ||||
| unused, unused, unused, back = files | unused, unused, unused, back = files | ||||
| localpath = _workingpath(repo, fcd) | localpath = _workingpath(repo, fcd) | ||||
| basepath, otherpath = _maketempfiles(repo, fco, fca) | with _maketempfiles(repo, fco, fca) as temppaths: | ||||
| try: | basepath, otherpath = temppaths | ||||
| outpath = "" | outpath = "" | ||||
| mylabel, otherlabel = labels[:2] | mylabel, otherlabel = labels[:2] | ||||
| if len(labels) >= 3: | if len(labels) >= 3: | ||||
| baselabel = labels[2] | baselabel = labels[2] | ||||
| else: | else: | ||||
| baselabel = 'base' | baselabel = 'base' | ||||
| env = {'HG_FILE': fcd.path(), | env = {'HG_FILE': fcd.path(), | ||||
| 'HG_MY_NODE': short(mynode), | 'HG_MY_NODE': short(mynode), | ||||
| cmd = toolpath + ' ' + args | cmd = toolpath + ' ' + args | ||||
| if _toolbool(ui, tool, "gui"): | if _toolbool(ui, tool, "gui"): | ||||
| repo.ui.status(_('running merge tool %s for file %s\n') % | repo.ui.status(_('running merge tool %s for file %s\n') % | ||||
| (tool, fcd.path())) | (tool, fcd.path())) | ||||
| repo.ui.debug('launching merge tool: %s\n' % cmd) | repo.ui.debug('launching merge tool: %s\n' % cmd) | ||||
| r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool') | r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool') | ||||
| repo.ui.debug('merge tool returned: %d\n' % r) | repo.ui.debug('merge tool returned: %d\n' % r) | ||||
| return True, r, False | return True, r, False | ||||
| finally: | |||||
| util.unlink(basepath) | |||||
| util.unlink(otherpath) | |||||
| def _formatconflictmarker(ctx, template, label, pad): | def _formatconflictmarker(ctx, template, label, pad): | ||||
| """Applies the given template to the ctx, prefixed by the label. | """Applies the given template to the ctx, prefixed by the label. | ||||
| Pad is the minimum width of the label prefix, so that multiple markers | Pad is the minimum width of the label prefix, so that multiple markers | ||||
| can have aligned templated parts. | can have aligned templated parts. | ||||
| """ | """ | ||||
| if ctx.node() is None: | if ctx.node() is None: | ||||
| if isinstance(fcd, context.overlayworkingfilectx): | if isinstance(fcd, context.overlayworkingfilectx): | ||||
| util.writefile(back, fcd.data()) | util.writefile(back, fcd.data()) | ||||
| else: | else: | ||||
| util.copyfile(a, back) | util.copyfile(a, back) | ||||
| # A arbitraryfilectx is returned, so we can run the same functions on | # A arbitraryfilectx is returned, so we can run the same functions on | ||||
| # the backup context regardless of where it lives. | # the backup context regardless of where it lives. | ||||
| return context.arbitraryfilectx(back, repo=repo) | return context.arbitraryfilectx(back, repo=repo) | ||||
| @contextlib.contextmanager | |||||
| def _maketempfiles(repo, fco, fca): | def _maketempfiles(repo, fco, fca): | ||||
| """Writes out `fco` and `fca` as temporary files, so an external merge | """Writes out `fco` and `fca` as temporary files, so an external merge | ||||
| tool may use them. | tool may use them. | ||||
| """ | """ | ||||
| def temp(prefix, ctx): | def temp(prefix, ctx): | ||||
| fullbase, ext = os.path.splitext(ctx.path()) | fullbase, ext = os.path.splitext(ctx.path()) | ||||
| pre = "%s~%s." % (os.path.basename(fullbase), prefix) | pre = "%s~%s." % (os.path.basename(fullbase), prefix) | ||||
| (fd, name) = tempfile.mkstemp(prefix=pre, suffix=ext) | (fd, name) = tempfile.mkstemp(prefix=pre, suffix=ext) | ||||
| data = repo.wwritedata(ctx.path(), ctx.data()) | data = repo.wwritedata(ctx.path(), ctx.data()) | ||||
| f = os.fdopen(fd, r"wb") | f = os.fdopen(fd, r"wb") | ||||
| f.write(data) | f.write(data) | ||||
| f.close() | f.close() | ||||
| return name | return name | ||||
| b = temp("base", fca) | b = temp("base", fca) | ||||
| c = temp("other", fco) | c = temp("other", fco) | ||||
| try: | |||||
| return b, c | yield b, c | ||||
| finally: | |||||
| util.unlink(b) | |||||
| util.unlink(c) | |||||
| def _filemerge(premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=None): | def _filemerge(premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=None): | ||||
| """perform a 3-way merge in the working directory | """perform a 3-way merge in the working directory | ||||
| premerge = whether this is a premerge | premerge = whether this is a premerge | ||||
| mynode = parent node before merge | mynode = parent node before merge | ||||
| orig = original local filename before merge | orig = original local filename before merge | ||||
| fco = other file context | fco = other file context | ||||