diff --git a/mercurial/commit.py b/mercurial/commit.py index f9a3edf2dee4f11117699967c226b882a98957e0_bWVyY3VyaWFsL2NvbW1pdC5weQ==..bf27967e594db17b8a3ba8dd1176ebcbc82d7692_bWVyY3VyaWFsL2NvbW1pdC5weQ== 100644 --- a/mercurial/commit.py +++ b/mercurial/commit.py @@ -332,5 +332,16 @@ ): fparent1, fparent2 = fparent2, nullid + force_new_node = False + # The file might have been deleted by merge code and user explicitly choose + # to revert the file and keep it. The other case can be where there is + # change-delete or delete-change conflict and user explicitly choose to keep + # the file. The goal is to create a new filenode for users explicit choices + if ( + repo.ui.configbool(b'experimental', b'merge-track-salvaged') + and ms.active() + and ms.extras(fname).get(b'merge-removal-candidate') == b'yes' + ): + force_new_node = True # is the file changed? text = fctx.data() @@ -335,6 +346,6 @@ # is the file changed? text = fctx.data() - if fparent2 != nullid or meta or flog.cmp(fparent1, text): + if fparent2 != nullid or meta or flog.cmp(fparent1, text) or force_new_node: if touched is None: # do not overwrite added touched = 'modified' fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2) diff --git a/mercurial/configitems.py b/mercurial/configitems.py index f9a3edf2dee4f11117699967c226b882a98957e0_bWVyY3VyaWFsL2NvbmZpZ2l0ZW1zLnB5..bf27967e594db17b8a3ba8dd1176ebcbc82d7692_bWVyY3VyaWFsL2NvbmZpZ2l0ZW1zLnB5 100644 --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -590,6 +590,11 @@ coreconfigitem( b'experimental', b'maxdeltachainspan', default=-1, ) +# tracks files which were undeleted (merge might delete them but we explicitly +# kept/undeleted them) and creates new filenodes for them +coreconfigitem( + b'experimental', b'merge-track-salvaged', default=False, +) coreconfigitem( b'experimental', b'mergetempdirprefix', default=None, ) diff --git a/mercurial/merge.py b/mercurial/merge.py index f9a3edf2dee4f11117699967c226b882a98957e0_bWVyY3VyaWFsL21lcmdlLnB5..bf27967e594db17b8a3ba8dd1176ebcbc82d7692_bWVyY3VyaWFsL21lcmdlLnB5 100644 --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -776,7 +776,13 @@ # - ma is the same as m1 or m2, which we're just going to diff again later # - The caller specifically asks for a full diff, which is useful during bid # merge. - if pa not in ([wctx, p2] + wctx.parents()) and not forcefulldiff: + # - we are tracking salvaged files specifically hence should process all + # files + if ( + pa not in ([wctx, p2] + wctx.parents()) + and not forcefulldiff + and not repo.ui.configbool(b'experimental', b'merge-track-salvaged') + ): # Identify which files are relevant to the merge, so we can limit the # total m1-vs-m2 diff to just those files. This has significant # performance benefits in large repositories. @@ -903,6 +909,10 @@ (f, None, f, False, pa.node()), b'prompt changed/deleted', ) + if branchmerge: + mresult.addcommitinfo( + f, b'merge-removal-candidate', b'yes' + ) elif n1 == addednodeid: # This file was locally added. We should forget it instead of # deleting it. @@ -913,6 +923,15 @@ mresult.addfile( f, mergestatemod.ACTION_REMOVE, None, b'other deleted', ) + if branchmerge: + # the file must be absent after merging, + # howeber the user might make + # the file reappear using revert and if they does, + # we force create a new node + mresult.addcommitinfo( + f, b'merge-removal-candidate', b'yes' + ) + else: # file not in ancestor, not in remote mresult.addfile( f, @@ -1012,6 +1031,10 @@ (None, f, f, False, pa.node()), b'prompt deleted/changed', ) + if branchmerge: + mresult.addcommitinfo( + f, b'merge-removal-candidate', b'yes' + ) else: mresult.addfile( f, @@ -1019,6 +1042,12 @@ None, b'local not present, remote unchanged', ) + if branchmerge: + # the file must be absent after merging + # however the user might make + # the file reappear using revert and if they does, + # we force create a new node + mresult.addcommitinfo(f, b'merge-removal-candidate', b'yes') if repo.ui.configbool(b'experimental', b'merge.checkpathconflicts'): # If we are merging, look for path conflicts. diff --git a/mercurial/mergestate.py b/mercurial/mergestate.py index f9a3edf2dee4f11117699967c226b882a98957e0_bWVyY3VyaWFsL21lcmdlc3RhdGUucHk=..bf27967e594db17b8a3ba8dd1176ebcbc82d7692_bWVyY3VyaWFsL21lcmdlc3RhdGUucHk= 100644 --- a/mercurial/mergestate.py +++ b/mercurial/mergestate.py @@ -261,7 +261,7 @@ hex(fco.filenode()), fcl.flags(), ] - self._stateextras[fd] = {b'ancestorlinknode': hex(fca.node())} + self._stateextras[fd][b'ancestorlinknode'] = hex(fca.node()) self._dirty = True def addpathconflict(self, path, frename, forigin): diff --git a/tests/test-merge-changedelete.t b/tests/test-merge-changedelete.t index f9a3edf2dee4f11117699967c226b882a98957e0_dGVzdHMvdGVzdC1tZXJnZS1jaGFuZ2VkZWxldGUudA==..bf27967e594db17b8a3ba8dd1176ebcbc82d7692_dGVzdHMvdGVzdC1tZXJnZS1jaGFuZ2VkZWxldGUudA== 100644 --- a/tests/test-merge-changedelete.t +++ b/tests/test-merge-changedelete.t @@ -83,8 +83,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -86,8 +87,9 @@ file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "u") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -148,8 +150,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "r") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -151,8 +154,9 @@ file: file2 (state "r") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "u") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -226,8 +230,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "r") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -229,8 +234,9 @@ file: file2 (state "r") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "u") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -288,8 +294,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -291,8 +298,9 @@ file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "u") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -337,8 +345,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "r") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -340,8 +349,9 @@ file: file2 (state "r") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "r") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -382,8 +392,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "r") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -385,8 +396,9 @@ file: file2 (state "r") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "r") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -428,8 +440,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -431,8 +444,9 @@ file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "u") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -485,8 +499,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -488,8 +503,9 @@ file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "u") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -544,8 +560,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -547,8 +564,9 @@ file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "u") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -600,8 +618,9 @@ ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) other path: file1 (node 0000000000000000000000000000000000000000) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff @@ -603,8 +622,9 @@ file: file2 (state "u") local path: file2 (hash 0000000000000000000000000000000000000000, flags "") ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) extra: ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff + extra: merge-removal-candidate = yes file: file3 (state "u") local path: file3 (hash d5b0a58bc47161b1b8a831084b366f757c4f0b11, flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) diff --git a/tests/test-merge-criss-cross.t b/tests/test-merge-criss-cross.t index f9a3edf2dee4f11117699967c226b882a98957e0_dGVzdHMvdGVzdC1tZXJnZS1jcmlzcy1jcm9zcy50..bf27967e594db17b8a3ba8dd1176ebcbc82d7692_dGVzdHMvdGVzdC1tZXJnZS1jcmlzcy1jcm9zcy50 100644 --- a/tests/test-merge-criss-cross.t +++ b/tests/test-merge-criss-cross.t @@ -1,3 +1,15 @@ +#testcases old newfilenode + +#if newfilenode +Enable the config option +------------------------ + + $ cat >> $HGRCPATH < [experimental] + > merge-track-salvaged = True + > EOF +#endif + Criss cross merging $ hg init criss-cross @@ -519,6 +531,16 @@ $ hg merge 'desc("updating-both-file")' -t :local 1 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) + $ hg debugmergestate + local (working copy): 7801bc9b9899de5e304bd162cafde9b78e10ab9b + other (merge rev): 9b610631ab29024c5f44af7d2c19658ef8f8f071 + file: the-file (state "r") + local path: the-file (hash 0000000000000000000000000000000000000000, flags "") + ancestor path: the-file (node 4b69178b9bdae28b651393b46e631427a72f217a) + other path: the-file (node 59e363a07dc876278f0e41756236f30213b6b460) + extra: ancestorlinknode = 955800955977bd6c103836ee3e437276e940a589 + extra: merge-removal-candidate = yes + extra: other-file (filenode-source = other) $ hg ci -m "merge-deleting-the-file-from-deleted" $ hg manifest other-file @@ -522,9 +544,13 @@ $ hg ci -m "merge-deleting-the-file-from-deleted" $ hg manifest other-file + $ hg debugrevlogindex the-file + rev linkrev nodeid p1 p2 + 0 0 4b69178b9bda 000000000000 000000000000 + 1 1 59e363a07dc8 4b69178b9bda 000000000000 $ hg update 'desc("updating-both-file")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("delete-the-file")' -t :other 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) @@ -525,10 +551,19 @@ $ hg update 'desc("updating-both-file")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("delete-the-file")' -t :other 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) + $ hg debugmergestate + local (working copy): 9b610631ab29024c5f44af7d2c19658ef8f8f071 + other (merge rev): 7801bc9b9899de5e304bd162cafde9b78e10ab9b + file: the-file (state "r") + local path: the-file (hash 6d2e02da5a9fe0691363dc6b573845fa271eaa35, flags "") + ancestor path: the-file (node 4b69178b9bdae28b651393b46e631427a72f217a) + other path: the-file (node 0000000000000000000000000000000000000000) + extra: ancestorlinknode = 955800955977bd6c103836ee3e437276e940a589 + extra: merge-removal-candidate = yes $ hg ci -m "merge-deleting-the-file-from-updated" created new head $ hg manifest other-file @@ -531,10 +566,14 @@ $ hg ci -m "merge-deleting-the-file-from-updated" created new head $ hg manifest other-file + $ hg debugrevlogindex the-file + rev linkrev nodeid p1 p2 + 0 0 4b69178b9bda 000000000000 000000000000 + 1 1 59e363a07dc8 4b69178b9bda 000000000000 $ hg update 'desc("delete-the-file")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("updating-both-file")' -t :other 1 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) @@ -535,12 +574,22 @@ $ hg update 'desc("delete-the-file")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("updating-both-file")' -t :other 1 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) + $ hg debugmergestate + local (working copy): 7801bc9b9899de5e304bd162cafde9b78e10ab9b + other (merge rev): 9b610631ab29024c5f44af7d2c19658ef8f8f071 + file: the-file (state "r") + local path: the-file (hash 0000000000000000000000000000000000000000, flags "") + ancestor path: the-file (node 4b69178b9bdae28b651393b46e631427a72f217a) + other path: the-file (node 59e363a07dc876278f0e41756236f30213b6b460) + extra: ancestorlinknode = 955800955977bd6c103836ee3e437276e940a589 + extra: merge-removal-candidate = yes + extra: other-file (filenode-source = other) $ hg ci -m "merge-keeping-the-file-from-deleted" created new head $ hg manifest other-file the-file @@ -541,7 +590,13 @@ $ hg ci -m "merge-keeping-the-file-from-deleted" created new head $ hg manifest other-file the-file + $ hg debugrevlogindex the-file + rev linkrev nodeid p1 p2 + 0 0 4b69178b9bda 000000000000 000000000000 + 1 1 59e363a07dc8 4b69178b9bda 000000000000 + 2 5 885af55420b3 59e363a07dc8 000000000000 (newfilenode !) + $ hg update 'desc("updating-both-file")' @@ -547,5 +602,6 @@ $ hg update 'desc("updating-both-file")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (newfilenode !) + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) $ hg merge 'desc("delete-the-file")' -t :local 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) @@ -549,9 +605,18 @@ $ hg merge 'desc("delete-the-file")' -t :local 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) + $ hg debugmergestate + local (working copy): 9b610631ab29024c5f44af7d2c19658ef8f8f071 + other (merge rev): 7801bc9b9899de5e304bd162cafde9b78e10ab9b + file: the-file (state "r") + local path: the-file (hash 6d2e02da5a9fe0691363dc6b573845fa271eaa35, flags "") + ancestor path: the-file (node 4b69178b9bdae28b651393b46e631427a72f217a) + other path: the-file (node 0000000000000000000000000000000000000000) + extra: ancestorlinknode = 955800955977bd6c103836ee3e437276e940a589 + extra: merge-removal-candidate = yes $ hg ci -m "merge-keeping-the-file-from-updated" created new head $ hg manifest other-file the-file @@ -552,9 +617,36 @@ $ hg ci -m "merge-keeping-the-file-from-updated" created new head $ hg manifest other-file the-file +XXX: This should create a new filenode because user explicitly decided to keep +the file. If we reuse the same filenode, future merges (criss-cross ones mostly) +will think that file remain unchanged and user explicit choice will not be taken +in consideration. + $ hg debugrevlogindex the-file + rev linkrev nodeid p1 p2 + 0 0 4b69178b9bda 000000000000 000000000000 + 1 1 59e363a07dc8 4b69178b9bda 000000000000 + 2 5 885af55420b3 59e363a07dc8 000000000000 (newfilenode !) + + $ hg log -G -T '{node|short} {desc}\n' + @ 5e3eccec60d8 merge-keeping-the-file-from-updated + |\ + +---o 38a4c3e7cac8 merge-keeping-the-file-from-deleted (newfilenode !) + +---o e9b708131723 merge-keeping-the-file-from-deleted (old !) + | |/ + +---o a4e0e44229dc merge-deleting-the-file-from-updated + | |/ + +---o adfd88e5d7d3 merge-deleting-the-file-from-deleted + | |/ + | o 7801bc9b9899 delete-the-file + | | + o | 9b610631ab29 updating-both-file + |/ + o 955800955977 root-commit + + There the resulting merge together (leading to criss cross situation). Check the conflict is properly detected. @@ -567,6 +659,8 @@ (branch merge, don't forget to commit) $ ls -1 other-file + $ hg debugmergestate + no merge state found (merging a deletion with keeping → conflict) BROKEN: this should result in conflict @@ -574,7 +668,8 @@ $ hg update --clean 'desc("merge-deleting-the-file-from-deleted")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (newfilenode !) + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) (branch merge, don't forget to commit) $ ls -1 other-file @@ -578,8 +673,21 @@ (branch merge, don't forget to commit) $ ls -1 other-file + the-file (newfilenode !) + +#if newfilenode + $ hg debugmergestate + local (working copy): adfd88e5d7d3d3e22bdd26512991ee64d59c1d8f + other (merge rev): 38a4c3e7cac8c294ecb0a7a85a05464e9836ca78 + extra: the-file (merge-removal-candidate = yes) +#else + $ hg debugmergestate + local (working copy): adfd88e5d7d3d3e22bdd26512991ee64d59c1d8f + other (merge rev): e9b7081317232edce73f7ad5ae0b7807ff5c326a + extra: the-file (merge-removal-candidate = yes) +#endif (merging a deletion with keeping → conflict) BROKEN: this should result in conflict $ hg update --clean 'desc("merge-deleting-the-file-from-deleted")' @@ -581,11 +689,12 @@ (merging a deletion with keeping → conflict) BROKEN: this should result in conflict $ hg update --clean 'desc("merge-deleting-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (newfilenode !) + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file @@ -587,8 +696,12 @@ $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file + $ hg debugmergestate + local (working copy): adfd88e5d7d3d3e22bdd26512991ee64d59c1d8f + other (merge rev): 5e3eccec60d88f94a7ba57c351f32cb24c15fe0c + extra: the-file (merge-removal-candidate = yes) (merging two deletion together → no conflict) @@ -599,6 +712,8 @@ (branch merge, don't forget to commit) $ ls -1 other-file + $ hg debugmergestate + no merge state found (merging a deletion with keeping → conflict) BROKEN: this should result in conflict @@ -606,7 +721,8 @@ $ hg update --clean 'desc("merge-deleting-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (newfilenode !) + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) (branch merge, don't forget to commit) $ ls -1 other-file @@ -610,8 +726,20 @@ (branch merge, don't forget to commit) $ ls -1 other-file + the-file (newfilenode !) +#if newfilenode + $ hg debugmergestate + local (working copy): a4e0e44229dc130be2915b92c957c093f8c7ee3e + other (merge rev): 38a4c3e7cac8c294ecb0a7a85a05464e9836ca78 + extra: the-file (merge-removal-candidate = yes) +#else + $ hg debugmergestate + local (working copy): a4e0e44229dc130be2915b92c957c093f8c7ee3e + other (merge rev): e9b7081317232edce73f7ad5ae0b7807ff5c326a + extra: the-file (merge-removal-candidate = yes) +#endif (merging a deletion with keeping → conflict) BROKEN: this should result in conflict $ hg update --clean 'desc("merge-deleting-the-file-from-updated")' @@ -613,11 +741,12 @@ (merging a deletion with keeping → conflict) BROKEN: this should result in conflict $ hg update --clean 'desc("merge-deleting-the-file-from-updated")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (newfilenode !) + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file @@ -619,11 +748,15 @@ $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file + $ hg debugmergestate + local (working copy): a4e0e44229dc130be2915b92c957c093f8c7ee3e + other (merge rev): 5e3eccec60d88f94a7ba57c351f32cb24c15fe0c + extra: the-file (merge-removal-candidate = yes) (merging two "keeping" together → no conflict) $ hg update --clean 'desc("merge-keeping-the-file-from-updated")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-deleted")' @@ -624,11 +757,12 @@ (merging two "keeping" together → no conflict) $ hg update --clean 'desc("merge-keeping-the-file-from-updated")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("merge-keeping-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (newfilenode !) + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) (branch merge, don't forget to commit) $ ls -1 other-file the-file @@ -631,9 +765,18 @@ (branch merge, don't forget to commit) $ ls -1 other-file the-file +#if newfilenode + $ hg debugmergestate + local (working copy): 5e3eccec60d88f94a7ba57c351f32cb24c15fe0c + other (merge rev): 38a4c3e7cac8c294ecb0a7a85a05464e9836ca78 + extra: the-file (filenode-source = other) +#else + $ hg debugmergestate + no merge state found +#endif (merging a deletion with keeping → conflict) BROKEN: this should result in conflict $ hg update --clean 'desc("merge-keeping-the-file-from-updated")' @@ -635,12 +778,13 @@ (merging a deletion with keeping → conflict) BROKEN: this should result in conflict $ hg update --clean 'desc("merge-keeping-the-file-from-updated")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (newfilenode !) + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) $ hg merge 'desc("merge-deleted-the-file-from-deleted")' abort: empty revision set [255] $ ls -1 other-file the-file @@ -641,9 +785,11 @@ $ hg merge 'desc("merge-deleted-the-file-from-deleted")' abort: empty revision set [255] $ ls -1 other-file the-file + $ hg debugmergestate + no merge state found (merging a deletion with keeping → conflict) BROKEN: this should result in conflict @@ -656,7 +802,11 @@ $ ls -1 other-file the-file + $ hg debugmergestate + local (working copy): 5e3eccec60d88f94a7ba57c351f32cb24c15fe0c + other (merge rev): a4e0e44229dc130be2915b92c957c093f8c7ee3e + extra: the-file (merge-removal-candidate = yes) (merging two "keeping" together → no conflict) $ hg update --clean 'desc("merge-keeping-the-file-from-deleted")' @@ -659,11 +809,12 @@ (merging two "keeping" together → no conflict) $ hg update --clean 'desc("merge-keeping-the-file-from-deleted")' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (newfilenode !) + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file the-file @@ -664,9 +815,11 @@ $ hg merge 'desc("merge-keeping-the-file-from-updated")' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ ls -1 other-file the-file + $ hg debugmergestate + no merge state found (merging a deletion with keeping → conflict) BROKEN: this should result in conflict @@ -679,6 +832,8 @@ $ ls -1 other-file the-file + $ hg debugmergestate + no merge state found (merging a deletion with keeping → conflict) BROKEN: this should result in conflict @@ -691,3 +846,14 @@ $ ls -1 other-file the-file +#if newfilenode + $ hg debugmergestate + local (working copy): 38a4c3e7cac8c294ecb0a7a85a05464e9836ca78 + other (merge rev): a4e0e44229dc130be2915b92c957c093f8c7ee3e + extra: the-file (merge-removal-candidate = yes) +#else + $ hg debugmergestate + local (working copy): e9b7081317232edce73f7ad5ae0b7807ff5c326a + other (merge rev): a4e0e44229dc130be2915b92c957c093f8c7ee3e + extra: the-file (merge-removal-candidate = yes) +#endif