Mercurial > public > mercurial-scm > hg
comparison mercurial/filemerge.py @ 48782:c7dbfc363655
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
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Fri, 11 Feb 2022 21:39:55 -0800 |
parents | 8dd5853eaa04 |
children | 218154867575 |
comparison
equal
deleted
inserted
replaced
48781:8dd5853eaa04 | 48782:c7dbfc363655 |
---|---|
875 b"l": b" [%s]" % labels[0], | 875 b"l": b" [%s]" % labels[0], |
876 b"o": b" [%s]" % labels[1], | 876 b"o": b" [%s]" % labels[1], |
877 } | 877 } |
878 | 878 |
879 | 879 |
880 def _makebackup(repo, ui, wctx, fcd): | 880 def _makebackup(repo, ui, fcd): |
881 """Makes and returns a filectx-like object for ``fcd``'s backup file. | 881 """Makes and returns a filectx-like object for ``fcd``'s backup file. |
882 | 882 |
883 In addition to preserving the user's pre-existing modifications to `fcd` | 883 In addition to preserving the user's pre-existing modifications to `fcd` |
884 (if any), the backup is used to undo certain premerges, confirm whether a | 884 (if any), the backup is used to undo certain premerges, confirm whether a |
885 merge changed anything, and determine what line endings the new file should | 885 merge changed anything, and determine what line endings the new file should |
892 return None | 892 return None |
893 # TODO: Break this import cycle somehow. (filectx -> ctx -> fileset -> | 893 # TODO: Break this import cycle somehow. (filectx -> ctx -> fileset -> |
894 # merge -> filemerge). (I suspect the fileset import is the weakest link) | 894 # merge -> filemerge). (I suspect the fileset import is the weakest link) |
895 from . import context | 895 from . import context |
896 | 896 |
897 backup = scmutil.backuppath(ui, repo, fcd.path()) | 897 if isinstance(fcd, context.overlayworkingfilectx): |
898 inworkingdir = backup.startswith(repo.wvfs.base) and not backup.startswith( | 898 # If we're merging in-memory, we're free to put the backup anywhere. |
899 repo.vfs.base | 899 fd, backup = pycompat.mkstemp(b'hg-merge-backup') |
900 ) | 900 with os.fdopen(fd, 'wb') as f: |
901 if isinstance(fcd, context.overlayworkingfilectx) and inworkingdir: | 901 f.write(fcd.data()) |
902 # If the backup file is to be in the working directory, and we're | |
903 # merging in-memory, we must redirect the backup to the memory context | |
904 # so we don't disturb the working directory. | |
905 relpath = backup[len(repo.wvfs.base) + 1 :] | |
906 wctx[relpath].write(fcd.data(), fcd.flags()) | |
907 return wctx[relpath] | |
908 else: | 902 else: |
909 # Otherwise, write to wherever path the user specified the backups | 903 backup = scmutil.backuppath(ui, repo, fcd.path()) |
910 # should go. We still need to switch based on whether the source is | 904 a = _workingpath(repo, fcd) |
911 # in-memory so we can use the fast path of ``util.copy`` if both are | 905 util.copyfile(a, backup) |
912 # on disk. | 906 |
913 if isinstance(fcd, context.overlayworkingfilectx): | 907 return context.arbitraryfilectx(backup, repo=repo) |
914 util.writefile(backup, fcd.data()) | |
915 else: | |
916 a = _workingpath(repo, fcd) | |
917 util.copyfile(a, backup) | |
918 # A arbitraryfilectx is returned, so we can run the same functions on | |
919 # the backup context regardless of where it lives. | |
920 return context.arbitraryfilectx(backup, repo=repo) | |
921 | 908 |
922 | 909 |
923 @contextlib.contextmanager | 910 @contextlib.contextmanager |
924 def _maketempfiles(fco, fca, localpath, uselocalpath): | 911 def _maketempfiles(fco, fca, localpath, uselocalpath): |
925 """Writes out `fco` and `fca` as temporary files, and (if uselocalpath) | 912 """Writes out `fco` and `fca` as temporary files, and (if uselocalpath) |
1063 b'in-memory merge does not support merge conflicts' | 1050 b'in-memory merge does not support merge conflicts' |
1064 ) | 1051 ) |
1065 ui.warn(onfailure % fduipath) | 1052 ui.warn(onfailure % fduipath) |
1066 return 1, False | 1053 return 1, False |
1067 | 1054 |
1068 backup = _makebackup(repo, ui, wctx, fcd) | 1055 backup = _makebackup(repo, ui, fcd) |
1069 r = 1 | 1056 r = 1 |
1070 try: | 1057 try: |
1071 internalmarkerstyle = ui.config(b'ui', b'mergemarkers') | 1058 internalmarkerstyle = ui.config(b'ui', b'mergemarkers') |
1072 if isexternal: | 1059 if isexternal: |
1073 markerstyle = _toolstr(ui, tool, b'mergemarkers') | 1060 markerstyle = _toolstr(ui, tool, b'mergemarkers') |