diff en/ch05-collab.xml @ 749:7e7c47481e4f

Oops, this is the real merge for my hg's oddity
author Dongsheng Song <dongsheng.song@gmail.com>
date Fri, 20 Mar 2009 16:43:35 +0800
parents en/ch06-collab.xml@e0ac2341a861
children 1c13ed2130a7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch05-collab.xml	Fri Mar 20 16:43:35 2009 +0800
@@ -0,0 +1,1437 @@
+<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
+
+<chapter id="cha.collab">
+  <?dbhtml filename="collaborating-with-other-people.html"?>
+  <title>Collaborating with other people</title>
+
+  <para>As a completely decentralised tool, Mercurial doesn't impose
+    any policy on how people ought to work with each other.  However,
+    if you're new to distributed revision control, it helps to have
+    some tools and examples in mind when you're thinking about
+    possible workflow models.</para>
+
+  <sect1>
+    <title>Mercurial's web interface</title>
+
+    <para>Mercurial has a powerful web interface that provides several
+      useful capabilities.</para>
+
+    <para>For interactive use, the web interface lets you browse a
+      single repository or a collection of repositories.  You can view
+      the history of a repository, examine each change (comments and
+      diffs), and view the contents of each directory and file.</para>
+
+    <para>Also for human consumption, the web interface provides an
+      RSS feed of the changes in a repository.  This lets you
+      <quote>subscribe</quote> to a repository using your favourite
+      feed reader, and be automatically notified of activity in that
+      repository as soon as it happens.  I find this capability much
+      more convenient than the model of subscribing to a mailing list
+      to which notifications are sent, as it requires no additional
+      configuration on the part of whoever is serving the
+      repository.</para>
+
+    <para>The web interface also lets remote users clone a repository,
+      pull changes from it, and (when the server is configured to
+      permit it) push changes back to it.  Mercurial's HTTP tunneling
+      protocol aggressively compresses data, so that it works
+      efficiently even over low-bandwidth network connections.</para>
+
+    <para>The easiest way to get started with the web interface is to
+      use your web browser to visit an existing repository, such as
+      the master Mercurial repository at <ulink
+	url="http://www.selenic.com/repo/hg?style=gitweb">http://www.selenic.com/repo/hg?style=gitweb</ulink>.</para>
+
+    <para>If you're interested in providing a web interface to your
+      own repositories, Mercurial provides two ways to do this.  The
+      first is using the <command role="hg-cmd">hg serve</command>
+      command, which is best suited to short-term
+      <quote>lightweight</quote> serving.  See section <xref
+	linkend="sec.collab.serve"/> below for details of how to use
+      this command.  If you have a long-lived repository that you'd
+      like to make permanently available, Mercurial has built-in
+      support for the CGI (Common Gateway Interface) standard, which
+      all common web servers support.  See section <xref
+	linkend="sec.collab.cgi"/> for details of CGI
+      configuration.</para>
+
+  </sect1>
+  <sect1>
+    <title>Collaboration models</title>
+
+    <para>With a suitably flexible tool, making decisions about
+      workflow is much more of a social engineering challenge than a
+      technical one. Mercurial imposes few limitations on how you can
+      structure the flow of work in a project, so it's up to you and
+      your group to set up and live with a model that matches your own
+      particular needs.</para>
+
+    <sect2>
+      <title>Factors to keep in mind</title>
+
+      <para>The most important aspect of any model that you must keep
+	in mind is how well it matches the needs and capabilities of
+	the people who will be using it.  This might seem
+	self-evident; even so, you still can't afford to forget it for
+	a moment.</para>
+
+      <para>I once put together a workflow model that seemed to make
+	perfect sense to me, but that caused a considerable amount of
+	consternation and strife within my development team.  In spite
+	of my attempts to explain why we needed a complex set of
+	branches, and how changes ought to flow between them, a few
+	team members revolted.  Even though they were smart people,
+	they didn't want to pay attention to the constraints we were
+	operating under, or face the consequences of those constraints
+	in the details of the model that I was advocating.</para>
+
+      <para>Don't sweep foreseeable social or technical problems under
+	the rug. Whatever scheme you put into effect, you should plan
+	for mistakes and problem scenarios.  Consider adding automated
+	machinery to prevent, or quickly recover from, trouble that
+	you can anticipate.  As an example, if you intend to have a
+	branch with not-for-release changes in it, you'd do well to
+	think early about the possibility that someone might
+	accidentally merge those changes into a release branch.  You
+	could avoid this particular problem by writing a hook that
+	prevents changes from being merged from an inappropriate
+	branch.</para>
+
+    </sect2>
+    <sect2>
+      <title>Informal anarchy</title>
+
+      <para>I wouldn't suggest an <quote>anything goes</quote>
+	approach as something sustainable, but it's a model that's
+	easy to grasp, and it works perfectly well in a few unusual
+	situations.</para>
+
+      <para>As one example, many projects have a loose-knit group of
+	collaborators who rarely physically meet each other.  Some
+	groups like to overcome the isolation of working at a distance
+	by organising occasional <quote>sprints</quote>.  In a sprint,
+	a number of people get together in a single location (a
+	company's conference room, a hotel meeting room, that kind of
+	place) and spend several days more or less locked in there,
+	hacking intensely on a handful of projects.</para>
+
+      <para>A sprint is the perfect place to use the <command
+	  role="hg-cmd">hg serve</command> command, since <command
+	  role="hg-cmd">hg serve</command> does not require any fancy
+	server infrastructure.  You can get started with <command
+	  role="hg-cmd">hg serve</command> in moments, by reading
+	section <xref linkend="sec.collab.serve"/> below.  Then simply
+	tell
+	the person next to you that you're running a server, send the
+	URL to them in an instant message, and you immediately have a
+	quick-turnaround way to work together.  They can type your URL
+	into their web browser and quickly review your changes; or
+	they can pull a bugfix from you and verify it; or they can
+	clone a branch containing a new feature and try it out.</para>
+
+      <para>The charm, and the problem, with doing things in an ad hoc
+	fashion like this is that only people who know about your
+	changes, and where they are, can see them.  Such an informal
+	approach simply doesn't scale beyond a handful people, because
+	each individual needs to know about $n$ different repositories
+	to pull from.</para>
+
+    </sect2>
+    <sect2>
+      <title>A single central repository</title>
+
+      <para>For smaller projects migrating from a centralised revision
+	control tool, perhaps the easiest way to get started is to
+	have changes flow through a single shared central repository.
+	This is also the most common <quote>building block</quote> for
+	more ambitious workflow schemes.</para>
+
+      <para>Contributors start by cloning a copy of this repository.
+	They can pull changes from it whenever they need to, and some
+	(perhaps all) developers have permission to push a change back
+	when they're ready for other people to see it.</para>
+
+      <para>Under this model, it can still often make sense for people
+	to pull changes directly from each other, without going
+	through the central repository.  Consider a case in which I
+	have a tentative bug fix, but I am worried that if I were to
+	publish it to the central repository, it might subsequently
+	break everyone else's trees as they pull it.  To reduce the
+	potential for damage, I can ask you to clone my repository
+	into a temporary repository of your own and test it.  This
+	lets us put off publishing the potentially unsafe change until
+	it has had a little testing.</para>
+
+      <para>In this kind of scenario, people usually use the
+	<command>ssh</command> protocol to securely push changes to
+	the central repository, as documented in section <xref
+	  linkend="sec.collab.ssh"/>.  It's also
+	usual to publish a read-only copy of the repository over HTTP
+	using CGI, as in section <xref linkend="sec.collab.cgi"/>.
+	Publishing over HTTP
+	satisfies the needs of people who don't have push access, and
+	those who want to use web browsers to browse the repository's
+	history.</para>
+
+    </sect2>
+    <sect2>
+      <title>Working with multiple branches</title>
+
+      <para>Projects of any significant size naturally tend to make
+	progress on several fronts simultaneously.  In the case of
+	software, it's common for a project to go through periodic
+	official releases.  A release might then go into
+	<quote>maintenance mode</quote> for a while after its first
+	publication; maintenance releases tend to contain only bug
+	fixes, not new features.  In parallel with these maintenance
+	releases, one or more future releases may be under
+	development.  People normally use the word
+	<quote>branch</quote> to refer to one of these many slightly
+	different directions in which development is
+	proceeding.</para>
+
+      <para>Mercurial is particularly well suited to managing a number
+	of simultaneous, but not identical, branches.  Each
+	<quote>development direction</quote> can live in its own
+	central repository, and you can merge changes from one to
+	another as the need arises.  Because repositories are
+	independent of each other, unstable changes in a development
+	branch will never affect a stable branch unless someone
+	explicitly merges those changes in.</para>
+
+      <para>Here's an example of how this can work in practice.  Let's
+	say you have one <quote>main branch</quote> on a central
+	server.</para>
+
+      &interaction.branching.init;
+
+      <para>People clone it, make changes locally, test them, and push
+	them back.</para>
+
+      <para>Once the main branch reaches a release milestone, you can
+	use the <command role="hg-cmd">hg tag</command> command to
+	give a permanent name to the milestone revision.</para>
+
+	&interaction.branching.tag;
+
+      <para>Let's say some ongoing
+	development occurs on the main branch.</para>
+
+      &interaction.branching.main;
+
+      <para>Using the tag that was recorded at the milestone, people
+	who clone that repository at any time in the future can use
+	<command role="hg-cmd">hg update</command> to get a copy of
+	the working directory exactly as it was when that tagged
+	revision was committed.</para>
+
+      &interaction.branching.update;
+
+      <para>In addition, immediately after the main branch is tagged,
+	someone can then clone the main branch on the server to a new
+	<quote>stable</quote> branch, also on the server.</para>
+
+      &interaction.branching.clone;
+
+      <para>Someone who needs to make a change to the stable branch
+	can then clone <emphasis>that</emphasis> repository, make
+	their changes, commit, and push their changes back there.</para>
+
+      &interaction.branching.stable;
+
+      <para>Because Mercurial repositories are independent, and
+	Mercurial doesn't move changes around automatically, the
+	stable and main branches are <emphasis>isolated</emphasis>
+	from each other.  The changes that you made on the main branch
+	don't <quote>leak</quote> to the stable branch, and vice
+	versa.</para>
+
+      <para>You'll often want all of your bugfixes on the stable
+	branch to show up on the main branch, too.  Rather than
+	rewrite a bugfix on the main branch, you can simply pull and
+	merge changes from the stable to the main branch, and
+	Mercurial will bring those bugfixes in for you.</para>
+
+	&interaction.branching.merge;
+
+      <para>The main branch will still contain changes that are not on
+	the stable branch, but it will also contain all of the
+	bugfixes from the stable branch.  The stable branch remains
+	unaffected by these changes.</para>
+
+    </sect2>
+    <sect2>
+      <title>Feature branches</title>
+
+      <para>For larger projects, an effective way to manage change is
+	to break up a team into smaller groups.  Each group has a
+	shared branch of its own, cloned from a single
+	<quote>master</quote> branch used by the entire project.
+	People working on an individual branch are typically quite
+	isolated from developments on other branches.</para>
+
+      <informalfigure id="fig.collab.feature-branches">
+        <mediaobject>
+          <imageobject><imagedata fileref="images/feature-branches.png"/>
+          </imageobject>
+          <textobject><phrase>XXX add text</phrase></textobject>
+          <caption><para id="fig.collab.feature-branches.caption">Feature
+            branches</para></caption>
+        </mediaobject>
+      </informalfigure>
+
+      <para>When a particular feature is deemed to be in suitable
+	shape, someone on that feature team pulls and merges from the
+	master branch into the feature branch, then pushes back up to
+	the master branch.</para>
+
+    </sect2>
+    <sect2>
+      <title>The release train</title>
+
+      <para>Some projects are organised on a <quote>train</quote>
+	basis: a release is scheduled to happen every few months, and
+	whatever features are ready when the <quote>train</quote> is
+	ready to leave are allowed in.</para>
+
+      <para>This model resembles working with feature branches.  The
+	difference is that when a feature branch misses a train,
+	someone on the feature team pulls and merges the changes that
+	went out on that train release into the feature branch, and
+	the team continues its work on top of that release so that
+	their feature can make the next release.</para>
+
+    </sect2>
+    <sect2>
+      <title>The Linux kernel model</title>
+
+      <para>The development of the Linux kernel has a shallow
+	hierarchical structure, surrounded by a cloud of apparent
+	chaos.  Because most Linux developers use
+	<command>git</command>, a distributed revision control tool
+	with capabilities similar to Mercurial, it's useful to
+	describe the way work flows in that environment; if you like
+	the ideas, the approach translates well across tools.</para>
+
+      <para>At the center of the community sits Linus Torvalds, the
+	creator of Linux.  He publishes a single source repository
+	that is considered the <quote>authoritative</quote> current
+	tree by the entire developer community. Anyone can clone
+	Linus's tree, but he is very choosy about whose trees he pulls
+	from.</para>
+
+      <para>Linus has a number of <quote>trusted lieutenants</quote>.
+	As a general rule, he pulls whatever changes they publish, in
+	most cases without even reviewing those changes.  Some of
+	those lieutenants are generally agreed to be
+	<quote>maintainers</quote>, responsible for specific
+	subsystems within the kernel.  If a random kernel hacker wants
+	to make a change to a subsystem that they want to end up in
+	Linus's tree, they must find out who the subsystem's
+	maintainer is, and ask that maintainer to take their change.
+	If the maintainer reviews their changes and agrees to take
+	them, they'll pass them along to Linus in due course.</para>
+
+      <para>Individual lieutenants have their own approaches to
+	reviewing, accepting, and publishing changes; and for deciding
+	when to feed them to Linus.  In addition, there are several
+	well known branches that people use for different purposes.
+	For example, a few people maintain <quote>stable</quote>
+	repositories of older versions of the kernel, to which they
+	apply critical fixes as needed.  Some maintainers publish
+	multiple trees: one for experimental changes; one for changes
+	that they are about to feed upstream; and so on.  Others just
+	publish a single tree.</para>
+
+      <para>This model has two notable features.  The first is that
+	it's <quote>pull only</quote>.  You have to ask, convince, or
+	beg another developer to take a change from you, because there
+	are almost no trees to which more than one person can push,
+	and there's no way to push changes into a tree that someone
+	else controls.</para>
+
+      <para>The second is that it's based on reputation and acclaim.
+	If you're an unknown, Linus will probably ignore changes from
+	you without even responding.  But a subsystem maintainer will
+	probably review them, and will likely take them if they pass
+	their criteria for suitability. The more <quote>good</quote>
+	changes you contribute to a maintainer, the more likely they
+	are to trust your judgment and accept your changes.  If you're
+	well-known and maintain a long-lived branch for something
+	Linus hasn't yet accepted, people with similar interests may
+	pull your changes regularly to keep up with your work.</para>
+
+      <para>Reputation and acclaim don't necessarily cross subsystem
+	or <quote>people</quote> boundaries.  If you're a respected
+	but specialised storage hacker, and you try to fix a
+	networking bug, that change will receive a level of scrutiny
+	from a network maintainer comparable to a change from a
+	complete stranger.</para>
+
+      <para>To people who come from more orderly project backgrounds,
+	the comparatively chaotic Linux kernel development process
+	often seems completely insane.  It's subject to the whims of
+	individuals; people make sweeping changes whenever they deem
+	it appropriate; and the pace of development is astounding.
+	And yet Linux is a highly successful, well-regarded piece of
+	software.</para>
+
+    </sect2>
+    <sect2>
+      <title>Pull-only versus shared-push collaboration</title>
+
+      <para>A perpetual source of heat in the open source community is
+	whether a development model in which people only ever pull
+	changes from others is <quote>better than</quote> one in which
+	multiple people can push changes to a shared
+	repository.</para>
+
+      <para>Typically, the backers of the shared-push model use tools
+	that actively enforce this approach.  If you're using a
+	centralised revision control tool such as Subversion, there's
+	no way to make a choice over which model you'll use: the tool
+	gives you shared-push, and if you want to do anything else,
+	you'll have to roll your own approach on top (such as applying
+	a patch by hand).</para>
+
+      <para>A good distributed revision control tool, such as
+	Mercurial, will support both models.  You and your
+	collaborators can then structure how you work together based
+	on your own needs and preferences, not on what contortions
+	your tools force you into.</para>
+
+    </sect2>
+    <sect2>
+      <title>Where collaboration meets branch management</title>
+
+      <para>Once you and your team set up some shared repositories and
+	start propagating changes back and forth between local and
+	shared repos, you begin to face a related, but slightly
+	different challenge: that of managing the multiple directions
+	in which your team may be moving at once.  Even though this
+	subject is intimately related to how your team collaborates,
+	it's dense enough to merit treatment of its own, in chapter
+	<xref linkend="chap.branch"/>.</para>
+
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>The technical side of sharing</title>
+
+    <para>The remainder of this chapter is devoted to the question of
+      serving data to your collaborators.</para>
+
+  </sect1>
+  <sect1 id="sec.collab.serve">
+    <title>Informal sharing with <command role="hg-cmd">hg
+	serve</command></title>
+
+    <para>Mercurial's <command role="hg-cmd">hg serve</command>
+      command is wonderfully suited to small, tight-knit, and
+      fast-paced group environments.  It also provides a great way to
+      get a feel for using Mercurial commands over a network.</para>
+
+    <para>Run <command role="hg-cmd">hg serve</command> inside a
+      repository, and in under a second it will bring up a specialised
+      HTTP server; this will accept connections from any client, and
+      serve up data for that repository until you terminate it.
+      Anyone who knows the URL of the server you just started, and can
+      talk to your computer over the network, can then use a web
+      browser or Mercurial to read data from that repository.  A URL
+      for a <command role="hg-cmd">hg serve</command> instance running
+      on a laptop is likely to look something like
+      <literal>http://my-laptop.local:8000/</literal>.</para>
+
+    <para>The <command role="hg-cmd">hg serve</command> command is
+      <emphasis>not</emphasis> a general-purpose web server. It can do
+      only two things:</para>
+    <itemizedlist>
+      <listitem><para>Allow people to browse the history of the
+	  repository it's serving, from their normal web
+	  browsers.</para>
+      </listitem>
+      <listitem><para>Speak Mercurial's wire protocol, so that people
+	  can <command role="hg-cmd">hg clone</command> or <command
+	    role="hg-cmd">hg pull</command> changes from that
+	  repository.</para>
+      </listitem></itemizedlist>
+    <para>In particular, <command role="hg-cmd">hg serve</command>
+      won't allow remote users to <emphasis>modify</emphasis> your
+      repository.  It's intended for read-only use.</para>
+
+    <para>If you're getting started with Mercurial, there's nothing to
+      prevent you from using <command role="hg-cmd">hg serve</command>
+      to serve up a repository on your own computer, then use commands
+      like <command role="hg-cmd">hg clone</command>, <command
+	role="hg-cmd">hg incoming</command>, and so on to talk to that
+      server as if the repository was hosted remotely. This can help
+      you to quickly get acquainted with using commands on
+      network-hosted repositories.</para>
+
+    <sect2>
+      <title>A few things to keep in mind</title>
+
+      <para>Because it provides unauthenticated read access to all
+	clients, you should only use <command role="hg-cmd">hg
+	  serve</command> in an environment where you either don't
+	care, or have complete control over, who can access your
+	network and pull data from your repository.</para>
+
+      <para>The <command role="hg-cmd">hg serve</command> command
+	knows nothing about any firewall software you might have
+	installed on your system or network.  It cannot detect or
+	control your firewall software.  If other people are unable to
+	talk to a running <command role="hg-cmd">hg serve</command>
+	instance, the second thing you should do
+	(<emphasis>after</emphasis> you make sure that they're using
+	the correct URL) is check your firewall configuration.</para>
+
+      <para>By default, <command role="hg-cmd">hg serve</command>
+	listens for incoming connections on port 8000.  If another
+	process is already listening on the port you want to use, you
+	can specify a different port to listen on using the <option
+	  role="hg-opt-serve">-p</option> option.</para>
+
+      <para>Normally, when <command role="hg-cmd">hg serve</command>
+	starts, it prints no output, which can be a bit unnerving.  If
+	you'd like to confirm that it is indeed running correctly, and
+	find out what URL you should send to your collaborators, start
+	it with the <option role="hg-opt-global">-v</option>
+	option.</para>
+
+    </sect2>
+  </sect1>
+  <sect1 id="sec.collab.ssh">
+    <title>Using the Secure Shell (ssh) protocol</title>
+
+    <para>You can pull and push changes securely over a network
+      connection using the Secure Shell (<literal>ssh</literal>)
+      protocol.  To use this successfully, you may have to do a little
+      bit of configuration on the client or server sides.</para>
+
+    <para>If you're not familiar with ssh, it's a network protocol
+      that lets you securely communicate with another computer.  To
+      use it with Mercurial, you'll be setting up one or more user
+      accounts on a server so that remote users can log in and execute
+      commands.</para>
+
+    <para>(If you <emphasis>are</emphasis> familiar with ssh, you'll
+      probably find some of the material that follows to be elementary
+      in nature.)</para>
+
+    <sect2>
+      <title>How to read and write ssh URLs</title>
+
+      <para>An ssh URL tends to look like this:</para>
+      <programlisting>ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting>
+      <orderedlist>
+	<listitem><para>The <quote><literal>ssh://</literal></quote>
+	    part tells Mercurial to use the ssh protocol.</para>
+	</listitem>
+	<listitem><para>The <quote><literal>bos@</literal></quote>
+	    component indicates what username to log into the server
+	    as.  You can leave this out if the remote username is the
+	    same as your local username.</para>
+	</listitem>
+	<listitem><para>The
+	    <quote><literal>hg.serpentine.com</literal></quote> gives
+	    the hostname of the server to log into.</para>
+	</listitem>
+	<listitem><para>The <quote>:22</quote> identifies the port
+	    number to connect to the server on.  The default port is
+	    22, so you only need to specify a colon and port number if
+	    you're <emphasis>not</emphasis> using port 22.</para>
+	</listitem>
+	<listitem><para>The remainder of the URL is the local path to
+	    the repository on the server.</para>
+	</listitem></orderedlist>
+
+      <para>There's plenty of scope for confusion with the path
+	component of ssh URLs, as there is no standard way for tools
+	to interpret it.  Some programs behave differently than others
+	when dealing with these paths. This isn't an ideal situation,
+	but it's unlikely to change.  Please read the following
+	paragraphs carefully.</para>
+
+      <para>Mercurial treats the path to a repository on the server as
+	relative to the remote user's home directory.  For example, if
+	user <literal>foo</literal> on the server has a home directory
+	of <filename class="directory">/home/foo</filename>, then an
+	ssh URL that contains a path component of <filename
+	  class="directory">bar</filename> <emphasis>really</emphasis>
+	refers to the directory <filename
+	  class="directory">/home/foo/bar</filename>.</para>
+
+      <para>If you want to specify a path relative to another user's
+	home directory, you can use a path that starts with a tilde
+	character followed by the user's name (let's call them
+	<literal>otheruser</literal>), like this.</para>
+      <programlisting>ssh://server/~otheruser/hg/repo</programlisting>
+
+      <para>And if you really want to specify an
+	<emphasis>absolute</emphasis> path on the server, begin the
+	path component with two slashes, as in this example.</para>
+      <programlisting>ssh://server//absolute/path</programlisting>
+
+    </sect2>
+    <sect2>
+      <title>Finding an ssh client for your system</title>
+
+      <para>Almost every Unix-like system comes with OpenSSH
+	preinstalled.  If you're using such a system, run
+	<literal>which ssh</literal> to find out if the
+	<command>ssh</command> command is installed (it's usually in
+	<filename class="directory">/usr/bin</filename>).  In the
+	unlikely event that it isn't present, take a look at your
+	system documentation to figure out how to install it.</para>
+
+      <para>On Windows, you'll first need to download a suitable ssh
+	client.  There are two alternatives.</para>
+      <itemizedlist>
+	<listitem><para>Simon Tatham's excellent PuTTY package
+	    <citation>web:putty</citation> provides a complete suite
+	    of ssh client commands.</para>
+	</listitem>
+	<listitem><para>If you have a high tolerance for pain, you can
+	    use the Cygwin port of OpenSSH.</para>
+	</listitem></itemizedlist>
+      <para>In either case, you'll need to edit your <filename
+      role="special">hg.ini</filename> file to
+	tell Mercurial where to find the actual client command.  For
+	example, if you're using PuTTY, you'll need to use the
+	<command>plink</command> command as a command-line ssh
+	client.</para>
+      <programlisting>[ui]
+ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key"</programlisting>
+
+      <note>
+	<para>  The path to <command>plink</command> shouldn't contain
+	  any whitespace characters, or Mercurial may not be able to
+	  run it correctly (so putting it in <filename
+	    class="directory">C:\Program Files</filename> is probably
+	  not a good idea).</para>
+      </note>
+
+    </sect2>
+    <sect2>
+      <title>Generating a key pair</title>
+
+      <para>To avoid the need to repetitively type a password every
+	time you need to use your ssh client, I recommend generating a
+	key pair.  On a Unix-like system, the
+	<command>ssh-keygen</command> command will do the trick. On
+	Windows, if you're using PuTTY, the
+	<command>puttygen</command> command is what you'll
+	need.</para>
+
+      <para>When you generate a key pair, it's usually
+	<emphasis>highly</emphasis> advisable to protect it with a
+	passphrase.  (The only time that you might not want to do this
+	is when you're using the ssh protocol for automated tasks on a
+	secure network.)</para>
+
+      <para>Simply generating a key pair isn't enough, however.
+	You'll need to add the public key to the set of authorised
+	keys for whatever user you're logging in remotely as.  For
+	servers using OpenSSH (the vast majority), this will mean
+	adding the public key to a list in a file called <filename
+	  role="special">authorized_keys</filename> in their <filename
+	  role="special" class="directory">.ssh</filename>
+	directory.</para>
+
+      <para>On a Unix-like system, your public key will have a
+	<filename>.pub</filename> extension.  If you're using
+	<command>puttygen</command> on Windows, you can save the
+	public key to a file of your choosing, or paste it from the
+	window it's displayed in straight into the <filename
+	  role="special">authorized_keys</filename> file.</para>
+
+    </sect2>
+    <sect2>
+      <title>Using an authentication agent</title>
+
+      <para>An authentication agent is a daemon that stores
+	passphrases in memory (so it will forget passphrases if you
+	log out and log back in again). An ssh client will notice if
+	it's running, and query it for a passphrase.  If there's no
+	authentication agent running, or the agent doesn't store the
+	necessary passphrase, you'll have to type your passphrase
+	every time Mercurial tries to communicate with a server on
+	your behalf (e.g. whenever you pull or push changes).</para>
+
+      <para>The downside of storing passphrases in an agent is that
+	it's possible for a well-prepared attacker to recover the
+	plain text of your passphrases, in some cases even if your
+	system has been power-cycled. You should make your own
+	judgment as to whether this is an acceptable risk.  It
+	certainly saves a lot of repeated typing.</para>
+
+      <para>On Unix-like systems, the agent is called
+	<command>ssh-agent</command>, and it's often run automatically
+	for you when you log in.  You'll need to use the
+	<command>ssh-add</command> command to add passphrases to the
+	agent's store.  On Windows, if you're using PuTTY, the
+	<command>pageant</command> command acts as the agent.  It adds
+	an icon to your system tray that will let you manage stored
+	passphrases.</para>
+
+    </sect2>
+    <sect2>
+      <title>Configuring the server side properly</title>
+
+      <para>Because ssh can be fiddly to set up if you're new to it,
+	there's a variety of things that can go wrong.  Add Mercurial
+	on top, and there's plenty more scope for head-scratching.
+	Most of these potential problems occur on the server side, not
+	the client side.  The good news is that once you've gotten a
+	configuration working, it will usually continue to work
+	indefinitely.</para>
+
+      <para>Before you try using Mercurial to talk to an ssh server,
+	it's best to make sure that you can use the normal
+	<command>ssh</command> or <command>putty</command> command to
+	talk to the server first.  If you run into problems with using
+	these commands directly, Mercurial surely won't work.  Worse,
+	it will obscure the underlying problem.  Any time you want to
+	debug ssh-related Mercurial problems, you should drop back to
+	making sure that plain ssh client commands work first,
+	<emphasis>before</emphasis> you worry about whether there's a
+	problem with Mercurial.</para>
+
+      <para>The first thing to be sure of on the server side is that
+	you can actually log in from another machine at all.  If you
+	can't use <command>ssh</command> or <command>putty</command>
+	to log in, the error message you get may give you a few hints
+	as to what's wrong.  The most common problems are as
+	follows.</para>
+      <itemizedlist>
+	<listitem><para>If you get a <quote>connection refused</quote>
+	    error, either there isn't an SSH daemon running on the
+	    server at all, or it's inaccessible due to firewall
+	    configuration.</para>
+	</listitem>
+	<listitem><para>If you get a <quote>no route to host</quote>
+	    error, you either have an incorrect address for the server
+	    or a seriously locked down firewall that won't admit its
+	    existence at all.</para>
+	</listitem>
+	<listitem><para>If you get a <quote>permission denied</quote>
+	    error, you may have mistyped the username on the server,
+	    or you could have mistyped your key's passphrase or the
+	    remote user's password.</para>
+	</listitem></itemizedlist>
+      <para>In summary, if you're having trouble talking to the
+	server's ssh daemon, first make sure that one is running at
+	all.  On many systems it will be installed, but disabled, by
+	default.  Once you're done with this step, you should then
+	check that the server's firewall is configured to allow
+	incoming connections on the port the ssh daemon is listening
+	on (usually 22).  Don't worry about more exotic possibilities
+	for misconfiguration until you've checked these two
+	first.</para>
+
+      <para>If you're using an authentication agent on the client side
+	to store passphrases for your keys, you ought to be able to
+	log into the server without being prompted for a passphrase or
+	a password.  If you're prompted for a passphrase, there are a
+	few possible culprits.</para>
+      <itemizedlist>
+	<listitem><para>You might have forgotten to use
+	    <command>ssh-add</command> or <command>pageant</command>
+	    to store the passphrase.</para>
+	</listitem>
+	<listitem><para>You might have stored the passphrase for the
+	    wrong key.</para>
+	</listitem></itemizedlist>
+      <para>If you're being prompted for the remote user's password,
+	there are another few possible problems to check.</para>
+      <itemizedlist>
+	<listitem><para>Either the user's home directory or their
+	    <filename role="special" class="directory">.ssh</filename>
+	    directory might have excessively liberal permissions.  As
+	    a result, the ssh daemon will not trust or read their
+	    <filename role="special">authorized_keys</filename> file.
+	    For example, a group-writable home or <filename
+	      role="special" class="directory">.ssh</filename>
+	    directory will often cause this symptom.</para>
+	</listitem>
+	<listitem><para>The user's <filename
+	      role="special">authorized_keys</filename> file may have
+	    a problem. If anyone other than the user owns or can write
+	    to that file, the ssh daemon will not trust or read
+	    it.</para>
+	</listitem></itemizedlist>
+
+      <para>In the ideal world, you should be able to run the
+	following command successfully, and it should print exactly
+	one line of output, the current date and time.</para>
+      <programlisting>ssh myserver date</programlisting>
+
+      <para>If, on your server, you have login scripts that print
+	banners or other junk even when running non-interactive
+	commands like this, you should fix them before you continue,
+	so that they only print output if they're run interactively.
+	Otherwise these banners will at least clutter up Mercurial's
+	output.  Worse, they could potentially cause problems with
+	running Mercurial commands remotely.  Mercurial makes tries to
+	detect and ignore banners in non-interactive
+	<command>ssh</command> sessions, but it is not foolproof.  (If
+	you're editing your login scripts on your server, the usual
+	way to see if a login script is running in an interactive
+	shell is to check the return code from the command
+	<literal>tty -s</literal>.)</para>
+
+      <para>Once you've verified that plain old ssh is working with
+	your server, the next step is to ensure that Mercurial runs on
+	the server.  The following command should run
+	successfully:</para>
+
+      <programlisting>ssh myserver hg version</programlisting>
+
+      <para>If you see an error message instead of normal <command
+	  role="hg-cmd">hg version</command> output, this is usually
+	because you haven't installed Mercurial to <filename
+	  class="directory">/usr/bin</filename>.  Don't worry if this
+	is the case; you don't need to do that.  But you should check
+	for a few possible problems.</para>
+      <itemizedlist>
+	<listitem><para>Is Mercurial really installed on the server at
+	    all?  I know this sounds trivial, but it's worth
+	    checking!</para>
+	</listitem>
+	<listitem><para>Maybe your shell's search path (usually set
+	    via the <envar>PATH</envar> environment variable) is
+	    simply misconfigured.</para>
+	</listitem>
+	<listitem><para>Perhaps your <envar>PATH</envar> environment
+	    variable is only being set to point to the location of the
+	    <command>hg</command> executable if the login session is
+	    interactive.  This can happen if you're setting the path
+	    in the wrong shell login script.  See your shell's
+	    documentation for details.</para>
+	</listitem>
+	<listitem><para>The <envar>PYTHONPATH</envar> environment
+	    variable may need to contain the path to the Mercurial
+	    Python modules.  It might not be set at all; it could be
+	    incorrect; or it may be set only if the login is
+	    interactive.</para>
+	</listitem></itemizedlist>
+
+      <para>If you can run <command role="hg-cmd">hg version</command>
+	over an ssh connection, well done! You've got the server and
+	client sorted out.  You should now be able to use Mercurial to
+	access repositories hosted by that username on that server.
+	If you run into problems with Mercurial and ssh at this point,
+	try using the <option role="hg-opt-global">--debug</option>
+	option to get a clearer picture of what's going on.</para>
+
+    </sect2>
+    <sect2>
+      <title>Using compression with ssh</title>
+
+      <para>Mercurial does not compress data when it uses the ssh
+	protocol, because the ssh protocol can transparently compress
+	data.  However, the default behaviour of ssh clients is
+	<emphasis>not</emphasis> to request compression.</para>
+
+      <para>Over any network other than a fast LAN (even a wireless
+	network), using compression is likely to significantly speed
+	up Mercurial's network operations.  For example, over a WAN,
+	someone measured compression as reducing the amount of time
+	required to clone a particularly large repository from 51
+	minutes to 17 minutes.</para>
+
+      <para>Both <command>ssh</command> and <command>plink</command>
+	accept a <option role="cmd-opt-ssh">-C</option> option which
+	turns on compression.  You can easily edit your <filename
+	  role="special">~/.hgrc</filename> to enable compression for
+	all of Mercurial's uses of the ssh protocol.</para>
+      <programlisting>[ui]
+ssh = ssh -C</programlisting>
+
+      <para>If you use <command>ssh</command>, you can configure it to
+	always use compression when talking to your server.  To do
+	this, edit your <filename
+	  role="special">.ssh/config</filename> file (which may not
+	yet exist), as follows.</para>
+      <programlisting>Host hg
+  Compression yes
+  HostName hg.example.com</programlisting>
+      <para>This defines an alias, <literal>hg</literal>.  When you
+	use it on the <command>ssh</command> command line or in a
+	Mercurial <literal>ssh</literal>-protocol URL, it will cause
+	<command>ssh</command> to connect to
+	<literal>hg.example.com</literal> and use compression.  This
+	gives you both a shorter name to type and compression, each of
+	which is a good thing in its own right.</para>
+
+    </sect2>
+  </sect1>
+  <sect1 id="sec.collab.cgi">
+    <title>Serving over HTTP using CGI</title>
+
+    <para>Depending on how ambitious you are, configuring Mercurial's
+      CGI interface can take anything from a few moments to several
+      hours.</para>
+
+    <para>We'll begin with the simplest of examples, and work our way
+      towards a more complex configuration.  Even for the most basic
+      case, you're almost certainly going to need to read and modify
+      your web server's configuration.</para>
+
+    <note>
+      <para>  Configuring a web server is a complex, fiddly, and
+	highly system-dependent activity.  I can't possibly give you
+	instructions that will cover anything like all of the cases
+	you will encounter. Please use your discretion and judgment in
+	following the sections below.  Be prepared to make plenty of
+	mistakes, and to spend a lot of time reading your server's
+	error logs.</para>
+    </note>
+
+    <sect2>
+      <title>Web server configuration checklist</title>
+
+      <para>Before you continue, do take a few moments to check a few
+	aspects of your system's setup.</para>
+
+      <orderedlist>
+	<listitem><para>Do you have a web server installed at all?
+	    Mac OS X ships with Apache, but many other systems may not
+	    have a web server installed.</para>
+	</listitem>
+	<listitem><para>If you have a web server installed, is it
+	    actually running?  On most systems, even if one is
+	    present, it will be disabled by default.</para>
+	</listitem>
+	<listitem><para>Is your server configured to allow you to run
+	    CGI programs in the directory where you plan to do so?
+	    Most servers default to explicitly disabling the ability
+	    to run CGI programs.</para>
+	</listitem></orderedlist>
+
+      <para>If you don't have a web server installed, and don't have
+	substantial experience configuring Apache, you should consider
+	using the <literal>lighttpd</literal> web server instead of
+	Apache.  Apache has a well-deserved reputation for baroque and
+	confusing configuration. While <literal>lighttpd</literal> is
+	less capable in some ways than Apache, most of these
+	capabilities are not relevant to serving Mercurial
+	repositories.  And <literal>lighttpd</literal> is undeniably
+	<emphasis>much</emphasis> easier to get started with than
+	Apache.</para>
+
+    </sect2>
+    <sect2>
+      <title>Basic CGI configuration</title>
+
+      <para>On Unix-like systems, it's common for users to have a
+	subdirectory named something like <filename
+	  class="directory">public_html</filename> in their home
+	directory, from which they can serve up web pages.  A file
+	named <filename>foo</filename> in this directory will be
+	accessible at a URL of the form
+	<literal>http://www.example.com/username/foo</literal>.</para>
+
+      <para>To get started, find the <filename
+	  role="special">hgweb.cgi</filename> script that should be
+	present in your Mercurial installation.  If you can't quickly
+	find a local copy on your system, simply download one from the
+	master Mercurial repository at <ulink
+	  url="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>.</para>
+
+      <para>You'll need to copy this script into your <filename
+	  class="directory">public_html</filename> directory, and
+	ensure that it's executable.</para>
+      <programlisting>cp .../hgweb.cgi ~/public_html
+chmod 755 ~/public_html/hgweb.cgi</programlisting>
+      <para>The <literal>755</literal> argument to
+	<command>chmod</command> is a little more general than just
+	making the script executable: it ensures that the script is
+	executable by anyone, and that <quote>group</quote> and
+	<quote>other</quote> write permissions are
+	<emphasis>not</emphasis> set.  If you were to leave those
+	write permissions enabled, Apache's <literal>suexec</literal>
+	subsystem would likely refuse to execute the script.  In fact,
+	<literal>suexec</literal> also insists that the
+	<emphasis>directory</emphasis> in which the script resides
+	must not be writable by others.</para>
+      <programlisting>chmod 755 ~/public_html</programlisting>
+
+      <sect3 id="sec.collab.wtf">
+	<title>What could <emphasis>possibly</emphasis> go
+	  wrong?</title>
+
+	<para>Once you've copied the CGI script into place, go into a
+	  web browser, and try to open the URL <ulink
+	    url="http://myhostname/
+	    myuser/hgweb.cgi">http://myhostname/
+	    myuser/hgweb.cgi</ulink>, <emphasis>but</emphasis> brace
+	  yourself for instant failure.  There's a high probability
+	  that trying to visit this URL will fail, and there are many
+	  possible reasons for this.  In fact, you're likely to
+	  stumble over almost every one of the possible errors below,
+	  so please read carefully.  The following are all of the
+	  problems I ran into on a system running Fedora 7, with a
+	  fresh installation of Apache, and a user account that I
+	  created specially to perform this exercise.</para>
+
+	<para>Your web server may have per-user directories disabled.
+	  If you're using Apache, search your config file for a
+	  <literal>UserDir</literal> directive.  If there's none
+	  present, per-user directories will be disabled.  If one
+	  exists, but its value is <literal>disabled</literal>, then
+	  per-user directories will be disabled.  Otherwise, the
+	  string after <literal>UserDir</literal> gives the name of
+	  the subdirectory that Apache will look in under your home
+	  directory, for example <filename
+	    class="directory">public_html</filename>.</para>
+
+	<para>Your file access permissions may be too restrictive.
+	  The web server must be able to traverse your home directory
+	  and directories under your <filename
+	    class="directory">public_html</filename> directory, and
+	  read files under the latter too.  Here's a quick recipe to
+	  help you to make your permissions more appropriate.</para>
+	<programlisting>chmod 755 ~
+find ~/public_html -type d -print0 | xargs -0r chmod 755
+find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting>
+
+	<para>The other possibility with permissions is that you might
+	  get a completely empty window when you try to load the
+	  script.  In this case, it's likely that your access
+	  permissions are <emphasis>too permissive</emphasis>.  Apache's
+	  <literal>suexec</literal> subsystem won't execute a script
+	  that's group- or world-writable, for example.</para>
+
+	<para>Your web server may be configured to disallow execution
+	  of CGI programs in your per-user web directory.  Here's
+	  Apache's default per-user configuration from my Fedora
+	  system.</para>
+
+	<programlisting><![CDATA[&ch06-apache-config.lst;]]></programlisting>
+
+	<para>If you find a similar-looking
+	  <literal>Directory</literal> group in your Apache
+	  configuration, the directive to look at inside it is
+	  <literal>Options</literal>. Add <literal>ExecCGI</literal>
+	  to the end of this list if it's missing, and restart the web
+	  server.</para>
+
+	<para>If you find that Apache serves you the text of the CGI
+	  script instead of executing it, you may need to either
+	  uncomment (if already present) or add a directive like
+	  this.</para>
+	<programlisting>AddHandler cgi-script .cgi</programlisting>
+
+	<para>The next possibility is that you might be served with a
+	  colourful Python backtrace claiming that it can't import a
+	  <literal>mercurial</literal>-related module.  This is
+	  actually progress!  The server is now capable of executing
+	  your CGI script.  This error is only likely to occur if
+	  you're running a private installation of Mercurial, instead
+	  of a system-wide version.  Remember that the web server runs
+	  the CGI program without any of the environment variables
+	  that you take for granted in an interactive session.  If
+	  this error happens to you, edit your copy of <filename
+	    role="special">hgweb.cgi</filename> and follow the
+	  directions inside it to correctly set your
+	  <envar>PYTHONPATH</envar> environment variable.</para>
+
+	<para>Finally, you are <emphasis>certain</emphasis> to by
+	  served with another colourful Python backtrace: this one
+	  will complain that it can't find <filename
+	    class="directory">/path/to/repository</filename>.  Edit
+	  your <filename role="special">hgweb.cgi</filename> script
+	  and replace the <filename
+	    class="directory">/path/to/repository</filename> string
+	  with the complete path to the repository you want to serve
+	  up.</para>
+
+	<para>At this point, when you try to reload the page, you
+	  should be presented with a nice HTML view of your
+	  repository's history.  Whew!</para>
+
+      </sect3>
+      <sect3>
+	<title>Configuring lighttpd</title>
+
+	<para>To be exhaustive in my experiments, I tried configuring
+	  the increasingly popular <literal>lighttpd</literal> web
+	  server to serve the same repository as I described with
+	  Apache above.  I had already overcome all of the problems I
+	  outlined with Apache, many of which are not server-specific.
+	  As a result, I was fairly sure that my file and directory
+	  permissions were good, and that my <filename
+	    role="special">hgweb.cgi</filename> script was properly
+	  edited.</para>
+
+	<para>Once I had Apache running, getting
+	  <literal>lighttpd</literal> to serve the repository was a
+	  snap (in other words, even if you're trying to use
+	  <literal>lighttpd</literal>, you should read the Apache
+	  section).  I first had to edit the
+	  <literal>mod_access</literal> section of its config file to
+	  enable <literal>mod_cgi</literal> and
+	  <literal>mod_userdir</literal>, both of which were disabled
+	  by default on my system.  I then added a few lines to the
+	  end of the config file, to configure these modules.</para>
+	<programlisting>userdir.path = "public_html"
+cgi.assign = (".cgi" =&gt; "" )</programlisting>
+	<para>With this done, <literal>lighttpd</literal> ran
+	  immediately for me.  If I had configured
+	  <literal>lighttpd</literal> before Apache, I'd almost
+	  certainly have run into many of the same system-level
+	  configuration problems as I did with Apache.  However, I
+	  found <literal>lighttpd</literal> to be noticeably easier to
+	  configure than Apache, even though I've used Apache for over
+	  a decade, and this was my first exposure to
+	  <literal>lighttpd</literal>.</para>
+
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Sharing multiple repositories with one CGI script</title>
+
+      <para>The <filename role="special">hgweb.cgi</filename> script
+	only lets you publish a single repository, which is an
+	annoying restriction.  If you want to publish more than one
+	without wracking yourself with multiple copies of the same
+	script, each with different names, a better choice is to use
+	the <filename role="special">hgwebdir.cgi</filename>
+	script.</para>
+
+      <para>The procedure to configure <filename
+	  role="special">hgwebdir.cgi</filename> is only a little more
+	involved than for <filename
+	  role="special">hgweb.cgi</filename>.  First, you must obtain
+	a copy of the script.  If you don't have one handy, you can
+	download a copy from the master Mercurial repository at <ulink
+	  url="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>.</para>
+
+      <para>You'll need to copy this script into your <filename
+	  class="directory">public_html</filename> directory, and
+	ensure that it's executable.</para>
+      <programlisting>cp .../hgwebdir.cgi ~/public_html
+chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting>
+      <para>With basic configuration out of the way, try to visit
+	<ulink url="http://myhostname/
+	  myuser/hgwebdir.cgi">http://myhostname/
+	  myuser/hgwebdir.cgi</ulink> in your browser.  It should
+	display an empty list of repositories.  If you get a blank
+	window or error message, try walking through the list of
+	potential problems in section <xref
+	  linkend="sec.collab.wtf"/>.</para>
+
+      <para>The <filename role="special">hgwebdir.cgi</filename>
+	script relies on an external configuration file.  By default,
+	it searches for a file named <filename
+	  role="special">hgweb.config</filename> in the same directory
+	as itself.  You'll need to create this file, and make it
+	world-readable.  The format of the file is similar to a
+	Windows <quote>ini</quote> file, as understood by Python's
+	<literal>ConfigParser</literal>
+	<citation>web:configparser</citation> module.</para>
+
+      <para>The easiest way to configure <filename
+	  role="special">hgwebdir.cgi</filename> is with a section
+	named <literal>collections</literal>.  This will automatically
+	publish <emphasis>every</emphasis> repository under the
+	directories you name.  The section should look like
+	this:</para>
+      <programlisting>[collections]
+/my/root = /my/root</programlisting>
+      <para>Mercurial interprets this by looking at the directory name
+	on the <emphasis>right</emphasis> hand side of the
+	<quote><literal>=</literal></quote> sign; finding repositories
+	in that directory hierarchy; and using the text on the
+	<emphasis>left</emphasis> to strip off matching text from the
+	names it will actually list in the web interface.  The
+	remaining component of a path after this stripping has
+	occurred is called a <quote>virtual path</quote>.</para>
+
+      <para>Given the example above, if we have a repository whose
+	local path is <filename
+	  class="directory">/my/root/this/repo</filename>, the CGI
+	script will strip the leading <filename
+	  class="directory">/my/root</filename> from the name, and
+	publish the repository with a virtual path of <filename
+	  class="directory">this/repo</filename>.  If the base URL for
+	our CGI script is <ulink url="http://myhostname/
+	  myuser/hgwebdir.cgi">http://myhostname/
+	  myuser/hgwebdir.cgi</ulink>, the complete URL for that
+	repository will be <ulink url="http://myhostname/
+	  myuser/hgwebdir.cgi/this/repo">http://myhostname/
+	  myuser/hgwebdir.cgi/this/repo</ulink>.</para>
+
+      <para>If we replace <filename
+	  class="directory">/my/root</filename> on the left hand side
+	of this example with <filename
+	  class="directory">/my</filename>, then <filename
+	  role="special">hgwebdir.cgi</filename> will only strip off
+	<filename class="directory">/my</filename> from the repository
+	name, and will give us a virtual path of <filename
+	  class="directory">root/this/repo</filename> instead of
+	<filename class="directory">this/repo</filename>.</para>
+
+      <para>The <filename role="special">hgwebdir.cgi</filename>
+	script will recursively search each directory listed in the
+	<literal>collections</literal> section of its configuration
+	file, but it will <literal>not</literal> recurse into the
+	repositories it finds.</para>
+
+      <para>The <literal>collections</literal> mechanism makes it easy
+	to publish many repositories in a <quote>fire and
+	  forget</quote> manner.  You only need to set up the CGI
+	script and configuration file one time.  Afterwards, you can
+	publish or unpublish a repository at any time by simply moving
+	it into, or out of, the directory hierarchy in which you've
+	configured <filename role="special">hgwebdir.cgi</filename> to
+	look.</para>
+
+      <sect3>
+	<title>Explicitly specifying which repositories to
+	  publish</title>
+
+	<para>In addition to the <literal>collections</literal>
+	  mechanism, the <filename
+	    role="special">hgwebdir.cgi</filename> script allows you
+	  to publish a specific list of repositories.  To do so,
+	  create a <literal>paths</literal> section, with contents of
+	  the following form.</para>
+	<programlisting>[paths]
+repo1 = /my/path/to/some/repo
+repo2 = /some/path/to/another</programlisting>
+	<para>In this case, the virtual path (the component that will
+	  appear in a URL) is on the left hand side of each
+	  definition, while the path to the repository is on the
+	  right.  Notice that there does not need to be any
+	  relationship between the virtual path you choose and the
+	  location of a repository in your filesystem.</para>
+
+	<para>If you wish, you can use both the
+	  <literal>collections</literal> and <literal>paths</literal>
+	  mechanisms simultaneously in a single configuration
+	  file.</para>
+
+	<note>
+	  <para>  If multiple repositories have the same virtual path,
+	    <filename role="special">hgwebdir.cgi</filename> will not
+	    report an error.  Instead, it will behave
+	    unpredictably.</para>
+	</note>
+
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Downloading source archives</title>
+
+      <para>Mercurial's web interface lets users download an archive
+	of any revision.  This archive will contain a snapshot of the
+	working directory as of that revision, but it will not contain
+	a copy of the repository data.</para>
+
+      <para>By default, this feature is not enabled.  To enable it,
+	you'll need to add an <envar
+	  role="rc-item-web">allow_archive</envar> item to the
+	<literal role="rc-web">web</literal> section of your <filename
+	  role="special">~/.hgrc</filename>.</para>
+
+    </sect2>
+    <sect2>
+      <title>Web configuration options</title>
+
+      <para>Mercurial's web interfaces (the <command role="hg-cmd">hg
+	  serve</command> command, and the <filename
+	  role="special">hgweb.cgi</filename> and <filename
+	  role="special">hgwebdir.cgi</filename> scripts) have a
+	number of configuration options that you can set.  These
+	belong in a section named <literal
+	  role="rc-web">web</literal>.</para>
+      <itemizedlist>
+	<listitem><para><envar
+	      role="rc-item-web">allow_archive</envar>: Determines
+	    which (if any) archive download mechanisms Mercurial
+	    supports.  If you enable this feature, users of the web
+	    interface will be able to download an archive of whatever
+	    revision of a repository they are viewing. To enable the
+	    archive feature, this item must take the form of a
+	    sequence of words drawn from the list below.</para>
+	  <itemizedlist>
+	    <listitem><para><literal>bz2</literal>: A
+		<command>tar</command> archive, compressed using
+		<literal>bzip2</literal> compression.  This has the
+		best compression ratio, but uses the most CPU time on
+		the server.</para>
+	    </listitem>
+	    <listitem><para><literal>gz</literal>: A
+		<command>tar</command> archive, compressed using
+		<literal>gzip</literal> compression.</para>
+	    </listitem>
+	    <listitem><para><literal>zip</literal>: A
+		<command>zip</command> archive, compressed using LZW
+		compression.  This format has the worst compression
+		ratio, but is widely used in the Windows world.</para>
+	    </listitem>
+	  </itemizedlist>
+	  <para>  If you provide an empty list, or don't have an
+	    <envar role="rc-item-web">allow_archive</envar> entry at
+	    all, this feature will be disabled.  Here is an example of
+	    how to enable all three supported formats.</para>
+	  <programlisting>[web]
+allow_archive = bz2 gz zip</programlisting>
+	</listitem>
+	<listitem><para><envar role="rc-item-web">allowpull</envar>:
+	    Boolean.  Determines whether the web interface allows
+	    remote users to <command role="hg-cmd">hg pull</command>
+	    and <command role="hg-cmd">hg clone</command> this
+	    repository over HTTP.  If set to <literal>no</literal> or
+	    <literal>false</literal>, only the
+	    <quote>human-oriented</quote> portion of the web interface
+	    is available.</para>
+	</listitem>
+	<listitem><para><envar role="rc-item-web">contact</envar>:
+	    String.  A free-form (but preferably brief) string
+	    identifying the person or group in charge of the
+	    repository.  This often contains the name and email
+	    address of a person or mailing list.  It often makes sense
+	    to place this entry in a repository's own <filename
+	      role="special">.hg/hgrc</filename> file, but it can make
+	    sense to use in a global <filename
+	      role="special">~/.hgrc</filename> if every repository
+	    has a single maintainer.</para>
+	</listitem>
+	<listitem><para><envar role="rc-item-web">maxchanges</envar>:
+	    Integer.  The default maximum number of changesets to
+	    display in a single page of output.</para>
+	</listitem>
+	<listitem><para><envar role="rc-item-web">maxfiles</envar>:
+	    Integer.  The default maximum number of modified files to
+	    display in a single page of output.</para>
+	</listitem>
+	<listitem><para><envar role="rc-item-web">stripes</envar>:
+	    Integer.  If the web interface displays alternating
+	    <quote>stripes</quote> to make it easier to visually align
+	    rows when you are looking at a table, this number controls
+	    the number of rows in each stripe.</para>
+	</listitem>
+	<listitem><para><envar role="rc-item-web">style</envar>:
+	    Controls the template Mercurial uses to display the web
+	    interface.  Mercurial ships with two web templates, named
+	    <literal>default</literal> and <literal>gitweb</literal>
+	    (the latter is much more visually attractive).  You can
+	    also specify a custom template of your own; see chapter
+	    <xref linkend="chap.template"/> for details.
+	    Here, you can see how to enable the
+	    <literal>gitweb</literal> style.</para>
+	  <programlisting>[web]
+style = gitweb</programlisting>
+	</listitem>
+	<listitem><para><envar role="rc-item-web">templates</envar>:
+	    Path.  The directory in which to search for template
+	    files.  By default, Mercurial searches in the directory in
+	    which it was installed.</para>
+	</listitem></itemizedlist>
+      <para>If you are using <filename
+	  role="special">hgwebdir.cgi</filename>, you can place a few
+	configuration items in a <literal role="rc-web">web</literal>
+	section of the <filename
+	  role="special">hgweb.config</filename> file instead of a
+	<filename role="special">~/.hgrc</filename> file, for
+	convenience.  These items are <envar
+	  role="rc-item-web">motd</envar> and <envar
+	  role="rc-item-web">style</envar>.</para>
+
+      <sect3>
+	<title>Options specific to an individual repository</title>
+
+	<para>A few <literal role="rc-web">web</literal> configuration
+	  items ought to be placed in a repository's local <filename
+	    role="special">.hg/hgrc</filename>, rather than a user's
+	  or global <filename role="special">~/.hgrc</filename>.</para>
+	<itemizedlist>
+	  <listitem><para><envar
+		role="rc-item-web">description</envar>: String.  A
+	      free-form (but preferably brief) string that describes
+	      the contents or purpose of the repository.</para>
+	  </listitem>
+	  <listitem><para><envar role="rc-item-web">name</envar>:
+	      String.  The name to use for the repository in the web
+	      interface.  This overrides the default name, which is
+	      the last component of the repository's path.</para>
+	  </listitem></itemizedlist>
+
+      </sect3>
+      <sect3>
+	<title>Options specific to the <command role="hg-cmd">hg
+	    serve</command> command</title>
+
+	<para>Some of the items in the <literal
+	    role="rc-web">web</literal> section of a <filename
+	    role="special">~/.hgrc</filename> file are only for use
+	  with the <command role="hg-cmd">hg serve</command>
+	  command.</para>
+	<itemizedlist>
+	  <listitem><para><envar role="rc-item-web">accesslog</envar>:
+	      Path.  The name of a file into which to write an access
+	      log.  By default, the <command role="hg-cmd">hg
+		serve</command> command writes this information to
+	      standard output, not to a file.  Log entries are written
+	      in the standard <quote>combined</quote> file format used
+	      by almost all web servers.</para>
+	  </listitem>
+	  <listitem><para><envar role="rc-item-web">address</envar>:
+	      String.  The local address on which the server should
+	      listen for incoming connections.  By default, the server
+	      listens on all addresses.</para>
+	  </listitem>
+	  <listitem><para><envar role="rc-item-web">errorlog</envar>:
+	      Path.  The name of a file into which to write an error
+	      log.  By default, the <command role="hg-cmd">hg
+		serve</command> command writes this information to
+	      standard error, not to a file.</para>
+	  </listitem>
+	  <listitem><para><envar role="rc-item-web">ipv6</envar>:
+	      Boolean.  Whether to use the IPv6 protocol. By default,
+	      IPv6 is not used.</para>
+	  </listitem>
+	  <listitem><para><envar role="rc-item-web">port</envar>:
+	      Integer.  The TCP port number on which the server should
+	      listen.  The default port number used is 8000.</para>
+	  </listitem></itemizedlist>
+
+      </sect3>
+      <sect3>
+	<title>Choosing the right <filename
+	    role="special">~/.hgrc</filename> file to add <literal
+	    role="rc-web">web</literal> items to</title>
+
+	<para>It is important to remember that a web server like
+	  Apache or <literal>lighttpd</literal> will run under a user
+	  ID that is different to yours. CGI scripts run by your
+	  server, such as <filename
+	    role="special">hgweb.cgi</filename>, will usually also run
+	  under that user ID.</para>
+
+	<para>If you add <literal role="rc-web">web</literal> items to
+	  your own personal <filename role="special">~/.hgrc</filename> file, CGI scripts won't read that
+	  <filename role="special">~/.hgrc</filename> file.  Those
+	  settings will thus only affect the behaviour of the <command
+	    role="hg-cmd">hg serve</command> command when you run it.
+	  To cause CGI scripts to see your settings, either create a
+	  <filename role="special">~/.hgrc</filename> file in the
+	  home directory of the user ID that runs your web server, or
+	  add those settings to a system-wide <filename
+	    role="special">~/.hgrc</filename> file.</para>
+
+
+      </sect3>
+    </sect2>
+  </sect1>
+</chapter>
+
+<!--
+local variables: 
+sgml-parent-document: ("00book.xml" "book" "chapter")
+end:
+-->