# HG changeset patch # User Martin von Zweigbergk # Date 2022-02-12 05:39:55 # Node ID c7dbfc3636556ddabb93b2315c9da47e19c86e78 # Parent 8dd5853eaa04c569d0672cad346992ee2cd4a480 filemerge: when using in-memory merge, always put backup files in temp dir Before calling a merge tool, we create a backup of the local side of the merge. That file can be put in the working copy or in a temporary directory, depending on the user's config. When we're merging in memory, we don't want to write to the actual, on-disk working copy, so we write the file to the in-memory working copy instead. However, since we don't support external merge tools with in-memory merge, it makes no difference where the file is actually stored (and if we ever do add support for external merge tools, then the file clearly can't live in the in-memory working-copy object anyway). So, since it doesn't matter where the file is stored, we can simplify by always putting them in the system's temp directory. Differential Revision: https://phab.mercurial-scm.org/D12187 diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py --- a/mercurial/filemerge.py +++ b/mercurial/filemerge.py @@ -877,7 +877,7 @@ def partextras(labels): } -def _makebackup(repo, ui, wctx, fcd): +def _makebackup(repo, ui, fcd): """Makes and returns a filectx-like object for ``fcd``'s backup file. In addition to preserving the user's pre-existing modifications to `fcd` @@ -894,30 +894,17 @@ def _makebackup(repo, ui, wctx, fcd): # merge -> filemerge). (I suspect the fileset import is the weakest link) from . import context - backup = scmutil.backuppath(ui, repo, fcd.path()) - inworkingdir = backup.startswith(repo.wvfs.base) and not backup.startswith( - repo.vfs.base - ) - if isinstance(fcd, context.overlayworkingfilectx) and inworkingdir: - # If the backup file is to be in the working directory, and we're - # merging in-memory, we must redirect the backup to the memory context - # so we don't disturb the working directory. - relpath = backup[len(repo.wvfs.base) + 1 :] - wctx[relpath].write(fcd.data(), fcd.flags()) - return wctx[relpath] + if isinstance(fcd, context.overlayworkingfilectx): + # If we're merging in-memory, we're free to put the backup anywhere. + fd, backup = pycompat.mkstemp(b'hg-merge-backup') + with os.fdopen(fd, 'wb') as f: + f.write(fcd.data()) else: - # Otherwise, write to wherever path the user specified the backups - # should go. We still need to switch based on whether the source is - # in-memory so we can use the fast path of ``util.copy`` if both are - # on disk. - if isinstance(fcd, context.overlayworkingfilectx): - util.writefile(backup, fcd.data()) - else: - a = _workingpath(repo, fcd) - util.copyfile(a, backup) - # A arbitraryfilectx is returned, so we can run the same functions on - # the backup context regardless of where it lives. - return context.arbitraryfilectx(backup, repo=repo) + backup = scmutil.backuppath(ui, repo, fcd.path()) + a = _workingpath(repo, fcd) + util.copyfile(a, backup) + + return context.arbitraryfilectx(backup, repo=repo) @contextlib.contextmanager @@ -1065,7 +1052,7 @@ def filemerge(repo, wctx, mynode, orig, ui.warn(onfailure % fduipath) return 1, False - backup = _makebackup(repo, ui, wctx, fcd) + backup = _makebackup(repo, ui, fcd) r = 1 try: internalmarkerstyle = ui.config(b'ui', b'mergemarkers')