commit: force create a new filenode if it was set in mergestate by merge
authorPulkit Goyal <7895pulkit@gmail.com>
Thu, 03 Sep 2020 13:58:14 +0530
changeset 45585 479cce8c9882
parent 45584 4c8a93ec6908
child 45586 8c02c6262a5e
commit: force create a new filenode if it was set in mergestate by merge For reasons mentioned in previous commits, we will like to forcefully create a new filenode sometimes. Combination of this patch and previous one, we fixed a case in `test-merge-combination.t`. This does not yet results in conflict where it should, I need to investigate more about what's happening as it should be a change-delete conflict now. Differential Revision: https://phab.mercurial-scm.org/D8989
mercurial/commit.py
tests/test-merge-criss-cross.t
--- a/mercurial/commit.py	Thu Sep 03 13:44:06 2020 +0530
+++ b/mercurial/commit.py	Thu Sep 03 13:58:14 2020 +0530
@@ -332,9 +332,20 @@
             ):
                 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()
-    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)
--- a/tests/test-merge-criss-cross.t	Thu Sep 03 13:44:06 2020 +0530
+++ b/tests/test-merge-criss-cross.t	Thu Sep 03 13:58:14 2020 +0530
@@ -593,17 +593,15 @@
   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 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)
@@ -630,11 +628,13 @@
      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  e9b708131723 merge-keeping-the-file-from-deleted
+  +---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
   | |/
@@ -666,16 +666,19 @@
   $ 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
+  the-file (newfilenode !)
 
 (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)
@@ -698,16 +701,19 @@
   $ 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
+  the-file (newfilenode !)
 
 (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)
@@ -719,7 +725,8 @@
   $ 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
@@ -729,7 +736,8 @@
 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]
@@ -752,7 +760,8 @@
 (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)