changeset 23638:09be050ca98c

merge: let bid merge work on the file->action dict By moving the conversion from the file->action dict after the bid merge code, bid merge can be simplified a little. A few tests are affected by this change. Where we used to iterate over the actions first in order of the action type ('g', 'r', etc.) [1], we now iterate in order of filename. This difference affects the order of debug log statements. [1] And then in the non-deterministic order of files in the manifest dictionary (the order returned from manifest.diff()).
author Martin von Zweigbergk <martinvonz@google.com>
date Thu, 11 Dec 2014 20:56:53 -0800
parents 13f53a2aa342
children 35c724903157
files mercurial/merge.py tests/test-merge-criss-cross.t
diffstat 2 files changed, 24 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/merge.py	Mon Dec 08 13:24:10 2014 -0800
+++ b/mercurial/merge.py	Thu Dec 11 20:56:53 2014 -0800
@@ -525,12 +525,6 @@
         raise util.Abort(_("untracked files in working directory differ "
                            "from files in requested revision"))
 
-    # Convert to dictionary-of-lists format
-    actionbyfile = actions
-    actions = dict((m, []) for m in 'a f g cd dc r dm dg m e k'.split())
-    for f, (m, args, msg) in actionbyfile.iteritems():
-        actions[m].append((f, args, msg))
-
     return actions, diverge, renamedelete
 
 def _resolvetrivial(repo, wctx, mctx, ancestor, actions):
@@ -583,22 +577,21 @@
                 # Arbitrarily pick warnings from first iteration
                 diverge = diverge1
                 renamedelete = renamedelete1
-            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]
+            for f, a in sorted(actions.iteritems()):
+                m, 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:
-                        fbids[f] = {m: [a]}
+                        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 = dict((m, []) for m in actions.keys())
+        actions = {}
         for f, bids in sorted(fbids.items()):
             # bids is a mapping from action method to list af actions
             # Consensus?
@@ -606,19 +599,19 @@
                 m, l = bids.items()[0]
                 if util.all(a == l[0] for a in l[1:]): # len(bids) is > 1
                     repo.ui.note(" %s: consensus for %s\n" % (f, m))
-                    actions[m].append(l[0])
+                    actions[f] = l[0]
                     continue
             # If keep is an option, just do it.
             if 'k' in bids:
                 repo.ui.note(" %s: picking 'keep' action\n" % f)
-                actions['k'].append(bids['k'][0])
+                actions[f] = bids['k'][0]
                 continue
             # If there are gets and they all agree [how could they not?], do it.
             if 'g' in bids:
                 ga0 = bids['g'][0]
                 if util.all(a == ga0 for a in bids['g'][1:]):
                     repo.ui.note(" %s: picking 'get' action\n" % f)
-                    actions['g'].append(ga0)
+                    actions[f] = ga0
                     continue
             # TODO: Consider other simple actions such as mode changes
             # Handle inefficient democrazy.
@@ -630,10 +623,16 @@
             m, l = bids.items()[0]
             repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
                          (f, m))
-            actions[m].append(l[0])
+            actions[f] = l[0]
             continue
         repo.ui.note(_('end of auction\n\n'))
 
+    # Convert to dictionary-of-lists format
+    actionbyfile = actions
+    actions = dict((m, []) for m in 'a f g cd dc r dm dg m e k'.split())
+    for f, (m, args, msg) in actionbyfile.iteritems():
+        actions[m].append((f, args, msg))
+
     _resolvetrivial(repo, wctx, mctx, ancestors[0], actions)
 
     if wctx.rev() is None:
--- a/tests/test-merge-criss-cross.t	Mon Dec 08 13:24:10 2014 -0800
+++ b/tests/test-merge-criss-cross.t	Thu Dec 11 20:56:53 2014 -0800
@@ -141,8 +141,8 @@
   resolving manifests
    branchmerge: True, force: False, partial: False
    ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
+   f1: versions differ -> m
    f2: remote unchanged -> k
-   f1: versions differ -> m
   
   auction for merging merge bids
    f1: picking 'get' action
@@ -184,8 +184,8 @@
   resolving manifests
    branchmerge: True, force: False, partial: False
    ancestor: 40663881a6dd, local: adfe50279922+, remote: 3b08d01b0ab5
+   f1: versions differ -> m
    f2: remote is newer -> g
-   f1: versions differ -> m
   
   auction for merging merge bids
    f1: picking 'keep' action
@@ -249,8 +249,8 @@
   resolving manifests
    branchmerge: True, force: False, partial: False
    ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
+   f1: versions differ -> m
    f2: remote unchanged -> k
-   f1: versions differ -> m
   
   auction for merging merge bids
    f1: picking 'get' action