# HG changeset patch # User Brendan Cully # Date 1335151836 25200 # Node ID d9901eb3e42d89f65d5e9481f7e5abe6f72ba6aa # Parent 4fe874697a4dc80f3a128569a1d6bd5d460ec9eb# Parent cbf2ea2f5ca169d22e0729cb71a21b808574b90e Merge stable diff -r 4fe874697a4d -r d9901eb3e42d hgext/fetch.py --- a/hgext/fetch.py Mon Apr 23 01:39:26 2012 +0200 +++ b/hgext/fetch.py Sun Apr 22 20:30:36 2012 -0700 @@ -23,10 +23,9 @@ Otherwise, the working directory is updated to include the new changes. - When a merge occurs, the newly pulled changes are assumed to be - "authoritative". The head of the new changes is used as the first - parent, with local changes as the second. To switch the merge - order, use --switch-parent. + When a merge is needed, the working directory is first updated to + the newly pulled changes. Local changes are then merged into the + pulled changes. To switch the merge order, use --switch-parent. See :hg:`help dates` for a list of formats valid for -d/--date. diff -r 4fe874697a4d -r d9901eb3e42d mercurial/bdiff.c --- a/mercurial/bdiff.c Mon Apr 23 01:39:26 2012 +0200 +++ b/mercurial/bdiff.c Sun Apr 22 20:30:36 2012 -0700 @@ -339,10 +339,12 @@ struct line *al, *bl; struct hunk l, *h; int an, bn, len = 0, la, lb, count; + PyThreadState *_save; if (!PyArg_ParseTuple(args, "s#s#:bdiff", &sa, &la, &sb, &lb)) return NULL; + _save = PyEval_SaveThread(); an = splitlines(sa, la, &al); bn = splitlines(sb, lb, &bl); if (!al || !bl) @@ -361,6 +363,8 @@ la = h->a2; lb = h->b2; } + PyEval_RestoreThread(_save); + _save = NULL; result = PyBytes_FromStringAndSize(NULL, len); @@ -385,6 +389,8 @@ } nomem: + if (_save) + PyEval_RestoreThread(_save); free(al); free(bl); freehunks(l.next); diff -r 4fe874697a4d -r d9901eb3e42d mercurial/merge.py --- a/mercurial/merge.py Mon Apr 23 01:39:26 2012 +0200 +++ b/mercurial/merge.py Sun Apr 22 20:30:36 2012 -0700 @@ -110,10 +110,18 @@ folded[fold] = fn if wctx: + # class to delay looking up copy mapping + class pathcopies(object): + @util.propertycache + def map(self): + # {dst@mctx: src@wctx} copy mapping + return copies.pathcopies(wctx, mctx) + pc = pathcopies() + for fn in wctx: fold = util.normcase(fn) mfn = folded.get(fold, None) - if mfn and (mfn != fn): + if mfn and mfn != fn and pc.map.get(mfn) != fn: raise util.Abort(_("case-folding collision between %s and %s") % (mfn, fn)) @@ -568,7 +576,11 @@ action = [] folding = not util.checkcase(repo.path) if folding: - _checkcollision(p2, branchmerge and p1) + # collision check is not needed for clean update + if not branchmerge and force: + _checkcollision(p2, None) + else: + _checkcollision(p2, wc) if not force: _checkunknown(repo, wc, p2) action += _forgetremoved(wc, p2, branchmerge) diff -r 4fe874697a4d -r d9901eb3e42d mercurial/patch.py --- a/mercurial/patch.py Mon Apr 23 01:39:26 2012 +0200 +++ b/mercurial/patch.py Sun Apr 22 20:30:36 2012 -0700 @@ -230,7 +230,7 @@ elif line.startswith("# Node ID "): nodeid = line[10:] elif line.startswith("# Parent "): - parents.append(line[10:]) + parents.append(line[9:].lstrip()) elif not line.startswith("# "): hgpatchheader = False elif line == '---' and gitsendmail: diff -r 4fe874697a4d -r d9901eb3e42d tests/test-casecollision-merge.t --- a/tests/test-casecollision-merge.t Mon Apr 23 01:39:26 2012 +0200 +++ b/tests/test-casecollision-merge.t Sun Apr 22 20:30:36 2012 -0700 @@ -6,104 +6,204 @@ test for branch merging ################################ - $ hg init repo1 - $ cd repo1 - -create base revision +test for rename awareness of case-folding collision check: - $ echo base > base.txt - $ hg add base.txt - $ hg commit -m 'base' +(1) colliding file is one renamed from collided file: +this is also case for issue3370. -add same file in different case on both heads + $ hg init merge_renameaware_1 + $ cd merge_renameaware_1 - $ echo a > a.txt - $ hg add a.txt - $ hg commit -m 'add a.txt' - + $ echo a > a + $ hg add a + $ hg commit -m '#0' + $ hg rename a tmp + $ hg rename tmp A + $ hg commit -m '#1' $ hg update 0 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - - $ echo A > A.TXT - $ hg add A.TXT - $ hg commit -m 'add A.TXT' + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo 'modified at #2' > a + $ hg commit -m '#2' created new head -merge another, and fail with case-folding collision + $ hg merge + merging a and A to A + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg status -A + M A + a + R a + $ cat A + modified at #2 + + $ hg update --clean 1 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge + merging A and a to A + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg status -A + M A + a + $ cat A + modified at #2 + + $ cd .. + +(2) colliding file is not related to collided file + + $ hg init merge_renameaware_2 + $ cd merge_renameaware_2 + + $ echo a > a + $ hg add a + $ hg commit -m '#0' + $ hg remove a + $ hg commit -m '#1' + $ echo A > A + $ hg add A + $ hg commit -m '#2' + $ hg update --clean 0 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo 'modified at #3' > a + $ hg commit -m '#3' + created new head $ hg merge - abort: case-folding collision between a.txt and A.TXT + abort: case-folding collision between A and a [255] + $ hg parents --template '{rev}\n' + 3 + $ hg status -A + C a + $ cat a + modified at #3 -check clean-ness of working directory - - $ hg status + $ hg update --clean 2 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg merge + abort: case-folding collision between a and A + [255] $ hg parents --template '{rev}\n' 2 + $ hg status -A + C A + $ cat A + A + $ cd .. + ################################ test for linear updates ################################ - $ hg init repo2 - $ cd repo2 +test for rename awareness of case-folding collision check: -create base revision (rev:0) +(1) colliding file is one renamed from collided file + + $ hg init linearupdate_renameaware_1 + $ cd linearupdate_renameaware_1 - $ hg import --bypass --exact - < # HG changeset patch - > # User null - > # Date 1 0 - > # Node ID e1bdf414b0ea9c831fd3a14e94a0a18e1410f98b - > # Parent 0000000000000000000000000000000000000000 - > add a - > - > diff --git a/a b/a - > new file mode 100644 - > --- /dev/null - > +++ b/a - > @@ -0,0 +1,3 @@ - > +this is line 1 - > +this is line 2 - > +this is line 3 - > EOF - applying patch from stdin - -create rename revision (rev:1) - - $ hg import --bypass --exact - < # HG changeset patch - > # User null - > # Date 1 0 - > # Node ID 9dca9f19bb91851bc693544b598b0740629edfad - > # Parent e1bdf414b0ea9c831fd3a14e94a0a18e1410f98b - > rename a to A - > - > diff --git a/a b/A - > rename from a - > rename to A - > EOF - applying patch from stdin - -update to base revision, and modify 'a' + $ echo a > a + $ hg add a + $ hg commit -m '#0' + $ hg rename a tmp + $ hg rename tmp A + $ hg commit -m '#1' $ hg update 0 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ echo 'this is added line' >> a + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved -update to current tip linearly - + $ echo 'this is added line' >> a $ hg update 1 merging a and A to A 0 files updated, 1 files merged, 0 files removed, 0 files unresolved - -check status and contents of file - $ hg status -A M A $ cat A - this is line 1 - this is line 2 - this is line 3 + a this is added line + + $ cd .. + +(2) colliding file is not related to collided file + + $ hg init linearupdate_renameaware_2 + $ cd linearupdate_renameaware_2 + + $ echo a > a + $ hg add a + $ hg commit -m '#0' + $ hg remove a + $ hg commit -m '#1' + $ echo A > A + $ hg add A + $ hg commit -m '#2' + + $ hg update 0 + abort: case-folding collision between a and A + [255] + $ hg parents --template '{rev}\n' + 2 + $ hg status -A + C A + $ cat A + A + + $ hg update --check 0 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg parents --template '{rev}\n' + 0 + $ hg status -A + C a + $ cat a + a + + $ hg update --clean 2 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg parents --template '{rev}\n' + 2 + $ hg status -A + C A + $ cat A + A + + $ cd .. + +(3) colliding file is not related to collided file: added in working dir + + $ hg init linearupdate_renameaware_3 + $ cd linearupdate_renameaware_3 + + $ echo a > a + $ hg add a + $ hg commit -m '#0' + $ hg rename a b + $ hg commit -m '#1' + $ hg update 0 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ echo B > B + $ hg add B + $ hg status + A B + $ hg update + abort: case-folding collision between b and B + [255] + + $ hg update --check + abort: uncommitted local changes + [255] + + $ hg update --clean + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg parents --template '{rev}\n' + 1 + $ hg status -A + C b + $ cat b + a + + $ cd .. diff -r 4fe874697a4d -r d9901eb3e42d tests/test-impexp-branch.t --- a/tests/test-impexp-branch.t Mon Apr 23 01:39:26 2012 +0200 +++ b/tests/test-impexp-branch.t Sun Apr 22 20:30:36 2012 -0700 @@ -1,3 +1,6 @@ + $ echo '[extensions]' >> $HGRCPATH + $ echo 'mq =' >> $HGRCPATH + $ cat >findbranch.py < import re, sys > @@ -55,3 +58,14 @@ applying ../r0.patch $ hg import --exact ../r1.patch applying ../r1.patch + +Test --exact and patch header separators (issue3356) + + $ hg strip --no-backup . + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + >>> import re + >>> p = file('../r1.patch', 'rb').read() + >>> p = re.sub(r'Parent\s+', 'Parent ', p) + >>> file('../r1-ws.patch', 'wb').write(p) + $ hg import --exact ../r1-ws.patch + applying ../r1-ws.patch