changeset 2831:eda8eb561134

branching: merge with stable
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 09 Aug 2017 13:21:44 +0200
parents fb795bdaa06c (current diff) 499b2dd69107 (diff)
children 07b9fcf8b6d3
files hgext3rd/topic/__init__.py
diffstat 7 files changed, 640 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/docs/makefile	Tue Jul 25 16:58:31 2017 +0200
+++ b/docs/makefile	Wed Aug 09 13:21:44 2017 +0200
@@ -1,10 +1,13 @@
 
-all: tutorials/tutorial.rst static/logo-evolve.ico
+all: tutorials/tutorial.rst tutorials/topic-tutorial.rst static/logo-evolve.ico
 	sphinx-build . ../html/
 
 tutorials/tutorial.rst: tutorials/tutorial.t
 	python test2rst.py tutorials/
 
+tutorials/topic-tutorial.rst: tutorials/topic-tutorial.t
+	python test2rst.py tutorials/
+
 static/logo-evolve.ico: static/logo-evolve.svg
 	convert -resize 36x36 static/logo-evolve.svg static/logo-evolve.ico
 
--- a/docs/test2rst.py	Tue Jul 25 16:58:31 2017 +0200
+++ b/docs/test2rst.py	Wed Aug 09 13:21:44 2017 +0200
@@ -2,14 +2,8 @@
 
 import os
 import os.path as op
-import re
 import sys
 
