Patchwork [3,of,8] merge: add `ACTION_KEEP_ABSENT` to represent files we want to keep absent

login
register
mail settings
Submitter Pulkit Goyal
Date Sept. 14, 2020, 11:15 a.m.
Message ID <2c58747e0a1ebe17b6bf.1600082119@workspace>
Download mbox | patch
Permalink /patch/47157/
State Accepted
Headers show

Comments

Pulkit Goyal - Sept. 14, 2020, 11:15 a.m.
# HG changeset patch
# User Pulkit Goyal <7895pulkit@gmail.com>
# Date 1598960306 -19800
#      Tue Sep 01 17:08:26 2020 +0530
# Node ID 2c58747e0a1ebe17b6bf1f4f393da2be57bce63a
# Parent  cfabb1ccdf7a2cb67bb2819f798bad53c6aac977
# EXP-Topic merge-newnode
merge: add `ACTION_KEEP_ABSENT` to represent files we want to keep absent

There are files which were deleted/not present in working copy parent but were
present on other side of merge. On merge, we might decide to keep them deleted.
We want to track such cases more closely, rather all kind of cases which results
from some kind of merging logic.

We do have `ACTION_KEEP` but having a dedicated action for the absent case is
more cleaner.

Initially I named the action as `ACTION_KEEP_DELETED` but later realized that
file can be not-present because of other reasons than deletion like rename,
hence decided to use more generic name `ACTION_KEEP_ABSENT`.

Differential Revision: https://phab.mercurial-scm.org/D8974

Patch

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -563,7 +563,10 @@  class mergeresult(object):
     It has information about what actions need to be performed on dirstate
     mapping of divergent renames and other such cases. '''
 
-    NO_OP_ACTIONS = (mergestatemod.ACTION_KEEP,)
+    NO_OP_ACTIONS = (
+        mergestatemod.ACTION_KEEP,
+        mergestatemod.ACTION_KEEP_ABSENT,
+    )
 
     def __init__(self):
         """
@@ -1175,6 +1178,11 @@  def calculateupdates(
                 repo.ui.note(_(b" %s: picking 'keep' action\n") % f)
                 mresult.addfile(f, *bids[mergestatemod.ACTION_KEEP][0])
                 continue
+            # If keep absent is an option, just do that
+            if mergestatemod.ACTION_KEEP_ABSENT in bids:
+                repo.ui.note(_(b" %s: picking 'keep absent' action\n") % f)
+                mresult.addfile(f, *bids[mergestatemod.ACTION_KEEP_ABSENT][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]
@@ -1486,6 +1494,11 @@  def applyupdates(
     ):
         repo.ui.debug(b" %s: %s -> k\n" % (f, msg))
         # no progress
+    for f, args, msg in mresult.getactions(
+        (mergestatemod.ACTION_KEEP_ABSENT,), sort=True
+    ):
+        repo.ui.debug(b" %s: %s -> ka\n" % (f, msg))
+        # no progress
 
     # directory rename, move local
     for f, args, msg in mresult.getactions(
diff --git a/mercurial/mergestate.py b/mercurial/mergestate.py
--- a/mercurial/mergestate.py
+++ b/mercurial/mergestate.py
@@ -120,6 +120,10 @@  ACTION_MERGE = b'm'
 ACTION_LOCAL_DIR_RENAME_GET = b'dg'
 ACTION_DIR_RENAME_MOVE_LOCAL = b'dm'
 ACTION_KEEP = b'k'
+# the file was absent on local side before merge and we should
+# keep it absent (absent means file not present, it can be a result
+# of file deletion, rename etc.)
+ACTION_KEEP_ABSENT = b'ka'
 ACTION_EXEC = b'e'
 ACTION_CREATED_MERGE = b'cm'
 
@@ -837,6 +841,10 @@  def recordupdates(repo, actions, branchm
     for f, args, msg in actions.get(ACTION_KEEP, []):
         pass
 
+    # keep deleted
+    for f, args, msg in actions.get(ACTION_KEEP_ABSENT, []):
+        pass
+
     # get
     for f, args, msg in actions.get(ACTION_GET, []):
         if branchmerge: