diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -523,7 +523,6 @@ narrowed. """ # TODO: handle with nonconflicttypes - nooptypes = {mergestatemod.ACTION_KEEP} nonconflicttypes = { mergestatemod.ACTION_ADD, mergestatemod.ACTION_ADD_MODIFIED, @@ -541,7 +540,7 @@ pass elif not branchmerge: mresult.removefile(f) # just updating, ignore changes outside clone - elif action[0] in nooptypes: + elif action[0] in mergeresult.NO_OP_ACTIONS: mresult.removefile(f) # merge does not affect file elif action[0] in nonconflicttypes: raise error.Abort( @@ -564,6 +563,11 @@ 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, + mergestatemod.ACTION_KEEP_ABSENT, + ) + def __init__(self): """ filemapping: dict of filename as keys and action related info as values @@ -711,12 +715,12 @@ a not in ( mergestatemod.ACTION_GET, - mergestatemod.ACTION_KEEP, mergestatemod.ACTION_EXEC, mergestatemod.ACTION_REMOVE, mergestatemod.ACTION_PATH_CONFLICT_RESOLVE, ) and self._actionmapping[a] + and a not in self.NO_OP_ACTIONS ): return True @@ -1167,6 +1171,11 @@ 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] @@ -1412,7 +1421,7 @@ wctx[f].audit() wctx[f].remove() - numupdates = mresult.len() - mresult.len((mergestatemod.ACTION_KEEP,)) + numupdates = mresult.len() - mresult.len(mergeresult.NO_OP_ACTIONS) progress = repo.ui.makeprogress( _(b'updating'), unit=_(b'files'), total=numupdates ) @@ -1521,6 +1530,11 @@ ): 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_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 @@ 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: diff --git a/mercurial/sparse.py b/mercurial/sparse.py --- a/mercurial/sparse.py +++ b/mercurial/sparse.py @@ -399,7 +399,7 @@ temporaryfiles.append(file) prunedactions[file] = action elif branchmerge: - if type != mergestatemod.ACTION_KEEP: + if type not in mergemod.mergeresult.NO_OP_ACTIONS: temporaryfiles.append(file) prunedactions[file] = action elif type == mergestatemod.ACTION_FORGET: