view tests/test-import.t @ 46582:b0a3ca02d17a

copies-rust: implement PartialEqual manually Now that we know that each (dest, rev) pair has at most a unique CopySource, we can simplify comparison a lot. This "simple" step buy a good share of the previous slowdown back in some case: Repo Case Source-Rev Dest-Rev # of revisions old time new time Difference Factor time per rev --------------------------------------------------------------------------------------------------------------------------------------------------------------- mozilla-try x00000_revs_x00000_added_x000_copies 9b2a99adc05e 8e29777b48e6 : 382065 revs, 43.304637 s, 34.443661 s, -8.860976 s, × 0.7954, 90 µs/rev Full benchmark: Repo Case Source-Rev Dest-Rev # of revisions old time new time Difference Factor time per rev --------------------------------------------------------------------------------------------------------------------------------------------------------------- mercurial x_revs_x_added_0_copies ad6b123de1c7 39cfcef4f463 : 1 revs, 0.000043 s, 0.000043 s, +0.000000 s, × 1.0000, 43 µs/rev mercurial x_revs_x_added_x_copies 2b1c78674230 0c1d10351869 : 6 revs, 0.000114 s, 0.000117 s, +0.000003 s, × 1.0263, 19 µs/rev mercurial x000_revs_x000_added_x_copies 81f8ff2a9bf2 dd3267698d84 : 1032 revs, 0.004937 s, 0.004892 s, -0.000045 s, × 0.9909, 4 µs/rev pypy x_revs_x_added_0_copies aed021ee8ae8 099ed31b181b : 9 revs, 0.000339 s, 0.000196 s, -0.000143 s, × 0.5782, 21 µs/rev pypy x_revs_x000_added_0_copies 4aa4e1f8e19a 359343b9ac0e : 1 revs, 0.000049 s, 0.000050 s, +0.000001 s, × 1.0204, 50 µs/rev pypy x_revs_x_added_x_copies ac52eb7bbbb0 72e022663155 : 7 revs, 0.000202 s, 0.000117 s, -0.000085 s, × 0.5792, 16 µs/rev pypy x_revs_x00_added_x_copies c3b14617fbd7 ace7255d9a26 : 1 revs, 0.000409 s, 0.6f1f4a s, -0.000087 s, × 0.7873, 322 µs/rev pypy x_revs_x000_added_x000_copies df6f7a526b60 a83dc6a2d56f : 6 revs, 0.011984 s, 0.011949 s, -0.000035 s, × 0.9971, 1991 µs/rev pypy x000_revs_xx00_added_0_copies 89a76aede314 2f22446ff07e : 4785 revs, 0.050820 s, 0.050802 s, -0.000018 s, × 0.9996, 10 µs/rev pypy x000_revs_x000_added_x_copies 8a3b5bfd266e 2c68e87c3efe : 6780 revs, 0.087953 s, 0.088090 s, +0.000137 s, × 1.0016, 12 µs/rev pypy x000_revs_x000_added_x000_copies 89a76aede314 7b3dda341c84 : 5441 revs, 0.062902 s, 0.062079 s, -0.000823 s, × 0.9869, 11 µs/rev pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 43645 revs, 0.679234 s, 0.635337 s, -0.043897 s, × 0.9354, 14 µs/rev pypy x0000_revs_xx000_added_0_copies bf2c629d0071 4ffed77c095c : 2 revs, 0.013095 s, 0.013262 s, +0.000167 s, × 1.0128, 6631 µs/rev pypy x0000_revs_xx000_added_x000_copies 08ea3258278e d9fa043f30c0 : 11316 revs, 0.120910 s, 0.120085 s, -0.000825 s, × 0.9932, 10 µs/rev netbeans x_revs_x_added_0_copies fb0955ffcbcd a01e9239f9e7 : 2 revs, 0.000087 s, 0.000085 s, -0.000002 s, × 0.9770, 42 µs/rev netbeans x_revs_x000_added_0_copies 6f360122949f 20eb231cc7d0 : 2 revs, 0.000107 s, 0.000110 s, +0.000003 s, × 1.0280, 55 µs/rev netbeans x_revs_x_added_x_copies 1ada3faf6fb6 5a39d12eecf4 : 3 revs, 0.000186 s, 0.000177 s, -0.000009 s, × 0.9516, 59 µs/rev netbeans x_revs_x00_added_x_copies 35be93ba1e2c 9eec5e90c05f : 9 revs, 0.000754 s, 0.000743 s, -0.000011 s, × 0.9854, 82 µs/rev netbeans x000_revs_xx00_added_0_copies eac3045b4fdd 51d4ae7f1290 : 1421 revs, 0.010443 s, 0.010168 s, -0.000275 s, × 0.9737, 7 µs/rev netbeans x000_revs_x000_added_x_copies e2063d266acd 6081d72689dc : 1533 revs, 0.015697 s, 0.015946 s, +0.000249 s, × 1.0159, 10 µs/rev netbeans x000_revs_x000_added_x000_copies ff453e9fee32 411350406ec2 : 5750 revs, 0.063528 s, 0.062712 s, -0.000816 s, × 0.9872, 10 µs/rev netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : 66949 revs, 0.545515 s, 0.523832 s, -0.021683 s, × 0.9603, 7 µs/rev mozilla-central x_revs_x_added_0_copies 3697f962bb7b 7015fcdd43a2 : 2 revs, 0.000089 s, 0.000090 s, +0.000001 s, × 1.0112, 45 µs/rev mozilla-central x_revs_x000_added_0_copies dd390860c6c9 40d0c5bed75d : 8 revs, 0.000265 s, 0.000264 s, -0.000001 s, × 0.9962, 33 µs/rev mozilla-central x_revs_x_added_x_copies 8d198483ae3b 14207ffc2b2f : 9 revs, 0.000381 s, 0.000187 s, -0.000194 s, × 0.4908, 20 µs/rev mozilla-central x_revs_x00_added_x_copies 98cbc58cc6bc 446a150332c3 : 7 revs, 0.000672 s, 0.000665 s, -0.000007 s, × 0.9896, 95 µs/rev mozilla-central x_revs_x000_added_x000_copies 3c684b4b8f68 0a5e72d1b479 : 3 revs, 0.003497 s, 0.003556 s, +0.000059 s, × 1.0169, 1185 µs/rev mozilla-central x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 6 revs, 0.073204 s, 0.071345 s, -0.001859 s, × 0.9746, 11890 µs/rev mozilla-central x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 1593 revs, 0.006482 s, 0.006551 s, +0.000069 s, × 1.0106, 4 µs/rev mozilla-central x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 41 revs, 0.005066 s, 0.005078 s, +0.000012 s, × 1.0024, 123 µs/rev mozilla-central x000_revs_x000_added_x000_copies 7c97034feb78 4407bd0c6330 : 7839 revs, 0.065707 s, 0.065823 s, +0.000116 s, × 1.0018, 8 µs/rev mozilla-central x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 615 revs, 0.026800 s, 0.027050 s, +0.000250 s, × 1.0093, 43 µs/rev mozilla-central x0000_revs_xx000_added_x000_copies f78c615a656c 96a38b690156 : 30263 revs, 0.203856 s, 0.202443 s, -0.001413 s, × 0.9931, 6 µs/rev mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : 153721 revs, 1.293394 s, 1.261583 s, -0.031811 s, × 0.9754, 8 µs/rev mozilla-central x00000_revs_x00000_added_x000_copies 76caed42cf7c 1daa622bbe42 : 204976 revs, 1.698239 s, 1.643869 s, -0.054370 s, × 0.9680, 8 µs/rev mozilla-try x_revs_x_added_0_copies aaf6dde0deb8 9790f499805a : 2 revs, 0.000875 s, 0.000868 s, -0.000007 s, × 0.9920, 434 µs/rev mozilla-try x_revs_x000_added_0_copies d8d0222927b4 5bb8ce8c7450 : 2 revs, 0.000891 s, 0.000887 s, -0.000004 s, × 0.9955, 443 µs/rev mozilla-try x_revs_x_added_x_copies 092fcca11bdb 936255a0384a : 4 revs, 0.000292 s, 0.000168 s, -0.000124 s, × 0.5753, 42 µs/rev mozilla-try x_revs_x00_added_x_copies b53d2fadbdb5 017afae788ec : 2 revs, 0.003939 s, 0.001160 s, -0.002779 s, × 0.2945, 580 µs/rev mozilla-try x_revs_x000_added_x000_copies 20408ad61ce5 6f0ee96e21ad : 1 revs, 0.033027 s, 0.033016 s, -0.000011 s, × 0.9997, 33016 µs/rev mozilla-try x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 6 revs, 0.073703 s, 0.073312 s, -0.39ae31 s, × 0.9947, 12218 µs/rev mozilla-try x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 1593 revs, 0.006469 s, 0.006485 s, +0.000016 s, × 1.0025, 4 µs/rev mozilla-try x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 41 revs, 0.005278 s, 0.005494 s, +0.000216 s, × 1.0409, 134 µs/rev mozilla-try x000_revs_x000_added_x000_copies 1346fd0130e4 4c65cbdabc1f : 6657 revs, 0.064995 s, 0.064879 s, -0.000116 s, × 0.9982, 9 µs/rev mozilla-try x0000_revs_x_added_0_copies 63519bfd42ee a36a2a865d92 : 40314 revs, 0.301041 s, 0.301469 s, +0.000428 s, × 1.0014, 7 µs/rev mozilla-try x0000_revs_x_added_x_copies 9fe69ff0762d bcabf2a78927 : 38690 revs, 0.285575 s, 0.297113 s, +0.011538 s, × 1.0404, 7 µs/rev mozilla-try x0000_revs_xx000_added_x_copies 156f6e2674f2 4d0f2c178e66 : 8598 revs, 0.085597 s, 0.085890 s, +0.000293 s, × 1.0034, 9 µs/rev mozilla-try x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 615 revs, 0.027118 s, 0.027718 s, +0.000600 s, × 1.0221, 45 µs/rev mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 97052 revs, 2.119204 s, 2.048949 s, -0.070255 s, × 0.9668, 21 µs/rev mozilla-try x0000_revs_x0000_added_x0000_copies e928c65095ed e951f4ad123a : 52031 revs, 0.701479 s, 0.685924 s, -0.015555 s, × 0.9778, 13 µs/rev mozilla-try x00000_revs_x_added_0_copies 6a320851d377 1ebb79acd503 : 363753 revs, 4.482399 s, 4.482891 s, +0.000492 s, × 1.0001, 12 µs/rev mozilla-try x00000_revs_x00000_added_0_copies dc8a3ca7010e d16fde900c9c : 34414 revs, 0.574082 s, 0.577633 s, +0.003551 s, × 1.0062, 16 µs/rev mozilla-try x00000_revs_x_added_x_copies 5173c4b6f97c 95d83ee7242d : 362229 revs, 4.480366 s, 4.397816 s, -0.082550 s, × 0.9816, 12 µs/rev mozilla-try x00000_revs_x000_added_x_copies 9126823d0e9c ca82787bb23c : 359344 revs, 4.369070 s, 4.370538 s, +0.001468 s, × 1.0003, 12 µs/rev mozilla-try x00000_revs_x0000_added_x0000_copies 8d3fafa80d4b eb884023b810 : 192665 revs, 1.592506 s, 1.570439 s, -0.022067 s, × 0.9861, 8 µs/rev mozilla-try x00000_revs_x00000_added_x0000_copies 1b661134e2ca 1ae03d022d6d : 228985 revs, 87.824489 s, 88.388512 s, +0.564023 s, × 1.0064, 386 µs/rev mozilla-try x00000_revs_x00000_added_x000_copies 9b2a99adc05e 8e29777b48e6 : 382065 revs, 43.304637 s, 34.443661 s, -8.860976 s, × 0.7954, 90 µs/rev private : 459513 revs, 33.853687 s, 27.370148 s, -6.483539 s, × 0.8085, 59 µs/rev Differential Revision: https://phab.mercurial-scm.org/D9653
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 16 Dec 2020 11:11:05 +0100
parents 2eb8ad899fa6
children b7fde9237c92
line wrap: on
line source

  $ hg init a
  $ mkdir a/d1
  $ mkdir a/d1/d2
  $ echo line 1 > a/a
  $ echo line 1 > a/d1/d2/a
  $ hg --cwd a ci -Ama
  adding a
  adding d1/d2/a

  $ echo line 2 >> a/a
  $ hg --cwd a ci -u someone -d '1 0' -m'second change'

import with no args:

  $ hg --cwd a import
  abort: need at least one patch to import
  [10]

generate patches for the test

  $ hg --cwd a export tip > exported-tip.patch
  $ hg --cwd a diff -r0:1 > diffed-tip.patch


import exported patch
(this also tests that editor is not invoked, if the patch contains the
commit message and '--edit' is not specified)

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ HGEDITOR=cat hg --cwd b import --debug ../exported-tip.patch
  applying ../exported-tip.patch
  Subject: 
  
  Content-Type: text/plain
  found patch at byte 202
  patch generated by hg export
  From: someone
  Date: 1 0
  Node ID: 1d4bd90af0e43687763d158dfa83ff2a4b6c0c32
  message:
  second change
  patching file a
  committing files:
  a
  committing manifest
  committing changelog
  created 1d4bd90af0e4
  updating the branch cache

message and committer and date should be same

  $ hg --cwd b tip
  changeset:   1:1d4bd90af0e4
  tag:         tip
  user:        someone
  date:        Thu Jan 01 00:00:01 1970 +0000
  summary:     second change
  
  $ rm -r b


import exported patch with external patcher
(this also tests that editor is invoked, if the '--edit' is specified,
regardless of the commit message in the patch)

  $ cat > dummypatch.py <<EOF
  > from __future__ import print_function
  > print('patching file a')
  > open('a', 'wb').write(b'line2\n')
  > EOF
  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ HGEDITOR=cat hg --config ui.patch="\"$PYTHON\" ../dummypatch.py" --cwd b import --edit ../exported-tip.patch
  applying ../exported-tip.patch
  second change
  
  
  HG: Enter commit message.  Lines beginning with 'HG:' are removed.
  HG: Leave message empty to abort commit.
  HG: --
  HG: user: someone
  HG: branch 'default'
  HG: changed a
  $ cat b/a
  line2
  $ rm -r b


import of plain diff should fail without message
(this also tests that editor is invoked, if the patch doesn't contain
the commit message, regardless of '--edit')

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ cat > $TESTTMP/editor.sh <<EOF
  > env | grep HGEDITFORM
  > cat \$1
  > EOF
  $ HGEDITOR="sh $TESTTMP/editor.sh" hg --cwd b import ../diffed-tip.patch
  applying ../diffed-tip.patch
  HGEDITFORM=import.normal.normal
  
  
  HG: Enter commit message.  Lines beginning with 'HG:' are removed.
  HG: Leave message empty to abort commit.
  HG: --
  HG: user: test
  HG: branch 'default'
  HG: changed a
  abort: empty commit message
  [10]

Test avoiding editor invocation at applying the patch with --exact,
even if commit message is empty

  $ echo a >> b/a
  $ hg --cwd b commit -m ' '
  $ hg --cwd b tip -T "{node}\n"
  d8804f3f5396d800812f579c8452796a5993bdb2
  $ hg --cwd b export -o ../empty-log.diff .
  $ hg --cwd b update -q -C ".^1"
  $ hg --cwd b --config extensions.strip= strip -q tip
  $ HGEDITOR=cat hg --cwd b import --exact ../empty-log.diff
  applying ../empty-log.diff
  $ hg --cwd b tip -T "{node}\n"
  d8804f3f5396d800812f579c8452796a5993bdb2

  $ rm -r b


import of plain diff should be ok with message

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg --cwd b import -mpatch ../diffed-tip.patch
  applying ../diffed-tip.patch
  $ rm -r b


import of plain diff with specific date and user
(this also tests that editor is not invoked, if
'--message'/'--logfile' is specified and '--edit' is not)

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg --cwd b import -mpatch -d '1 0' -u 'user@nowhere.net' ../diffed-tip.patch
  applying ../diffed-tip.patch
  $ hg -R b tip -pv
  changeset:   1:ca68f19f3a40
  tag:         tip
  user:        user@nowhere.net
  date:        Thu Jan 01 00:00:01 1970 +0000
  files:       a
  description:
  patch
  
  
  diff -r 80971e65b431 -r ca68f19f3a40 a
  --- a/a	Thu Jan 01 00:00:00 1970 +0000
  +++ b/a	Thu Jan 01 00:00:01 1970 +0000
  @@ -1,1 +1,2 @@
   line 1
  +line 2
  
  $ rm -r b


import of plain diff should be ok with --no-commit
(this also tests that editor is not invoked, if '--no-commit' is
specified, regardless of '--edit')

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ HGEDITOR=cat hg --cwd b import --no-commit --edit ../diffed-tip.patch
  applying ../diffed-tip.patch
  $ hg --cwd b diff --nodates
  diff -r 80971e65b431 a
  --- a/a
  +++ b/a
  @@ -1,1 +1,2 @@
   line 1
  +line 2
  $ rm -r b


import of malformed plain diff should fail

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ sed 's/1,1/foo/' < diffed-tip.patch > broken.patch
  $ hg --cwd b import -mpatch ../broken.patch
  applying ../broken.patch
  abort: bad hunk #1
  [255]
  $ rm -r b

hg -R repo import
put the clone in a subdir - having a directory named "a"
used to hide a bug.

  $ mkdir dir
  $ hg clone -r0 a dir/b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ cd dir
  $ hg -R b import ../exported-tip.patch
  applying ../exported-tip.patch
  $ cd ..
  $ rm -r dir


import from stdin

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg --cwd b import - < exported-tip.patch
  applying patch from stdin
  $ rm -r b


import two patches in one stream

  $ hg init b
  $ hg --cwd a export 0:tip | hg --cwd b import -
  applying patch from stdin
  $ hg --cwd a id
  1d4bd90af0e4 tip
  $ hg --cwd b id
  1d4bd90af0e4 tip
  $ rm -r b


override commit message

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg --cwd b import -m 'override' - < exported-tip.patch
  applying patch from stdin
  $ hg --cwd b tip | grep override
  summary:     override
  $ rm -r b

  $ cat > mkmsg.py <<EOF
  > import email.message
  > import sys
  > msg = email.message.Message()
  > patch = open(sys.argv[1], 'rb').read()
  > msg.set_payload(b'email commit message\n' + patch)
  > msg['Subject'] = 'email patch'
  > msg['From'] = 'email patcher'
  > open(sys.argv[2], 'wb').write(bytes(msg))
  > EOF


plain diff in email, subject, message body

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ "$PYTHON" mkmsg.py diffed-tip.patch msg.patch
  $ hg --cwd b import ../msg.patch
  applying ../msg.patch
  $ hg --cwd b tip | grep email
  user:        email patcher
  summary:     email patch
  $ rm -r b


plain diff in email, no subject, message body

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ grep -v '^Subject:' msg.patch | hg --cwd b import -
  applying patch from stdin
  $ rm -r b


plain diff in email, subject, no message body

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ grep -v '^email ' msg.patch | hg --cwd b import -
  applying patch from stdin
  $ rm -r b


plain diff in email, no subject, no message body, should fail

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import -
  applying patch from stdin
  abort: empty commit message
  [10]
  $ rm -r b


hg export in email, should use patch header

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ "$PYTHON" mkmsg.py exported-tip.patch msg.patch
  $ cat msg.patch | hg --cwd b import -
  applying patch from stdin
  $ hg --cwd b tip | grep second
  summary:     second change
  $ rm -r b

hg email --plain, should read X-Mercurial-Node header

  $ cat >> a/.hg/hgrc << EOF
  > [extensions]
  > patchbomb =
  > [email]
  > from = foo
  > cc = foo
  > to = bar
  > EOF
  $ hg --cwd a email -m ../tip-plain.mbox --plain --date '1970-1-1 0:1' tip
  this patch series consists of 1 patches.
  
  
  sending [PATCH] second change ...

  $ hg clone -r0 a b -q
  $ hg --cwd b import --debug ../tip-plain.mbox
  applying ../tip-plain.mbox
  Node ID: 1d4bd90af0e43687763d158dfa83ff2a4b6c0c32
  Subject: second change
  From: foo
  Content-Type: text/plain
  found patch at byte 0
  message:
  second change
  patching file a
  committing files:
  a
  committing manifest
  committing changelog
  created de620f6fe949
  updating the branch cache
  $ hg --cwd b tip
  changeset:   1:de620f6fe949
  tag:         tip
  user:        foo
  date:        Thu Jan 01 00:00:00 1970 +0000
  summary:     second change
  
  $ hg --cwd b phase tip
  1: draft
  $ rm -r b


hg import --secret

  $ hg clone -r0 a b -q
  $ hg --cwd b import --no-commit --secret ../exported-tip.patch
  abort: cannot specify both --no-commit and --secret
  [10]
  $ hg --cwd b import --secret ../exported-tip.patch
  applying ../exported-tip.patch
  $ hg --cwd b diff -c . --nodates
  diff -r 80971e65b431 -r 1d4bd90af0e4 a
  --- a/a
  +++ b/a
  @@ -1,1 +1,2 @@
   line 1
  +line 2
  $ hg --cwd b phase
  1: secret
  $ hg --cwd b --config extensions.strip= strip 1 --no-backup --quiet
  $ HGEDITOR=cat hg --cwd b import --secret --edit ../exported-tip.patch
  applying ../exported-tip.patch
  second change
  
  
  HG: Enter commit message.  Lines beginning with 'HG:' are removed.
  HG: Leave message empty to abort commit.
  HG: --
  HG: user: someone
  HG: branch 'default'
  HG: changed a
  $ hg --cwd b diff -c . --nodates
  diff -r 80971e65b431 -r 1d4bd90af0e4 a
  --- a/a
  +++ b/a
  @@ -1,1 +1,2 @@
   line 1
  +line 2
  $ hg --cwd b phase
  1: secret
  $ hg --cwd b --config extensions.strip= strip 1 --no-backup --quiet
  $ hg --cwd b import --bypass --secret ../exported-tip.patch
  applying ../exported-tip.patch
  $ hg --cwd b phase -r tip
  1: secret
  $ hg --cwd b --config extensions.strip= strip 1 --no-backup --quiet
  $ rm -r b


subject: duplicate detection, removal of [PATCH]
The '---' tests the gitsendmail handling without proper mail headers

  $ cat > mkmsg2.py <<EOF
  > import email.message
  > import sys
  > msg = email.message.Message()
  > patch = open(sys.argv[1], 'rb').read()
  > msg.set_payload(b'email patch\n\nnext line\n---\n' + patch)
  > msg['Subject'] = '[PATCH] email patch'
  > msg['From'] = 'email patcher'
  > open(sys.argv[2], 'wb').write(bytes(msg))
  > EOF


plain diff in email, [PATCH] subject, message body with subject

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ "$PYTHON" mkmsg2.py diffed-tip.patch msg.patch
  $ cat msg.patch | hg --cwd b import -
  applying patch from stdin
  $ hg --cwd b tip --template '{desc}\n'
  email patch
  
  next line
  $ rm -r b


Issue963: Parent of working dir incorrect after import of multiple
patches and rollback

We weren't backing up the correct dirstate file when importing many
patches: import patch1 patch2; rollback

  $ echo line 3 >> a/a
  $ hg --cwd a ci -m'third change'
  $ hg --cwd a export -o '../patch%R' 1 2
  $ hg clone -qr0 a b
  $ hg --cwd b parents --template 'parent: {rev}\n'
  parent: 0
  $ hg --cwd b import -v ../patch1 ../patch2
  applying ../patch1
  patching file a
  committing files:
  a
  committing manifest
  committing changelog
  created 1d4bd90af0e4
  applying ../patch2
  patching file a
  committing files:
  a
  committing manifest
  committing changelog
  created 6d019af21222
  $ hg --cwd b rollback
  repository tip rolled back to revision 0 (undo import)
  working directory now based on revision 0
  $ hg --cwd b parents --template 'parent: {rev}\n'
  parent: 0

Test that "hg rollback" doesn't restore dirstate to one at the
beginning of the rolled back transaction in not-"parent-gone" case.

invoking pretxncommit hook will cause marking '.hg/dirstate' as a file
to be restored when rolling back, after DirstateTransactionPlan (see wiki
page for detail).

  $ hg --cwd b branch -q foobar
  $ hg --cwd b commit -m foobar
  $ hg --cwd b update 0 -q
  $ hg --cwd b import ../patch1 ../patch2 --config hooks.pretxncommit=true
  applying ../patch1
  applying ../patch2
  $ hg --cwd b update -q 1
  $ hg --cwd b rollback -q
  $ hg --cwd b parents --template 'parent: {rev}\n'
  parent: 1

  $ hg --cwd b update -q -C 0
  $ hg --cwd b --config extensions.strip= strip -q 1

Test visibility of in-memory dirstate changes inside transaction to
external process

  $ echo foo > a/foo
  $ hg --cwd a commit -A -m 'adding foo' foo
  $ hg --cwd a export -o '../patch%R' 3

  $ cat > $TESTTMP/checkvisibility.sh <<EOF
  > echo "===="
  > hg parents --template "VISIBLE {rev}:{node|short}\n"
  > hg status -amr
  > # test that pending changes are hidden
  > unset HG_PENDING
  > hg parents --template "ACTUAL  {rev}:{node|short}\n"
  > hg status -amr
  > echo "===="
  > EOF

== test visibility to external editor

  $ (cd b && sh "$TESTTMP/checkvisibility.sh")
  ====
  VISIBLE 0:80971e65b431
  ACTUAL  0:80971e65b431
  ====

  $ HGEDITOR="sh $TESTTMP/checkvisibility.sh" hg --cwd b import -v --edit ../patch1 ../patch2 ../patch3
  applying ../patch1
  patching file a
  ====
  VISIBLE 0:80971e65b431
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  committing files:
  a
  committing manifest
  committing changelog
  created 1d4bd90af0e4
  applying ../patch2
  patching file a
  ====
  VISIBLE 1:1d4bd90af0e4
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  committing files:
  a
  committing manifest
  committing changelog
  created 6d019af21222
  applying ../patch3
  patching file foo
  adding foo
  ====
  VISIBLE 2:6d019af21222
  A foo
  ACTUAL  0:80971e65b431
  M a
  ====
  committing files:
  foo
  committing manifest
  committing changelog
  created 55e3f75b2378

  $ hg --cwd b rollback -q

(content of file "a" is already changed and it should be recognized as
"M", even though dirstate is restored to one before "hg import")

  $ (cd b && sh "$TESTTMP/checkvisibility.sh")
  ====
  VISIBLE 0:80971e65b431
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  $ hg --cwd b revert --no-backup a
  $ rm -f b/foo

== test visibility to precommit external hook

  $ cat >> b/.hg/hgrc <<EOF
  > [hooks]
  > precommit.visibility = sh $TESTTMP/checkvisibility.sh
  > EOF

  $ (cd b && sh "$TESTTMP/checkvisibility.sh")
  ====
  VISIBLE 0:80971e65b431
  ACTUAL  0:80971e65b431
  ====

  $ hg --cwd b import ../patch1 ../patch2 ../patch3
  applying ../patch1
  ====
  VISIBLE 0:80971e65b431
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  applying ../patch2
  ====
  VISIBLE 1:1d4bd90af0e4
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  applying ../patch3
  ====
  VISIBLE 2:6d019af21222
  A foo
  ACTUAL  0:80971e65b431
  M a
  ====

  $ hg --cwd b rollback -q
  $ (cd b && sh "$TESTTMP/checkvisibility.sh")
  ====
  VISIBLE 0:80971e65b431
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  $ hg --cwd b revert --no-backup a
  $ rm -f b/foo

  $ cat >> b/.hg/hgrc <<EOF
  > [hooks]
  > precommit.visibility =
  > EOF

== test visibility to pretxncommit external hook

  $ cat >> b/.hg/hgrc <<EOF
  > [hooks]
  > pretxncommit.visibility = sh $TESTTMP/checkvisibility.sh
  > EOF

  $ (cd b && sh "$TESTTMP/checkvisibility.sh")
  ====
  VISIBLE 0:80971e65b431
  ACTUAL  0:80971e65b431
  ====

  $ hg --cwd b import ../patch1 ../patch2 ../patch3
  applying ../patch1
  ====
  VISIBLE 0:80971e65b431
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  applying ../patch2
  ====
  VISIBLE 1:1d4bd90af0e4
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  applying ../patch3
  ====
  VISIBLE 2:6d019af21222
  A foo
  ACTUAL  0:80971e65b431
  M a
  ====

  $ hg --cwd b rollback -q
  $ (cd b && sh "$TESTTMP/checkvisibility.sh")
  ====
  VISIBLE 0:80971e65b431
  M a
  ACTUAL  0:80971e65b431
  M a
  ====
  $ hg --cwd b revert --no-backup a
  $ rm -f b/foo

  $ cat >> b/.hg/hgrc <<EOF
  > [hooks]
  > pretxncommit.visibility =
  > EOF

  $ rm -r b


importing a patch in a subdirectory failed at the commit stage

  $ echo line 2 >> a/d1/d2/a
  $ hg --cwd a ci -u someoneelse -d '1 0' -m'subdir change'

hg import in a subdirectory

  $ hg clone -r0 a b
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 2 changes to 2 files
  new changesets 80971e65b431
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg --cwd a export tip > tmp
  $ sed -e 's/d1\/d2\///' < tmp > subdir-tip.patch
  $ dir=`pwd`
  $ cd b/d1/d2 2>&1 > /dev/null
  $ hg import  ../../../subdir-tip.patch
  applying ../../../subdir-tip.patch
  $ cd "$dir"

message should be 'subdir change'
committer should be 'someoneelse'

  $ hg --cwd b tip
  changeset:   1:3577f5aea227
  tag:         tip
  user:        someoneelse
  date:        Thu Jan 01 00:00:01 1970 +0000
  summary:     subdir change
  

should be empty

  $ hg --cwd b status


Test fuzziness (ambiguous patch location, fuzz=2)

  $ hg init fuzzy
  $ cd fuzzy
  $ echo line1 > a
  $ echo line0 >> a
  $ echo line3 >> a
  $ hg ci -Am adda
  adding a
  $ echo line1 > a
  $ echo line2 >> a
  $ echo line0 >> a
  $ echo line3 >> a
  $ hg ci -m change a
  $ hg export tip > fuzzy-tip.patch
  $ hg up -C 0
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ echo line1 > a
  $ echo line0 >> a
  $ echo line1 >> a
  $ echo line0 >> a
  $ hg ci -m brancha
  created new head
  $ hg import --config patch.fuzz=0 -v fuzzy-tip.patch
  applying fuzzy-tip.patch
  patching file a
  Hunk #1 FAILED at 0
  1 out of 1 hunks FAILED -- saving rejects to file a.rej
  abort: patch failed to apply
  [255]
  $ hg import --no-commit -v fuzzy-tip.patch
  applying fuzzy-tip.patch
  patching file a
  Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
  applied to working directory
  $ hg revert -a
  reverting a

Test --exact failure

  $ sed 's/^# Parent .*/# Parent '"`hg log -r. -T '{node}'`"'/' \
  > < fuzzy-tip.patch > fuzzy-reparent.patch
  $ hg import --config patch.fuzz=0 --exact fuzzy-reparent.patch
  applying fuzzy-reparent.patch
  patching file a
  Hunk #1 FAILED at 0
  1 out of 1 hunks FAILED -- saving rejects to file a.rej
  abort: patch failed to apply
  [255]
  $ hg up -qC
  $ hg import --config patch.fuzz=2 --exact fuzzy-reparent.patch
  applying fuzzy-reparent.patch
  patching file a
  Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
  transaction abort!
  rollback completed
  abort: patch is damaged or loses information
  [255]
  $ hg up -qC

  $ grep '^#' fuzzy-tip.patch > empty.patch
  $ cat <<'EOF' >> empty.patch
  > change
  > 
  > diff -r bb90ef1daa38 -r 0e9b883378d4 a
  > --- a/a	Thu Jan 01 00:00:00 1970 +0000
  > --- b/a	Thu Jan 01 00:00:00 1970 +0000
  > EOF
  $ hg import --exact empty.patch
  applying empty.patch
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  abort: patch is damaged or loses information
  [255]
  $ hg up -qC

import with --no-commit should have written .hg/last-message.txt

  $ cat .hg/last-message.txt
  change (no-eol)


test fuzziness with eol=auto

  $ hg --config patch.eol=auto import --no-commit -v fuzzy-tip.patch
  applying fuzzy-tip.patch
  patching file a
  Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
  applied to working directory
  $ cd ..


Test hunk touching empty files (issue906)

  $ hg init empty
  $ cd empty
  $ touch a
  $ touch b1
  $ touch c1
  $ echo d > d
  $ hg ci -Am init
  adding a
  adding b1
  adding c1
  adding d
  $ echo a > a
  $ echo b > b1
  $ hg mv b1 b2
  $ echo c > c1
  $ hg copy c1 c2
  $ rm d
  $ touch d
  $ hg diff --git
  diff --git a/a b/a
  --- a/a
  +++ b/a
  @@ -0,0 +1,1 @@
  +a
  diff --git a/b1 b/b2
  rename from b1
  rename to b2
  --- a/b1
  +++ b/b2
  @@ -0,0 +1,1 @@
  +b
  diff --git a/c1 b/c1
  --- a/c1
  +++ b/c1
  @@ -0,0 +1,1 @@
  +c
  diff --git a/c1 b/c2
  copy from c1
  copy to c2
  --- a/c1
  +++ b/c2
  @@ -0,0 +1,1 @@
  +c
  diff --git a/d b/d
  --- a/d
  +++ b/d
  @@ -1,1 +0,0 @@
  -d
  $ hg ci -m empty
  $ hg export --git tip > empty.diff
  $ hg up -C 0
  4 files updated, 0 files merged, 2 files removed, 0 files unresolved
  $ hg import empty.diff
  applying empty.diff
  $ for name in a b1 b2 c1 c2 d; do
  >   echo % $name file
  >   test -f $name && cat $name
  >   done
  % a file
  a
  % b1 file
  % b2 file
  b
  % c1 file
  c
  % c2 file
  c
  % d file
  $ cd ..


Test importing a patch ending with a binary file removal

  $ hg init binaryremoval
  $ cd binaryremoval
  $ echo a > a
  $ "$PYTHON" -c "open('b', 'wb').write(b'a\x00b')"
  $ hg ci -Am addall
  adding a
  adding b
  $ hg rm a
  $ hg rm b
  $ hg st
  R a
  R b
  $ hg ci -m remove
  $ hg export --git . > remove.diff
  $ cat remove.diff | grep git
  diff --git a/a b/a
  diff --git a/b b/b
  $ hg up -C 0
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg import remove.diff
  applying remove.diff
  $ hg manifest
  $ cd ..


Issue927: test update+rename with common name

  $ hg init t
  $ cd t
  $ touch a
  $ hg ci -Am t
  adding a
  $ echo a > a

Here, bfile.startswith(afile)

  $ hg copy a a2
  $ hg ci -m copya
  $ hg export --git tip > copy.diff
  $ hg up -C 0
  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
  $ hg import copy.diff
  applying copy.diff

a should contain an 'a'

  $ cat a
  a

and a2 should have duplicated it

  $ cat a2
  a
  $ cd ..


test -p0

  $ hg init p0
  $ cd p0
  $ echo a > a
  $ hg ci -Am t
  adding a
  $ hg import -p foo
  abort: invalid value 'foo' for option -p, expected int
  [10]
  $ hg import -p0 - << EOF
  > foobar
  > --- a	Sat Apr 12 22:43:58 2008 -0400
  > +++ a	Sat Apr 12 22:44:05 2008 -0400
  > @@ -1,1 +1,1 @@
  > -a
  > +bb
  > EOF
  applying patch from stdin
  $ hg status
  $ cat a
  bb

test --prefix

  $ mkdir -p dir/dir2
  $ echo b > dir/dir2/b
  $ hg ci -Am b
  adding dir/dir2/b
  $ hg import -p2 --prefix dir - << EOF
  > foobar
  > --- drop1/drop2/dir2/b
  > +++ drop1/drop2/dir2/b
  > @@ -1,1 +1,1 @@
  > -b
  > +cc
  > EOF
  applying patch from stdin
  $ hg status
  $ cat dir/dir2/b
  cc
  $ cd ..


test paths outside repo root

  $ mkdir outside
  $ touch outside/foo
  $ hg init inside
  $ cd inside
  $ hg import - <<EOF
  > diff --git a/a b/b
  > rename from ../outside/foo
  > rename to bar
  > EOF
  applying patch from stdin
  abort: path contains illegal component: ../outside/foo
  [255]
  $ cd ..


test import with similarity and git and strip (issue295 et al.)

  $ hg init sim
  $ cd sim
  $ echo 'this is a test' > a
  $ hg ci -Ama
  adding a
  $ cat > ../rename.diff <<EOF
  > diff --git a/foo/a b/foo/a
  > deleted file mode 100644
  > --- a/foo/a
  > +++ /dev/null
  > @@ -1,1 +0,0 @@
  > -this is a test
  > diff --git a/foo/b b/foo/b
  > new file mode 100644
  > --- /dev/null
  > +++ b/foo/b
  > @@ -0,0 +1,2 @@
  > +this is a test
  > +foo
  > EOF
  $ hg import --no-commit -v -s 1 ../rename.diff -p2
  applying ../rename.diff
  patching file a
  patching file b
  adding b
  recording removal of a as rename to b (88% similar)
  applied to working directory
  $ echo 'mod b' > b
  $ hg st -C
  A b
    a
  R a
  $ hg revert -a
  forgetting b
  undeleting a
  $ cat b
  mod b
  $ rm b
  $ hg import --no-commit -v -s 100 ../rename.diff -p2
  applying ../rename.diff
  patching file a
  patching file b
  adding b
  applied to working directory
  $ hg st -C
  A b
  R a
  $ cd ..


Issue1495: add empty file from the end of patch

  $ hg init addemptyend
  $ cd addemptyend
  $ touch a
  $ hg addremove
  adding a
  $ hg ci -m "commit"
  $ cat > a.patch <<EOF
  > add a, b
  > diff --git a/a b/a
  > --- a/a
  > +++ b/a
  > @@ -0,0 +1,1 @@
  > +a
  > diff --git a/b b/b
  > new file mode 100644
  > EOF
  $ hg import --no-commit a.patch
  applying a.patch

apply a good patch followed by an empty patch (mainly to ensure
that dirstate is *not* updated when import crashes)
  $ hg update -q -C .
  $ rm b
  $ touch empty.patch
  $ hg import a.patch empty.patch
  applying a.patch
  applying empty.patch
  transaction abort!
  rollback completed
  abort: empty.patch: no diffs found
  [10]
  $ hg tip --template '{rev}  {desc|firstline}\n'
  0  commit
  $ hg -q status
  M a
  $ cd ..

create file when source is not /dev/null

  $ cat > create.patch <<EOF
  > diff -Naur proj-orig/foo proj-new/foo
  > --- proj-orig/foo       1969-12-31 16:00:00.000000000 -0800
  > +++ proj-new/foo        2009-07-17 16:50:45.801368000 -0700
  > @@ -0,0 +1,1 @@
  > +a
  > EOF

some people have patches like the following too

  $ cat > create2.patch <<EOF
  > diff -Naur proj-orig/foo proj-new/foo
  > --- proj-orig/foo.orig  1969-12-31 16:00:00.000000000 -0800
  > +++ proj-new/foo        2009-07-17 16:50:45.801368000 -0700
  > @@ -0,0 +1,1 @@
  > +a
  > EOF
  $ hg init oddcreate
  $ cd oddcreate
  $ hg import --no-commit ../create.patch
  applying ../create.patch
  $ cat foo
  a
  $ rm foo
  $ hg revert foo
  $ hg import --no-commit ../create2.patch
  applying ../create2.patch
  $ cat foo
  a

  $ cd ..

Issue1859: first line mistaken for email headers

  $ hg init emailconfusion
  $ cd emailconfusion
  $ cat > a.patch <<EOF
  > module: summary
  > 
  > description
  > 
  > 
  > diff -r 000000000000 -r 9b4c1e343b55 test.txt
  > --- /dev/null
  > +++ b/a
  > @@ -0,0 +1,1 @@
  > +a
  > EOF
  $ hg import -d '0 0' a.patch
  applying a.patch
  $ hg parents -v
  changeset:   0:5a681217c0ad
  tag:         tip
  user:        test
  date:        Thu Jan 01 00:00:00 1970 +0000
  files:       a
  description:
  module: summary
  
  description
  
  
  $ cd ..


in commit message

  $ hg init commitconfusion
  $ cd commitconfusion
  $ cat > a.patch <<EOF
  > module: summary
  > 
  > --- description
  > 
  > diff --git a/a b/a
  > new file mode 100644
  > --- /dev/null
  > +++ b/a
  > @@ -0,0 +1,1 @@
  > +a
  > EOF
  > hg import -d '0 0' a.patch
  > hg parents -v
  > cd ..
  > 
  > echo '% tricky header splitting'
  > cat > trickyheaders.patch <<EOF
  > From: User A <user@a>
  > Subject: [PATCH] from: tricky!
  > 
  > # HG changeset patch
  > # User User B
  > # Date 1266264441 18000
  > # Branch stable
  > # Node ID f2be6a1170ac83bf31cb4ae0bad00d7678115bc0
  > # Parent  0000000000000000000000000000000000000000
  > from: tricky!
  > 
  > That is not a header.
  > 
  > diff -r 000000000000 -r f2be6a1170ac foo
  > --- /dev/null
  > +++ b/foo
  > @@ -0,0 +1,1 @@
  > +foo
  > EOF
  applying a.patch
  changeset:   0:f34d9187897d
  tag:         tip
  user:        test
  date:        Thu Jan 01 00:00:00 1970 +0000
  files:       a
  description:
  module: summary
  
  
  % tricky header splitting

  $ hg init trickyheaders
  $ cd trickyheaders
  $ hg import -d '0 0' ../trickyheaders.patch
  applying ../trickyheaders.patch
  $ hg export --git tip
  # HG changeset patch
  # User User B
  # Date 0 0
  #      Thu Jan 01 00:00:00 1970 +0000
  # Node ID eb56ab91903632294ac504838508cb370c0901d2
  # Parent  0000000000000000000000000000000000000000
  from: tricky!
  
  That is not a header.
  
  diff --git a/foo b/foo
  new file mode 100644
  --- /dev/null
  +++ b/foo
  @@ -0,0 +1,1 @@
  +foo
  $ cd ..


Issue2102: hg export and hg import speak different languages

  $ hg init issue2102
  $ cd issue2102
  $ mkdir -p src/cmd/gc
  $ touch src/cmd/gc/mksys.bash
  $ hg ci -Am init
  adding src/cmd/gc/mksys.bash
  $ hg import - <<EOF
  > # HG changeset patch
  > # User Rob Pike
  > # Date 1216685449 25200
  > # Node ID 03aa2b206f499ad6eb50e6e207b9e710d6409c98
  > # Parent  93d10138ad8df586827ca90b4ddb5033e21a3a84
  > help management of empty pkg and lib directories in perforce
  > 
  > R=gri
  > DELTA=4  (4 added, 0 deleted, 0 changed)
  > OCL=13328
  > CL=13328
  > 
  > diff --git a/lib/place-holder b/lib/place-holder
  > new file mode 100644
  > --- /dev/null
  > +++ b/lib/place-holder
  > @@ -0,0 +1,2 @@
  > +perforce does not maintain empty directories.
  > +this file helps.
  > diff --git a/pkg/place-holder b/pkg/place-holder
  > new file mode 100644
  > --- /dev/null
  > +++ b/pkg/place-holder
  > @@ -0,0 +1,2 @@
  > +perforce does not maintain empty directories.
  > +this file helps.
  > diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
  > old mode 100644
  > new mode 100755
  > EOF
  applying patch from stdin

#if execbit

  $ hg sum
  parent: 1:d59915696727 tip
   help management of empty pkg and lib directories in perforce
  branch: default
  commit: (clean)
  update: (current)
  phases: 2 draft

  $ hg diff --git -c tip
  diff --git a/lib/place-holder b/lib/place-holder
  new file mode 100644
  --- /dev/null
  +++ b/lib/place-holder
  @@ -0,0 +1,2 @@
  +perforce does not maintain empty directories.
  +this file helps.
  diff --git a/pkg/place-holder b/pkg/place-holder
  new file mode 100644
  --- /dev/null
  +++ b/pkg/place-holder
  @@ -0,0 +1,2 @@
  +perforce does not maintain empty directories.
  +this file helps.
  diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
  old mode 100644
  new mode 100755

#else

  $ hg sum
  parent: 1:28f089cc9ccc tip
   help management of empty pkg and lib directories in perforce
  branch: default
  commit: (clean)
  update: (current)
  phases: 2 draft

  $ hg diff --git -c tip
  diff --git a/lib/place-holder b/lib/place-holder
  new file mode 100644
  --- /dev/null
  +++ b/lib/place-holder
  @@ -0,0 +1,2 @@
  +perforce does not maintain empty directories.
  +this file helps.
  diff --git a/pkg/place-holder b/pkg/place-holder
  new file mode 100644
  --- /dev/null
  +++ b/pkg/place-holder
  @@ -0,0 +1,2 @@
  +perforce does not maintain empty directories.
  +this file helps.

/* The mode change for mksys.bash is missing here, because on platforms  */
/* that don't support execbits, mode changes in patches are ignored when */
/* they are imported. This is obviously also the reason for why the hash */
/* in the created changeset is different to the one you see above the    */
/* #else clause */

#endif
  $ cd ..


diff lines looking like headers

  $ hg init difflineslikeheaders
  $ cd difflineslikeheaders
  $ echo a >a
  $ echo b >b
  $ echo c >c
  $ hg ci -Am1
  adding a
  adding b
  adding c

  $ echo "key: value" >>a
  $ echo "key: value" >>b
  $ echo "foo" >>c
  $ hg ci -m2

  $ hg up -C 0
  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg diff --git -c1 >want
  $ hg diff -c1 | hg import --no-commit -
  applying patch from stdin
  $ hg diff --git >have
  $ diff want have
  $ cd ..

import a unified diff with no lines of context (diff -U0)

  $ hg init diffzero
  $ cd diffzero
  $ cat > f << EOF
  > c2
  > c4
  > c5
  > EOF
  $ hg commit -Am0
  adding f

  $ hg import --no-commit - << EOF
  > # HG changeset patch
  > # User test
  > # Date 0 0
  > # Node ID f4974ab632f3dee767567b0576c0ec9a4508575c
  > # Parent  8679a12a975b819fae5f7ad3853a2886d143d794
  > 1
  > diff -r 8679a12a975b -r f4974ab632f3 f
  > --- a/f	Thu Jan 01 00:00:00 1970 +0000
  > +++ b/f	Thu Jan 01 00:00:00 1970 +0000
  > @@ -0,0 +1,1 @@
  > +c1
  > @@ -1,0 +3,1 @@
  > +c3
  > @@ -3,1 +4,0 @@
  > -c5
  > EOF
  applying patch from stdin

  $ cat f
  c1
  c2
  c3
  c4

  $ cd ..

commit message that looks like a diff header (issue1879)

  $ hg init headerlikemsg
  $ cd headerlikemsg
  $ touch empty
  $ echo nonempty >> nonempty
  $ hg ci -qAl - <<EOF
  > blah blah
  > diff blah
  > blah blah
  > EOF
  $ hg --config diff.git=1 log -pv
  changeset:   0:c6ef204ef767
  tag:         tip
  user:        test
  date:        Thu Jan 01 00:00:00 1970 +0000
  files:       empty nonempty
  description:
  blah blah
  diff blah
  blah blah
  
  
  diff --git a/empty b/empty
  new file mode 100644
  diff --git a/nonempty b/nonempty
  new file mode 100644
  --- /dev/null
  +++ b/nonempty
  @@ -0,0 +1,1 @@
  +nonempty
  

 (without --git, empty file is lost, but commit message should be preserved)

  $ hg init plain
  $ hg export 0 | hg -R plain import -
  applying patch from stdin
  $ hg --config diff.git=1 -R plain log -pv
  changeset:   0:60a2d231e71f
  tag:         tip
  user:        test
  date:        Thu Jan 01 00:00:00 1970 +0000
  files:       nonempty
  description:
  blah blah
  diff blah
  blah blah
  
  
  diff --git a/nonempty b/nonempty
  new file mode 100644
  --- /dev/null
  +++ b/nonempty
  @@ -0,0 +1,1 @@
  +nonempty
  

 (with --git, patch contents should be fully preserved)

  $ hg init git
  $ hg --config diff.git=1 export 0 | hg -R git import -
  applying patch from stdin
  $ hg --config diff.git=1 -R git log -pv
  changeset:   0:c6ef204ef767
  tag:         tip
  user:        test
  date:        Thu Jan 01 00:00:00 1970 +0000
  files:       empty nonempty
  description:
  blah blah
  diff blah
  blah blah
  
  
  diff --git a/empty b/empty
  new file mode 100644
  diff --git a/nonempty b/nonempty
  new file mode 100644
  --- /dev/null
  +++ b/nonempty
  @@ -0,0 +1,1 @@
  +nonempty
  

  $ cd ..

no segfault while importing a unified diff which start line is zero but chunk
size is non-zero

  $ hg init startlinezero
  $ cd startlinezero
  $ echo foo > foo
  $ hg commit -Amfoo
  adding foo

  $ hg import --no-commit - << EOF
  > diff a/foo b/foo
  > --- a/foo
  > +++ b/foo
  > @@ -0,1 +0,1 @@
  >  foo
  > EOF
  applying patch from stdin

  $ cd ..

Test corner case involving fuzz and skew

  $ hg init morecornercases
  $ cd morecornercases

  $ cat > 01-no-context-beginning-of-file.diff <<EOF
  > diff --git a/a b/a
  > --- a/a
  > +++ b/a
  > @@ -1,0 +1,1 @@
  > +line
  > EOF

  $ cat > 02-no-context-middle-of-file.diff <<EOF
  > diff --git a/a b/a
  > --- a/a
  > +++ b/a
  > @@ -1,1 +1,1 @@
  > -2
  > +add some skew
  > @@ -2,0 +2,1 @@
  > +line
  > EOF

  $ cat > 03-no-context-end-of-file.diff <<EOF
  > diff --git a/a b/a
  > --- a/a
  > +++ b/a
  > @@ -10,0 +10,1 @@
  > +line
  > EOF

  $ cat > 04-middle-of-file-completely-fuzzed.diff <<EOF
  > diff --git a/a b/a
  > --- a/a
  > +++ b/a
  > @@ -1,1 +1,1 @@
  > -2
  > +add some skew
  > @@ -2,2 +2,3 @@
  >  not matching, should fuzz
  >  ... a bit
  > +line
  > EOF

  $ cat > a <<EOF
  > 1
  > 2
  > 3
  > 4
  > EOF
  $ hg ci -Am adda a
  $ for p in *.diff; do
  >   hg import -v --no-commit $p
  >   cat a
  >   hg revert -aqC a
  >   # patch -p1 < $p
  >   # cat a
  >   # hg revert -aC a
  > done
  applying 01-no-context-beginning-of-file.diff
  patching file a
  applied to working directory
  1
  line
  2
  3
  4
  applying 02-no-context-middle-of-file.diff
  patching file a
  Hunk #1 succeeded at 2 (offset 1 lines).
  Hunk #2 succeeded at 4 (offset 1 lines).
  applied to working directory
  1
  add some skew
  3
  line
  4
  applying 03-no-context-end-of-file.diff
  patching file a
  Hunk #1 succeeded at 5 (offset -6 lines).
  applied to working directory
  1
  2
  3
  4
  line
  applying 04-middle-of-file-completely-fuzzed.diff
  patching file a
  Hunk #1 succeeded at 2 (offset 1 lines).
  Hunk #2 succeeded at 5 with fuzz 2 (offset 1 lines).
  applied to working directory
  1
  add some skew
  3
  4
  line
  $ cd ..

Test partial application
------------------------

prepare a stack of patches depending on each other

  $ hg init partial
  $ cd partial
  $ cat << EOF > a
  > one
  > two
  > three
  > four
  > five
  > six
  > seven
  > EOF
  $ hg add a
  $ echo 'b' > b
  $ hg add b
  $ hg commit -m 'initial' -u Babar
  $ cat << EOF > a
  > one
  > two
  > 3
  > four
  > five
  > six
  > seven
  > EOF
  $ hg commit -m 'three' -u Celeste
  $ cat << EOF > a
  > one
  > two
  > 3
  > 4
  > five
  > six
  > seven
  > EOF
  $ hg commit -m 'four' -u Rataxes
  $ cat << EOF > a
  > one
  > two
  > 3
  > 4
  > 5
  > six
  > seven
  > EOF
  $ echo bb >> b
  $ hg commit -m 'five' -u Arthur
  $ echo 'Babar' > jungle
  $ hg add jungle
  $ hg ci -m 'jungle' -u Zephir
  $ echo 'Celeste' >> jungle
  $ hg ci -m 'extended jungle' -u Cornelius
  $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
  @  extended jungle [Cornelius] 1: +1/-0
  |
  o  jungle [Zephir] 1: +1/-0
  |
  o  five [Arthur] 2: +2/-1
  |
  o  four [Rataxes] 1: +1/-1
  |
  o  three [Celeste] 1: +1/-1
  |
  o  initial [Babar] 2: +8/-0
  
Adding those config options should not change the output of diffstat. Bugfix #4755.

  $ hg log -r . --template '{diffstat}\n'
  1: +1/-0
  $ hg log -r . --template '{diffstat}\n' --config diff.git=1 \
  >   --config diff.noprefix=1
  1: +1/-0

Importing with some success and some errors:

  $ hg update --rev 'desc(initial)'
  2 files updated, 0 files merged, 1 files removed, 0 files unresolved
  $ hg export --rev 'desc(five)' | hg import --partial -
  applying patch from stdin
  patching file a
  Hunk #1 FAILED at 1
  1 out of 1 hunks FAILED -- saving rejects to file a.rej
  patch applied partially
  (fix the .rej files and run `hg commit --amend`)
  [1]

  $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
  @  five [Arthur] 1: +1/-0
  |
  | o  extended jungle [Cornelius] 1: +1/-0
  | |
  | o  jungle [Zephir] 1: +1/-0
  | |
  | o  five [Arthur] 2: +2/-1
  | |
  | o  four [Rataxes] 1: +1/-1
  | |
  | o  three [Celeste] 1: +1/-1
  |/
  o  initial [Babar] 2: +8/-0
  
  $ hg export
  # HG changeset patch
  # User Arthur
  # Date 0 0
  #      Thu Jan 01 00:00:00 1970 +0000
  # Node ID 26e6446bb2526e2be1037935f5fca2b2706f1509
  # Parent  8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
  five
  
  diff -r 8e4f0351909e -r 26e6446bb252 b
  --- a/b	Thu Jan 01 00:00:00 1970 +0000
  +++ b/b	Thu Jan 01 00:00:00 1970 +0000
  @@ -1,1 +1,2 @@
   b
  +bb
  $ hg status -c .
  C a
  C b
  $ ls -A
  .hg
  a
  a.rej
  b

Importing with zero success:

  $ hg update --rev 'desc(initial)'
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg export --rev 'desc(four)' | hg import --partial -
  applying patch from stdin
  patching file a
  Hunk #1 FAILED at 0
  1 out of 1 hunks FAILED -- saving rejects to file a.rej
  patch applied partially
  (fix the .rej files and run `hg commit --amend`)
  [1]

  $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
  @  four [Rataxes] 0: +0/-0
  |
  | o  five [Arthur] 1: +1/-0
  |/
  | o  extended jungle [Cornelius] 1: +1/-0
  | |
  | o  jungle [Zephir] 1: +1/-0
  | |
  | o  five [Arthur] 2: +2/-1
  | |
  | o  four [Rataxes] 1: +1/-1
  | |
  | o  three [Celeste] 1: +1/-1
  |/
  o  initial [Babar] 2: +8/-0
  
  $ hg export
  # HG changeset patch
  # User Rataxes
  # Date 0 0
  #      Thu Jan 01 00:00:00 1970 +0000
  # Node ID cb9b1847a74d9ad52e93becaf14b98dbcc274e1e
  # Parent  8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
  four
  
  $ hg status -c .
  C a
  C b
  $ ls -A
  .hg
  a
  a.rej
  b

Importing with unknown file:

  $ hg update --rev 'desc(initial)'
  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg export --rev 'desc("extended jungle")' | hg import --partial -
  applying patch from stdin
  unable to find 'jungle' for patching
  (use '--prefix' to apply patch relative to the current directory)
  1 out of 1 hunks FAILED -- saving rejects to file jungle.rej
  patch applied partially
  (fix the .rej files and run `hg commit --amend`)
  [1]

  $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
  @  extended jungle [Cornelius] 0: +0/-0
  |
  | o  four [Rataxes] 0: +0/-0
  |/
  | o  five [Arthur] 1: +1/-0
  |/
  | o  extended jungle [Cornelius] 1: +1/-0
  | |
  | o  jungle [Zephir] 1: +1/-0
  | |
  | o  five [Arthur] 2: +2/-1
  | |
  | o  four [Rataxes] 1: +1/-1
  | |
  | o  three [Celeste] 1: +1/-1
  |/
  o  initial [Babar] 2: +8/-0
  
  $ hg export
  # HG changeset patch
  # User Cornelius
  # Date 0 0
  #      Thu Jan 01 00:00:00 1970 +0000
  # Node ID 1fb1f86bef43c5a75918178f8d23c29fb0a7398d
  # Parent  8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
  extended jungle
  
  $ hg status -c .
  C a
  C b
  $ ls -A
  .hg
  a
  a.rej
  b
  jungle.rej

Importing multiple failing patches:

  $ hg update --rev 'desc(initial)'
  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ echo 'B' > b # just to make another commit
  $ hg commit -m "a new base"
  created new head
  $ hg export --rev 'desc("four") + desc("extended jungle")' | hg import --partial -
  applying patch from stdin
  patching file a
  Hunk #1 FAILED at 0
  1 out of 1 hunks FAILED -- saving rejects to file a.rej
  patch applied partially
  (fix the .rej files and run `hg commit --amend`)
  [1]
  $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
  @  four [Rataxes] 0: +0/-0
  |
  o  a new base [test] 1: +1/-1
  |
  | o  extended jungle [Cornelius] 0: +0/-0
  |/
  | o  four [Rataxes] 0: +0/-0
  |/
  | o  five [Arthur] 1: +1/-0
  |/
  | o  extended jungle [Cornelius] 1: +1/-0
  | |
  | o  jungle [Zephir] 1: +1/-0
  | |
  | o  five [Arthur] 2: +2/-1
  | |
  | o  four [Rataxes] 1: +1/-1
  | |
  | o  three [Celeste] 1: +1/-1
  |/
  o  initial [Babar] 2: +8/-0
  
  $ hg export
  # HG changeset patch
  # User Rataxes
  # Date 0 0
  #      Thu Jan 01 00:00:00 1970 +0000
  # Node ID a9d7b6d0ffbb4eb12b7d5939250fcd42e8930a1d
  # Parent  f59f8d2e95a8ca5b1b4ca64320140da85f3b44fd
  four
  
  $ hg status -c .
  C a
  C b

Importing some extra header
===========================

  $ cat > $TESTTMP/parseextra.py <<EOF
  > import mercurial.cmdutil
  > import mercurial.patch
  > 
  > def processfoo(repo, data, extra, opts):
  >     if b'foo' in data:
  >         extra[b'foo'] = data[b'foo']
  > def postimport(ctx):
  >     if b'foo' in ctx.extra():
  >         ctx.repo().ui.write(b'imported-foo: %s\n' % ctx.extra()[b'foo'])
  > 
  > mercurial.patch.patchheadermap.append((b'Foo', b'foo'))
  > mercurial.cmdutil.extrapreimport.append(b'foo')
  > mercurial.cmdutil.extrapreimportmap[b'foo'] = processfoo
  > mercurial.cmdutil.extrapostimport.append(b'foo')
  > mercurial.cmdutil.extrapostimportmap[b'foo'] = postimport
  > EOF
  $ cat >> $HGRCPATH <<EOF
  > [extensions]
  > parseextra=$TESTTMP/parseextra.py
  > EOF
  $ hg up -C tip
  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ cat > $TESTTMP/foo.patch <<EOF
  > # HG changeset patch
  > # User Rataxes
  > # Date 0 0
  > #      Thu Jan 01 00:00:00 1970 +0000
  > # Foo bar
  > height
  > 
  > --- a/a	Thu Jan 01 00:00:00 1970 +0000
  > +++ b/a	Wed Oct 07 09:17:44 2015 +0000
  > @@ -5,3 +5,4 @@
  >  five
  >  six
  >  seven
  > +heigt
  > EOF
  $ hg import $TESTTMP/foo.patch
  applying $TESTTMP/foo.patch
  imported-foo: bar
  $ hg log --debug -r . | grep extra
  extra:       branch=default
  extra:       foo=bar

Warn the user that paths are relative to the root of
repository when file not found for patching

  $ mkdir filedir
  $ echo "file1" >> filedir/file1
  $ hg add filedir/file1
  $ hg commit -m "file1"
  $ cd filedir
  $ hg import -p 2 - <<EOF
  > # HG changeset patch
  > # User test
  > # Date 0 0
  > file2
  > 
  > diff --git a/filedir/file1 b/filedir/file1
  > --- a/filedir/file1
  > +++ b/filedir/file1
  > @@ -1,1 +1,2 @@
  >  file1
  > +file2
  > EOF
  applying patch from stdin
  unable to find 'file1' for patching
  (use '--prefix' to apply patch relative to the current directory)
  1 out of 1 hunks FAILED -- saving rejects to file file1.rej
  abort: patch failed to apply
  [255]

test import crash (issue5375)
  $ cd ..
  $ hg init repo
  $ cd repo
  $ printf "diff --git a/a b/b\nrename from a\nrename to b" | hg import -
  applying patch from stdin
  a not tracked!
  abort: source file 'a' does not exist
  [255]

test immature end of hunk

  $ hg import - <<'EOF'
  > diff --git a/foo b/foo
  > --- a/foo
  > --- b/foo
  > @@ -0,0 +1,1 @@
  > EOF
  applying patch from stdin
  abort: bad hunk #1: incomplete hunk
  [255]

  $ hg import - <<'EOF'
  > diff --git a/foo b/foo
  > --- a/foo
  > --- b/foo
  > @@ -0,0 +1,1 @@
  > \ No newline at end of file
  > EOF
  applying patch from stdin
  abort: bad hunk #1: incomplete hunk
  [255]