-# line starts with two chars one of which is not a space (and both are not
-# newlines obviously) and ends with one or more newlines followed by two spaces
-# on a next line (indented text)
-CODEBLOCK = re.compile(r'()\n(([^ \n][^\n]|[^\n][^ \n])[^\n]*)\n+  ')
-
 INDEX = '''
 Mercurial tests
 ===============
@@ -20,10 +14,29 @@
 
 
 def rstify(orig, name):
-    header = '%s\n%s\n\n' % (name, '=' * len(name))
-    content = header + orig
-    content = CODEBLOCK.sub(r'\n\1\n\n::\n\n  ', content)
-    return content
+    newlines = []
+
+    code_block_mode = False
+
+    for line in orig.splitlines():
+
+        # Emtpy lines doesn't change output
+        if not line:
+            newlines.append(line)
+            continue
+
+        codeline = line.startswith('  ')
+        if codeline:
+            if code_block_mode is False:
+                newlines.extend(['::', ''])
+
+            code_block_mode = True
+        else:
+            code_block_mode = False
+
+        newlines.append(line)
+
+    return "\n".join(newlines)
 
 
 def main(base):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/tutorials/topic-tutorial.t	Wed Aug 09 13:21:44 2017 +0200
@@ -0,0 +1,1 @@
+../../tests/test-topic-tutorial.t
\ No newline at end of file
--- a/hgext3rd/topic/__init__.py	Tue Jul 25 16:58:31 2017 +0200
+++ b/hgext3rd/topic/__init__.py	Wed Aug 09 13:21:44 2017 +0200
@@ -118,7 +118,7 @@
               'topic.active': 'green',
              }
 
-version = '0.3.0.dev'
+__version__ = '0.3.0.dev'
 testedwith = '4.0.2 4.1.3 4.2.1'
 minimumhgversion = '4.0'
 buglink = 'https://bz.mercurial-scm.org/'
--- a/tests/test-topic-tutorial.t	Tue Jul 25 16:58:31 2017 +0200
+++ b/tests/test-topic-tutorial.t	Wed Aug 09 13:21:44 2017 +0200
@@ -2,18 +2,27 @@
 Topic Tutorial
 ==============
 
-.. This test file is also supposed to be able to compile as a rest file.
+This Mercurial configuration example is used for testing.
 
-
-.. Some Setup::
+.. Various setup
 
   $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ cat >> $HGRCPATH << EOF
+  > [experimental]
+  > evolution=all
+  > [extensions]
+  > evolve=
+  > EOF
+
   $ hg init server
+
   $ cd server
+
   $ cat >> .hg/hgrc << EOF
   > [ui]
   > user= Shopping Master
   > EOF
+
   $ cat >> shopping << EOF
   > Spam
   > Whizzo butter
@@ -23,8 +32,10 @@
   > Blancmange
   > Salmon mousse
   > EOF
+
   $ hg commit -A -m "Shopping list"
   adding shopping
+
   $ cd ..
   $ hg clone server client
   updating to branch default
@@ -36,13 +47,13 @@
   > EOF
 
 Topic branches are lightweight branches which disappear when changes are
-finalized (move to the public phase). They can help users to organise and share
+finalized (move to the public phase). They can help users to organize and share
 their unfinished work.
 
 Topic Basics
 ============
 
-Let's say we use Mercurial to manage our shopping list::
+Let's say we use Mercurial to manage our shopping list:
 
   $ hg log --graph
   @  changeset:   0:38da43f0a2ea
@@ -52,16 +63,17 @@
      summary:     Shopping list
   
 
-We are about to make some additions to this list and would like to do them
-within a topic. Creating a new topic is done using the ``topic`` command::
+We are about to make some additions to this list and would like to do them 
+within a topic. Creating a new topic is done using the ``topic`` command:
 
   $ hg topic food
 
 Much like a named branch, our topic is active but it does not contain any
-changesets yet::
+changesets yet:
 
   $ hg topic
    * food
+
   $ hg summary
   parent: 0:38da43f0a2ea tip
    Shopping list
@@ -69,6 +81,7 @@
   commit: (clean)
   update: (current)
   topic:  food
+
   $ hg log --graph
   @  changeset:   0:38da43f0a2ea
      tag:         tip
@@ -77,7 +90,7 @@
      summary:     Shopping list
   
 
-Our next commit will be part of the active topic::
+Our next commit will be part of the active topic:
 
   $ cat >> shopping << EOF
   > Egg
@@ -85,7 +98,9 @@
   > Vinegar
   > Oil
   > EOF
+
   $ hg commit -m "adding condiments"
+
   $ hg log --graph --rev 'topic("food")'
   @  changeset:   1:13900241408b
   |  tag:         tip
@@ -95,14 +110,16 @@
      summary:     adding condiments
   
 
-And future commits will be part of that topic too::
+And future commits will be part of that topic too:
 
   $ cat >> shopping << EOF
   > Bananas
   > Pear
   > Apple
   > EOF
+
   $ hg commit -m "adding fruits"
+
   $ hg log --graph --rev 'topic("food")'
   @  changeset:   2:287de11b401f
   |  tag:         tip
@@ -119,7 +136,7 @@
   
 
 We can get a compact view of the content of our topic using the ``stack``
-command::
+command:
 
   $ hg stack
   ### topic: food
@@ -128,15 +145,16 @@
   t1: adding condiments
   t0^ Shopping list (base)
 
-The topic deactivates when we update away from it::
+The topic deactivates when we update away from it:
 
-  $ hg up default
+  $ hg update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg topic
      food
 
 Note that ``default`` (name of the branch) now refers to the tipmost
-changeset of default without a topic::
+changeset of default without a topic:
 
   $ hg log --graph
   o  changeset:   2:287de11b401f
@@ -157,27 +175,29 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     Shopping list
   
+And updating back to the topic reactivates it:
 
-And updating back to the topic reactivates it::
-
-  $ hg up food
+  $ hg update food
   switching to topic food
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg topic
    * food
 
 Updating to any changeset that is part of a topic activates the topic
-regardless of how the revision was specified::
+regardless of how the revision was specified:
 
-  $ hg up default
+  $ hg update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg up --rev 'desc("condiments")'
+
+  $ hg update --rev 'desc("condiments")'
   switching to topic food
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg topic
    * food
 
-.. server side activity::
+.. Server side activity:
 
   $ cd ../server/
   $ cat > shopping << EOF
@@ -191,11 +211,13 @@
   > Blancmange
   > Salmon mousse
   > EOF
+
   $ hg commit -A -m "Adding clothes"
+
   $ cd ../client
 
 The topic will also affect the rebase and the merge destinations. Let's pull
-the latest update from the main server::
+the latest update from the main server:
 
   $ hg pull
   pulling from $TESTTMP/server (glob)
@@ -205,6 +227,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
   (run 'hg heads' to see heads)
+
   $ hg log -G
   o  changeset:   3:6104862e8b84
   |  tag:         tip
@@ -232,26 +255,29 @@
   
 
 The topic head will not be considered when merging from the new head of the
-branch::
+branch:
 
-  $ hg up default
+  $ hg update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg merge
   abort: branch 'default' has one head - please merge with an explicit rev
   (run 'hg heads' to see all heads)
   [255]
 
-But the topic will see that branch head as a valid destination::
+But the topic will see that branch head as a valid destination:
 
-  $ hg up food
+  $ hg update food
   switching to topic food
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg rebase
   rebasing 1:13900241408b "adding condiments"
   merging shopping
   switching to topic food
   rebasing 2:287de11b401f "adding fruits"
   merging shopping
+
   $ hg log --graph
   @  changeset:   5:2d50db8b5b4c
   |  tag:         tip
@@ -278,10 +304,11 @@
      summary:     Shopping list
   
 
-The topic information will disappear when we publish the changesets::
+The topic information will disappear when we publish the changesets:
 
   $ hg topic
    * food
+
   $ hg push
   pushing to $TESTTMP/server (glob)
   searching for changes
@@ -290,8 +317,10 @@
   adding file changes
   added 2 changesets with 2 changes to 1 files
   2 new obsolescence markers
+
   $ hg topic
    * food
+
   $ hg log --graph
   @  changeset:   5:2d50db8b5b4c
   |  tag:         tip
@@ -315,7 +344,7 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     Shopping list
   
-  $ hg up default
+  $ hg update default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 Working with Multiple Topics
@@ -326,35 +355,39 @@
 multiple features at the same time.
 
 We might go shopping in a hardware store in the same go, so let's add some
-tools to the shopping list within a new topic::
+tools to the shopping list within a new topic:
 
   $ hg topic tools
   $ echo hammer >> shopping
-  $ hg ci -m 'Adding hammer'
+  $ hg commit -m 'Adding hammer'
+
   $ echo saw >> shopping
-  $ hg ci -m 'Adding saw'
+  $ hg commit -m 'Adding saw'
+
   $ echo drill >> shopping
-  $ hg ci -m 'Adding drill'
+  $ hg commit -m 'Adding drill'
 
 But we are not sure we will actually go to the hardware store, so in the
 meantime, we want to extend the list with drinks. We go back to the official
-default branch and start a new topic::
+default branch and start a new topic:
 
-  $ hg up default
+  $ hg update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg topic drinks
   $ echo 'apple juice' >> shopping
-  $ hg ci -m 'Adding apple juice'
+  $ hg commit -m 'Adding apple juice'
+
   $ echo 'orange juice' >> shopping
-  $ hg ci -m 'Adding orange juice'
+  $ hg commit -m 'Adding orange juice'
 
-We now have two topics::
+We now have two topics:
 
   $ hg topic
    * drinks
      tools
 
-The information displayed by ``hg stack`` adapts to the active topic::
+The information displayed by ``hg stack`` adapts to the active topic:
 
   $ hg stack
   ### topic: drinks
@@ -362,9 +395,11 @@
   t2@ Adding orange juice (current)
   t1: Adding apple juice
   t0^ adding fruits (base)
-  $ hg up tools
+
+  $ hg update tools
   switching to topic tools
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg stack
   ### topic: tools
   ### branch: default
@@ -374,29 +409,29 @@
   t0^ adding fruits (base)
 
 They are seen as independent branches by Mercurial. No rebase or merge
-between them will be attempted by default::
+between them will be attempted by default:
 
   $ hg rebase
   nothing to rebase
   [1]
 
-.. server activity::
+Server activity:
 
   $ cd ../server
-  $ hg up
+  $ hg update
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ mv shopping foo
   $ echo 'Coat' > shopping
   $ cat foo >> shopping
-  $ hg ci -m 'add a coat'
+  $ hg commit -m 'add a coat'
   $ echo 'Coat' > shopping
   $ echo 'Shoes' >> shopping
   $ cat foo >> shopping
   $ rm foo
-  $ hg ci -m 'add a pair of shoes'
+  $ hg commit -m 'add a pair of shoes'
   $ cd ../client
 
-Let's see what other people did in the meantime::
+Let's see what other people did in the meantime:
 
   $ hg pull
   pulling from $TESTTMP/server (glob)
@@ -408,8 +443,73 @@
   (run 'hg heads' to see heads)
 
 There are new changes! We can simply use ``hg rebase`` to update our
-changeset on top of the latest::
+changeset on top of the latest:
 
+  $ hg log -G
+  o  changeset:   12:fbff9bc37a43
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add a pair of shoes
+  |
+  o  changeset:   11:f2d6cacc6115
+  |  parent:      5:2d50db8b5b4c
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add a coat
+  |
+  | o  changeset:   10:70dfa201ed73
+  | |  topic:       drinks
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding orange juice
+  | |
+  | o  changeset:   9:8dfa45bd5e0c
+  |/   topic:       drinks
+  |    parent:      5:2d50db8b5b4c
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding apple juice
+  |
+  | @  changeset:   8:34255b455dac
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding drill
+  | |
+  | o  changeset:   7:cffff85af537
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding saw
+  | |
+  | o  changeset:   6:183984ef46d1
+  |/   topic:       tools
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding hammer
+  |
+  o  changeset:   5:2d50db8b5b4c
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     adding fruits
+  |
+  o  changeset:   4:4011b46eeb33
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     adding condiments
+  |
+  o  changeset:   3:6104862e8b84
+  |  parent:      0:38da43f0a2ea
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding clothes
+  |
+  o  changeset:   0:38da43f0a2ea
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     Shopping list
+  
   $ hg rebase
   rebasing 6:183984ef46d1 "Adding hammer"
   merging shopping
@@ -420,7 +520,7 @@
   merging shopping
 
 But what about the other topic? You can use 'hg topic --verbose' to see
-information about all the topics::
+information about all the topics:
 
   $ hg topic --verbose
      drinks (on branch: default, 2 changesets, 2 behind)
@@ -429,7 +529,7 @@
 The "2 behind" is telling you that there are 2 new changesets on the named
 branch of the topic. You need to merge or rebase to incorporate them.
 
-Pushing that topic would create a new head, and therefore will be prevented::
+Pushing that topic would create a new head, and therefore will be prevented:
 
   $ hg push --rev drinks
   pushing to $TESTTMP/server (glob)
@@ -440,7 +540,7 @@
 
 
 Even after a rebase, pushing all active topics at the same time will complain
-about the multiple heads it would create on that branch::
+about the multiple heads it would create on that branch:
 
   $ hg rebase -b drinks
   rebasing 9:8dfa45bd5e0c "Adding apple juice"
@@ -449,6 +549,7 @@
   rebasing 10:70dfa201ed73 "Adding orange juice"
   merging shopping
   switching to topic tools
+
   $ hg push
   pushing to $TESTTMP/server (glob)
   searching for changes
@@ -457,7 +558,7 @@
   [255]
 
 Publishing only one of them is allowed (as long as it does not create a new
-branch head as we just saw in the previous case)::
+branch head as we just saw in the previous case):
 
   $ hg push -r drinks
   pushing to $TESTTMP/server (glob)
@@ -469,10 +570,60 @@
   2 new obsolescence markers
 
 The published topic has now disappeared, and the other is now marked as
-"behind"::
+"behind":
 
   $ hg topic --verbose
    * tools (on branch: default, 3 changesets, 2 behind)
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t3@ Adding drill (current)
+  t2: Adding saw
+  t1: Adding hammer
+  t0^ add a pair of shoes (base)
+
+Working Within Your Stack
+===========================
+
+Navigating within your stack
+----------------------------
+
+As we saw before `stack` display changesets on your current topic in a clean way:
+
+  $ hg topics --verbose
+   * tools (on branch: default, 3 changesets, 2 behind)
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t3@ Adding drill (current)
+  t2: Adding saw
+  t1: Adding hammer
+  t0^ add a pair of shoes (base)
+
+You can navigate in your current stack with `previous` and `next`.
+
+`previous` will takes you to the parent of your working directory parent on the same topic.
+
+  $ hg previous
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  [14] Adding saw
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t3: Adding drill
+  t2@ Adding saw (current)
+  t1: Adding hammer
+  t0^ add a pair of shoes (base)
+
+`next` will moves take you to the children of your working directory parent on the same topic.
+
+  $ hg next
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  [15] Adding drill
+
   $ hg stack
   ### topic: tools
   ### branch: default, 2 behind
@@ -481,3 +632,394 @@
   t1: Adding hammer
   t0^ add a pair of shoes (base)
 
+You can also directly access changesets within your stack with the revset `t#`.
+
+  $ hg update t1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t3: Adding drill
+  t2: Adding saw
+  t1@ Adding hammer (current)
+  t0^ add a pair of shoes (base)
+
+Editing your work mid-stack
+---------------------------
+
+It's easy to edit your work inside your stack:
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t3: Adding drill
+  t2: Adding saw
+  t1@ Adding hammer (current)
+  t0^ add a pair of shoes (base)
+
+  $ hg amend -m "Adding hammer to the shopping list"
+  2 new unstable changesets
+
+Understanding the current situation with hg log is not so easy:
+
+  $ hg log -G -r "t0::"
+  @  changeset:   18:b7509bd417f8
+  |  tag:         tip
+  |  topic:       tools
+  |  parent:      12:fbff9bc37a43
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding hammer to the shopping list
+  |
+  | o  changeset:   17:4cd7c1591a67
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding orange juice
+  | |
+  | o  changeset:   16:20759cb47ff8
+  |/   parent:      12:fbff9bc37a43
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding apple juice
+  |
+  | o  changeset:   15:bb1e6254f532
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  trouble:     unstable
+  | |  summary:     Adding drill
+  | |
+  | o  changeset:   14:d4f97f32f8a1
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  trouble:     unstable
+  | |  summary:     Adding saw
+  | |
+  | x  changeset:   13:a8ab3599d53d
+  |/   topic:       tools
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    obsolete:    rewritten as b7509bd417f8
+  |    summary:     Adding hammer
+  |
+  o  changeset:   12:fbff9bc37a43
+  |  user:        test
+  ~  date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     add a pair of shoes
+  
+Fortunately stack show you a better visualization:
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t3$ Adding drill (unstable)
+  t2$ Adding saw (unstable)
+  t1@ Adding hammer to the shopping list (current)
+  t0^ add a pair of shoes (base)
+
+It's easy to stabilize the situation, `next` has an `--evolve` option:
+
+  $ hg next --evolve
+  move:[14] Adding saw
+  atop:[18] Adding hammer to the shopping list
+  working directory now at d5c51ee5762a
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t3$ Adding drill (unstable)
+  t2@ Adding saw (current)
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+One more to go:
+
+  $ hg next --evolve
+  move:[15] Adding drill
+  atop:[19] Adding saw
+  working directory now at bae3758e46bf
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t3@ Adding drill (current)
+  t2: Adding saw
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+Let's take a look at `hg log` once again:
+
+  $ hg log -G -r "t0::"
+  @  changeset:   20:bae3758e46bf
+  |  tag:         tip
+  |  topic:       tools
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding drill
+  |
+  o  changeset:   19:d5c51ee5762a
+  |  topic:       tools
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding saw
+  |
+  o  changeset:   18:b7509bd417f8
+  |  topic:       tools
+  |  parent:      12:fbff9bc37a43
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding hammer to the shopping list
+  |
+  | o  changeset:   17:4cd7c1591a67
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding orange juice
+  | |
+  | o  changeset:   16:20759cb47ff8
+  |/   parent:      12:fbff9bc37a43
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding apple juice
+  |
+  o  changeset:   12:fbff9bc37a43
+  |  user:        test
+  ~  date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     add a pair of shoes
+  
+Multi-headed stack
+------------------
+
+Stack is also very helpful when you have a multi-headed stack:
+
+  $ hg up t1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ echo "nails" > new_shopping
+  $ cat shopping >> new_shopping
+  $ mv new_shopping shopping
+
+  $ hg commit -m 'Adding nails'
+
+  $ hg stack
+  ### topic: tools (2 heads)
+  ### branch: default, 2 behind
+  t4: Adding drill
+  t3: Adding saw
+  t1^ Adding hammer to the shopping list (base)
+  t2@ Adding nails (current)
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+Solving this situation is easy with a topic, use merge or rebase.
+Merge within a multi-headed stack will use the other topic head as
+redestination if the topic has multiple heads.
+
+  $ hg log -G
+  @  changeset:   21:f936c6da9d61
+  |  tag:         tip
+  |  topic:       tools
+  |  parent:      18:b7509bd417f8
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding nails
+  |
+  | o  changeset:   20:bae3758e46bf
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding drill
+  | |
+  | o  changeset:   19:d5c51ee5762a
+  |/   topic:       tools
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding saw
+  |
+  o  changeset:   18:b7509bd417f8
+  |  topic:       tools
+  |  parent:      12:fbff9bc37a43
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding hammer to the shopping list
+  |
+  | o  changeset:   17:4cd7c1591a67
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding orange juice
+  | |
+  | o  changeset:   16:20759cb47ff8
+  |/   parent:      12:fbff9bc37a43
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding apple juice
+  |
+  o  changeset:   12:fbff9bc37a43
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add a pair of shoes
+  |
+  o  changeset:   11:f2d6cacc6115
+  |  parent:      5:2d50db8b5b4c
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add a coat
+  |
+  o  changeset:   5:2d50db8b5b4c
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     adding fruits
+  |
+  o  changeset:   4:4011b46eeb33
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     adding condiments
+  |
+  o  changeset:   3:6104862e8b84
+  |  parent:      0:38da43f0a2ea
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding clothes
+  |
+  o  changeset:   0:38da43f0a2ea
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     Shopping list
+  
+
+  $ hg up t4
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg rebase
+  rebasing 19:d5c51ee5762a "Adding saw"
+  merging shopping
+  rebasing 20:bae3758e46bf "Adding drill"
+  merging shopping
+
+  $ hg commit -m "Merge tools"
+  nothing changed
+  [1]
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t4@ Adding drill (current)
+  t3: Adding saw
+  t2: Adding nails
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+Collaborating through non-publishing server
+===========================================
+
+.. setup:
+
+.. Let's create a non-publishing server:
+
+  $ cd ..
+
+  $ hg clone server non-publishing-server
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ cd non-publishing-server
+  $ cat >> .hg/hgrc << EOF
+  > [phases]
+  > publish = false
+  > EOF
+
+.. And another client:
+
+  $ cd ..
+
+  $ hg clone server other-client
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ cd client
+
+We can now share theses drafts changesets:
+
+  $ hg push ../non-publishing-server -r tools
+  pushing to ../non-publishing-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 4 changes to 1 files (+1 heads)
+  8 new obsolescence markers
+
+Pushing the new topic branch to a non publishing server did not required
+--force. As long as new heads are on their own topic, Mercurial will not
+complains about them.
+
+From another client, we will gets them with their topic:
+
+  $ cd ../other-client
+
+  $ hg pull ../non-publishing-server
+  pulling from ../non-publishing-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 4 changes to 1 files (+1 heads)
+  8 new obsolescence markers
+  (run 'hg heads' to see heads)
+
+  $ hg topics --verbose
+     tools (on branch: default, 4 changesets, 2 behind)
+
+  $ hg up tools
+  switching to topic tools
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t4@ Adding drill (current)
+  t3: Adding saw
+  t2: Adding nails
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+We can also add new changesets and share them:
+
+  $ echo screws >> shopping
+
+  $ hg commit -A -m "Adding screws"
+
+  $ hg push ../non-publishing-server
+  pushing to ../non-publishing-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+And retrieve them on the first client:
+
+  $ cd ../client
+
+  $ hg pull ../non-publishing-server
+  pulling from ../non-publishing-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  (run 'hg update' to get a working copy)
+
+  $ hg update
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg stack
+  ### topic: tools
+  ### branch: default, 2 behind
+  t5@ Adding screws (current)
+  t4: Adding drill
+  t3: Adding saw
+  t2: Adding nails
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
--- a/tests/test-tutorial.t	Tue Jul 25 16:58:31 2017 +0200
+++ b/tests/test-tutorial.t	Wed Aug 09 13:21:44 2017 +0200
@@ -3,6 +3,7 @@
 -------------
 
 This Mercurial configuration example is used for testing.
+
 .. Various setup
 
   $ cat >> $HGRCPATH << EOF
@@ -158,7 +159,7 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-hopefully. I can use `hg commit --amend` to rewrite my faulty changeset!
+Hopefully. I can use `hg commit --amend` to rewrite my faulty changeset!
 
   $ sed -i'' -e s/Bananos/Banana/ shopping
   $ hg diff
@@ -207,7 +208,7 @@
 Getting rid of branchy history
 ----------------------------------
 
-While I was working on my list. someone made a change remotely.
+While I was working on my list. Someone made a change remotely.
 
   $ cd ../remote
   $ hg up -q
@@ -226,7 +227,7 @@
   added 1 changesets with 1 changes to 1 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
-I now have a new heads. Note that this remote head is immutable
+I now have a new head. Note that this remote head is immutable.
 
   $ hg log -G
   o  9ca060c80d74 (public): SPAM
@@ -238,7 +239,7 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-instead of merging my head with the new one. I'm going to rebase my work
+Instead of merging my head with the new one. I'm going to rebase my work
 
   $ hg diff
   $ hg rebase --dest 9ca060c80d74 --source 4d5dc8187023
@@ -263,7 +264,7 @@
 Removing changesets
 ------------------------
 
-I add new item to my list
+I add new items to my list.
 
   $ cat >> shopping << EOF
   > car
@@ -284,7 +285,7 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-I have a new commit but I realize that don't want it. (transport shop list does
+I have a new commit but I realize that don't want it. (Transport shop list does
 not fit well in my standard shopping list)
 
   $ hg prune . # "." is for working directory parent
@@ -513,7 +514,7 @@
 -----------------------
 
 
-sharing mutable changesets
+Sharing mutable changesets
 ----------------------------
 
 To share mutable changesets with others, just check that the repo you interact
@@ -524,7 +525,7 @@
   $ hg -R ../local/ showconfig phases
   [1]
 
-the localrepo does not have any specific configuration for `phases.publish`. It
+The localrepo does not have any specific configuration for `phases.publish`. It
 is ``true`` by default.
 
   $ hg pull local
@@ -550,8 +551,6 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-
-
 We do not want to publish the "bathroom changeset". Let's rollback the last transaction.
 
 .. Warning: Rollback is actually a dangerous kind of internal command that is deprecated and should not be exposed to user. Please forget you read about it until someone fix this tutorial.
@@ -570,7 +569,7 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-Let's make the local repo "non publishing"
+Let's make the local repo "non publishing".
 
   $ echo '[phases]' >> ../local/.hg/hgrc
   $ echo 'publish=false' >> ../local/.hg/hgrc
@@ -641,7 +640,6 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-
 When we pull from remote again we get an unstable state!
 
   $ hg pull remote
@@ -692,8 +690,6 @@
   [255]
  
 
-
-
 To resolve this unstable state, you need to rebase bf1b0d202029 onto
 a44c85f957d3. The `hg evolve` command will do this for you.
 
@@ -730,8 +726,7 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-
-We can push this evolution to remote
+We can push this evolution to remote.
 
   $ hg push remote
   pushing to $TESTTMP/remote (glob)
@@ -743,7 +738,8 @@
   3 new obsolescence markers
   obsoleted 2 changesets
 
-remote get a warning that current working directory is based on an obsolete changeset
+Remote get a warning that current working directory is based on an obsolete
+changeset.
 
   $ cd ../remote
   $ hg pull local # we up again to trigger the warning. it was displayed during the push
@@ -753,7 +749,7 @@
   working directory parent is obsolete! (bf1b0d202029)
   (use 'hg evolve' to update to its successor: ee942144f952)
 
-now let's see where we are, and update to the successor
+Now let's see where we are, and update to the successor.
 
   $ hg parents
   bf1b0d202029 (draft): animals
@@ -767,7 +763,7 @@
 Relocating unstable change after prune
 ----------------------------------------------
 
-The remote guy keep working
+The remote guy keeps working.
 
   $ sed -i'' -e 's/Spam/Spam Spam Spam Spam/g' shopping
   $ hg commit -m "SPAM SPAM SPAM"
@@ -811,7 +807,7 @@
 
 
 The animals changeset is still displayed because the "SPAM SPAM SPAM" changeset
-is neither dead or obsolete.  My repository is in an unstable state again.
+is neither dead or obsolete. My repository is in an unstable state again.
 
   $ hg log -G
   o  99f039c5ec9e (draft): SPAM SPAM SPAM
@@ -830,7 +826,6 @@
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
-
   $ hg log -r 'unstable()'
   99f039c5ec9e (draft): SPAM SPAM SPAM
 
@@ -855,8 +850,6 @@
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
-
-
 Handling Divergent amend
 ----------------------------------------------
 
--- a/tests/testlib/topic_setup.sh	Tue Jul 25 16:58:31 2017 +0200
+++ b/tests/testlib/topic_setup.sh	Wed Aug 09 13:21:44 2017 +0200
@@ -1,4 +1,5 @@
 #!/bin/sh
+. $TESTDIR/testlib/pythonpath.sh
 
 # This file holds logic that is used in many tests.
 # It can be called in a test like this:
@@ -11,5 +12,5 @@
 
 [extensions]
 rebase=
+topic=
 EOF
-echo "topic=$(echo $(dirname $TESTDIR))/hgext3rd/topic" >> $HGRCPATH