[PATCH 6 of 8] merge: use separate lists for each action type
Pierre-Yves David
pierre-yves.david at ens-lyon.org
Wed May 7 16:30:32 CDT 2014
On 05/01/2014 04:42 PM, Mads Kiilerich wrote:
> # HG changeset patch
> # User Mads Kiilerich <madski at unity3d.com>
> # Date 1393550758 -3600
> # Fri Feb 28 02:25:58 2014 +0100
> # Branch stable
> # Node ID 68cb67727ca4447bad6349b6f7d75d799d35f6ed
> # Parent 9d786e6be4319bf31467eb715fb432c68ccd4507
> merge: use separate lists for each action type
>
> This replaces the grand unified action list that had multiple action types as
> tuples in one big list. That list was iterated multiple times just to find
> actions of a specific type. This data model also made some code more
> convoluted than necessary.
>
> Instead we now store actions as a tuple of lists. Using multiple lists gives a
> bit of cut'n'pasted code but also enables other optimizations.
I like this change very much.
> This patch uses 'if True:' to preserve indentations and help reviewing. It also
> limits the number of conflicts with other pending patches. It can trivially be
> cleaned up later.
>
> The changes to test output are due to changes in the ordering of debug output.
> That is mainly because we now do the debug logging for files when we actually
> process them. Files are also processed in a slightly different but still
> correct order. It is now primarily ordered by action type, secondarily by
> filename.
I though this reordering already happened in patch 2 of this series?
> diff --git a/mercurial/merge.py b/mercurial/merge.py
> --- a/mercurial/merge.py
> +++ b/mercurial/merge.py
> @@ -310,63 +310,44 @@ def _forgetremoved(wctx, mctx, branchmer
> as removed.
> """
>
> - actions = []
> - state = branchmerge and 'r' or 'f'
> + ractions = []
> + factions = xactions = []
> + if branchmerge:
> + xactions = ractions
> for f in wctx.deleted():
> if f not in mctx:
> - actions.append((f, state, None, "forget deleted"))
> + xactions.append((f, None, "forget deleted"))
>
> if not branchmerge:
> for f in wctx.removed():
> if f not in mctx:
> - actions.append((f, "f", None, "forget removed"))
> + factions.append((f, None, "forget removed"))
>
> - return actions
> + return ractions, factions
>
> def _checkcollision(repo, wmf, actions):
> # build provisional merged manifest up
> pmmf = set(wmf)
>
> - def addop(f, args):
> - pmmf.add(f)
> - def removeop(f, args):
> + # k, dr, e and rd are nop
> + for m in 'a', 'f', 'g', 'cd', 'dc':
> + for f, args, msg in actions[m]:
> + pmmf.add(f)
> + for f, args, msg in actions['r']:
> pmmf.discard(f)
> - def nop(f, args):
> - pass
> -
> - def renamemoveop(f, args):
> + for f, args, msg in actions['dm']:
> f2, flags = args
> pmmf.discard(f2)
> pmmf.add(f)
> - def renamegetop(f, args):
> + for f, args, msg in actions['dg']:
> f2, flags = args
> pmmf.add(f)
> - def mergeop(f, args):
> + for f, args, msg in actions['m']:
> f1, f2, fa, move, anc = args
> if move:
> pmmf.discard(f1)
> pmmf.add(f)
>
> - opmap = {
> - "a": addop,
> - "dm": renamemoveop,
> - "dg": renamegetop,
> - "dr": nop,
> - "e": nop,
> - "k": nop,
> - "f": addop, # untracked file should be kept in working directory
> - "g": addop,
> - "m": mergeop,
> - "r": removeop,
> - "rd": nop,
> - "cd": addop,
> - "dc": addop,
> - }
> - for f, m, args, msg in actions:
> - op = opmap.get(m)
> - assert op, m
> - op(f, args)
> -
> # check case-folding collision in provisional merged manifest
> foldmap = {}
> for f in sorted(pmmf):
> @@ -386,7 +367,9 @@ def manifestmerge(repo, wctx, p2, pa, br
> acceptremote = accept the incoming changes without prompting
> """
>
> - actions, copy, movewithdir = [], {}, {}
> + actions = dict((m, []) for m in ['a', 'f', 'g', 'cd', 'dc', 'r',
> + 'dm', 'dg', 'm', 'dr', 'e', 'rd', 'k'])
This line is twice the standard size, you can probably switch to a
version for loop.
> @@ -803,126 +775,120 @@ def calculateupdates(repo, wctx, mctx, a
> actions = manifestmerge(repo, wctx, mctx, ancestor,
> branchmerge, force,
> partial, acceptremote, followcopies)
> - for a in sorted(actions, key=lambda a: (a[1], a)):
> - f, m, args, msg = a
> - repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
> - if f in fbids:
> - fbids[f].append(a)
> - else:
> - fbids[f] = [a]
> + for m, l in sorted(actions.items()):
> + for a in l:
> + f, args, msg = a
> + repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
> + if f in fbids:
> + d = fbids[f]
> + if m in d:
> + d[m].append(a)
> + else:
> + d[m] = [a]
> + else:
> + fbids[f] = {m: [a]}
>
> # Pick the best bid for each file
> repo.ui.note(_('\nauction for merging merge bids\n'))
> - actions = []
> + actions = dict((m, []) for m in actions.keys())
> for f, bidsl in sorted(fbids.items()):
> # Consensus?
> - a0 = bidsl[0]
> - if util.all(a == a0 for a in bidsl[1:]): # len(bidsl) is > 1
> - repo.ui.note(" %s: consensus for %s\n" % (f, a0[1]))
> - actions.append(a0)
> - continue
> - # Group bids by kind of action
> - bids = {}
> - for a in bidsl:
> - m = a[1]
> - if m in bids:
> - bids[m].append(a)
> - else:
> - bids[m] = [a]
> + if len(bidsl) == 1: # one kind of method
> + m, l = bidsl.items()[0]
> + if util.all(a == l[0] for a in l[1:]): # len(bidsl) is > 1
> + repo.ui.note(" %s: consensus for %s\n" % (f, m))
> + actions[m].append(l[0])
> + continue
I do not understand the "# one kind of method"
--
Pierre-Yves David
More information about the Mercurial-devel
mailing list