Mercurial > hg
changeset 27131:d837da26155e
merge: add a new action type representing files to add/mark as modified
This is somewhat different from the currently existing 'a' action, for the
following case:
- dirty working copy, with file 'fa' added and 'fm' modified
- hg merge --force with a rev that neither has 'fa' nor 'fm'
- for the change/delete conflicts we pick 'changed' for both 'fa' and 'fm'.
In this case 'branchmerge' is true, but we need to distinguish between 'fa',
which should ultimately be marked added, and 'fm', which should be marked
modified.
Our current strategy is to just not touch the dirstate at all. That works for
now, but won't work once we move change/delete conflicts to the resolve phase.
In that case we may perform repeated re-resolves, some of which might mark the
file removed or remove the file from the dirstate. We'll need to re-add the
file to the dirstate, and we need to be able to figure out whether we mark the
file added or modified. That is what the new 'am' action lets us do.
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Mon, 30 Nov 2015 10:19:39 -0800 |
parents | 6f045b563fa5 |
children | baa7571f40c5 |
files | mercurial/merge.py tests/test-rename-merge2.t |
diffstat | 2 files changed, 23 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/merge.py Mon Nov 30 10:03:21 2015 -0800 +++ b/mercurial/merge.py Mon Nov 30 10:19:39 2015 -0800 @@ -479,7 +479,10 @@ if fcd.isabsent(): # dc: remote picked action = 'g' elif fco.isabsent(): # cd: local picked - action = 'a' + if dfile in self.localctx: + action = 'am' + else: + action = 'a' # else: regular merges (no action necessary) self._results[dfile] = r, action @@ -524,7 +527,7 @@ def actions(self): """return lists of actions to perform on the dirstate""" - actions = {'r': [], 'f': [], 'a': [], 'g': []} + actions = {'r': [], 'f': [], 'a': [], 'am': [], 'g': []} for f, (r, action) in self._results.iteritems(): if action is not None: actions[action].append((f, None, "merge result")) @@ -631,7 +634,7 @@ if actions: # k, dr, e and rd are no-op - for m in 'a', 'f', 'g', 'cd', 'dc': + for m in 'a', 'am', 'f', 'g', 'cd', 'dc': for f, args, msg in actions[m]: pmmf.add(f) for f, args, msg in actions['r']: @@ -1065,6 +1068,12 @@ z += 1 progress(_updating, z, item=f, total=numupdates, unit=_files) + # re-add/mark as modified (manifest only, just log it) + for f, args, msg in actions['am']: + repo.ui.debug(" %s: %s -> am\n" % (f, msg)) + z += 1 + progress(_updating, z, item=f, total=numupdates, unit=_files) + # keep (noop, just log it) for f, args, msg in actions['k']: repo.ui.debug(" %s: %s -> k\n" % (f, msg)) @@ -1189,6 +1198,13 @@ if not branchmerge: repo.dirstate.add(f) + # re-add/mark as modified + for f, args, msg in actions.get('am', []): + if branchmerge: + repo.dirstate.normallookup(f) + else: + repo.dirstate.add(f) + # exec change for f, args, msg in actions.get('e', []): repo.dirstate.normallookup(f) @@ -1390,7 +1406,7 @@ repo, wc, p2, pas, branchmerge, force, partial, mergeancestor, followcopies) # Convert to dictionary-of-lists format - actions = dict((m, []) for m in 'a f g cd dc r dm dg m e k'.split()) + actions = dict((m, []) for m in 'a am f g cd dc r dm dg m e k'.split()) for f, (m, args, msg) in actionbyfile.iteritems(): if m not in actions: actions[m] = [] @@ -1411,6 +1427,8 @@ "use (c)hanged version or (d)elete?" "$$ &Changed $$ &Delete") % f, 0): actions['r'].append((f, None, "prompt delete")) + elif f in p1: + actions['am'].append((f, None, "prompt keep")) else: actions['a'].append((f, None, "prompt keep"))
--- a/tests/test-rename-merge2.t Mon Nov 30 10:03:21 2015 -0800 +++ b/tests/test-rename-merge2.t Mon Nov 30 10:19:39 2015 -0800 @@ -725,7 +725,7 @@ use (c)hanged version or (d)elete? c preserving b for resolve of b preserving rev for resolve of rev - a: prompt keep -> a + a: prompt keep -> am b: both created -> m (premerge) picked tool 'python ../merge' for b (binary False symlink False) merging b