tests/test-mq.t
changeset 11894 a15936ac7ec5
parent 11715 4f9dfb54c8b5
child 11907 863567a1364f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mq.t	Sun Aug 15 21:41:45 2010 +0900
@@ -0,0 +1,1359 @@
+  $ . $TESTDIR/helpers.sh
+
+  $ checkundo()
+  > {
+  >     if [ -f .hg/store/undo ]; then
+  >     echo ".hg/store/undo still exists after $1"
+  >     fi
+  > }
+
+  $ echo "[extensions]" >> $HGRCPATH
+  $ echo "mq=" >> $HGRCPATH
+
+  $ echo "[mq]" >> $HGRCPATH
+  $ echo "plain=true" >> $HGRCPATH
+
+
+help
+
+  $ hg help mq
+  mq extension - manage a stack of patches
+  
+  This extension lets you work with a stack of patches in a Mercurial
+  repository. It manages two stacks of patches - all known patches, and applied
+  patches (subset of known patches).
+  
+  Known patches are represented as patch files in the .hg/patches directory.
+  Applied patches are both patch files and changesets.
+  
+  Common tasks (use "hg help command" for more details):
+  
+    create new patch                          qnew
+    import existing patch                     qimport
+  
+    print patch series                        qseries
+    print applied patches                     qapplied
+  
+    add known patch to applied stack          qpush
+    remove patch from applied stack           qpop
+    refresh contents of top applied patch     qrefresh
+  
+  By default, mq will automatically use git patches when required to avoid
+  losing file mode changes, copy records, binary files or empty files creations
+  or deletions. This behaviour can be configured with:
+  
+    [mq]
+    git = auto/keep/yes/no
+  
+  If set to 'keep', mq will obey the [diff] section configuration while
+  preserving existing git patches upon qrefresh. If set to 'yes' or 'no', mq
+  will override the [diff] section and always generate git or regular patches,
+  possibly losing data in the second case.
+  
+  You will by default be managing a patch queue named "patches". You can create
+  other, independent patch queues with the "hg qqueue" command.
+  
+  list of commands:
+  
+   qapplied     print the patches already applied
+   qclone       clone main and patch repository at same time
+   qdelete      remove patches from queue
+   qdiff        diff of the current patch and subsequent modifications
+   qfinish      move applied patches into repository history
+   qfold        fold the named patches into the current patch
+   qgoto        push or pop patches until named patch is at top of stack
+   qguard       set or print guards for a patch
+   qheader      print the header of the topmost or specified patch
+   qimport      import a patch
+   qnew         create a new patch
+   qnext        print the name of the next patch
+   qpop         pop the current patch off the stack
+   qprev        print the name of the previous patch
+   qpush        push the next patch onto the stack
+   qqueue       manage multiple patch queues
+   qrefresh     update the current patch
+   qrename      rename a patch
+   qselect      set or print guarded patches to push
+   qseries      print the entire series file
+   qtop         print the name of the current patch
+   qunapplied   print the patches not yet applied
+   strip        strip changesets and all their descendants from the repository
+  
+  use "hg -v help mq" to show aliases and global options
+
+  $ hg init a
+  $ cd a
+  $ echo a > a
+  $ hg ci -Ama
+  adding a
+
+  $ hg clone . ../k
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ mkdir b
+  $ echo z > b/z
+  $ hg ci -Ama
+  adding b/z
+
+
+qinit
+
+  $ hg qinit
+
+  $ cd ..
+  $ hg init b
+
+
+-R qinit
+
+  $ hg -R b qinit
+
+  $ hg init c
+
+
+qinit -c
+
+  $ hg --cwd c qinit -c
+  $ hg -R c/.hg/patches st
+  A .hgignore
+  A series
+
+
+qinit; qinit -c
+
+  $ hg init d
+  $ cd d
+  $ hg qinit
+  $ hg qinit -c
+
+qinit -c should create both files if they don't exist
+
+  $ cat .hg/patches/.hgignore
+  ^\.hg
+  ^\.mq
+  syntax: glob
+  status
+  guards
+  $ cat .hg/patches/series
+  $ hg qinit -c
+  abort: repository .* already exists!
+  $ cd ..
+
+  $ echo '% qinit; <stuff>; qinit -c'
+  % qinit; <stuff>; qinit -c
+  $ hg init e
+  $ cd e
+  $ hg qnew A
+  $ checkundo qnew
+  $ echo foo > foo
+  $ hg add foo
+  $ hg qrefresh
+  $ hg qnew B
+  $ echo >> foo
+  $ hg qrefresh
+  $ echo status >> .hg/patches/.hgignore
+  $ echo bleh >> .hg/patches/.hgignore
+  $ hg qinit -c
+  adding .hg/patches/A
+  adding .hg/patches/B
+  $ hg -R .hg/patches status
+  A .hgignore
+  A A
+  A B
+  A series
+
+qinit -c shouldn't touch these files if they already exist
+
+  $ cat .hg/patches/.hgignore
+  status
+  bleh
+  $ cat .hg/patches/series
+  A
+  B
+
+status --mq with color (issue2096)
+
+  $ hg status --mq --config extensions.color= --color=always
+  A .hgignore
+  A A
+  A B
+  A series
+  $ cd ..
+
+
+init --mq without repo
+
+  $ mkdir f
+  $ cd f
+  $ hg init --mq
+  abort: There is no Mercurial repository here (.hg not found)
+  $ cd ..
+
+init --mq with repo path
+
+  $ hg init g
+  $ hg init --mq g
+  $ test -d g/.hg/patches/.hg && echo "ok" || echo "failed"
+  ok
+
+init --mq with nonexistent directory
+
+  $ hg init --mq nonexistentdir
+  abort: repository nonexistentdir not found!
+
+
+init --mq with bundle (non "local")
+
+  $ hg -R a bundle --all a.bundle >/dev/null
+  $ hg init --mq a.bundle
+  abort: only a local queue repository may be initialized
+
+  $ cd a
+
+  $ hg qnew -m 'foo bar' test.patch
+
+  $ echo '# comment' > .hg/patches/series.tmp
+  $ echo >> .hg/patches/series.tmp # empty line
+  $ cat .hg/patches/series >> .hg/patches/series.tmp
+  $ mv .hg/patches/series.tmp .hg/patches/series
+
+
+qrefresh
+
+  $ echo a >> a
+  $ hg qrefresh
+  $ cat .hg/patches/test.patch
+  foo bar
+  
+  diff -r [a-f0-9]* a
+  --- a/a\t(?P<date>.*)
+  \+\+\+ b/a\t(?P<date2>.*)
+  @@ -1,1 +1,2 @@
+   a
+  +a
+
+empty qrefresh
+
+  $ hg qrefresh -X a
+
+revision:
+
+  $ hg diff -r -2 -r -1
+
+patch:
+
+  $ cat .hg/patches/test.patch
+  foo bar
+  
+
+working dir diff:
+
+  $ hg diff --nodates -q
+  --- a/a
+  +++ b/a
+  @@ -1,1 +1,2 @@
+   a
+  +a
+
+restore things
+
+  $ hg qrefresh
+  $ checkundo qrefresh
+
+
+qpop
+
+  $ hg qpop
+  popping test.patch
+  patch queue now empty
+  $ checkundo qpop
+
+
+qpush with dump of tag cache
+Dump the tag cache to ensure that it has exactly one head after qpush.
+
+  $ rm -f .hg/tags.cache
+  $ hg tags > /dev/null
+
+.hg/tags.cache (pre qpush):
+
+  $ cat .hg/tags.cache
+  1 [\da-f]{40}
+  
+  $ hg qpush
+  applying test.patch
+  now at: test.patch
+  $ hg tags > /dev/null
+
+.hg/tags.cache (post qpush):
+
+  $ cat .hg/tags.cache
+  2 [\da-f]{40}
+  
+  $ checkundo qpush
+  $ cd ..
+
+
+pop/push outside repo
+  $ hg -R a qpop
+  popping test.patch
+  patch queue now empty
+  $ hg -R a qpush
+  applying test.patch
+  now at: test.patch
+
+  $ cd a
+  $ hg qnew test2.patch
+
+qrefresh in subdir
+
+  $ cd b
+  $ echo a > a
+  $ hg add a
+  $ hg qrefresh
+
+pop/push -a in subdir
+
+  $ hg qpop -a
+  popping test2.patch
+  popping test.patch
+  patch queue now empty
+  $ hg --traceback qpush -a
+  applying test.patch
+  applying test2.patch
+  now at: test2.patch
+
+
+setting columns & formatted tests truncating (issue1912)
+
+  $ COLUMNS=4 hg qseries --config ui.formatted=true
+  test.patch
+  test2.patch
+  $ COLUMNS=20 hg qseries --config ui.formatted=true -vs
+  0 A test.patch: f...
+  1 A test2.patch: 
+  $ hg qpop
+  popping test2.patch
+  now at: test.patch
+  $ hg qseries -vs
+  0 A test.patch: foo bar
+  1 U test2.patch: 
+  $ hg sum | grep mq
+  mq:     1 applied, 1 unapplied
+  $ hg qpush
+  applying test2.patch
+  now at: test2.patch
+  $ hg sum | grep mq
+  mq:     2 applied
+  $ hg qapplied
+  test.patch
+  test2.patch
+  $ hg qtop
+  test2.patch
+
+
+prev
+
+  $ hg qapp -1
+  test.patch
+
+next
+
+  $ hg qunapp -1
+  all patches applied
+
+  $ hg qpop
+  popping test2.patch
+  now at: test.patch
+
+commit should fail
+
+  $ hg commit
+  abort: cannot commit over an applied mq patch
+
+push should fail
+
+  $ hg push ../../k
+  pushing to ../../k
+  abort: source has mq patches applied
+
+
+import should fail
+
+  $ hg st .
+  $ echo foo >> ../a
+  $ hg diff > ../../import.diff
+  $ hg revert --no-backup ../a
+  $ hg import ../../import.diff
+  abort: cannot import over an applied patch
+  $ hg st
+
+import --no-commit should succeed
+
+  $ hg import --no-commit ../../import.diff
+  applying ../../import.diff
+  $ hg st
+  M a
+  $ hg revert --no-backup ../a
+
+
+qunapplied
+
+  $ hg qunapplied
+  test2.patch
+
+
+qpush/qpop with index
+
+  $ hg qnew test1b.patch
+  $ echo 1b > 1b
+  $ hg add 1b
+  $ hg qrefresh
+  $ hg qpush 2
+  applying test2.patch
+  now at: test2.patch
+  $ hg qpop 0
+  popping test2.patch
+  popping test1b.patch
+  now at: test.patch
+  $ hg qpush test.patch+1
+  applying test1b.patch
+  now at: test1b.patch
+  $ hg qpush test.patch+2
+  applying test2.patch
+  now at: test2.patch
+  $ hg qpop test2.patch-1
+  popping test2.patch
+  now at: test1b.patch
+  $ hg qpop test2.patch-2
+  popping test1b.patch
+  now at: test.patch
+  $ hg qpush test1b.patch+1
+  applying test1b.patch
+  applying test2.patch
+  now at: test2.patch
+
+
+qpush --move
+
+  $ hg qpop -a
+  popping test2.patch
+  popping test1b.patch
+  popping test.patch
+  patch queue now empty
+  $ hg qguard test1b.patch -- -negguard
+  $ hg qguard test2.patch -- +posguard
+  $ hg qpush --move test2.patch # can't move guarded patch
+  cannot push 'test2.patch' - guarded by ['+posguard']
+  $ hg qselect posguard
+  number of unguarded, unapplied patches has changed from 2 to 3
+  $ hg qpush --move test2.patch # move to front
+  applying test2.patch
+  now at: test2.patch
+  $ hg qpush --move test1b.patch # negative guard unselected
+  applying test1b.patch
+  now at: test1b.patch
+  $ hg qpush --move test.patch # noop move
+  applying test.patch
+  now at: test.patch
+  $ hg qseries -v
+  0 A test2.patch
+  1 A test1b.patch
+  2 A test.patch
+  $ hg qpop -a
+  popping test.patch
+  popping test1b.patch
+  popping test2.patch
+  patch queue now empty
+
+cleaning up
+
+  $ hg qselect --none
+  guards deactivated
+  number of unguarded, unapplied patches has changed from 3 to 2
+  $ hg qguard --none test1b.patch
+  $ hg qguard --none test2.patch
+  $ hg qpush --move test.patch
+  applying test.patch
+  now at: test.patch
+  $ hg qpush --move test1b.patch
+  applying test1b.patch
+  now at: test1b.patch
+  $ hg qpush --move bogus # nonexistent patch
+  abort: patch bogus not in series
+  $ hg qpush --move # no patch
+  abort: please specify the patch to move
+  $ hg qpush --move test.patch # already applied
+  abort: cannot push to a previous patch: test.patch
+  $ hg qpush
+  applying test2.patch
+  now at: test2.patch
+
+
+series after move
+
+  $ cat `hg root`/.hg/patches/series
+  test.patch
+  test1b.patch
+  test2.patch
+  # comment
+  
+
+
+pop, qapplied, qunapplied
+
+  $ hg qseries -v
+  0 A test.patch
+  1 A test1b.patch
+  2 A test2.patch
+
+qapplied -1 test.patch
+
+  $ hg qapplied -1 test.patch
+  only one patch applied
+
+qapplied -1 test1b.patch
+
+  $ hg qapplied -1 test1b.patch
+  test.patch
+
+qapplied -1 test2.patch
+
+  $ hg qapplied -1 test2.patch
+  test1b.patch
+
+qapplied -1
+
+  $ hg qapplied -1
+  test1b.patch
+
+qapplied
+
+  $ hg qapplied
+  test.patch
+  test1b.patch
+  test2.patch
+
+qapplied test1b.patch
+
+  $ hg qapplied test1b.patch
+  test.patch
+  test1b.patch
+
+qunapplied -1
+
+  $ hg qunapplied -1
+  all patches applied
+
+qunapplied
+
+  $ hg qunapplied
+
+popping
+
+  $ hg qpop
+  popping test2.patch
+  now at: test1b.patch
+
+qunapplied -1
+
+  $ hg qunapplied -1
+  test2.patch
+
+qunapplied
+
+  $ hg qunapplied
+  test2.patch
+
+qunapplied test2.patch
+
+  $ hg qunapplied test2.patch
+
+qunapplied -1 test2.patch
+
+  $ hg qunapplied -1 test2.patch
+  all patches applied
+
+popping -a
+
+  $ hg qpop -a
+  popping test1b.patch
+  popping test.patch
+  patch queue now empty
+
+qapplied
+
+  $ hg qapplied
+
+qapplied -1
+
+  $ hg qapplied -1
+  no patches applied
+  $ hg qpush
+  applying test.patch
+  now at: test.patch
+
+
+push should succeed
+
+  $ hg qpop -a
+  popping test.patch
+  patch queue now empty
+  $ hg push ../../k
+  pushing to ../../k
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+
+qpush/qpop error codes
+
+  $ errorcode()
+  > {
+  >     hg "$@" && echo "  $@ succeeds" || echo "  $@ fails"
+  > }
+
+
+we want to start with some patches applied
+
+  $ hg qpush -a
+  applying test.patch
+  applying test1b.patch
+  applying test2.patch
+  now at: test2.patch
+
+% pops all patches and succeeds
+
+  $ errorcode qpop -a
+  popping test2.patch
+  popping test1b.patch
+  popping test.patch
+  patch queue now empty
+    qpop -a succeeds
+
+% does nothing and succeeds
+
+  $ errorcode qpop -a
+  no patches applied
+    qpop -a succeeds
+
+% fails - nothing else to pop
+
+  $ errorcode qpop
+  no patches applied
+    qpop fails
+
+% pushes a patch and succeeds
+
+  $ errorcode qpush
+  applying test.patch
+  now at: test.patch
+    qpush succeeds
+
+% pops a patch and succeeds
+
+  $ errorcode qpop
+  popping test.patch
+  patch queue now empty
+    qpop succeeds
+
+% pushes up to test1b.patch and succeeds
+
+  $ errorcode qpush test1b.patch
+  applying test.patch
+  applying test1b.patch
+  now at: test1b.patch
+    qpush test1b.patch succeeds
+
+% does nothing and succeeds
+
+  $ errorcode qpush test1b.patch
+  qpush: test1b.patch is already at the top
+    qpush test1b.patch succeeds
+
+% does nothing and succeeds
+
+  $ errorcode qpop test1b.patch
+  qpop: test1b.patch is already at the top
+    qpop test1b.patch succeeds
+
+% fails - can't push to this patch
+
+  $ errorcode qpush test.patch
+  abort: cannot push to a previous patch: test.patch
+    qpush test.patch fails
+
+% fails - can't pop to this patch
+
+  $ errorcode qpop test2.patch
+  abort: patch test2.patch is not applied
+    qpop test2.patch fails
+
+% pops up to test.patch and succeeds
+
+  $ errorcode qpop test.patch
+  popping test1b.patch
+  now at: test.patch
+    qpop test.patch succeeds
+
+% pushes all patches and succeeds
+
+  $ errorcode qpush -a
+  applying test1b.patch
+  applying test2.patch
+  now at: test2.patch
+    qpush -a succeeds
+
+% does nothing and succeeds
+
+  $ errorcode qpush -a
+  all patches are currently applied
+    qpush -a succeeds
+
+% fails - nothing else to push
+
+  $ errorcode qpush
+  patch series already fully applied
+    qpush fails
+
+% does nothing and succeeds
+
+  $ errorcode qpush test2.patch
+  qpush: test2.patch is already at the top
+    qpush test2.patch succeeds
+
+
+
+strip
+
+  $ cd ../../b
+  $ echo x>x
+  $ hg ci -Ama
+  adding x
+  $ hg strip tip | hidebackup
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  saved backup bundle to 
+  $ hg unbundle .hg/strip-backup/*
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  (run 'hg update' to get a working copy)
+
+
+strip with local changes, should complain
+
+  $ hg up
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo y>y
+  $ hg add y
+  $ hg strip tip | hidebackup
+  abort: local changes found
+
+--force strip with local changes
+
+  $ hg strip -f tip | hidebackup
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  saved backup bundle to 
+
+
+cd b; hg qrefresh
+
+  $ hg init refresh
+  $ cd refresh
+  $ echo a > a
+  $ hg ci -Ama
+  adding a
+  $ hg qnew -mfoo foo
+  $ echo a >> a
+  $ hg qrefresh
+  $ mkdir b
+  $ cd b
+  $ echo f > f
+  $ hg add f
+  $ hg qrefresh
+  $ cat ../.hg/patches/foo
+  foo
+  
+  diff -r cb9a9f314b8b a
+  --- a/a\t(?P<date>.*)
+  \+\+\+ b/a\t(?P<date>.*)
+  @@ -1,1 +1,2 @@
+   a
+  +a
+  diff -r cb9a9f314b8b b/f
+  --- /dev/null\t(?P<date>.*)
+  \+\+\+ b/b/f\t(?P<date>.*)
+  @@ -0,0 +1,1 @@
+  +f
+
+hg qrefresh .
+
+  $ hg qrefresh .
+  $ cat ../.hg/patches/foo
+  foo
+  
+  diff -r cb9a9f314b8b b/f
+  --- /dev/null\t(?P<date>.*)
+  \+\+\+ b/b/f\t(?P<date>.*)
+  @@ -0,0 +1,1 @@
+  +f
+  $ hg status
+  M a
+
+
+qpush failure
+
+  $ cd ..
+  $ hg qrefresh
+  $ hg qnew -mbar bar
+  $ echo foo > foo
+  $ echo bar > bar
+  $ hg add foo bar
+  $ hg qrefresh
+  $ hg qpop -a
+  popping bar
+  popping foo
+  patch queue now empty
+  $ echo bar > foo
+  $ hg qpush -a
+  applying foo
+  applying bar
+  file foo already exists
+  1 out of 1 hunks FAILED -- saving rejects to file foo.rej
+  patch failed, unable to continue (try -v)
+  patch failed, rejects left in working dir
+  errors during apply, please fix and refresh bar
+  $ hg st
+  ? foo
+  ? foo.rej
+
+
+mq tags
+
+  $ hg log --template '{rev} {tags}\n' -r qparent:qtip
+  0 qparent
+  1 foo qbase
+  2 bar qtip tip
+
+
+bad node in status
+
+  $ hg qpop
+  popping bar
+  now at: foo
+  $ hg strip -qn tip
+  $ hg tip
+  changeset:   0:cb9a9f314b8b
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     a
+  
+  $ hg branches
+  default                        0:cb9a9f314b8b
+  $ hg qpop
+  no patches applied
+
+  $ cat >>$HGRCPATH <<EOF
+  > [diff]
+  > git = True
+  > EOF
+  $ cd ..
+  $ hg init git
+  $ cd git
+  $ hg qinit
+
+  $ hg qnew -m'new file' new
+  $ echo foo > new
+  $ chmod +x new
+  $ hg add new
+  $ hg qrefresh
+  $ cat .hg/patches/new
+  new file
+  
+  diff --git a/new b/new
+  new file mode 100755
+  --- /dev/null
+  +++ b/new
+  @@ -0,0 +1,1 @@
+  +foo
+
+  $ hg qnew -m'copy file' copy
+  $ hg cp new copy
+  $ hg qrefresh
+  $ cat .hg/patches/copy
+  copy file
+  
+  diff --git a/new b/copy
+  copy from new
+  copy to copy
+
+  $ hg qpop
+  popping copy
+  now at: new
+  $ hg qpush
+  applying copy
+  now at: copy
+  $ hg qdiff
+  diff --git a/new b/copy
+  copy from new
+  copy to copy
+  $ cat >>$HGRCPATH <<EOF
+  > [diff]
+  > git = False
+  > EOF
+  $ hg qdiff --git
+  diff --git a/new b/copy
+  copy from new
+  copy to copy
+  $ cd ..
+
+
+test file addition in slow path
+
+  $ hg init slow
+  $ cd slow
+  $ hg qinit
+  $ echo foo > foo
+  $ hg add foo
+  $ hg ci -m 'add foo'
+  $ hg qnew bar
+  $ echo bar > bar
+  $ hg add bar
+  $ hg mv foo baz
+  $ hg qrefresh --git
+  $ hg up -C 0
+  1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo >> foo
+  $ hg ci -m 'change foo'
+  created new head
+  $ hg up -C 1
+  2 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg qrefresh --git 2>&1 | grep -v 'saving bundle'
+  $ cat .hg/patches/bar
+  diff --git a/bar b/bar
+  new file mode 100644
+  --- /dev/null
+  +++ b/bar
+  @@ -0,0 +1,1 @@
+  +bar
+  diff --git a/foo b/baz
+  rename from foo
+  rename to baz
+  $ hg log -v --template '{rev} {file_copies}\n' -r .
+  2 baz (foo)
+  $ hg qrefresh --git
+  $ cat .hg/patches/bar
+  diff --git a/bar b/bar
+  new file mode 100644
+  --- /dev/null
+  +++ b/bar
+  @@ -0,0 +1,1 @@
+  +bar
+  diff --git a/foo b/baz
+  rename from foo
+  rename to baz
+  $ hg log -v --template '{rev} {file_copies}\n' -r .
+  2 baz (foo)
+  $ hg qrefresh
+  $ grep 'diff --git' .hg/patches/bar
+  diff --git a/bar b/bar
+  diff --git a/foo b/baz
+
+
+test file move chains in the slow path
+
+  $ hg up -C 1
+  1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo >> foo
+  $ hg ci -m 'change foo again'
+  $ hg up -C 2
+  2 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg mv bar quux
+  $ hg mv baz bleh
+  $ hg qrefresh --git 2>&1 | grep -v 'saving bundle'
+  $ cat .hg/patches/bar
+  diff --git a/foo b/bleh
+  rename from foo
+  rename to bleh
+  diff --git a/quux b/quux
+  new file mode 100644
+  --- /dev/null
+  +++ b/quux
+  @@ -0,0 +1,1 @@
+  +bar
+  $ hg log -v --template '{rev} {file_copies}\n' -r .
+  3 bleh (foo)
+  $ hg mv quux fred
+  $ hg mv bleh barney
+  $ hg qrefresh --git
+  $ cat .hg/patches/bar
+  diff --git a/foo b/barney
+  rename from foo
+  rename to barney
+  diff --git a/fred b/fred
+  new file mode 100644
+  --- /dev/null
+  +++ b/fred
+  @@ -0,0 +1,1 @@
+  +bar
+  $ hg log -v --template '{rev} {file_copies}\n' -r .
+  3 barney (foo)
+
+
+refresh omitting an added file
+
+  $ hg qnew baz
+  $ echo newfile > newfile
+  $ hg add newfile
+  $ hg qrefresh
+  $ hg st -A newfile
+  C newfile
+  $ hg qrefresh -X newfile
+  $ hg st -A newfile
+  A newfile
+  $ hg revert newfile
+  $ rm newfile
+  $ hg qpop
+  popping baz
+  now at: bar
+  $ hg qdel baz
+
+
+create a git patch
+
+  $ echo a > alexander
+  $ hg add alexander
+  $ hg qnew -f --git addalexander
+  $ grep diff .hg/patches/addalexander
+  diff --git a/alexander b/alexander
+
+
+create a git binary patch
+
+  $ cat > writebin.py <<EOF
+  > import sys
+  > path = sys.argv[1]
+  > open(path, 'wb').write('BIN\x00ARY')
+  > EOF
+  $ python writebin.py bucephalus
+
+  $ python "$TESTDIR/md5sum.py" bucephalus
+  8ba2a2f3e77b55d03051ff9c24ad65e7  bucephalus
+  $ hg add bucephalus
+  $ hg qnew -f --git addbucephalus
+  $ grep diff .hg/patches/addbucephalus
+  diff --git a/bucephalus b/bucephalus
+
+
+check binary patches can be popped and pushed
+
+  $ hg qpop
+  popping addbucephalus
+  now at: addalexander
+  $ test -f bucephalus && echo % bucephalus should not be there
+  $ hg qpush
+  applying addbucephalus
+  now at: addbucephalus
+  $ test -f bucephalus || echo % bucephalus should be there
+  $ python "$TESTDIR/md5sum.py" bucephalus
+  8ba2a2f3e77b55d03051ff9c24ad65e7  bucephalus
+
+
+
+strip again
+
+  $ cd ..
+  $ hg init strip
+  $ cd strip
+  $ touch foo
+  $ hg add foo
+  $ hg ci -m 'add foo'
+  $ echo >> foo
+  $ hg ci -m 'change foo 1'
+  $ hg up -C 0
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo 1 >> foo
+  $ hg ci -m 'change foo 2'
+  created new head
+  $ HGMERGE=true hg merge
+  merging foo
+  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m merge
+  $ hg log
+  changeset:   3:99615015637b
+  tag:         tip
+  parent:      2:20cbbe65cff7
+  parent:      1:d2871fc282d4
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     merge
+  
+  changeset:   2:20cbbe65cff7
+  parent:      0:53245c60e682
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     change foo 2
+  
+  changeset:   1:d2871fc282d4
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     change foo 1
+  
+  changeset:   0:53245c60e682
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     add foo
+  
+  $ hg strip 1 | hidebackup
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to 
+  $ checkundo strip
+  $ hg log
+  changeset:   1:20cbbe65cff7
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     change foo 2
+  
+  changeset:   0:53245c60e682
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     add foo
+  
+  $ cd ..
+
+
+qclone
+
+  $ qlog()
+  > {
+  >     echo 'main repo:'
+  >     hg log --template '    rev {rev}: {desc}\n'
+  >     echo 'patch repo:'
+  >     hg -R .hg/patches log --template '    rev {rev}: {desc}\n'
+  > }
+  $ hg init qclonesource
+  $ cd qclonesource
+  $ echo foo > foo
+  $ hg add foo
+  $ hg ci -m 'add foo'
+  $ hg qinit
+  $ hg qnew patch1
+  $ echo bar >> foo
+  $ hg qrefresh -m 'change foo'
+  $ cd ..
+
+
+repo with unversioned patch dir
+
+  $ hg qclone qclonesource failure
+  abort: versioned patch repository not found (see init --mq)
+
+  $ cd qclonesource
+  $ hg qinit -c
+  adding .hg/patches/patch1
+  $ hg qci -m checkpoint
+  $ qlog
+  main repo:
+      rev 1: change foo
+      rev 0: add foo
+  patch repo:
+      rev 0: checkpoint
+  $ cd ..
+
+
+repo with patches applied
+
+  $ hg qclone qclonesource qclonedest
+  updating to branch default
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd qclonedest
+  $ qlog
+  main repo:
+      rev 0: add foo
+  patch repo:
+      rev 0: checkpoint
+  $ cd ..
+
+
+repo with patches unapplied
+
+  $ cd qclonesource
+  $ hg qpop -a
+  popping patch1
+  patch queue now empty
+  $ qlog
+  main repo:
+      rev 0: add foo
+  patch repo:
+      rev 0: checkpoint
+  $ cd ..
+  $ hg qclone qclonesource qclonedest2
+  updating to branch default
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd qclonedest2
+  $ qlog
+  main repo:
+      rev 0: add foo
+  patch repo:
+      rev 0: checkpoint
+  $ cd ..
+
+
+test applying on an empty file (issue 1033)
+
+  $ hg init empty
+  $ cd empty
+  $ touch a
+  $ hg ci -Am addempty
+  adding a
+  $ echo a > a
+  $ hg qnew -f -e changea
+  $ hg qpop
+  popping changea
+  patch queue now empty
+  $ hg qpush
+  applying changea
+  now at: changea
+  $ cd ..
+
+
+test qpush with --force, issue1087
+
+  $ hg init forcepush
+  $ cd forcepush
+  $ echo hello > hello.txt
+  $ echo bye > bye.txt
+  $ hg ci -Ama
+  adding bye.txt
+  adding hello.txt
+  $ hg qnew -d '0 0' empty
+  $ hg qpop
+  popping empty
+  patch queue now empty
+  $ echo world >> hello.txt
+
+
+qpush should fail, local changes
+
+  $ hg qpush
+  abort: local changes found, refresh first
+
+
+apply force, should not discard changes with empty patch
+
+  $ hg qpush -f
+  applying empty
+  patch empty is empty
+  now at: empty
+  $ hg diff --config diff.nodates=True
+  diff -r bf5fc3f07a0a hello.txt
+  --- a/hello.txt
+  +++ b/hello.txt
+  @@ -1,1 +1,2 @@
+   hello
+  +world
+  $ hg qdiff --config diff.nodates=True
+  diff -r 9ecee4f634e3 hello.txt
+  --- a/hello.txt
+  +++ b/hello.txt
+  @@ -1,1 +1,2 @@
+   hello
+  +world
+  $ hg log -l1 -p
+  changeset:   1:bf5fc3f07a0a
+  tag:         empty
+  tag:         qbase
+  tag:         qtip
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     imported patch empty
+  
+  
+  $ hg qref -d '0 0'
+  $ hg qpop
+  popping empty
+  patch queue now empty
+  $ echo universe >> hello.txt
+  $ echo universe >> bye.txt
+
+
+qpush should fail, local changes
+
+  $ hg qpush
+  abort: local changes found, refresh first
+
+
+apply force, should discard changes in hello, but not bye
+
+  $ hg qpush -f
+  applying empty
+  now at: empty
+  $ hg st
+  M bye.txt
+  $ hg diff --config diff.nodates=True
+  diff -r ba252371dbc1 bye.txt
+  --- a/bye.txt
+  +++ b/bye.txt
+  @@ -1,1 +1,2 @@
+   bye
+  +universe
+  $ hg qdiff --config diff.nodates=True
+  diff -r 9ecee4f634e3 bye.txt
+  --- a/bye.txt
+  +++ b/bye.txt
+  @@ -1,1 +1,2 @@
+   bye
+  +universe
+  diff -r 9ecee4f634e3 hello.txt
+  --- a/hello.txt
+  +++ b/hello.txt
+  @@ -1,1 +1,3 @@
+   hello
+  +world
+  +universe
+
+
+test popping revisions not in working dir ancestry
+
+  $ hg qseries -v
+  0 A empty
+  $ hg up qparent
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg qpop
+  popping empty
+  patch queue now empty
+
+  $ cd ..
+  $ hg init deletion-order
+  $ cd deletion-order
+
+  $ touch a
+  $ hg ci -Aqm0
+
+  $ hg qnew rename-dir
+  $ hg rm a
+  $ hg qrefresh
+
+  $ mkdir a b
+  $ touch a/a b/b
+  $ hg add -q a b
+  $ hg qrefresh
+
+
+test popping must remove files added in subdirectories first
+
+  $ hg qpop
+  popping rename-dir
+  patch queue now empty
+  $ cd ..
+