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