[PATCH STABLE] import: fix parent selection when importing merges

Patrick Mezard pmezard at gmail.com
Wed Nov 16 06:31:23 CST 2011


# HG changeset patch
# User Patrick Mezard <pmezard at gmail.com>
# Date 1321444390 -3600
# Branch stable
# Node ID d44677e801464c4308cad2331dbfce49a1bf4666
# Parent  6eff984d8e76811f1ce129a424236abf0afaa191
import: fix parent selection when importing merges

With "wp1" and "wp2" the current working directory parents, "p1" and "p2" the
patch parents and "parents" the resulting commit parents, the current behaviour
is:

--bypass --exact p2 parents
0        0       0  [wp1, wp2]
0        0       1  [wp1, wp2]/buggy
0        1       0  [p1]
0        1       1  [p1, p2]
1        0       0  [wp1, wp2]
1        0       1  [p1, p2]
1        1       0  [p1]
1        1       1  [p1, p2]

The original behaviour before f53dc0787424 was:

--bypass --exact p2 parents
0        0       0  [wp1, wp2]
0        0       1  if p1 == wp1 then [p1, p2] otherwise [wp1, wp2]
0        1       0  [p1]
0        1       1  [p1, p2]

This patch restores the previous behaviour when --bypass is not set, and align
--bypass behaviour when --exact is not set with merge diffs.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3490,6 +3490,12 @@
                 try:
                     p1 = repo[p1]
                     p2 = repo[p2]
+                    # Without any options, consider p2 only if the
+                    # patch is being applied on top of the recorded
+                    # first parent.
+                    if p1 != parents[0]:
+                        p1 = parents[0]
+                        p2 = repo[nullid]
                 except error.RepoError:
                     p1, p2 = parents
             else:
@@ -3497,9 +3503,9 @@
 
             n = None
             if update:
-                if opts.get('exact') and p1 != parents[0]:
+                if p1 != parents[0]:
                     hg.clean(repo, p1.node())
-                if p1 != parents[0] and p2 != parents[1]:
+                if p2 != parents[1]:
                     repo.dirstate.setparents(p1.node(), p2.node())
 
                 if opts.get('exact') or opts.get('import_branch'):
@@ -3513,7 +3519,10 @@
                     if message:
                         msgs.append(message)
                 else:
-                    if opts.get('exact'):
+                    if opts.get('exact') or p2:
+                        # If you got here, you either use --force and know what
+                        # you are doing or used --exact or a merge patch while
+                        # being updated to its first parent.
                         m = None
                     else:
                         m = scmutil.matchfiles(repo, files or [])
diff --git a/tests/test-import-merge.t b/tests/test-import-merge.t
new file mode 100644
--- /dev/null
+++ b/tests/test-import-merge.t
@@ -0,0 +1,114 @@
+  $ echo "[extensions]" >> $HGRCPATH
+  $ echo "mq=" >> $HGRCPATH
+
+  $ tipparents() {
+  > hg parents --template "{rev}:{node|short} {desc|firstline}\n" -r tip
+  > }
+
+Test import and merge diffs
+
+  $ hg init repo
+  $ cd repo
+  $ echo a > a
+  $ hg ci -Am adda
+  adding a
+  $ echo a >> a
+  $ hg ci -m changea
+  $ echo c > c
+  $ hg ci -Am addc
+  adding c
+  $ hg up 0
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo b > b
+  $ hg ci -Am addb
+  adding b
+  created new head
+  $ hg up 1
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg merge 3
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m merge
+  $ hg export . > ../merge.diff
+  $ cd ..
+  $ hg clone -r2 repo repo2
+  adding changesets
+  adding manifests
+  adding file changes
+  added 3 changesets with 3 changes to 2 files
+  updating to branch default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd repo2
+  $ hg pull -r3 ../repo
+  pulling from ../repo
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  (run 'hg heads' to see heads, 'hg merge' to merge)
+
+Test without --exact and diff.p1 == workingdir.p1
+
+  $ hg up 1
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg import ../merge.diff
+  applying ../merge.diff
+  $ tipparents
+  1:540395c44225 changea
+  3:102a90ea7b4a addb
+  $ hg strip --no-backup tip
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+Test without --exact and diff.p1 != workingdir.p1
+
+  $ hg up 2
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg import ../merge.diff
+  applying ../merge.diff
+  $ tipparents
+  2:890ecaa90481 addc
+  $ hg strip --no-backup tip
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+Test with --exact
+
+  $ hg import --exact ../merge.diff
+  applying ../merge.diff
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ tipparents
+  1:540395c44225 changea
+  3:102a90ea7b4a addb
+  $ hg strip --no-backup tip
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+Test with --bypass and diff.p1 == workingdir.p1
+
+  $ hg up 1
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg import --bypass ../merge.diff
+  applying ../merge.diff
+  $ tipparents
+  1:540395c44225 changea
+  3:102a90ea7b4a addb
+  $ hg strip --no-backup tip
+
+Test with --bypass and diff.p1 != workingdir.p1
+
+  $ hg up 2
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg import --bypass ../merge.diff
+  applying ../merge.diff
+  $ tipparents
+  2:890ecaa90481 addc
+  $ hg strip --no-backup tip
+
+Test with --bypass and --exact
+
+  $ hg import --bypass --exact ../merge.diff
+  applying ../merge.diff
+  $ tipparents
+  1:540395c44225 changea
+  3:102a90ea7b4a addb
+  $ hg strip --no-backup tip
+


More information about the Mercurial-devel mailing list