# HG changeset patch # User Pulkit Goyal <7895pulkit@gmail.com> # Date 1601461014 -19800 # Node ID ad984583969a971623190c604e5b60e66054e160 # Parent 64461b43a7bf1f729dab39e39f4c2f77a432e5ce merge: if DELETED_CHANGED and GET are in actions, choose DELETED_CHANGED ACTION_GET represents that either the file is created on remote or it's newer on the remote side. However, since we have a ACTION_DELETE_CHANGED too, it means the file is not present locally and ACTION_GET is representing that file was created on remote. Having both ACTION_GET and ACTION_DELETED_CHANGED is conflicting because one says that file was created on remote and other says file has delete-changed conflicts. Let's choose ACTION_DELETED_CHANGED which will result in conflicts and make user choose the right way forward. diff -r 64461b43a7bf -r ad984583969a mercurial/merge.py --- a/mercurial/merge.py Wed Sep 30 15:09:25 2020 +0530 +++ b/mercurial/merge.py Wed Sep 30 15:46:54 2020 +0530 @@ -1220,6 +1220,21 @@ repo.ui.note(_(b" %s: picking 'keep new' action\n") % f) mresult.addfile(f, *bids[mergestatemod.ACTION_KEEP_NEW][0]) continue + # ACTION_GET and ACTION_DELETE_CHANGED are conflicting actions as + # one action states the file is newer/created on remote side and + # other states that file is deleted locally and changed on remote + # side. Let's fallback and rely on a conflicting action to let user + # do the right thing + if ( + mergestatemod.ACTION_DELETED_CHANGED in bids + and mergestatemod.ACTION_GET in bids + and len(bids) == 2 + ): + repo.ui.note(_(b" %s: picking 'delete/changed' action\n") % f) + mresult.addfile( + f, *bids[mergestatemod.ACTION_DELETED_CHANGED][0] + ) + continue # If there are gets and they all agree [how could they not?], do it. if mergestatemod.ACTION_GET in bids: ga0 = bids[mergestatemod.ACTION_GET][0] diff -r 64461b43a7bf -r ad984583969a tests/test-merge-criss-cross.t --- a/tests/test-merge-criss-cross.t Wed Sep 30 15:09:25 2020 +0530 +++ b/tests/test-merge-criss-cross.t Wed Sep 30 15:46:54 2020 +0530 @@ -663,14 +663,24 @@ no merge state found (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 + +#if newfilenode $ hg merge 'desc("merge-keeping-the-file-from-deleted")' - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (newfilenode !) + file 'the-file' was deleted in local [working copy] but was modified in other [merge rev]. 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) + You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. + What do you want to do? u + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] +#else + $ hg merge 'desc("merge-keeping-the-file-from-deleted")' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) +#endif $ ls -1 other-file the-file (newfilenode !) @@ -679,7 +689,12 @@ $ hg debugmergestate local (working copy): adfd88e5d7d3d3e22bdd26512991ee64d59c1d8f other (merge rev): 38a4c3e7cac8c294ecb0a7a85a05464e9836ca78 - extra: the-file (merge-removal-candidate = yes) + file: the-file (state "u") + local path: the-file (hash 0000000000000000000000000000000000000000, flags "") + ancestor path: the-file (node 59e363a07dc876278f0e41756236f30213b6b460) + other path: the-file (node 885af55420b35d7bf3bbd6f546615295bfe6544a) + extra: ancestorlinknode = 9b610631ab29024c5f44af7d2c19658ef8f8f071 + extra: merge-removal-candidate = yes #else $ hg debugmergestate local (working copy): adfd88e5d7d3d3e22bdd26512991ee64d59c1d8f @@ -716,14 +731,25 @@ no merge state found (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 + +#if newfilenode $ hg merge 'desc("merge-keeping-the-file-from-deleted")' - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (newfilenode !) + file 'the-file' was deleted in local [working copy] but was modified in other [merge rev]. 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (old !) + You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. + What do you want to do? u + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] +#else + $ hg merge 'desc("merge-keeping-the-file-from-deleted")' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) +#endif + $ ls -1 other-file the-file (newfilenode !) @@ -731,7 +757,12 @@ $ hg debugmergestate local (working copy): a4e0e44229dc130be2915b92c957c093f8c7ee3e other (merge rev): 38a4c3e7cac8c294ecb0a7a85a05464e9836ca78 - extra: the-file (merge-removal-candidate = yes) + file: the-file (state "u") + local path: the-file (hash 0000000000000000000000000000000000000000, flags "") + ancestor path: the-file (node 59e363a07dc876278f0e41756236f30213b6b460) + other path: the-file (node 885af55420b35d7bf3bbd6f546615295bfe6544a) + extra: ancestorlinknode = 9b610631ab29024c5f44af7d2c19658ef8f8f071 + extra: merge-removal-candidate = yes #else $ hg debugmergestate local (working copy): a4e0e44229dc130be2915b92c957c093f8c7ee3e