rev |
line source |
igor@412
|
1 \chapter{Colaborar con otros}
|
igor@402
|
2 \label{cha:collab}
|
igor@402
|
3
|
igor@412
|
4 Debido a su naturaleza descentralizada, Mercurial no impone política
|
igor@412
|
5 alguna de cómo deben trabajar los grupos de personas. Sin embargo, si
|
jerojasro@414
|
6 usted es nuevo al control distribuido de versiones, es bueno tener
|
igor@412
|
7 herramientas y ejemplos a la mano al pensar en posibles modelos de
|
igor@412
|
8 flujo de trabajo.
|
igor@412
|
9
|
igor@412
|
10 \section{La interfaz web de Mercurial}
|
igor@412
|
11
|
igor@412
|
12 Mercurial tiene una poderosa interfaz web que provee bastantes
|
igor@412
|
13 capacidades útiles.
|
igor@412
|
14
|
igor@412
|
15 Para uso interactivo, la interfaz le permite visualizar uno o varios
|
igor@412
|
16 repositorios. Puede ver la historia de un repositorio, examinar cada
|
igor@412
|
17 cambio(comentarios y diferencias), y ver los contenidos de cada
|
igor@412
|
18 directorio y fichero.
|
igor@412
|
19
|
igor@412
|
20 Adicionalmente la interfaz provee feeds de RSS de los cambios de los
|
igor@412
|
21 repositorios. Que le permite ``subscribirse''a un repositorio usando
|
igor@412
|
22 su herramienta de lectura de feeds favorita, y ser notificado
|
igor@412
|
23 automáticamente de la actividad en el repositorio tan pronto como
|
igor@412
|
24 sucede. Me gusta mucho más este modelo que el estar suscrito a una
|
igor@412
|
25 lista de correo a la cual se envían las notificaciones, dado que no
|
igor@412
|
26 requiere configuración adicional de parte de quien sea que está
|
igor@412
|
27 administrando el repositorio.
|
igor@412
|
28
|
igor@412
|
29 La interfaz web también permite clonar repositorios a los usuarios
|
igor@412
|
30 remotos, jalar cambios, y (cuando el servidor está configurado para
|
igor@412
|
31 permitirlo) publicar cambios en el mismo. El protocolo de tunneling
|
igor@412
|
32 de Mercurial comprime datos agresivamente, de forma que trabaja
|
igor@412
|
33 eficientemente incluso con conexiones de red con poco ancho de banda.
|
igor@412
|
34
|
igor@412
|
35 La forma más sencilla de iniciarse con la interfaz web es usar su
|
igor@412
|
36 navegador para visitar un repositorio existente, como por ejemplo el
|
igor@412
|
37 repositorio principal de Mercurial \url{http://www.selenic.com/repo/hg?style=gitweb}.
|
igor@412
|
38
|
igor@412
|
39 Si está interesado en proveer una interfaz web a sus propios
|
igor@412
|
40 repositorios, Mercurial provee dos formas de hacerlo. La primera es
|
igor@412
|
41 usando la orden \hgcmd{serve}, que está enfocada a servir ``de forma
|
igor@412
|
42 liviana'' y por intervalos cortos. Para más detalles de cómo usar
|
igor@412
|
43 esta orden vea la sección~\ref{sec:collab:serve} más adelante. Si
|
igor@412
|
44 tiene un repositorio que desea hacer permanente, Mercurial tiene
|
igor@412
|
45 soporte embebido del \command{ssh} para publicar cambios con seguridad
|
igor@412
|
46 al repositorio central, como se documenta en la
|
igor@412
|
47 sección~\ref{sec:collab:ssh}. Es muy usual que se publique una copia
|
igor@412
|
48 de sólo lectura en el repositorio que está corriendo sobre HTTP usando
|
igor@412
|
49 CGI, como en la sección~\ref{sec:collab:cgi}. Publicar sobre HTTP
|
igor@412
|
50 satisface las necesidades de la gente que no tiene permisos de
|
igor@412
|
51 publicación y de aquellos que quieren usar navegadores web para
|
igor@412
|
52 visualizar la historia del repositorio.
|
igor@412
|
53
|
igor@412
|
54 \subsection{Trabajo con muchas ramas}
|
igor@412
|
55
|
igor@412
|
56 Los proyectos de cierta talla tienden naturlamente a progresar de
|
igor@412
|
57 forma simultánea en varios frentes. En el caso del software, es común
|
igor@412
|
58 que un proyecto tenga versiones periódicas oficiales. Una versión
|
igor@412
|
59 puede entrar a ``modo mantenimiento'' por un tiempo después de su
|
igor@412
|
60 primera publicación; las versiones de mantenimiento tienden a contener
|
igor@412
|
61 solamente arreglos de fallos, pero no nuevas características. En
|
igor@412
|
62 paralelo con las versiones de mantenimiento puede haber una o muchas
|
igor@412
|
63 versiones futuras pueden estar en desarrollo. La gente usa normalmente
|
igor@412
|
64 la palabra ``rama'' para referirse a una de las direcciones
|
igor@412
|
65 ligeramente distintas en las cuales procede el desarrollo.
|
igor@412
|
66
|
igor@412
|
67 Mercurial está especialmente preparado para administrar un buen número
|
igor@412
|
68 de ramas simultáneas pero no idénticas. Cada ``dirección de
|
igor@412
|
69 desarrollo'' puede vivir en su propio repositorio central, y puede
|
igor@412
|
70 mezclar los cambios de una a otra de acuerdo con las necesidades. Dado
|
igor@412
|
71 que los repositorios son independientes, uno del otro, los cambios
|
igor@412
|
72 inestables de una rama de desarrollo nunca afectarán una rama estable
|
igor@412
|
73 a menos que alguien explícitamente mezcle los cambios.
|
igor@412
|
74
|
igor@412
|
75 A continuación un ejemplo de cómo podría hacerse esto en la
|
igor@412
|
76 práctica. Digamos que tiene una ``rama principal'' en un servidor
|
igor@412
|
77 central.
|
igor@402
|
78 \interaction{branching.init}
|
igor@412
|
79 Alguien lo clona, hace cambios locales, los prueba, y los publica allí
|
igor@412
|
80 mismo.
|
igor@412
|
81
|
igor@412
|
82 Una vez que la rama principal alcanza una estado de versión se puede
|
igor@412
|
83 usar la orden \hgcmd{tag} para dar un nombre permanente a la revisión.
|
igor@402
|
84 \interaction{branching.tag}
|
igor@412
|
85 Digamos que en la rama principal ocurre más desarrollo.
|
igor@402
|
86 \interaction{branching.main}
|
igor@412
|
87 Cuando se usa la etiqueta con que se identificó la versión, la gente
|
igor@412
|
88 puede clonar el repositorio en cualquier momento en el futuro
|
igor@412
|
89 empleando \hgcmd{update} para obtener una copia del directorio de
|
igor@412
|
90 trabajo exacta como cuando se creó la etiqueta de la revisión que se
|
igor@412
|
91 consignó.
|
igor@402
|
92 \interaction{branching.update}
|
igor@402
|
93
|
igor@412
|
94 Adicionalmente, justo después de que la rama principal se etiquete,
|
igor@412
|
95 alguien puede clonarla en el servidor a una nueva rama ``estable'',
|
igor@412
|
96 también en el servidor.
|
igor@402
|
97 \interaction{branching.clone}
|
igor@402
|
98
|
igor@412
|
99 Alguien que requiera hacer un cambio en la rama estable puede clonar
|
igor@412
|
100 \emph{ese} repositorio, hacer sus cambios, consignar y publicarlos
|
igor@412
|
101 posteriormente al inicial.
|
igor@402
|
102 \interaction{branching.stable}
|
igor@412
|
103 Puesto que los repositorios de Mercurial son independientes, y que
|
igor@412
|
104 Mercurial no mueve los cambios de un lado a otro automáticamente, las
|
igor@412
|
105 ramas estable y principal están \emph{aisladas} la una de la otra.
|
igor@412
|
106 Los cambios que haga en la rama principal no ``se filtran'' a la rama
|
igor@412
|
107 estable o vice versa.
|
igor@412
|
108
|
igor@412
|
109 Es usual que los arreglos de fallos de la rama estable deban hacerse
|
igor@412
|
110 aparecer en la rama principal también. En lugar de reescribir el
|
igor@412
|
111 arreglo del fallo en la rama principal, puede jalar y mezclar los
|
igor@412
|
112 cambios de la rama estable a la principal, Mercurial traerá tales
|
igor@412
|
113 arreglos por usted.
|
igor@402
|
114 \interaction{branching.merge}
|
igor@412
|
115 La rama principal contendtrá aún los cambios que no están en la
|
igor@412
|
116 estable y contendrá además todos los arreglos de fallos de la rama
|
igor@412
|
117 estable. La rama estable permanece incólume a tales cambios.
|
igor@402
|
118
|
igor@402
|
119 \subsection{Feature branches}
|
igor@402
|
120
|
igor@402
|
121 For larger projects, an effective way to manage change is to break up
|
igor@402
|
122 a team into smaller groups. Each group has a shared branch of its
|
igor@402
|
123 own, cloned from a single ``master'' branch used by the entire
|
igor@402
|
124 project. People working on an individual branch are typically quite
|
igor@402
|
125 isolated from developments on other branches.
|
igor@402
|
126
|
igor@402
|
127 \begin{figure}[ht]
|
igor@402
|
128 \centering
|
igor@402
|
129 \grafix{feature-branches}
|
igor@402
|
130 \caption{Feature branches}
|
igor@402
|
131 \label{fig:collab:feature-branches}
|
igor@402
|
132 \end{figure}
|
igor@402
|
133
|
igor@402
|
134 When a particular feature is deemed to be in suitable shape, someone
|
igor@402
|
135 on that feature team pulls and merges from the master branch into the
|
igor@402
|
136 feature branch, then pushes back up to the master branch.
|
igor@402
|
137
|
igor@402
|
138 \subsection{The release train}
|
igor@402
|
139
|
igor@402
|
140 Some projects are organised on a ``train'' basis: a release is
|
igor@402
|
141 scheduled to happen every few months, and whatever features are ready
|
igor@402
|
142 when the ``train'' is ready to leave are allowed in.
|
igor@402
|
143
|
igor@402
|
144 This model resembles working with feature branches. The difference is
|
igor@402
|
145 that when a feature branch misses a train, someone on the feature team
|
igor@402
|
146 pulls and merges the changes that went out on that train release into
|
igor@402
|
147 the feature branch, and the team continues its work on top of that
|
igor@402
|
148 release so that their feature can make the next release.
|
igor@402
|
149
|
igor@402
|
150 \subsection{The Linux kernel model}
|
igor@402
|
151
|
igor@402
|
152 The development of the Linux kernel has a shallow hierarchical
|
igor@402
|
153 structure, surrounded by a cloud of apparent chaos. Because most
|
igor@402
|
154 Linux developers use \command{git}, a distributed revision control
|
igor@402
|
155 tool with capabilities similar to Mercurial, it's useful to describe
|
igor@402
|
156 the way work flows in that environment; if you like the ideas, the
|
igor@402
|
157 approach translates well across tools.
|
igor@402
|
158
|
igor@402
|
159 At the center of the community sits Linus Torvalds, the creator of
|
igor@402
|
160 Linux. He publishes a single source repository that is considered the
|
igor@402
|
161 ``authoritative'' current tree by the entire developer community.
|
igor@402
|
162 Anyone can clone Linus's tree, but he is very choosy about whose trees
|
igor@402
|
163 he pulls from.
|
igor@402
|
164
|
igor@402
|
165 Linus has a number of ``trusted lieutenants''. As a general rule, he
|
igor@402
|
166 pulls whatever changes they publish, in most cases without even
|
igor@402
|
167 reviewing those changes. Some of those lieutenants are generally
|
igor@402
|
168 agreed to be ``maintainers'', responsible for specific subsystems
|
igor@402
|
169 within the kernel. If a random kernel hacker wants to make a change
|
igor@402
|
170 to a subsystem that they want to end up in Linus's tree, they must
|
igor@402
|
171 find out who the subsystem's maintainer is, and ask that maintainer to
|
igor@402
|
172 take their change. If the maintainer reviews their changes and agrees
|
igor@402
|
173 to take them, they'll pass them along to Linus in due course.
|
igor@402
|
174
|
igor@402
|
175 Individual lieutenants have their own approaches to reviewing,
|
igor@402
|
176 accepting, and publishing changes; and for deciding when to feed them
|
igor@402
|
177 to Linus. In addition, there are several well known branches that
|
igor@402
|
178 people use for different purposes. For example, a few people maintain
|
igor@402
|
179 ``stable'' repositories of older versions of the kernel, to which they
|
igor@402
|
180 apply critical fixes as needed. Some maintainers publish multiple
|
igor@402
|
181 trees: one for experimental changes; one for changes that they are
|
igor@402
|
182 about to feed upstream; and so on. Others just publish a single
|
igor@402
|
183 tree.
|
igor@402
|
184
|
igor@402
|
185 This model has two notable features. The first is that it's ``pull
|
igor@402
|
186 only''. You have to ask, convince, or beg another developer to take a
|
igor@402
|
187 change from you, because there are almost no trees to which more than
|
igor@402
|
188 one person can push, and there's no way to push changes into a tree
|
igor@402
|
189 that someone else controls.
|
igor@402
|
190
|
igor@402
|
191 The second is that it's based on reputation and acclaim. If you're an
|
igor@402
|
192 unknown, Linus will probably ignore changes from you without even
|
igor@402
|
193 responding. But a subsystem maintainer will probably review them, and
|
igor@402
|
194 will likely take them if they pass their criteria for suitability.
|
igor@402
|
195 The more ``good'' changes you contribute to a maintainer, the more
|
igor@402
|
196 likely they are to trust your judgment and accept your changes. If
|
igor@402
|
197 you're well-known and maintain a long-lived branch for something Linus
|
igor@402
|
198 hasn't yet accepted, people with similar interests may pull your
|
igor@402
|
199 changes regularly to keep up with your work.
|
igor@402
|
200
|
igor@402
|
201 Reputation and acclaim don't necessarily cross subsystem or ``people''
|
igor@402
|
202 boundaries. If you're a respected but specialised storage hacker, and
|
igor@402
|
203 you try to fix a networking bug, that change will receive a level of
|
igor@402
|
204 scrutiny from a network maintainer comparable to a change from a
|
igor@402
|
205 complete stranger.
|
igor@402
|
206
|
igor@402
|
207 To people who come from more orderly project backgrounds, the
|
igor@402
|
208 comparatively chaotic Linux kernel development process often seems
|
igor@402
|
209 completely insane. It's subject to the whims of individuals; people
|
igor@402
|
210 make sweeping changes whenever they deem it appropriate; and the pace
|
igor@402
|
211 of development is astounding. And yet Linux is a highly successful,
|
igor@402
|
212 well-regarded piece of software.
|
igor@402
|
213
|
igor@402
|
214 \subsection{Pull-only versus shared-push collaboration}
|
igor@402
|
215
|
igor@402
|
216 A perpetual source of heat in the open source community is whether a
|
igor@402
|
217 development model in which people only ever pull changes from others
|
igor@402
|
218 is ``better than'' one in which multiple people can push changes to a
|
igor@402
|
219 shared repository.
|
igor@402
|
220
|
igor@402
|
221 Typically, the backers of the shared-push model use tools that
|
igor@402
|
222 actively enforce this approach. If you're using a centralised
|
igor@402
|
223 revision control tool such as Subversion, there's no way to make a
|
igor@402
|
224 choice over which model you'll use: the tool gives you shared-push,
|
igor@402
|
225 and if you want to do anything else, you'll have to roll your own
|
igor@402
|
226 approach on top (such as applying a patch by hand).
|
igor@402
|
227
|
igor@402
|
228 A good distributed revision control tool, such as Mercurial, will
|
igor@402
|
229 support both models. You and your collaborators can then structure
|
igor@402
|
230 how you work together based on your own needs and preferences, not on
|
igor@402
|
231 what contortions your tools force you into.
|
igor@402
|
232
|
igor@402
|
233 \subsection{Where collaboration meets branch management}
|
igor@402
|
234
|
igor@402
|
235 Once you and your team set up some shared repositories and start
|
igor@402
|
236 propagating changes back and forth between local and shared repos, you
|
igor@402
|
237 begin to face a related, but slightly different challenge: that of
|
igor@402
|
238 managing the multiple directions in which your team may be moving at
|
igor@402
|
239 once. Even though this subject is intimately related to how your team
|
igor@402
|
240 collaborates, it's dense enough to merit treatment of its own, in
|
igor@402
|
241 chapter~\ref{chap:branch}.
|
igor@402
|
242
|
igor@402
|
243 \section{The technical side of sharing}
|
igor@402
|
244
|
igor@402
|
245 The remainder of this chapter is devoted to the question of serving
|
igor@402
|
246 data to your collaborators.
|
igor@402
|
247
|
igor@402
|
248 \section{Informal sharing with \hgcmd{serve}}
|
igor@402
|
249 \label{sec:collab:serve}
|
igor@402
|
250
|
igor@402
|
251 Mercurial's \hgcmd{serve} command is wonderfully suited to small,
|
igor@402
|
252 tight-knit, and fast-paced group environments. It also provides a
|
igor@402
|
253 great way to get a feel for using Mercurial commands over a network.
|
igor@402
|
254
|
igor@402
|
255 Run \hgcmd{serve} inside a repository, and in under a second it will
|
igor@402
|
256 bring up a specialised HTTP server; this will accept connections from
|
igor@402
|
257 any client, and serve up data for that repository until you terminate
|
igor@402
|
258 it. Anyone who knows the URL of the server you just started, and can
|
igor@402
|
259 talk to your computer over the network, can then use a web browser or
|
igor@402
|
260 Mercurial to read data from that repository. A URL for a
|
igor@402
|
261 \hgcmd{serve} instance running on a laptop is likely to look something
|
igor@402
|
262 like \Verb|http://my-laptop.local:8000/|.
|
igor@402
|
263
|
igor@402
|
264 The \hgcmd{serve} command is \emph{not} a general-purpose web server.
|
igor@402
|
265 It can do only two things:
|
igor@402
|
266 \begin{itemize}
|
igor@402
|
267 \item Allow people to browse the history of the repository it's
|
igor@402
|
268 serving, from their normal web browsers.
|
igor@402
|
269 \item Speak Mercurial's wire protocol, so that people can
|
igor@402
|
270 \hgcmd{clone} or \hgcmd{pull} changes from that repository.
|
igor@402
|
271 \end{itemize}
|
igor@402
|
272 In particular, \hgcmd{serve} won't allow remote users to \emph{modify}
|
igor@402
|
273 your repository. It's intended for read-only use.
|
igor@402
|
274
|
igor@402
|
275 If you're getting started with Mercurial, there's nothing to prevent
|
igor@402
|
276 you from using \hgcmd{serve} to serve up a repository on your own
|
igor@402
|
277 computer, then use commands like \hgcmd{clone}, \hgcmd{incoming}, and
|
igor@402
|
278 so on to talk to that server as if the repository was hosted remotely.
|
igor@402
|
279 This can help you to quickly get acquainted with using commands on
|
igor@402
|
280 network-hosted repositories.
|
igor@402
|
281
|
igor@402
|
282 \subsection{A few things to keep in mind}
|
igor@402
|
283
|
igor@402
|
284 Because it provides unauthenticated read access to all clients, you
|
igor@402
|
285 should only use \hgcmd{serve} in an environment where you either don't
|
igor@402
|
286 care, or have complete control over, who can access your network and
|
igor@402
|
287 pull data from your repository.
|
igor@402
|
288
|
igor@402
|
289 The \hgcmd{serve} command knows nothing about any firewall software
|
igor@402
|
290 you might have installed on your system or network. It cannot detect
|
igor@402
|
291 or control your firewall software. If other people are unable to talk
|
igor@402
|
292 to a running \hgcmd{serve} instance, the second thing you should do
|
igor@402
|
293 (\emph{after} you make sure that they're using the correct URL) is
|
igor@402
|
294 check your firewall configuration.
|
igor@402
|
295
|
igor@402
|
296 By default, \hgcmd{serve} listens for incoming connections on
|
igor@402
|
297 port~8000. If another process is already listening on the port you
|
igor@402
|
298 want to use, you can specify a different port to listen on using the
|
igor@402
|
299 \hgopt{serve}{-p} option.
|
igor@402
|
300
|
igor@402
|
301 Normally, when \hgcmd{serve} starts, it prints no output, which can be
|
igor@402
|
302 a bit unnerving. If you'd like to confirm that it is indeed running
|
igor@402
|
303 correctly, and find out what URL you should send to your
|
igor@402
|
304 collaborators, start it with the \hggopt{-v} option.
|
igor@402
|
305
|
igor@402
|
306 \section{Using the Secure Shell (ssh) protocol}
|
igor@402
|
307 \label{sec:collab:ssh}
|
igor@402
|
308
|
igor@402
|
309 You can pull and push changes securely over a network connection using
|
igor@402
|
310 the Secure Shell (\texttt{ssh}) protocol. To use this successfully,
|
igor@402
|
311 you may have to do a little bit of configuration on the client or
|
igor@402
|
312 server sides.
|
igor@402
|
313
|
igor@402
|
314 If you're not familiar with ssh, it's a network protocol that lets you
|
igor@402
|
315 securely communicate with another computer. To use it with Mercurial,
|
igor@402
|
316 you'll be setting up one or more user accounts on a server so that
|
igor@402
|
317 remote users can log in and execute commands.
|
igor@402
|
318
|
igor@402
|
319 (If you \emph{are} familiar with ssh, you'll probably find some of the
|
igor@402
|
320 material that follows to be elementary in nature.)
|
igor@402
|
321
|
igor@402
|
322 \subsection{How to read and write ssh URLs}
|
igor@402
|
323
|
igor@402
|
324 An ssh URL tends to look like this:
|
igor@402
|
325 \begin{codesample2}
|
igor@402
|
326 ssh://bos@hg.serpentine.com:22/hg/hgbook
|
igor@402
|
327 \end{codesample2}
|
igor@402
|
328 \begin{enumerate}
|
igor@402
|
329 \item The ``\texttt{ssh://}'' part tells Mercurial to use the ssh
|
igor@402
|
330 protocol.
|
igor@402
|
331 \item The ``\texttt{bos@}'' component indicates what username to log
|
igor@402
|
332 into the server as. You can leave this out if the remote username
|
igor@402
|
333 is the same as your local username.
|
igor@402
|
334 \item The ``\texttt{hg.serpentine.com}'' gives the hostname of the
|
igor@402
|
335 server to log into.
|
igor@402
|
336 \item The ``:22'' identifies the port number to connect to the server
|
igor@402
|
337 on. The default port is~22, so you only need to specify this part
|
igor@402
|
338 if you're \emph{not} using port~22.
|
igor@402
|
339 \item The remainder of the URL is the local path to the repository on
|
igor@402
|
340 the server.
|
igor@402
|
341 \end{enumerate}
|
igor@402
|
342
|
igor@402
|
343 There's plenty of scope for confusion with the path component of ssh
|
igor@402
|
344 URLs, as there is no standard way for tools to interpret it. Some
|
igor@402
|
345 programs behave differently than others when dealing with these paths.
|
igor@402
|
346 This isn't an ideal situation, but it's unlikely to change. Please
|
igor@402
|
347 read the following paragraphs carefully.
|
igor@402
|
348
|
igor@402
|
349 Mercurial treats the path to a repository on the server as relative to
|
igor@402
|
350 the remote user's home directory. For example, if user \texttt{foo}
|
igor@402
|
351 on the server has a home directory of \dirname{/home/foo}, then an ssh
|
igor@402
|
352 URL that contains a path component of \dirname{bar}
|
igor@402
|
353 \emph{really} refers to the directory \dirname{/home/foo/bar}.
|
igor@402
|
354
|
igor@402
|
355 If you want to specify a path relative to another user's home
|
igor@402
|
356 directory, you can use a path that starts with a tilde character
|
igor@402
|
357 followed by the user's name (let's call them \texttt{otheruser}), like
|
igor@402
|
358 this.
|
igor@402
|
359 \begin{codesample2}
|
igor@402
|
360 ssh://server/~otheruser/hg/repo
|
igor@402
|
361 \end{codesample2}
|
igor@402
|
362
|
igor@402
|
363 And if you really want to specify an \emph{absolute} path on the
|
igor@402
|
364 server, begin the path component with two slashes, as in this example.
|
igor@402
|
365 \begin{codesample2}
|
igor@402
|
366 ssh://server//absolute/path
|
igor@402
|
367 \end{codesample2}
|
igor@402
|
368
|
igor@402
|
369 \subsection{Finding an ssh client for your system}
|
igor@402
|
370
|
igor@402
|
371 Almost every Unix-like system comes with OpenSSH preinstalled. If
|
igor@402
|
372 you're using such a system, run \Verb|which ssh| to find out if
|
igor@402
|
373 the \command{ssh} command is installed (it's usually in
|
igor@402
|
374 \dirname{/usr/bin}). In the unlikely event that it isn't present,
|
igor@402
|
375 take a look at your system documentation to figure out how to install
|
igor@402
|
376 it.
|
igor@402
|
377
|
igor@402
|
378 On Windows, you'll first need to choose download a suitable ssh
|
igor@402
|
379 client. There are two alternatives.
|
igor@402
|
380 \begin{itemize}
|
igor@402
|
381 \item Simon Tatham's excellent PuTTY package~\cite{web:putty} provides
|
igor@402
|
382 a complete suite of ssh client commands.
|
igor@402
|
383 \item If you have a high tolerance for pain, you can use the Cygwin
|
igor@402
|
384 port of OpenSSH.
|
igor@402
|
385 \end{itemize}
|
igor@402
|
386 In either case, you'll need to edit your \hgini\ file to tell
|
igor@402
|
387 Mercurial where to find the actual client command. For example, if
|
igor@402
|
388 you're using PuTTY, you'll need to use the \command{plink} command as
|
igor@402
|
389 a command-line ssh client.
|
igor@402
|
390 \begin{codesample2}
|
igor@402
|
391 [ui]
|
igor@402
|
392 ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key"
|
igor@402
|
393 \end{codesample2}
|
igor@402
|
394
|
igor@402
|
395 \begin{note}
|
igor@402
|
396 The path to \command{plink} shouldn't contain any whitespace
|
igor@402
|
397 characters, or Mercurial may not be able to run it correctly (so
|
igor@402
|
398 putting it in \dirname{C:\\Program Files} is probably not a good
|
igor@402
|
399 idea).
|
igor@402
|
400 \end{note}
|
igor@402
|
401
|
igor@402
|
402 \subsection{Generating a key pair}
|
igor@402
|
403
|
igor@402
|
404 To avoid the need to repetitively type a password every time you need
|
igor@402
|
405 to use your ssh client, I recommend generating a key pair. On a
|
igor@402
|
406 Unix-like system, the \command{ssh-keygen} command will do the trick.
|
igor@402
|
407 On Windows, if you're using PuTTY, the \command{puttygen} command is
|
igor@402
|
408 what you'll need.
|
igor@402
|
409
|
igor@402
|
410 When you generate a key pair, it's usually \emph{highly} advisable to
|
igor@402
|
411 protect it with a passphrase. (The only time that you might not want
|
igor@402
|
412 to do this id when you're using the ssh protocol for automated tasks
|
igor@402
|
413 on a secure network.)
|
igor@402
|
414
|
igor@402
|
415 Simply generating a key pair isn't enough, however. You'll need to
|
igor@402
|
416 add the public key to the set of authorised keys for whatever user
|
igor@402
|
417 you're logging in remotely as. For servers using OpenSSH (the vast
|
igor@402
|
418 majority), this will mean adding the public key to a list in a file
|
igor@402
|
419 called \sfilename{authorized\_keys} in their \sdirname{.ssh}
|
igor@402
|
420 directory.
|
igor@402
|
421
|
igor@402
|
422 On a Unix-like system, your public key will have a \filename{.pub}
|
igor@402
|
423 extension. If you're using \command{puttygen} on Windows, you can
|
igor@402
|
424 save the public key to a file of your choosing, or paste it from the
|
igor@402
|
425 window it's displayed in straight into the
|
igor@402
|
426 \sfilename{authorized\_keys} file.
|
igor@402
|
427
|
igor@402
|
428 \subsection{Using an authentication agent}
|
igor@402
|
429
|
igor@402
|
430 An authentication agent is a daemon that stores passphrases in memory
|
igor@402
|
431 (so it will forget passphrases if you log out and log back in again).
|
igor@402
|
432 An ssh client will notice if it's running, and query it for a
|
igor@402
|
433 passphrase. If there's no authentication agent running, or the agent
|
igor@402
|
434 doesn't store the necessary passphrase, you'll have to type your
|
igor@402
|
435 passphrase every time Mercurial tries to communicate with a server on
|
igor@402
|
436 your behalf (e.g.~whenever you pull or push changes).
|
igor@402
|
437
|
igor@402
|
438 The downside of storing passphrases in an agent is that it's possible
|
igor@402
|
439 for a well-prepared attacker to recover the plain text of your
|
igor@402
|
440 passphrases, in some cases even if your system has been power-cycled.
|
igor@402
|
441 You should make your own judgment as to whether this is an acceptable
|
igor@402
|
442 risk. It certainly saves a lot of repeated typing.
|
igor@402
|
443
|
igor@402
|
444 On Unix-like systems, the agent is called \command{ssh-agent}, and
|
igor@402
|
445 it's often run automatically for you when you log in. You'll need to
|
igor@402
|
446 use the \command{ssh-add} command to add passphrases to the agent's
|
igor@402
|
447 store. On Windows, if you're using PuTTY, the \command{pageant}
|
igor@402
|
448 command acts as the agent. It adds an icon to your system tray that
|
igor@402
|
449 will let you manage stored passphrases.
|
igor@402
|
450
|
igor@402
|
451 \subsection{Configuring the server side properly}
|
igor@402
|
452
|
igor@402
|
453 Because ssh can be fiddly to set up if you're new to it, there's a
|
igor@402
|
454 variety of things that can go wrong. Add Mercurial on top, and
|
igor@402
|
455 there's plenty more scope for head-scratching. Most of these
|
igor@402
|
456 potential problems occur on the server side, not the client side. The
|
igor@402
|
457 good news is that once you've gotten a configuration working, it will
|
igor@402
|
458 usually continue to work indefinitely.
|
igor@402
|
459
|
igor@402
|
460 Before you try using Mercurial to talk to an ssh server, it's best to
|
igor@402
|
461 make sure that you can use the normal \command{ssh} or \command{putty}
|
igor@402
|
462 command to talk to the server first. If you run into problems with
|
igor@402
|
463 using these commands directly, Mercurial surely won't work. Worse, it
|
igor@402
|
464 will obscure the underlying problem. Any time you want to debug
|
igor@402
|
465 ssh-related Mercurial problems, you should drop back to making sure
|
igor@402
|
466 that plain ssh client commands work first, \emph{before} you worry
|
igor@402
|
467 about whether there's a problem with Mercurial.
|
igor@402
|
468
|
igor@402
|
469 The first thing to be sure of on the server side is that you can
|
igor@402
|
470 actually log in from another machine at all. If you can't use
|
igor@402
|
471 \command{ssh} or \command{putty} to log in, the error message you get
|
igor@402
|
472 may give you a few hints as to what's wrong. The most common problems
|
igor@402
|
473 are as follows.
|
igor@402
|
474 \begin{itemize}
|
igor@402
|
475 \item If you get a ``connection refused'' error, either there isn't an
|
igor@402
|
476 SSH daemon running on the server at all, or it's inaccessible due to
|
igor@402
|
477 firewall configuration.
|
igor@402
|
478 \item If you get a ``no route to host'' error, you either have an
|
igor@402
|
479 incorrect address for the server or a seriously locked down firewall
|
igor@402
|
480 that won't admit its existence at all.
|
igor@402
|
481 \item If you get a ``permission denied'' error, you may have mistyped
|
igor@402
|
482 the username on the server, or you could have mistyped your key's
|
igor@402
|
483 passphrase or the remote user's password.
|
igor@402
|
484 \end{itemize}
|
igor@402
|
485 In summary, if you're having trouble talking to the server's ssh
|
igor@402
|
486 daemon, first make sure that one is running at all. On many systems
|
igor@402
|
487 it will be installed, but disabled, by default. Once you're done with
|
igor@402
|
488 this step, you should then check that the server's firewall is
|
igor@402
|
489 configured to allow incoming connections on the port the ssh daemon is
|
igor@402
|
490 listening on (usually~22). Don't worry about more exotic
|
igor@402
|
491 possibilities for misconfiguration until you've checked these two
|
igor@402
|
492 first.
|
igor@402
|
493
|
igor@402
|
494 If you're using an authentication agent on the client side to store
|
igor@402
|
495 passphrases for your keys, you ought to be able to log into the server
|
igor@402
|
496 without being prompted for a passphrase or a password. If you're
|
igor@402
|
497 prompted for a passphrase, there are a few possible culprits.
|
igor@402
|
498 \begin{itemize}
|
igor@402
|
499 \item You might have forgotten to use \command{ssh-add} or
|
igor@402
|
500 \command{pageant} to store the passphrase.
|
igor@402
|
501 \item You might have stored the passphrase for the wrong key.
|
igor@402
|
502 \end{itemize}
|
igor@402
|
503 If you're being prompted for the remote user's password, there are
|
igor@402
|
504 another few possible problems to check.
|
igor@402
|
505 \begin{itemize}
|
igor@402
|
506 \item Either the user's home directory or their \sdirname{.ssh}
|
igor@402
|
507 directory might have excessively liberal permissions. As a result,
|
igor@402
|
508 the ssh daemon will not trust or read their
|
igor@402
|
509 \sfilename{authorized\_keys} file. For example, a group-writable
|
igor@402
|
510 home or \sdirname{.ssh} directory will often cause this symptom.
|
igor@402
|
511 \item The user's \sfilename{authorized\_keys} file may have a problem.
|
igor@402
|
512 If anyone other than the user owns or can write to that file, the
|
igor@402
|
513 ssh daemon will not trust or read it.
|
igor@402
|
514 \end{itemize}
|
igor@402
|
515
|
igor@402
|
516 In the ideal world, you should be able to run the following command
|
igor@402
|
517 successfully, and it should print exactly one line of output, the
|
igor@402
|
518 current date and time.
|
igor@402
|
519 \begin{codesample2}
|
igor@402
|
520 ssh myserver date
|
igor@402
|
521 \end{codesample2}
|
igor@402
|
522
|
igor@402
|
523 If, on your server, you have login scripts that print banners or other
|
igor@402
|
524 junk even when running non-interactive commands like this, you should
|
igor@402
|
525 fix them before you continue, so that they only print output if
|
igor@402
|
526 they're run interactively. Otherwise these banners will at least
|
igor@402
|
527 clutter up Mercurial's output. Worse, they could potentially cause
|
igor@402
|
528 problems with running Mercurial commands remotely. Mercurial makes
|
igor@402
|
529 tries to detect and ignore banners in non-interactive \command{ssh}
|
igor@402
|
530 sessions, but it is not foolproof. (If you're editing your login
|
igor@402
|
531 scripts on your server, the usual way to see if a login script is
|
igor@402
|
532 running in an interactive shell is to check the return code from the
|
igor@402
|
533 command \Verb|tty -s|.)
|
igor@402
|
534
|
igor@402
|
535 Once you've verified that plain old ssh is working with your server,
|
igor@402
|
536 the next step is to ensure that Mercurial runs on the server. The
|
igor@402
|
537 following command should run successfully:
|
igor@402
|
538 \begin{codesample2}
|
igor@402
|
539 ssh myserver hg version
|
igor@402
|
540 \end{codesample2}
|
igor@402
|
541 If you see an error message instead of normal \hgcmd{version} output,
|
igor@402
|
542 this is usually because you haven't installed Mercurial to
|
igor@402
|
543 \dirname{/usr/bin}. Don't worry if this is the case; you don't need
|
igor@402
|
544 to do that. But you should check for a few possible problems.
|
igor@402
|
545 \begin{itemize}
|
igor@402
|
546 \item Is Mercurial really installed on the server at all? I know this
|
igor@402
|
547 sounds trivial, but it's worth checking!
|
igor@402
|
548 \item Maybe your shell's search path (usually set via the \envar{PATH}
|
igor@402
|
549 environment variable) is simply misconfigured.
|
igor@402
|
550 \item Perhaps your \envar{PATH} environment variable is only being set
|
igor@402
|
551 to point to the location of the \command{hg} executable if the login
|
igor@402
|
552 session is interactive. This can happen if you're setting the path
|
igor@402
|
553 in the wrong shell login script. See your shell's documentation for
|
igor@402
|
554 details.
|
igor@402
|
555 \item The \envar{PYTHONPATH} environment variable may need to contain
|
igor@402
|
556 the path to the Mercurial Python modules. It might not be set at
|
igor@402
|
557 all; it could be incorrect; or it may be set only if the login is
|
igor@402
|
558 interactive.
|
igor@402
|
559 \end{itemize}
|
igor@402
|
560
|
igor@402
|
561 If you can run \hgcmd{version} over an ssh connection, well done!
|
igor@402
|
562 You've got the server and client sorted out. You should now be able
|
igor@402
|
563 to use Mercurial to access repositories hosted by that username on
|
igor@402
|
564 that server. If you run into problems with Mercurial and ssh at this
|
igor@402
|
565 point, try using the \hggopt{--debug} option to get a clearer picture
|
igor@402
|
566 of what's going on.
|
igor@402
|
567
|
igor@402
|
568 \subsection{Using compression with ssh}
|
igor@402
|
569
|
igor@402
|
570 Mercurial does not compress data when it uses the ssh protocol,
|
igor@402
|
571 because the ssh protocol can transparently compress data. However,
|
igor@402
|
572 the default behaviour of ssh clients is \emph{not} to request
|
igor@402
|
573 compression.
|
igor@402
|
574
|
igor@402
|
575 Over any network other than a fast LAN (even a wireless network),
|
igor@402
|
576 using compression is likely to significantly speed up Mercurial's
|
igor@402
|
577 network operations. For example, over a WAN, someone measured
|
igor@402
|
578 compression as reducing the amount of time required to clone a
|
igor@402
|
579 particularly large repository from~51 minutes to~17 minutes.
|
igor@402
|
580
|
igor@402
|
581 Both \command{ssh} and \command{plink} accept a \cmdopt{ssh}{-C}
|
igor@402
|
582 option which turns on compression. You can easily edit your \hgrc\ to
|
igor@402
|
583 enable compression for all of Mercurial's uses of the ssh protocol.
|
igor@402
|
584 \begin{codesample2}
|
igor@402
|
585 [ui]
|
igor@402
|
586 ssh = ssh -C
|
igor@402
|
587 \end{codesample2}
|
igor@402
|
588
|
igor@402
|
589 If you use \command{ssh}, you can configure it to always use
|
igor@402
|
590 compression when talking to your server. To do this, edit your
|
igor@402
|
591 \sfilename{.ssh/config} file (which may not yet exist), as follows.
|
igor@402
|
592 \begin{codesample2}
|
igor@402
|
593 Host hg
|
igor@402
|
594 Compression yes
|
igor@402
|
595 HostName hg.example.com
|
igor@402
|
596 \end{codesample2}
|
igor@402
|
597 This defines an alias, \texttt{hg}. When you use it on the
|
igor@402
|
598 \command{ssh} command line or in a Mercurial \texttt{ssh}-protocol
|
igor@402
|
599 URL, it will cause \command{ssh} to connect to \texttt{hg.example.com}
|
igor@402
|
600 and use compression. This gives you both a shorter name to type and
|
igor@402
|
601 compression, each of which is a good thing in its own right.
|
igor@402
|
602
|
igor@402
|
603 \section{Serving over HTTP using CGI}
|
igor@402
|
604 \label{sec:collab:cgi}
|
igor@402
|
605
|
igor@402
|
606 Depending on how ambitious you are, configuring Mercurial's CGI
|
igor@402
|
607 interface can take anything from a few moments to several hours.
|
igor@402
|
608
|
igor@402
|
609 We'll begin with the simplest of examples, and work our way towards a
|
igor@402
|
610 more complex configuration. Even for the most basic case, you're
|
igor@402
|
611 almost certainly going to need to read and modify your web server's
|
igor@402
|
612 configuration.
|
igor@402
|
613
|
igor@402
|
614 \begin{note}
|
igor@402
|
615 Configuring a web server is a complex, fiddly, and highly
|
igor@402
|
616 system-dependent activity. I can't possibly give you instructions
|
igor@402
|
617 that will cover anything like all of the cases you will encounter.
|
igor@402
|
618 Please use your discretion and judgment in following the sections
|
igor@402
|
619 below. Be prepared to make plenty of mistakes, and to spend a lot
|
igor@402
|
620 of time reading your server's error logs.
|
igor@402
|
621 \end{note}
|
igor@402
|
622
|
igor@402
|
623 \subsection{Web server configuration checklist}
|
igor@402
|
624
|
igor@402
|
625 Before you continue, do take a few moments to check a few aspects of
|
igor@402
|
626 your system's setup.
|
igor@402
|
627
|
igor@402
|
628 \begin{enumerate}
|
igor@402
|
629 \item Do you have a web server installed at all? Mac OS X ships with
|
igor@402
|
630 Apache, but many other systems may not have a web server installed.
|
igor@402
|
631 \item If you have a web server installed, is it actually running? On
|
igor@402
|
632 most systems, even if one is present, it will be disabled by
|
igor@402
|
633 default.
|
igor@402
|
634 \item Is your server configured to allow you to run CGI programs in
|
igor@402
|
635 the directory where you plan to do so? Most servers default to
|
igor@402
|
636 explicitly disabling the ability to run CGI programs.
|
igor@402
|
637 \end{enumerate}
|
igor@402
|
638
|
igor@402
|
639 If you don't have a web server installed, and don't have substantial
|
igor@402
|
640 experience configuring Apache, you should consider using the
|
igor@402
|
641 \texttt{lighttpd} web server instead of Apache. Apache has a
|
igor@402
|
642 well-deserved reputation for baroque and confusing configuration.
|
igor@402
|
643 While \texttt{lighttpd} is less capable in some ways than Apache, most
|
igor@402
|
644 of these capabilities are not relevant to serving Mercurial
|
igor@402
|
645 repositories. And \texttt{lighttpd} is undeniably \emph{much} easier
|
igor@402
|
646 to get started with than Apache.
|
igor@402
|
647
|
igor@402
|
648 \subsection{Basic CGI configuration}
|
igor@402
|
649
|
igor@402
|
650 On Unix-like systems, it's common for users to have a subdirectory
|
igor@402
|
651 named something like \dirname{public\_html} in their home directory,
|
igor@402
|
652 from which they can serve up web pages. A file named \filename{foo}
|
igor@402
|
653 in this directory will be accessible at a URL of the form
|
igor@402
|
654 \texttt{http://www.example.com/\~username/foo}.
|
igor@402
|
655
|
igor@402
|
656 To get started, find the \sfilename{hgweb.cgi} script that should be
|
igor@402
|
657 present in your Mercurial installation. If you can't quickly find a
|
igor@402
|
658 local copy on your system, simply download one from the master
|
igor@402
|
659 Mercurial repository at
|
igor@402
|
660 \url{http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi}.
|
igor@402
|
661
|
igor@402
|
662 You'll need to copy this script into your \dirname{public\_html}
|
igor@402
|
663 directory, and ensure that it's executable.
|
igor@402
|
664 \begin{codesample2}
|
igor@402
|
665 cp .../hgweb.cgi ~/public_html
|
igor@402
|
666 chmod 755 ~/public_html/hgweb.cgi
|
igor@402
|
667 \end{codesample2}
|
igor@402
|
668 The \texttt{755} argument to \command{chmod} is a little more general
|
igor@402
|
669 than just making the script executable: it ensures that the script is
|
igor@402
|
670 executable by anyone, and that ``group'' and ``other'' write
|
igor@402
|
671 permissions are \emph{not} set. If you were to leave those write
|
igor@402
|
672 permissions enabled, Apache's \texttt{suexec} subsystem would likely
|
igor@402
|
673 refuse to execute the script. In fact, \texttt{suexec} also insists
|
igor@402
|
674 that the \emph{directory} in which the script resides must not be
|
igor@402
|
675 writable by others.
|
igor@402
|
676 \begin{codesample2}
|
igor@402
|
677 chmod 755 ~/public_html
|
igor@402
|
678 \end{codesample2}
|
igor@402
|
679
|
igor@402
|
680 \subsubsection{What could \emph{possibly} go wrong?}
|
igor@402
|
681 \label{sec:collab:wtf}
|
igor@402
|
682
|
igor@402
|
683 Once you've copied the CGI script into place, go into a web browser,
|
igor@402
|
684 and try to open the URL \url{http://myhostname/~myuser/hgweb.cgi},
|
igor@402
|
685 \emph{but} brace yourself for instant failure. There's a high
|
igor@402
|
686 probability that trying to visit this URL will fail, and there are
|
igor@402
|
687 many possible reasons for this. In fact, you're likely to stumble
|
igor@402
|
688 over almost every one of the possible errors below, so please read
|
igor@402
|
689 carefully. The following are all of the problems I ran into on a
|
igor@402
|
690 system running Fedora~7, with a fresh installation of Apache, and a
|
igor@402
|
691 user account that I created specially to perform this exercise.
|
igor@402
|
692
|
igor@402
|
693 Your web server may have per-user directories disabled. If you're
|
igor@402
|
694 using Apache, search your config file for a \texttt{UserDir}
|
igor@402
|
695 directive. If there's none present, per-user directories will be
|
igor@402
|
696 disabled. If one exists, but its value is \texttt{disabled}, then
|
igor@402
|
697 per-user directories will be disabled. Otherwise, the string after
|
igor@402
|
698 \texttt{UserDir} gives the name of the subdirectory that Apache will
|
igor@402
|
699 look in under your home directory, for example \dirname{public\_html}.
|
igor@402
|
700
|
igor@402
|
701 Your file access permissions may be too restrictive. The web server
|
igor@402
|
702 must be able to traverse your home directory and directories under
|
igor@402
|
703 your \dirname{public\_html} directory, and read files under the latter
|
igor@402
|
704 too. Here's a quick recipe to help you to make your permissions more
|
igor@402
|
705 appropriate.
|
igor@402
|
706 \begin{codesample2}
|
igor@402
|
707 chmod 755 ~
|
igor@402
|
708 find ~/public_html -type d -print0 | xargs -0r chmod 755
|
igor@402
|
709 find ~/public_html -type f -print0 | xargs -0r chmod 644
|
igor@402
|
710 \end{codesample2}
|
igor@402
|
711
|
igor@402
|
712 The other possibility with permissions is that you might get a
|
igor@402
|
713 completely empty window when you try to load the script. In this
|
igor@402
|
714 case, it's likely that your access permissions are \emph{too
|
igor@402
|
715 permissive}. Apache's \texttt{suexec} subsystem won't execute a
|
igor@402
|
716 script that's group-~or world-writable, for example.
|
igor@402
|
717
|
igor@402
|
718 Your web server may be configured to disallow execution of CGI
|
igor@402
|
719 programs in your per-user web directory. Here's Apache's
|
igor@402
|
720 default per-user configuration from my Fedora system.
|
igor@402
|
721 \begin{codesample2}
|
igor@402
|
722 <Directory /home/*/public_html>
|
igor@402
|
723 AllowOverride FileInfo AuthConfig Limit
|
igor@402
|
724 Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
|
igor@402
|
725 <Limit GET POST OPTIONS>
|
igor@402
|
726 Order allow,deny
|
igor@402
|
727 Allow from all
|
igor@402
|
728 </Limit>
|
igor@402
|
729 <LimitExcept GET POST OPTIONS>
|
igor@402
|
730 Order deny,allow
|
igor@402
|
731 Deny from all
|
igor@402
|
732 </LimitExcept>
|
igor@402
|
733 </Directory>
|
igor@402
|
734 \end{codesample2}
|
igor@402
|
735 If you find a similar-looking \texttt{Directory} group in your Apache
|
igor@402
|
736 configuration, the directive to look at inside it is \texttt{Options}.
|
igor@402
|
737 Add \texttt{ExecCGI} to the end of this list if it's missing, and
|
igor@402
|
738 restart the web server.
|
igor@402
|
739
|
igor@402
|
740 If you find that Apache serves you the text of the CGI script instead
|
igor@402
|
741 of executing it, you may need to either uncomment (if already present)
|
igor@402
|
742 or add a directive like this.
|
igor@402
|
743 \begin{codesample2}
|
igor@402
|
744 AddHandler cgi-script .cgi
|
igor@402
|
745 \end{codesample2}
|
igor@402
|
746
|
igor@402
|
747 The next possibility is that you might be served with a colourful
|
igor@402
|
748 Python backtrace claiming that it can't import a
|
igor@402
|
749 \texttt{mercurial}-related module. This is actually progress! The
|
igor@402
|
750 server is now capable of executing your CGI script. This error is
|
igor@402
|
751 only likely to occur if you're running a private installation of
|
igor@402
|
752 Mercurial, instead of a system-wide version. Remember that the web
|
igor@402
|
753 server runs the CGI program without any of the environment variables
|
igor@402
|
754 that you take for granted in an interactive session. If this error
|
igor@402
|
755 happens to you, edit your copy of \sfilename{hgweb.cgi} and follow the
|
igor@402
|
756 directions inside it to correctly set your \envar{PYTHONPATH}
|
igor@402
|
757 environment variable.
|
igor@402
|
758
|
igor@402
|
759 Finally, you are \emph{certain} to by served with another colourful
|
igor@402
|
760 Python backtrace: this one will complain that it can't find
|
igor@402
|
761 \dirname{/path/to/repository}. Edit your \sfilename{hgweb.cgi} script
|
igor@402
|
762 and replace the \dirname{/path/to/repository} string with the complete
|
igor@402
|
763 path to the repository you want to serve up.
|
igor@402
|
764
|
igor@402
|
765 At this point, when you try to reload the page, you should be
|
igor@402
|
766 presented with a nice HTML view of your repository's history. Whew!
|
igor@402
|
767
|
igor@402
|
768 \subsubsection{Configuring lighttpd}
|
igor@402
|
769
|
igor@402
|
770 To be exhaustive in my experiments, I tried configuring the
|
igor@402
|
771 increasingly popular \texttt{lighttpd} web server to serve the same
|
igor@402
|
772 repository as I described with Apache above. I had already overcome
|
igor@402
|
773 all of the problems I outlined with Apache, many of which are not
|
igor@402
|
774 server-specific. As a result, I was fairly sure that my file and
|
igor@402
|
775 directory permissions were good, and that my \sfilename{hgweb.cgi}
|
igor@402
|
776 script was properly edited.
|
igor@402
|
777
|
igor@402
|
778 Once I had Apache running, getting \texttt{lighttpd} to serve the
|
igor@402
|
779 repository was a snap (in other words, even if you're trying to use
|
igor@402
|
780 \texttt{lighttpd}, you should read the Apache section). I first had
|
igor@402
|
781 to edit the \texttt{mod\_access} section of its config file to enable
|
igor@402
|
782 \texttt{mod\_cgi} and \texttt{mod\_userdir}, both of which were
|
igor@402
|
783 disabled by default on my system. I then added a few lines to the end
|
igor@402
|
784 of the config file, to configure these modules.
|
igor@402
|
785 \begin{codesample2}
|
igor@402
|
786 userdir.path = "public_html"
|
igor@402
|
787 cgi.assign = ( ".cgi" => "" )
|
igor@402
|
788 \end{codesample2}
|
igor@402
|
789 With this done, \texttt{lighttpd} ran immediately for me. If I had
|
igor@402
|
790 configured \texttt{lighttpd} before Apache, I'd almost certainly have
|
igor@402
|
791 run into many of the same system-level configuration problems as I did
|
igor@402
|
792 with Apache. However, I found \texttt{lighttpd} to be noticeably
|
igor@402
|
793 easier to configure than Apache, even though I've used Apache for over
|
igor@402
|
794 a decade, and this was my first exposure to \texttt{lighttpd}.
|
igor@402
|
795
|
igor@402
|
796 \subsection{Sharing multiple repositories with one CGI script}
|
igor@402
|
797
|
igor@402
|
798 The \sfilename{hgweb.cgi} script only lets you publish a single
|
igor@402
|
799 repository, which is an annoying restriction. If you want to publish
|
igor@402
|
800 more than one without wracking yourself with multiple copies of the
|
igor@402
|
801 same script, each with different names, a better choice is to use the
|
igor@402
|
802 \sfilename{hgwebdir.cgi} script.
|
igor@402
|
803
|
igor@402
|
804 The procedure to configure \sfilename{hgwebdir.cgi} is only a little
|
igor@402
|
805 more involved than for \sfilename{hgweb.cgi}. First, you must obtain
|
igor@402
|
806 a copy of the script. If you don't have one handy, you can download a
|
igor@402
|
807 copy from the master Mercurial repository at
|
igor@402
|
808 \url{http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi}.
|
igor@402
|
809
|
igor@402
|
810 You'll need to copy this script into your \dirname{public\_html}
|
igor@402
|
811 directory, and ensure that it's executable.
|
igor@402
|
812 \begin{codesample2}
|
igor@402
|
813 cp .../hgwebdir.cgi ~/public_html
|
igor@402
|
814 chmod 755 ~/public_html ~/public_html/hgwebdir.cgi
|
igor@402
|
815 \end{codesample2}
|
igor@402
|
816 With basic configuration out of the way, try to visit
|
igor@402
|
817 \url{http://myhostname/~myuser/hgwebdir.cgi} in your browser. It
|
igor@402
|
818 should display an empty list of repositories. If you get a blank
|
igor@402
|
819 window or error message, try walking through the list of potential
|
igor@402
|
820 problems in section~\ref{sec:collab:wtf}.
|
igor@402
|
821
|
igor@402
|
822 The \sfilename{hgwebdir.cgi} script relies on an external
|
igor@402
|
823 configuration file. By default, it searches for a file named
|
igor@402
|
824 \sfilename{hgweb.config} in the same directory as itself. You'll need
|
igor@402
|
825 to create this file, and make it world-readable. The format of the
|
igor@402
|
826 file is similar to a Windows ``ini'' file, as understood by Python's
|
igor@402
|
827 \texttt{ConfigParser}~\cite{web:configparser} module.
|
igor@402
|
828
|
igor@402
|
829 The easiest way to configure \sfilename{hgwebdir.cgi} is with a
|
igor@402
|
830 section named \texttt{collections}. This will automatically publish
|
igor@402
|
831 \emph{every} repository under the directories you name. The section
|
igor@402
|
832 should look like this:
|
igor@402
|
833 \begin{codesample2}
|
igor@402
|
834 [collections]
|
igor@402
|
835 /my/root = /my/root
|
igor@402
|
836 \end{codesample2}
|
igor@402
|
837 Mercurial interprets this by looking at the directory name on the
|
igor@402
|
838 \emph{right} hand side of the ``\texttt{=}'' sign; finding
|
igor@402
|
839 repositories in that directory hierarchy; and using the text on the
|
igor@402
|
840 \emph{left} to strip off matching text from the names it will actually
|
igor@402
|
841 list in the web interface. The remaining component of a path after
|
igor@402
|
842 this stripping has occurred is called a ``virtual path''.
|
igor@402
|
843
|
igor@402
|
844 Given the example above, if we have a repository whose local path is
|
igor@402
|
845 \dirname{/my/root/this/repo}, the CGI script will strip the leading
|
igor@402
|
846 \dirname{/my/root} from the name, and publish the repository with a
|
igor@402
|
847 virtual path of \dirname{this/repo}. If the base URL for our CGI
|
igor@402
|
848 script is \url{http://myhostname/~myuser/hgwebdir.cgi}, the complete
|
igor@402
|
849 URL for that repository will be
|
igor@402
|
850 \url{http://myhostname/~myuser/hgwebdir.cgi/this/repo}.
|
igor@402
|
851
|
igor@402
|
852 If we replace \dirname{/my/root} on the left hand side of this example
|
igor@402
|
853 with \dirname{/my}, then \sfilename{hgwebdir.cgi} will only strip off
|
igor@402
|
854 \dirname{/my} from the repository name, and will give us a virtual
|
igor@402
|
855 path of \dirname{root/this/repo} instead of \dirname{this/repo}.
|
igor@402
|
856
|
igor@402
|
857 The \sfilename{hgwebdir.cgi} script will recursively search each
|
igor@402
|
858 directory listed in the \texttt{collections} section of its
|
igor@402
|
859 configuration file, but it will \texttt{not} recurse into the
|
igor@402
|
860 repositories it finds.
|
igor@402
|
861
|
igor@402
|
862 The \texttt{collections} mechanism makes it easy to publish many
|
igor@402
|
863 repositories in a ``fire and forget'' manner. You only need to set up
|
igor@402
|
864 the CGI script and configuration file one time. Afterwards, you can
|
igor@402
|
865 publish or unpublish a repository at any time by simply moving it
|
igor@402
|
866 into, or out of, the directory hierarchy in which you've configured
|
igor@402
|
867 \sfilename{hgwebdir.cgi} to look.
|
igor@402
|
868
|
igor@402
|
869 \subsubsection{Explicitly specifying which repositories to publish}
|
igor@402
|
870
|
igor@402
|
871 In addition to the \texttt{collections} mechanism, the
|
igor@402
|
872 \sfilename{hgwebdir.cgi} script allows you to publish a specific list
|
igor@402
|
873 of repositories. To do so, create a \texttt{paths} section, with
|
igor@402
|
874 contents of the following form.
|
igor@402
|
875 \begin{codesample2}
|
igor@402
|
876 [paths]
|
igor@402
|
877 repo1 = /my/path/to/some/repo
|
igor@402
|
878 repo2 = /some/path/to/another
|
igor@402
|
879 \end{codesample2}
|
igor@402
|
880 In this case, the virtual path (the component that will appear in a
|
igor@402
|
881 URL) is on the left hand side of each definition, while the path to
|
igor@402
|
882 the repository is on the right. Notice that there does not need to be
|
igor@402
|
883 any relationship between the virtual path you choose and the location
|
igor@402
|
884 of a repository in your filesystem.
|
igor@402
|
885
|
igor@402
|
886 If you wish, you can use both the \texttt{collections} and
|
igor@402
|
887 \texttt{paths} mechanisms simultaneously in a single configuration
|
igor@402
|
888 file.
|
igor@402
|
889
|
igor@402
|
890 \begin{note}
|
igor@402
|
891 If multiple repositories have the same virtual path,
|
igor@402
|
892 \sfilename{hgwebdir.cgi} will not report an error. Instead, it will
|
igor@402
|
893 behave unpredictably.
|
igor@402
|
894 \end{note}
|
igor@402
|
895
|
igor@402
|
896 \subsection{Downloading source archives}
|
igor@402
|
897
|
igor@402
|
898 Mercurial's web interface lets users download an archive of any
|
igor@402
|
899 revision. This archive will contain a snapshot of the working
|
igor@402
|
900 directory as of that revision, but it will not contain a copy of the
|
igor@402
|
901 repository data.
|
igor@402
|
902
|
igor@402
|
903 By default, this feature is not enabled. To enable it, you'll need to
|
igor@402
|
904 add an \rcitem{web}{allow\_archive} item to the \rcsection{web}
|
igor@402
|
905 section of your \hgrc.
|
igor@402
|
906
|
igor@402
|
907 \subsection{Web configuration options}
|
igor@402
|
908
|
igor@402
|
909 Mercurial's web interfaces (the \hgcmd{serve} command, and the
|
igor@402
|
910 \sfilename{hgweb.cgi} and \sfilename{hgwebdir.cgi} scripts) have a
|
igor@402
|
911 number of configuration options that you can set. These belong in a
|
igor@402
|
912 section named \rcsection{web}.
|
igor@402
|
913 \begin{itemize}
|
igor@402
|
914 \item[\rcitem{web}{allow\_archive}] Determines which (if any) archive
|
igor@402
|
915 download mechanisms Mercurial supports. If you enable this
|
igor@402
|
916 feature, users of the web interface will be able to download an
|
igor@402
|
917 archive of whatever revision of a repository they are viewing.
|
igor@402
|
918 To enable the archive feature, this item must take the form of a
|
igor@402
|
919 sequence of words drawn from the list below.
|
igor@402
|
920 \begin{itemize}
|
igor@402
|
921 \item[\texttt{bz2}] A \command{tar} archive, compressed using
|
igor@402
|
922 \texttt{bzip2} compression. This has the best compression ratio,
|
igor@402
|
923 but uses the most CPU time on the server.
|
igor@402
|
924 \item[\texttt{gz}] A \command{tar} archive, compressed using
|
igor@402
|
925 \texttt{gzip} compression.
|
igor@402
|
926 \item[\texttt{zip}] A \command{zip} archive, compressed using LZW
|
igor@402
|
927 compression. This format has the worst compression ratio, but is
|
igor@402
|
928 widely used in the Windows world.
|
igor@402
|
929 \end{itemize}
|
igor@402
|
930 If you provide an empty list, or don't have an
|
igor@402
|
931 \rcitem{web}{allow\_archive} entry at all, this feature will be
|
igor@402
|
932 disabled. Here is an example of how to enable all three supported
|
igor@402
|
933 formats.
|
igor@402
|
934 \begin{codesample4}
|
igor@402
|
935 [web]
|
igor@402
|
936 allow_archive = bz2 gz zip
|
igor@402
|
937 \end{codesample4}
|
igor@402
|
938 \item[\rcitem{web}{allowpull}] Boolean. Determines whether the web
|
igor@402
|
939 interface allows remote users to \hgcmd{pull} and \hgcmd{clone} this
|
igor@402
|
940 repository over~HTTP. If set to \texttt{no} or \texttt{false}, only
|
igor@402
|
941 the ``human-oriented'' portion of the web interface is available.
|
igor@402
|
942 \item[\rcitem{web}{contact}] String. A free-form (but preferably
|
igor@402
|
943 brief) string identifying the person or group in charge of the
|
igor@402
|
944 repository. This often contains the name and email address of a
|
igor@402
|
945 person or mailing list. It often makes sense to place this entry in
|
igor@402
|
946 a repository's own \sfilename{.hg/hgrc} file, but it can make sense
|
igor@402
|
947 to use in a global \hgrc\ if every repository has a single
|
igor@402
|
948 maintainer.
|
igor@402
|
949 \item[\rcitem{web}{maxchanges}] Integer. The default maximum number
|
igor@402
|
950 of changesets to display in a single page of output.
|
igor@402
|
951 \item[\rcitem{web}{maxfiles}] Integer. The default maximum number
|
igor@402
|
952 of modified files to display in a single page of output.
|
igor@402
|
953 \item[\rcitem{web}{stripes}] Integer. If the web interface displays
|
igor@402
|
954 alternating ``stripes'' to make it easier to visually align rows
|
igor@402
|
955 when you are looking at a table, this number controls the number of
|
igor@402
|
956 rows in each stripe.
|
igor@402
|
957 \item[\rcitem{web}{style}] Controls the template Mercurial uses to
|
igor@402
|
958 display the web interface. Mercurial ships with two web templates,
|
igor@402
|
959 named \texttt{default} and \texttt{gitweb} (the latter is much more
|
igor@402
|
960 visually attractive). You can also specify a custom template of
|
igor@402
|
961 your own; see chapter~\ref{chap:template} for details. Here, you
|
igor@402
|
962 can see how to enable the \texttt{gitweb} style.
|
igor@402
|
963 \begin{codesample4}
|
igor@402
|
964 [web]
|
igor@402
|
965 style = gitweb
|
igor@402
|
966 \end{codesample4}
|
igor@402
|
967 \item[\rcitem{web}{templates}] Path. The directory in which to search
|
igor@402
|
968 for template files. By default, Mercurial searches in the directory
|
igor@402
|
969 in which it was installed.
|
igor@402
|
970 \end{itemize}
|
igor@402
|
971 If you are using \sfilename{hgwebdir.cgi}, you can place a few
|
igor@402
|
972 configuration items in a \rcsection{web} section of the
|
igor@402
|
973 \sfilename{hgweb.config} file instead of a \hgrc\ file, for
|
igor@402
|
974 convenience. These items are \rcitem{web}{motd} and
|
igor@402
|
975 \rcitem{web}{style}.
|
igor@402
|
976
|
igor@402
|
977 \subsubsection{Options specific to an individual repository}
|
igor@402
|
978
|
igor@402
|
979 A few \rcsection{web} configuration items ought to be placed in a
|
igor@402
|
980 repository's local \sfilename{.hg/hgrc}, rather than a user's or
|
igor@402
|
981 global \hgrc.
|
igor@402
|
982 \begin{itemize}
|
igor@402
|
983 \item[\rcitem{web}{description}] String. A free-form (but preferably
|
igor@402
|
984 brief) string that describes the contents or purpose of the
|
igor@402
|
985 repository.
|
igor@402
|
986 \item[\rcitem{web}{name}] String. The name to use for the repository
|
igor@402
|
987 in the web interface. This overrides the default name, which is the
|
igor@402
|
988 last component of the repository's path.
|
igor@402
|
989 \end{itemize}
|
igor@402
|
990
|
igor@402
|
991 \subsubsection{Options specific to the \hgcmd{serve} command}
|
igor@402
|
992
|
igor@402
|
993 Some of the items in the \rcsection{web} section of a \hgrc\ file are
|
igor@402
|
994 only for use with the \hgcmd{serve} command.
|
igor@402
|
995 \begin{itemize}
|
igor@402
|
996 \item[\rcitem{web}{accesslog}] Path. The name of a file into which to
|
igor@402
|
997 write an access log. By default, the \hgcmd{serve} command writes
|
igor@402
|
998 this information to standard output, not to a file. Log entries are
|
igor@402
|
999 written in the standard ``combined'' file format used by almost all
|
igor@402
|
1000 web servers.
|
igor@402
|
1001 \item[\rcitem{web}{address}] String. The local address on which the
|
igor@402
|
1002 server should listen for incoming connections. By default, the
|
igor@402
|
1003 server listens on all addresses.
|
igor@402
|
1004 \item[\rcitem{web}{errorlog}] Path. The name of a file into which to
|
igor@402
|
1005 write an error log. By default, the \hgcmd{serve} command writes this
|
igor@402
|
1006 information to standard error, not to a file.
|
igor@402
|
1007 \item[\rcitem{web}{ipv6}] Boolean. Whether to use the IPv6 protocol.
|
igor@402
|
1008 By default, IPv6 is not used.
|
igor@402
|
1009 \item[\rcitem{web}{port}] Integer. The TCP~port number on which the
|
igor@402
|
1010 server should listen. The default port number used is~8000.
|
igor@402
|
1011 \end{itemize}
|
igor@402
|
1012
|
igor@402
|
1013 \subsubsection{Choosing the right \hgrc\ file to add \rcsection{web}
|
igor@402
|
1014 items to}
|
igor@402
|
1015
|
igor@402
|
1016 It is important to remember that a web server like Apache or
|
igor@402
|
1017 \texttt{lighttpd} will run under a user~ID that is different to yours.
|
igor@402
|
1018 CGI scripts run by your server, such as \sfilename{hgweb.cgi}, will
|
igor@402
|
1019 usually also run under that user~ID.
|
igor@402
|
1020
|
igor@402
|
1021 If you add \rcsection{web} items to your own personal \hgrc\ file, CGI
|
igor@402
|
1022 scripts won't read that \hgrc\ file. Those settings will thus only
|
igor@402
|
1023 affect the behaviour of the \hgcmd{serve} command when you run it. To
|
igor@402
|
1024 cause CGI scripts to see your settings, either create a \hgrc\ file in
|
igor@402
|
1025 the home directory of the user ID that runs your web server, or add
|
igor@402
|
1026 those settings to a system-wide \hgrc\ file.
|
igor@402
|
1027
|
igor@402
|
1028
|
igor@402
|
1029 %%% Local Variables:
|
igor@402
|
1030 %%% mode: latex
|
igor@402
|
1031 %%% TeX-master: "00book"
|
igor@402
|
1032 %%% End:
|