igor@412: \chapter{Colaborar con otros}
igor@402: \label{cha:collab}
igor@402: 
igor@412: Debido a su naturaleza descentralizada, Mercurial no impone política
igor@412: alguna de cómo deben trabajar los grupos de personas. Sin embargo, si
jerojasro@414: usted es nuevo al control distribuido de versiones, es bueno tener
igor@412: herramientas y ejemplos a la mano al pensar en posibles modelos de
igor@412: flujo de trabajo.
igor@412: 
igor@412: \section{La interfaz web de Mercurial}
igor@412: 
igor@412: Mercurial tiene una poderosa interfaz web que provee bastantes
igor@412: capacidades útiles.
igor@412: 
igor@412: Para uso interactivo, la interfaz le permite visualizar uno o varios
jerojasro@516: repositorios. Puede ver el historial de un repositorio, examinar cada
jerojasro@520: cambio (comentarios y diferencias), y ver los contenidos de cada
igor@412: directorio y fichero.
igor@412: 
jerojasro@542: Adicionalmente la interfaz provee notificaciones RSS de los cambios de los
igor@412: repositorios. Que le permite ``subscribirse''a un repositorio usando
jerojasro@542: su herramienta de lectura de notificaciones favorita, y ser notificado
igor@412: automáticamente de la actividad en el repositorio tan pronto como
igor@412: sucede. Me gusta mucho más este modelo que el estar suscrito a una
igor@412: lista de correo a la cual se envían las notificaciones, dado que no
igor@412: requiere configuración adicional de parte de quien sea que está
igor@412: administrando el repositorio.
igor@412: 
igor@412: La interfaz web también permite clonar repositorios a los usuarios
igor@412: remotos, jalar cambios, y (cuando el servidor está configurado para
jerojasro@542: permitirlo) publicar cambios en el mismo.  El protocolo de entunelamiento
igor@412: de Mercurial comprime datos agresivamente, de forma que trabaja
igor@412: eficientemente incluso con conexiones de red con poco ancho de banda.
igor@412: 
igor@412: La forma más sencilla de iniciarse con la interfaz web es usar su
igor@412: navegador para visitar un repositorio existente, como por ejemplo el
igor@412: repositorio principal de Mercurial \url{http://www.selenic.com/repo/hg?style=gitweb}.
igor@412: 
igor@412: Si está interesado en proveer una interfaz web a sus propios
igor@412: repositorios, Mercurial provee dos formas de hacerlo.  La primera es
igor@412: usando la orden \hgcmd{serve}, que está enfocada a servir ``de forma
igor@412: liviana'' y por intervalos cortos.  Para más detalles de cómo usar
igor@412: esta orden vea la sección~\ref{sec:collab:serve} más adelante. Si
igor@412: tiene un repositorio que desea hacer permanente, Mercurial tiene
igor@412: soporte embebido del \command{ssh} para publicar cambios con seguridad
igor@412: al repositorio central, como se documenta en la
igor@412: sección~\ref{sec:collab:ssh}.  Es muy usual que se publique una copia
igor@412: de sólo lectura en el repositorio que está corriendo sobre HTTP usando
igor@412: CGI, como en la sección~\ref{sec:collab:cgi}.  Publicar sobre HTTP
igor@412: satisface las necesidades de la gente que no tiene permisos de
igor@412: publicación y de aquellos que quieren usar navegadores web para
jerojasro@516: visualizar el historial del repositorio.
igor@412: 
igor@412: \subsection{Trabajo con muchas ramas}
igor@412: 
jerojasro@542: Los proyectos de cierta talla tienden naturalmente a progresar de
igor@412: forma simultánea en varios frentes. En el caso del software, es común
igor@412: que un proyecto tenga versiones periódicas oficiales. Una versión
igor@412: puede entrar a ``modo mantenimiento'' por un tiempo después de su
igor@412: primera publicación; las versiones de mantenimiento tienden a contener
igor@412: solamente arreglos de fallos, pero no nuevas características. En
igor@412: paralelo con las versiones de mantenimiento puede haber una o muchas
igor@412: versiones futuras pueden estar en desarrollo. La gente usa normalmente
igor@412: la palabra ``rama'' para referirse a una de las direcciones
igor@412: ligeramente distintas en las cuales procede el desarrollo.
igor@412: 
igor@412: Mercurial está especialmente preparado para administrar un buen número
igor@412: de ramas simultáneas pero no idénticas. Cada ``dirección de
igor@412: desarrollo'' puede vivir en su propio repositorio central, y puede
igor@412: mezclar los cambios de una a otra de acuerdo con las necesidades. Dado
igor@412: que los repositorios son independientes, uno del otro, los cambios
igor@412: inestables de una rama de desarrollo nunca afectarán una rama estable
igor@412: a menos que alguien explícitamente mezcle los cambios.
igor@412: 
igor@412: A continuación un ejemplo de cómo podría hacerse esto en la
igor@412: práctica. Digamos que tiene una ``rama principal'' en un servidor
igor@412: central.
igor@402: \interaction{branching.init}
igor@412: Alguien lo clona, hace cambios locales, los prueba, y los publica allí
igor@412: mismo.
igor@412: 
igor@412: Una vez que la rama principal alcanza una estado de versión se puede
igor@412: usar la orden \hgcmd{tag} para dar un nombre permanente a la revisión.
igor@402: \interaction{branching.tag}
igor@412: Digamos que en la rama principal ocurre más desarrollo.
igor@402: \interaction{branching.main}
igor@412: Cuando se usa la etiqueta con que se identificó la versión, la gente
igor@412: puede clonar el repositorio en cualquier momento en el futuro
igor@412: empleando \hgcmd{update} para obtener una copia del directorio de
igor@412: trabajo exacta como cuando se creó la etiqueta de la revisión que se
igor@412: consignó.
igor@402: \interaction{branching.update}
igor@402: 
igor@412: Adicionalmente, justo después de que la rama principal se etiquete,
igor@412: alguien puede clonarla en el servidor a una nueva rama ``estable'',
igor@412: también en el servidor.
igor@402: \interaction{branching.clone}
igor@402: 
igor@412: Alguien que requiera hacer un cambio en la rama estable puede clonar
igor@412: \emph{ese} repositorio, hacer sus cambios, consignar y publicarlos
igor@412: posteriormente al inicial.
igor@402: \interaction{branching.stable}
igor@412: Puesto que los repositorios de Mercurial son independientes, y que
igor@412: Mercurial no mueve los cambios de un lado a otro automáticamente, las
igor@412: ramas estable y principal están \emph{aisladas} la una de la otra.
igor@412: Los cambios que haga en la rama principal no ``se filtran'' a la rama
igor@412: estable o vice versa.
igor@412: 
igor@412: Es usual que los arreglos de fallos de la rama estable deban hacerse
igor@412: aparecer en la rama principal también.  En lugar de reescribir el
igor@412: arreglo del fallo en la rama principal, puede jalar y mezclar los
igor@412: cambios de la rama estable a la principal, Mercurial traerá tales
igor@412: arreglos por usted.
igor@402: \interaction{branching.merge}
jerojasro@542: La rama principal contendrá aún los cambios que no están en la
igor@412: estable y contendrá además todos los arreglos de fallos de la rama
igor@412: estable.  La rama estable permanece incólume a tales cambios.
igor@402: 
igor@417: \subsection{Ramas de Características}
igor@417: 
igor@417: En proyectos grandes, una forma efectiva de administrar los cambios es
igor@417: dividir el equipo en grupos más pequeños. Cada grupo tiene una rama
igor@417: compartida, clonada de una rama ``principal'' que conforma el proyecto
igor@417: completo.   Aquellos que trabajan en ramas individuales típicamente
igor@417: están aislados de los desarrollos de otras ramas.
igor@402: 
igor@402: \begin{figure}[ht]
igor@402:   \centering
igor@402:   \grafix{feature-branches}
igor@417:   \caption{Ramas de Características}
igor@402:   \label{fig:collab:feature-branches}
igor@402: \end{figure}
igor@402: 
igor@417: Cuando una rama particular alcanza un estado deseado, alguien del
igor@417: equipo de características jala y fusiona de la rama principal hacia
igor@417: la rama de características y publica posteriormente a la rama principal.
igor@417: 
igor@417: \subsection{El tren de publicación}
igor@417: 
igor@417: Algunos proyectos se organizan al estilo``tren'': Una versión se
igor@417: planifica para ser liberada cada cierto tiempo, y las características
igor@417: que estén listas cuando ha llegado el momento ``tren'', se incorporan.
igor@417: 
igor@417: Este modelo tiene cierta similitud a las ramas de características. La
igor@417: diferencia es que cuando una característica pierde el tren, alguien en
igor@417: el equipo de características jala y fusiona los cambios que se fueron
igor@417: en la versión liberada hacia la rama de característica, y el trabajo
igor@417: continúa sobre lo fusionado para que la característica logre estar en
igor@417: la próxima versión.
igor@417: 
igor@417: \subsection{El modelo del kernel linux}
igor@417: 
igor@417: El desarrollo del Kernel Linux tiene una estructura jerárquica
igor@417: bastante horizontal, rodeada de una nube de caos aparente. Dado que la
igor@417: mayoría de desarrolladores usan \command{git}, una herramienta distribuida
igor@417: de control de versiones con capacidades similares a Mercurial, resulta
igor@417: de utilidad describir la forma en que el trabajo fluye en tal
igor@417: ambiente; si le gustan las ideas, la aproximación se traduce bien
igor@417: entre Git y Mercurial.
igor@417: 
igor@417: En el centro de la comunidad está Linus Torvalds, el creador de Linux.
igor@417: Él publica un único repositorio que es considerado el árbol
igor@417: ``oficial'' actual por la comunidad completa de
igor@417: desarrolladores. Cualquiera puede clonar el árbol de Linus, pero él es
igor@417: muy selectivo acerca de los árboles de los cuales jala.
igor@417: 
jerojasro@419: Linus tiene varios ``lugartenientes confiables''.  Como regla, él jala
igor@417: todos los cambios que ellos publican, en la mayoría de los casos sin
igor@417: siquiera revisarlos.  Algunos de sus lugartenientes generalmente
igor@417: aceptan ser los ``mantenedores'', responsables de subsistemas
igor@417: específicos dentro del kernel.  Si un hacker cualquiera desea hacer un
igor@417: cambio a un subsistema y busca que termine en el árbol de Linus, debe
jerojasro@419: encontrar quién es el mantenedor del subsistema y solicitarle que
igor@417: tenga en cuenta su cambio.  Si el mantenedor revisa los cambios y está
igor@417: de acuerdo en tomarlos, estos pasarán al árbol de Linus de acuerdo a
igor@417: lo expuesto.
igor@417: 
igor@417: Cada lugarteniente tiene su forma particular de revisar, aceptar y
igor@417: publicar los cambios; y para decidir cuando hacerlos presentes a
igor@417: Linus.  Adicionalmente existen varias ramas conocidas que mucha gente
igor@417: usa para propósitos distintos. Por ejemplo, pocas personas mantienen
igor@417: repositorios ``estables'' de versiones anteriores del kernel, a los
igor@417: cuales aplican arreglos de fallos críticos necesarios. Algunos
igor@417: mantenedores publican varios árboles: uno para cambios
igor@417: experimentales; uno para cambios que van a ofrecer al mantenedor
igor@417: principal; y así sucesivamente. Otros publican un solo árbol.
igor@417: 
igor@417: Este modelo tiene dos características notables. La primera es que son
igor@417: de ``jalar exclusivamente''.  Usted debe solicitar, convencer o
jerojasro@542: incluso rogar a otro desarrollador para que tome sus cambios, porque
igor@417: casi no hay árboles en los cuales más de una persona pueda publicar, y
igor@417: no hay forma de publicar cambios en un árbol que otra persona controla.
igor@417: 
igor@417: El segundo está basado en reputación y meritocracia.  Si usted es un
igor@417: desconocido, Linus probablemente ignorará sus cambios, sin siquiera
igor@417: responderle.  Pero un mantenedor de un subsistema probablemente los
igor@417: revisara, y los acogerá en caso de que aprueben su criterio de
igor@417: aplicabilidad.  A medida que usted ofrezca ``mejores'' cambios a un
jerojasro@419: mantenedor, habrá más posibilidad de que se confíe en su juicio y se
jerojasro@542: acepten los cambios.   Si usted es reconocido y mantiene una rama
igor@417: durante bastante tiempo para algo que Linus no ha aceptado, personas
igor@417: con intereses similares pueden jalar sus cambios regularmente para
igor@417: estar al día con su trabajo.
igor@417: 
igor@417: La reputación y meritocracia no necesariamente es transversal entre
igor@417: ``personas'' de diferentes subsistemas.  Si usted es respetado pero es
igor@417: un hacker en almacenamiento y trata de arreglar un fallo de redes,
igor@417: tal cambio puede recibir un nivel de escrutinio de un mantenedor de
igor@417: redes comparable con el que se le haría a un completo extraño.
igor@417: 
igor@417: Personas que vienen de proyectos con un ordenamiento distinto, sienten
igor@417: que el proceso comparativamente caótico del Kernel Linux es
igor@417: completamente lunático.  Es objeto de los caprichos individuales; la
igor@417: gente desecha cambios cuando lo desean; y la fase de desarrollo es
igor@417: alucinante. A pesar de eso Linux es una pieza de software exitosa y
igor@417: bien reconocida.
igor@417: 
igor@417: \subsection{Solamente jalar frente a colaboración pública}
igor@417: 
igor@417: Una fuente perpetua de discusiones en la comunidad de código abierto
igor@417: yace en el modelo de desarrollo en el cual la gente solamente jala
igor@417: cambios de otros ``es mejor que'' uno  en el cual muchas personas
igor@417: pueden publicar cambios a un repositorio compartido.
igor@417: 
jerojasro@542: Típicamente los partidarios del modelo de publicar usan las herramientas
igor@417: que se apegan a este modelo.  Si usted usa una herramienta
igor@417: centralizada de control de versiones como Subversion, no hay forma de
igor@417: elegir qué modelo va a usar: La herramienta le ofrece publicación
igor@417: compartida, y si desea hacer cualquier otra cosa, va a tener que
igor@417: aplicar una aproximación artificial (tal como aplicar parches a mano).
igor@417: 
igor@417: Una buena herramienta distribuida de control de versiones, tal como
igor@417: Mercurial soportará los dos modelos.   Usted y sus colaboradores
igor@417: pueden estructurar cómo trabajarán juntos basados en sus propias
igor@417: necesidades y preferencias,  sin depender de las peripecias que la
igor@417: herramienta les obligue a hacer.
igor@417: 
igor@417: \subsection{Cuando la colaboración encuentra la administración ramificada}
igor@417: 
igor@417: Una vez que usted y su equipo configurar algunos repositorios
igor@417: compartidos y comienzan a propagar cambios entre sus repositorios
igor@417: locales y compartidos, comenzará a encarar un reto relacionado, pero
igor@417: un poco distinto:  Administrar las direcciones en las cuales su equipo
jerojasro@542: puede moverse.   A pesar de que está íntimamente ligado acerca de cómo
igor@417: interactúa su equipo, es lo suficientemente denso para ameritar un
igor@417: tratamiento en el capítulo~\ref{chap:branch}.
igor@417: 
igor@417: \section{Aspectos técnicos de la colaboración}
igor@417: 
igor@417: Lo que resta del capítulo lo dedicamos a las cuestiones de servir
igor@417: datos a sus colaboradores.
igor@417: 
igor@417: \section{Compartir informalmente con \hgcmd{serve}}
igor@402: \label{sec:collab:serve}
igor@402: 
igor@417: La orden \hgcmd{serve} de Mercurial satisface de forma espectacular
igor@417: las necesidades de un grupo pequeño, acoplado y de corto
igor@417: tiempo.  Se constituye en una demostración de cómo se siente usar los
igor@417: comandos usando la red.
igor@417: 
igor@417: Ejecute \hgcmd{serve} dentro de un repositorio, y en pocos segundos
igor@417: iniciará un servidor HTTP especializado; aceptará conexiones desde
igor@417: cualquier cliente y servirá datos de este repositorio mientrs lo
igor@417: mantenga funcionando. Todo el que sepa el URL del servidor que ha
igor@417: iniciado, y que puede comunicarse con su computador por la red, puede
igor@417: usar un navegador web o Mercurial para leer datos del repositorio. Un
igor@417: URL para una instancia de \hgcmd{serve} ejecutándose en un portátil
igor@417: debería lucir algo \Verb|http://my-laptop.local:8000/|.
igor@417: 
igor@417: La orden \hgcmd{serve} \emph{no} es un servidor web de propósito
igor@417: general. Solamente puede hacer dos cosas:
igor@402: \begin{itemize}
jerojasro@516: \item Permitir que se pueda visualizar el historial del repositorio que
igor@417:   está sirviendo desde navegadores web.
igor@417: \item Hablar el protocolo de conexión de Mercurial para que puedan hacer
igor@417:   \hgcmd{clone} o \hgcmd{pull} (jalar) cambios de tal repositorio.
igor@402: \end{itemize}
igor@417: En particular, \hgcmd{serve} no permitirá que los usuarios remotos
igor@417: puedan \emph{modificar} su repositorio.  Es de tipo solo lectura.
igor@417: 
igor@417: Si está comenzando con Mercurial, no hay nada que le impida usar
igor@417: \hgcmd{serve} para servir un repositorio en su propio computador, y
igor@417: usar posteriormente órdenes como \hgcmd{clone}, \hgcmd{incoming}, para
igor@417: comunicarse con el servidor como si el repositorio estuviera alojado
igor@417: remotamente. Lo que además puede ayudarle a adecuarse rápidamente para
igor@417: usar comandos en repositorios alojados en la red.
igor@417: 
igor@417: \subsection{Cuestiones adicionales para tener en cuenta}
igor@417: 
igor@417: Dado que permite lectura sin autenticación a todos sus clientes,
igor@417: debería usar \hgcmd{serve} exclusivamente en ambientes en los cuáles
igor@417: no tenga problema en que otros vean, o en los cuales tenga control
igor@417: completo acerca de quien puede acceder a su red y jalar cambios de su
igor@417: repositorio.
igor@417: 
igor@417: La orden \hgcmd{serve} no tiene conocimiento acerca de programas
igor@417: cortafuegos que puedan estar instalados en su sistema o en su red. No
igor@417: puede detectar o controlar sus cortafuegos.  Si otras personas no
igor@417: pueden acceder a su instancia \hgcmd{serve}, lo siguiente que debería hacer
igor@417: (\emph{después} de asegurarse que tienen el URL correcto) es verificar
igor@417: su configuración de cortafuegos.
igor@417: 
igor@417: De forma predeterminada, \hgcmd{serve} escucha conexiones entrantes en
igor@417: el puerto~8000.  Si otro proceso está escuchando en tal puerto, usted
igor@417: podrá especificar un puerto distinto para escuchar con la opción
jerojasro@522: \hgopt{serve}{-p}.
igor@417: 
igor@417: Normalmente, cuando se inicia \hgcmd{serve}, no imprime nada, lo cual
igor@417: puede ser desconcertante.  Si desea confirmar que en efecto está
igor@417: ejecutándose correctamente, y darse cuenta qué URL debería enviar a
igor@417: sus colaboradores, inícielo con la opción \hggopt{-v}.
igor@402: 
igor@427: \section{Uso del protocolo Secure Shell (ssh)}
igor@402: \label{sec:collab:ssh}
igor@402: 
igor@427: Usted puede publicar y jalar cambios en la red de forma segura usando
igor@427: el protocolo Secure Shell (\texttt{ssh}).  Para usarlo satisfactoriamente,
igor@427: tendrá que hacer algo de configuración a nivel de cliente o el
igor@427: servidor.
igor@427: 
jerojasro@542: Si no está familiarizado con ssh, es un protocolo de red que le permite
igor@427: comunicarse con seguridad con otro computador.  Para usarlo con
igor@427: Mercurial, estará estableciendo una o más cuentas de usuario en un
igor@427: servidor de forma tal que los usuarios remotos puedan entrar y
igor@427: ejecutar órdenes.
igor@427: 
igor@427: (Si ssh le \emph{es} familiar, encontrará probablemente elemental una
igor@427: porción del material a continuación.)
igor@427: 
igor@427: \subsection{Cómo leer y escribir URLs de ssh}
igor@427: 
igor@427: Los URLs de ssh tienden a lucir de la siguiente forma:
igor@402: \begin{codesample2}
igor@402:   ssh://bos@hg.serpentine.com:22/hg/hgbook
igor@402: \end{codesample2}
igor@402: \begin{enumerate}
igor@427: \item La parte ``\texttt{ssh://}'' indica a Mercurial que use el
igor@427:   protocolo ssh.
igor@427: \item El componente ``\texttt{bos@}'' indica el nombre del usuario que
jerojasro@542:   está entrando al servidor.  Puede omitirlo si el usuario remoto
igor@427:   coincide con el usuario local.
igor@427: \item ``\texttt{hg.serpentine.com}'' es el nombre del servidor al cual
igor@427:   se desea entrar.
igor@427: \item El ``:22'' identifica el número del puerto en el servidor al cual
igor@427:   se conectará.  El predeterminado es el~22, así que solamente
igor@427:   necesitará especificar esa porción si \emph{no} está usando el
igor@427:   puerto~22.
igor@427: \item La última porción del URL es la ruta local al repositorio en el
igor@427:   servidor.
igor@402: \end{enumerate}
igor@402: 
igor@427: El componente de la ruta del URL para ssh es una fuente de confusión,
igor@427: puesto que no hay una forma estándar para que las herramientas puedan
igor@427: interpretarlo.  Algunos programas se comportan de manera distinta a
igor@427: otros cuando manipulan estas rutas.  No es la situación ideal, pero
igor@427: es muy poco probable que vaya a cambiar.  Por favor lea los párrafos
igor@427: siguientes cuidadosamente.
igor@427: 
igor@427: Mercurial trata la ruta al repositorio en el servidor como relativo al
jerojasro@542: directorio personal del usuario remoto.  Por ejemplo, si el usuario
igor@427: \texttt{foo} en el servidor tiene el directorio casa
igor@427: \dirname{/home/foo},
igor@427: entonces un URL ssh que contenga en su ruta a \dirname{bar}
igor@427: \emph{realmente} se refiere al directorio \dirname{/home/foo/bar}.
igor@427: 
igor@427: Si desea especificar una ruta relativa a otro directorio de usuario,
igor@427: puede usar una ruta que comience con un caracter tildado, seguido del
jerojasro@520: nombre del usuario (llamémosle \texttt{otrousuario}, así
igor@427: \begin{codesample2}
igor@427:   ssh://server/~otrousuario/hg/repo
igor@427: \end{codesample2}
igor@427: 
igor@427: Y si realmente desea especifica una ruta \emph{absoluta} en el
igor@427: servidor, comience con el componente de la ruta con dos barras como
igor@427: en el siguiente ejemplo:
igor@402: \begin{codesample2}
igor@402:   ssh://server//absolute/path
igor@402: \end{codesample2}
igor@402: 
igor@427: \subsection{Encontrar un cliente ssh para su sistema}
igor@427: 
igor@427: Casi todos los sistemas tipo Unix vienen con OpenSSH preinstalado.  Si
igor@427: usted está usando un sistema de estos, ejecute \Verb|which ssh| para
igor@427: identificar dónde está instalada la orden \command{ssh} (usualmente
igor@427: estará en \dirname{/usr/bin}).  Si por casualidad no está presente,
igor@427: vea la documentación de sus sistema para lograr instalarlo.
igor@427: 
igor@427: En Windows, tendrá que escoger primero un cliente adecuado para
igor@427: descargarlo.  Hay dos alternativas:
igor@402: \begin{itemize}
igor@427: \item El excelente paquete PuTTY~\cite{web:putty} de Simon Tatham, que
igor@427:   ofrece un suite completo de órdenes de cliente ssh.
igor@427: \item Si tiene alta tolerancia al dolor, puede usar el porte de Cygwin
igor@427:   para OpenSSH.
igor@402: \end{itemize}
igor@427: En cualquier caso, tendrá que editar su fichero \hgini\ para indicarle
igor@427: a Mercurial dónde encontrar la orden real del cliente.  Por ejemplo, si
igor@427: está usando PuTTY, tendrá que usar la orden \command{plink} como un
igor@427: cliente de línea de órdenes.
igor@402: \begin{codesample2}
igor@402:   [ui]
igor@427:   ssh = C:/ruta/a/plink.exe -ssh -i "C:/ruta/a/mi/llave/privada"
igor@402: \end{codesample2}
igor@402: 
igor@402: \begin{note}
igor@427:   La ruta a \command{plink} no debería contener espacios o caracteres
igor@427:   en blanco, o Mercurial no podrá encontrarlo correctamente (por lo
igor@427:   tanto, probablemente no sería buena idea colocarlo en 
igor@427:   \dirname{C:\\Program Files}
igor@402: \end{note}
igor@402: 
igor@427: \subsection{Generar un par de llaves}
igor@427: 
jerojasro@542: Para evitar la necesidad de teclear una clave de forma repetitiva cada
igor@427: vez que necesita usar el cliente, recomiendo generar un par de llaves.
igor@427: En un sistema tipo Unix, la orden \command{ssh-keygen} también se
igor@427: comportará bien. En Windows, si está usando PuTTY, la orden
igor@427: \command{puttygen} es la que necesitará.
igor@427: 
igor@427: Cuando genera un par de llaves, se aconseja \emph{comedidamente} 
igor@427: protegerlas con una frase de clave.  (La única oportunidad en la cual
igor@427: usted querría identificarse una única vez, es cuando está usando
igor@427: el protocolo ssh para tareas automatizadas en una red segura.)
igor@427: 
igor@427: No basta con generar un par de llaves.  Se requiere adicionar una llave
igor@427: pública al conjunto de llaves autorizadas para todos los usuarios
igor@427: remotos que se vayan a autenticar.  Para aquellos servidores que usen
jerojasro@520: OpenSSH (la gran mayoría), significará añadir la llave pública a la
igor@427: lista en el fichero llamado \sfilename{authorized\_keys} en su
igor@427: directorio \sdirname{.ssh}.
igor@427: 
igor@427: En sistemas tipo Unix, su llave pública tendrá la extensión
igor@427: \filename{.pub}.  Si usa \command{puttygen} en Windows, puede
igor@427: guardar la llave pública en un fichero de su elección, o pegarla desde
igor@427: la ventana en la cual se despliega directamente en el fichero
igor@427: \sfilename{authorized\_keys}.
igor@402: 
igor@428: \subsection{Uso de un agente de autenticación}
igor@428: 
jerojasro@542: Un agente de autenticación es un demonio que almacena frases clave en
jerojasro@520: memoria (olvidará las frases clave si sale y vuelve a entrar).  Un cliente
igor@428: ssh notará si está corriendo, y solicitará una frase clave.  Si no hay
igor@428: un agente de autenticación corriendo, o el agente no almacena la frase
igor@428: clave necesaria, tendrá que teclear su frase clave cada vez que 
jerojasro@520: Mercurial intente comunicarse con un servidor para usted (p.e.~cada vez
igor@428: que jale o publique cambios).
igor@428: 
igor@428: El problema de almacenar frases claves en un agente es que es posible
igor@428: para un atacante bien preparado recuperar el texto plano de su frase
jerojasro@542: clave, en algunos casos incluso si su sistema sea muy alternante.
igor@428: Es su decisión si es un riesgo aceptable.  Lo que si es seguro es que
igor@428: evita reteclear.
igor@428: 
igor@428: En sistemas tipo Unix, el agente se llama \command{ssh-agent}, y
igor@428: usualmente se ejecuta automáticamente cuando usted entra.  Tendrá que
igor@428: usar la orden \command{ssh-add} para añadir frases claves al agente.  En
igor@428: Windows, si está usando PuTTY, la orden \command{pageant} actúa como
jerojasro@542: el agente.  Añade un icono a su barra del sistema que le permitirá
igor@428: almacenar frases clave.
igor@428: 
igor@428: \subsection{Configurar el lado del servidor apropiadamente}
igor@428: 
igor@428: Dado que puede ser dispendioso configurar ssh si usted es nuevo, hay 
igor@428: una variedad de cosas que podrían ir mal.  Añada piense primero en
igor@428: Mercurial y hay mucho más en qué pensar.  La mayor parte de estos
jerojasro@542: problemas potenciales ocurren en el lado del servidor, no en el cliente.
igor@428: Las buenas noticias es que una vez tiene una configuración funcional,
igor@428: usualmente continuará trabajando indefinidamente.
igor@428: 
igor@428: Antes de intentar que Mercurial hable con un servidor ssh, es mejor
igor@428: asegurarse que puede usar la orden normal \command{ssh} o \command{putty}
igor@428: para comunicarse con el servidor primero.  Si tiene problemas usando
igor@428: estas órdenes directamente, de seguro Mercurial no funcionará.  Pero aún,
igor@428: esconderá el problema subyacente.  Cuando desee revisar un problema
igor@428: relacionado con ssh y Mercurial, debería asegurarse primero que las
igor@428: órdenes de ssh en el lado del cliente funcionan primero, \emph{antes}
igor@428: de preocuparse por si existe un problema con Mercurial.
igor@428: 
igor@428: Lo primero para asegurar en el lado del servidor es que puede entrar
igor@428: desde otra máquina.  Si no puede entrar con \command{ssh} o 
igor@428: \command{putty}, el mensaje de error que obtenga le puede dar pistas
igor@428: de qué ha ido mal.  Los problemas más comunes son los siguientes:
igor@402: \begin{itemize}
jerojasro@542: \item Si obtiene un error de ``conexión rehusada'', es posible que no 
jerojasro@542:   haya un demonio SSH corriendo en el servidor o que no pueda accederse
igor@428:   a él por configuraciones de cortafuegos.
igor@428: \item Si obtiene un error de ``no hay ruta hasta el servidor'', puede
igor@428:   tener la dirección del servidor incorrecta o un cortafuegos con
igor@428:   bloqueo agresivo que no permitirá su existencia.
igor@428: \item Si obtiene un mensaje de ``permiso denegado'', puede que haya
igor@428:   tecleado mal el usuario en el servidor, o que haya tecleado
igor@428:   incorrectamente la frase clave o la clave del usuario remoto.
igor@402: \end{itemize}
jerojasro@542: En resumen, si tiene problemas al comunicarse con el demonio ssh del
igor@428: servidor, primero asegúrese de que está corriendo.  En muchos sistemas
igor@428: estará instalado, pero deshabilitado de forma predeterminada.  Una vez
igor@428: que haya hecho este paso tendrá que revisar si el cortafuegos del
igor@428: servidor está configurado para recibir conexiones entrantes en el
jerojasro@542: puerto en el cual el demonio de ssh está escuchando (usualmente el~22).
igor@428: No trate de buscar otras posibilidades exóticas o configuraciones
jerojasro@542: erradas hasta que haya revisado primero estas dos.
igor@428: 
igor@428: Si está usando un agente de autenticación en el lado del cliente para
igor@428: almacenar las frase claves de sus contraseñas, debería poder entrar al
igor@428: servidor sin necesidad de que se le solicite frases claves o
igor@428: contraseñas.  Si se le pregunta alguna, a continuación algunas
igor@428: posibilidades:
igor@402: \begin{itemize}
igor@428: \item Puede haber olvidado usar \command{ssh-add} o
igor@428:   \command{pageant} para guardar la frase clave.
igor@428: \item Puede haber almacenado una frase clave errónea para la llave.
igor@402: \end{itemize}
igor@428: Si se le solicita la clave del usuario remoto, hay otras posibilidades
igor@428: que deben revisarse:
igor@402: \begin{itemize}
igor@428: \item O bien el directorio del usuario o su directorio \sdirname{.ssh}
igor@428:   tiene permisos excesivamente abiertos.  Como resultado el daemonio
igor@428:   ssh no creerá o leerá su fichero \sfilename{authorized\_keys}.  
igor@428:   Por ejemplo, un directorio casa o \sdirname{.ssh} causará aveces
igor@428:   este síntoma.
igor@428: \item El fichero de usuario \sfilename{authorized\_keys} puede tener
igor@428:   un problema.  Si alguien distinto al usuario es dueño o puede
jerojasro@542:   escribir el fichero, el demonio ssh no confiará o lo leerá.
igor@402: \end{itemize}
igor@402: 
igor@428: En un mundo ideal, debería poder ejecutar la siguiente orden
jerojasro@542: exitosamente, y debería imprimir exactamente una línea de salida,
igor@428: la fecha y hora actual.
igor@428: \begin{codesample2}
igor@428:   ssh miservidor fecha
igor@428: \end{codesample2}
igor@428: 
jerojasro@542: Si en su servidor tiene guión que se ejecuta a la entrada e imprime
igor@428: letreros o cualquier otra cosa, incluso cuando se ejecutan órdenes no
igor@428: interactivas como esta, debería arreglarlo antes de continuar, de
igor@428: forma que solamente imprima algo si se ejecuta interactivamente.  De
jerojasro@525: otra forma estos letreros al menos llenarán la salida de Mercurial. 
jerojasro@525: Incluso podrían causar problemas potenciales cuando se ejecuten
igor@428: órdenes de forma remota.  Mercurial intenta detectar e ignorar los
igor@428: letreros en sesiones no interactivas de \command{ssh}, pero no es
igor@428: a prueba de tontos.  (Si edita sus guiones de entrada en el servidor,
jerojasro@542: la forma usual de ver si un guión de línea de comandos se ejecuta en un intérprete
igor@428: interactivo, es verificar el código de retorno de la orden
igor@428: \Verb|tty -s|.)
igor@428: 
igor@428: Cuando verifique que el venerado ssh funciona en su servidor, el
igor@428: paso siguiente es asegurar que Mercurial corre en el servidor.  La
igor@428: orden siguiente debería ejecutarse satisfactoriamente:
igor@428: \begin{codesample2}
igor@428:   ssh miservidor hg version
igor@428: \end{codesample2}
igor@428: Si ve un mensaje de error en lugar de la salida usual de 
igor@428: \hgcmd{version}, será porque no ha instalado Mercurial en
igor@428: \dirname{/usr/bin}.  No se preocupe si este es el caso; no necesita
igor@428: hacerlo.  Pero debería revisar los posibles problemas presentados a
igor@428: continuación:
igor@402: \begin{itemize}
igor@428: \item Está instalado Mercurial en el servidor?  Se que suena trivial
igor@428:   pero es mejor revisar!
igor@428: \item Tal vez la ruta de búsqueda de la interfaz de órdenes
igor@428:   (normalmente vía la variable de ambiente \envar{PATH}) simplemente
igor@428:   está mal configurada.
igor@428: \item Puede ser que su variable de ambiente \envar{PATH} soalamente
igor@428:   apunte al lugar en el cual está el ejecutable \command{hg} si la
igor@428:   sesión de entrada es interactiva.  Puede suceder si establece la
jerojasro@542:   ruta en el guión de línea de comandos de entrada incorrecto.  Consulte la
igor@428:   documentación de su línea de órdenes.
igor@428: \item La variable de ambiente \envar{PYTHONPATH} puede requerir la
jerojasro@542:   ruta a los módulos de Mercurial en Python.  Puede que ni siquiera
igor@428:   está establecida; podría estar incorrecta; o puede ser que se
igor@428:   establezca únicamente cuando hay entradas interactivas.
igor@402: \end{itemize}
igor@402: 
igor@428: Si puede ejecutar \hgcmd{version} sobre una conexión ssh,
igor@428: felicitaciones!  Ha logrado la interacción entre el cliente y el 
igor@428: servidor.  Ahora debería poder acceder a los repositorios de
igor@428: Mercurial que tiene el usuario en el servidor.  Si tiene problemas
igor@428: con Mercurial y ssh en este punto, intente usar la opción
igor@428: \hggopt{--debug} para tener información más clara de lo que está
igor@428: sucediendo.
igor@428: 
igor@428: \subsection{Compresión con ssh}
igor@428: 
igor@428: Mercurial no comprime datos cuando usa el protocolo ssh, dado que
igor@428: el protocolo puede comprimir datos transparentemente.  Pero el
igor@428: comportamiento predeterminado del cliente ssh es \emph{no}
igor@428: solicitar compresión.
igor@428: 
jerojasro@520: Sobre cualquier red distinta a una LAN rápida (incluso con una red
igor@428: inalámbrica), hacer uso de compresión puede mejorar el rendimiento
igor@428: de las operaciones de Mercurial que involucren la red.  Por ejemplo,
igor@428: sobre WAN, alguien ha medido la compresión reduciendo la cantidad
igor@428: de tiempo requerido para clonar un repositorio particularmente
igor@428: grande de~51 minutos a~17 minutos.
igor@428: 
igor@428: Tanto \command{ssh} como \command{plink} aceptan la opción
igor@428: \cmdopt{ssh}{-C} que activa la compresión.  Puede editar fácilmente
igor@428: su \hgrc\ para habilitar la compresión para todos los usos de
igor@428: Mercurial sobre el protocolo ssh.
igor@402: \begin{codesample2}
igor@402:   [ui]
igor@402:   ssh = ssh -C
igor@402: \end{codesample2}
igor@402: 
igor@428: Si usa \command{ssh}, puede reconfigurarlo para que siempre use
igor@428: compresión cuando se comunique con su servidor.  Para hacerlo,
jerojasro@520: edite su fichero \sfilename{.ssh/config} (que puede no existir
igor@428: aún), de la siguiente forma:
igor@402: \begin{codesample2}
igor@402:   Host hg
igor@402:     Compression yes
igor@428:     HostName hg.ejemplo.com
igor@428: \end{codesample2}
igor@428: Que define un alias, \texttt{hg}.  Cuando lo usa con la orden
igor@428: \command{ssh} o con una URL de Mercurial con protocolo\texttt{ssh},
igor@428: logrará que \command{ssh} se conecte a \texttt{hg.ejemplo.com}
igor@428: con compresión.  Que le dará un nombre más corto para teclear y
igor@428: compresión, los cuales por derecho propio son buenos.
igor@402: 
igor@429: \section{Uso de CGI a través de HTTP}
igor@402: \label{sec:collab:cgi}
igor@402: 
igor@429: Dependiendo de qué tan ambicioso sea, configurar la interfaz CGI
igor@429: de Mercurial puede tomar desde unos minutos hasta varias horas.
igor@429: 
igor@429: Comenzaremos con el ejemplo más sencillo, y nos dirigiremos hacia
igor@429: configuraciones más complejas.  Incluso para el caso más básico
igor@429: necesitará leer y modificar su configuración del servidor web.
igor@402: 
igor@402: \begin{note}
igor@429:   Configurar un servidor web es una actividad compleja, engorrosa y
igor@429:   altamente dependiente del sistema.  De ninguna manera podremos
igor@429:   cubrir todos los casos posibles con los cuales pueda encontrarse.
jerojasro@542:   Use su discreción y juicio respecto a las secciones siguientes.
igor@429:   Esté preparado para cometer muchas equivocaciones, y emplear
igor@429:   bastante tiempo leyendo sus bitácoras de error del servidor.
igor@402: \end{note}
igor@402: 
igor@429: \subsection{Lista de chequeo de la configuración del servidor web}
igor@429: 
igor@429: Antes de continuar, tómese un tiempo para revisar ciertos aspectos de
igor@429: la configuración de su sistema:
igor@402: 
igor@402: \begin{enumerate}
igor@429: \item ¿Tiene un servidor web?  Mac OS X viene con Apache, pero otros
igor@429:   sistemas pueden no tener un servidor web instalado.
igor@429: \item Si tiene un servidor web instalado, ¿Está ejecutándose?  En la
igor@429:   mayoría de sistemas, aunque esté presente, puede no estar habilitado
igor@429:   de forma predeterminada.
igor@429: \item ¿u servidor está configurado para permitir ejecutar programas
igor@429:   CGI en el directorio donde planea hacerlo?  Casi todos los
igor@429:   servidores de forma predeterminada explícitamente inhiben la
igor@429:   habilidad de ejecutar programas CGI.
igor@402: \end{enumerate}
igor@402: 
igor@429: Si no tiene un servidor web instalado, y no tiene cierta experiencia
igor@429: configurando  Apache, debería considerar usar el servidor web
igor@429: \texttt{lighttpd} en lugar de Apache.  Apache tiene una reputación
igor@429: bien ganada por su configuración barroca y confusa.
igor@429: A pesar de que \texttt{lighttpd} tiene menos características que
igor@429: Apache en ciertas áreas, las mismas no son relevantes para servir
igor@429: repositorios de Mercurial.  Definitivamente es mucho más sencillo
igor@429: comenzar con \texttt{lighttpd} que con Apache.
igor@429: 
igor@429: \subsection{Configuración básica de CGI}
igor@429: 
igor@429: En sistemas tipo Unix es común que los usuarios tengan un subdirectorio
igor@429: con un nombre como \dirname{public\_html} en su directorio personal,
igor@429: desde el cual pueden servir páginas web.  Un fichero llamado \filename{foo}
igor@429: en este directorio será visible en una URL de la forma
igor@402: \texttt{http://www.example.com/\~username/foo}.
igor@402: 
igor@429: Para comenzar, encuentre el guión \sfilename{hgweb.cgi} que debería
igor@429: estar presente en su instalación de Mercurial.  Si no puede
igor@429: encontrarlo rápidamente una copia local en su sistema, puede
igor@429: descargarlo del repositorio principal de Mercurial en
igor@402: \url{http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi}.
igor@402: 
igor@429: Tendrá que copiar este guión en su directorio \dirname{public\_html},
igor@429: y asegurarse que sea ejecutable.
igor@402: \begin{codesample2}
igor@402:   cp .../hgweb.cgi ~/public_html
igor@402:   chmod 755 ~/public_html/hgweb.cgi
igor@402: \end{codesample2}
igor@429: El argumento \texttt{755} de la orden \command{chmod} es un poco más
igor@429: general que hacerlo ejecutable: Asegura que el guión sea ejecutable
jerojasro@542: por cualquiera, y que el ``grupo'' y los ``otros'' \emph{no}  tengan
igor@429: permiso de escritura.  Si dejara los permisos de escritura abiertos,
igor@429: , el subsistema \texttt{suexec} de  Apache probablemente se negaría
igor@429: a ejecutar el guión.  De hecho, \texttt{suexec} también insiste en que
igor@429: el \emph{directorio} en el cual reside el guión no tenga permiso de
igor@429: escritura para otros.
igor@402: \begin{codesample2}
igor@402:   chmod 755 ~/public_html
igor@402: \end{codesample2}
igor@402: 
igor@436: \subsubsection{¿Qué \emph{podría} resultar mal?}
igor@402: \label{sec:collab:wtf}
igor@402: 
igor@436: Cuando haya ubicado el CGI en el sitio correspondiente con un navegador
igor@436: intente visitar el URL \url{http://myhostname/~myuser/hgweb.cgi},
igor@436: \emph{sin} dejarse abatir por un error.  Hay una alta probabilidad de
igor@436: que esta primera visita al URL sea fallida, y hay muchas razones posibles
igor@436: para este comportamiento.  De hecho, podría toparse con cada uno de los
igor@436: errores que describimos a continuación, así que no deje de leerlos
igor@436: cuidadosamente.   A continuación presento los problemas que yo tuve en
igor@436: un sistema con Fedora~7, con una instalación nueva de Apache, y una
igor@436: cuenta de usuario que creé específicamente para desarrollar este
igor@436: ejercicio.
igor@436: 
igor@436: Su servidor web puede tener directorios por usuario deshabilitados. Si
igor@436: usa Apache, busque el fichero de configuración que contenga la
igor@436: directiva \texttt{UserDir}.  Si no está presente en sitio alguno, los
igor@436: directorios por usuario están deshabilitados.  Si la hay, pero su
igor@436: valor es \texttt{disabled}, los directorios por usuario estarán
igor@436: deshabilitados. La directiva \texttt{UserDir} en caso contrario tendrá
igor@436: el nombre del subdirectorio bajo el cual Apache mirará en el
igor@436: directorio de cada usuario, por ejemplo \dirname{public\_html}.
igor@436: 
igor@436: Los permisos de sus ficheros pueden ser demasiado restrictivos.  El
igor@436: servidor web debe poder recorrer su directorio personal y los
igor@436: directorios que estén bajo \dirname{public\_html}, además de tener
jerojasro@542: permiso para leer aquellos que estén adentro.  A continuación una
igor@436: receta rápida para hacer que sus permisos estén acordes con las
igor@436: necesidades básicas.
igor@402: \begin{codesample2}
igor@402:   chmod 755 ~
igor@402:   find ~/public_html -type d -print0 | xargs -0r chmod 755
igor@402:   find ~/public_html -type f -print0 | xargs -0r chmod 644
igor@402: \end{codesample2}
igor@402: 
igor@436: Otra posibilidad con los permisos es que obtenga una ventana
jerojasro@542: completamente en blanco cuando trata de cargar el guión. En cuyo
igor@436: caso, es posible que los permisos que tiene son \emph{demasiado
igor@436:  permisivos}.  El subsistema \texttt{suexec} de Apache no ejecutará un
jerojasro@542: guión que tenga permisos de escritura para el grupo o el planeta, por
igor@436: ejemplo.
igor@436: 
igor@436: Su servidor web puede estar configurado para evitar la ejecución de
igor@436: programas CGI en los directorios de usuario.  A continuación presento
igor@436: una configuración predeterminada por usuario en mi sistema Fedora.
igor@436: 
igor@402: \begin{codesample2}
igor@402:   <Directory /home/*/public_html>
igor@402:       AllowOverride FileInfo AuthConfig Limit
igor@402:       Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
igor@402:       <Limit GET POST OPTIONS>
igor@402:           Order allow,deny
igor@402:           Allow from all
igor@402:       </Limit>
igor@402:       <LimitExcept GET POST OPTIONS>
igor@402:           Order deny,allow
igor@402:           Deny from all
igor@402:       </LimitExcept>
igor@402:   </Directory>
igor@402: \end{codesample2}
igor@436: Si encuentra un grupo de instrucciones de \texttt{Directory} similares
igor@436: en su configuración de Apache,  la directiva a revisar es \texttt{Options}.
igor@436: Adicione \texttt{ExecCGI} al final de esta lista en caso de que haga
igor@436: falta y reinicie su servidor web.
igor@436: 
jerojasro@542: Si resulta que Apache le muestra el texto del guión CGI en lugar de
jerojasro@520: ejecutarlo, necesitará o bien descomentar (si se encuentra presente) o
igor@436: adicionar una directiva como la siguiente:
igor@402: \begin{codesample2}
igor@402:   AddHandler cgi-script .cgi
igor@402: \end{codesample2}
igor@402: 
igor@436: Otra posibilidad es que observe una traza de Python en colores
igor@436: informando que no puede importar un módulo relacionado con
igor@436: \texttt{mercurial}.  Esto es un gran progreso!  El servidor es capaz
jerojasro@542: de ejecutar su guión CGI.  Este error solamente ocurrirá si está
igor@436: ejecutando una instalación privada de Mercurial en lugar de una
igor@436: instalación para todo el sistema.  Recuerde que el servidor que
igor@436: ejecuta el programa CGI no cuenta con variables de ambiente de las
igor@436: cuales usted si dispone en una sesión interactiva.  Si este error le
igor@436: ocurre, edite su copia de \sfilename{hgweb.cgi} y siga las indicaciones
igor@436: dentro del mismo para establecer de forma adecuada su variable de
igor@436: ambiente \envar{PYTHONPATH}.
igor@436: 
igor@436: Finalmente, si encuentra \emph{otra} traza a todo color de Python al visitar
igor@436: el URL: Esta seguramente se referirá a que no puede encontrar
igor@436: \dirname{/path/to/repository}.  Edite su script \sfilename{hgweb.cgi}
jerojasro@542: y reemplace la cadena \dirname{/path/to/repository} con la ruta
igor@436: completa al repositorio que desea servir.
igor@436: 
igor@436: En este punto, cuando trate de recargar la página, deberá visualizar
jerojasro@517: una linda vista HTML del historial de su repositorio. Uff!
igor@402: 
igor@438: \subsubsection{Configuración de lighttpd}
igor@438: 
igor@438: En mi intención de ser exhaustivo, intenté configurar
igor@438: \texttt{lighttpd}, un servidor web con creciente aceptación, para
igor@438: servir los repositorios de la misma forma como lo describí
igor@438: anteriormente con Apache. Después de superar los problemas que mostré
igor@438: con Apache, muchos de los cuáles no son específicos del servidor.  Por
igor@438: lo tanto estaba seguro de que mis permisos para directorios y ficheros
igor@438: eran correctos y que mi guión \sfilename{hgweb.cgi} también lo era.
igor@438: 
igor@438: Dado que ya Apache estaba en ejecución correctamente, lograr que
jerojasro@520: \texttt{lighttpd} sirviera mi repositorio fue rápido (en otras
igor@438: palabras, si está tratando de usar \texttt{lighttpd}, debe leer la
igor@438: sección de Apache).  Primero tuve que editar la sección
igor@438: \texttt{mod\_access} para habilitar \texttt{mod\_cgi} y
igor@438: \texttt{mod\_userdir}, los cuales estaban inhabilitados en mi
igor@438: instalación predeterminada.  Añadí posteriormente unas líneas al final
igor@438: del fichero de configuración, para hacer lo propio con los módulos.
igor@402: \begin{codesample2}
igor@402:   userdir.path = "public_html"
igor@402:   cgi.assign = ( ".cgi" => "" )
igor@402: \end{codesample2}
igor@438: Hecho esto, \texttt{lighttpd} funcionó inmediatamente para
igor@438: mí. Configuré \texttt{lighttpd} antes que Apache, tuve casi los mismos
igor@438: reparos a nivel de configuración del sistema que con Apache.  De todas
igor@438: maneras, considero que \texttt{lighttpd} es bastante más sencillo de
igor@438: configurar que Apache, a pesar de haber usado Apache por lo menos por
igor@438: una década, y esta fue mi primera experiencia con \texttt{lighttpd}.
igor@438: 
jerojasro@542: \subsection{Compartir varios repositorios con un guión CGI}
igor@438: 
igor@438: El guión \sfilename{hgweb.cgi} permite publicar únicamente un
igor@438: repositorio, una restricción frustrante.  Si desea publicar más de uno
igor@438: sin complicarse con varias copias del mismo guión, cada una con un
igor@438: nombre distinto, resulta mucho mejor usar el guión
igor@438: \sfilename{hgwebdir.cgi}.
igor@438: 
igor@438: El procedimiento para configurar \sfilename{hgwebdir.cgi} tiene una
igor@438: porción adicional frente al trabajo requerido con
igor@438: \sfilename{hgweb.cgi}.  Primero se debe obtener una copia del
igor@438: guión. Si no tiene una a mano, puede descargar una copia del ftp
igor@438: principal del repositorio de Mercurial en
igor@402: \url{http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi}.
igor@402: 
igor@438: Necesitará una copia del guión en su directorio \dirname{public\_html},
igor@438: y asegurarse de que sea ejecutable.
igor@402: \begin{codesample2}
igor@402:   cp .../hgwebdir.cgi ~/public_html
igor@402:   chmod 755 ~/public_html ~/public_html/hgwebdir.cgi
igor@402: \end{codesample2}
igor@438: Con la configuración básica, intente visitar en su navegador
jerojasro@524: \url{http://myhostname/~myuser/hgwebdir.cgi}.  Debería mostrar una
igor@438: lista vacía de repositorios.  Si obtiene una ventana en blanco o un
igor@438: mensaje de error, verifique la lista de problemas potenciales en la 
igor@438: sección~\ref{sec:collab:wtf}.
igor@438: 
igor@438: El guión \sfilename{hgwebdir.cgi} se apoya en un fichero externo de
igor@438: configuración.  En principio, busca un fichero llamado
igor@438: \sfilename{hgweb.config} en el mismo directorio.  Tendrá que crear el
igor@438: fichero, y permitir lectura de todo el mundo.  El formato del fichero
igor@438: es similar a un fichero ``ini'' de Windows, que puede interpretar el módulo
igor@438: \texttt{ConfigParser}~\cite{web:configparser} de Python.
igor@438: 
igor@438: La forma más sencilla de configurar \sfilename{hgwebdir.cgi} es con
igor@438: una sección llamada \texttt{collections}.  Esta publicará automáticamente
igor@438: \emph{todos} los repositorios en los directorios que usted
igor@438: especifique.  La sección debería lucir así:
igor@402: \begin{codesample2}
igor@402:   [collections]
igor@438:   /mi/ruta = /mi/ruta
igor@438: \end{codesample2}
igor@438: Mercurial lo interpreta buscando el nombre del directorio que esté a la
igor@438: \emph{derecha} del símbolo ``\texttt{=}''; encontrando repositorios en
igor@438: la jerarquía de directorios; y usando el texto a la \emph{izquierda}
igor@438: para eliminar el texto de los nombres que mostrará en la interfaz
igor@438: web.  El componente restante de la ruta después de esta eliminación
igor@438: usualmente se llama ``ruta virtual''.
igor@438: 
igor@438: Dado el ejemplo de arriba, si tenemos un repositorio cuya ruta local es
igor@438: \dirname{/mi/ruta/este/repo}, el guión CGI eliminará la porción inicial
igor@438: \dirname{/mi/ruta} del nombre y publicará el repositorio con una ruta
igor@438: virtual \dirname{este/repo}.  Si el URL base de nuestro guión CGI es
igor@438: \url{http://myhostname/~myuser/hgwebdir.cgi}, el URL completo al
igor@438: repositorio será
igor@402: \url{http://myhostname/~myuser/hgwebdir.cgi/this/repo}.
igor@402: 
igor@438: Si reemplazamos \dirname{/mi/ruta} en el lado izquierdo de este
igor@438: ejemplo con \dirname{/mi}, \sfilename{hgwebdir.cgi} eliminará solamente
igor@438: \dirname{/mi} del nombre del repositorio, y nos ofrecerá la ruta
igor@438: virtual \dirname{ruta/este/repo} en lugar de \dirname{este/repo}.
igor@438: 
igor@438: El guión \sfilename{hgwebdir.cgi} buscará recursivamente en cada
jerojasro@516: directorio listado en la sección \texttt{collections} de su fichero de
igor@438: configuración, pero \texttt{no} hará el recorrido recursivo dentro de
igor@438: los repositorios que encuentre.
igor@438: 
igor@438: El mecanismo de \texttt{collections} permite publicar fácilmente
igor@438: repositorios de una forma ``hacer y olvidar''.  Solamente requiere
jerojasro@516: configurar el guión CGI y el fichero de configuración una vez.
igor@438: Después de eso puede publicar y sacar de publicación un repositorio en
igor@438: cualquier momento incluyéndolo o excluyéndolo de la jerarquía de
igor@438: directorios en la cual le haya indicado a \sfilename{hgwebdir.cgi} que
igor@438: mirase.
igor@438: 
igor@438: \subsubsection{Especificación explícita de los repositorios a publicar}
igor@438: 
igor@438: Además del mecanismo \texttt{collections}, el guión
igor@438: \sfilename{hgwebdir.cgi} le permite publicar una lista específica de
igor@438: repositorios.  Para hacerlo, cree una sección \texttt{paths}, con los
igor@438: contenidos de la siguiente forma:
igor@402: \begin{codesample2}
igor@402:   [paths]
igor@438:   repo1 = /mi/ruta/a/un/repo
igor@438:   repo2 = /ruta/a/otro/repo
igor@438: \end{codesample2}
igor@438: En este caso, la ruta virtual (el componente que aparecerá en el URL)
igor@438: está en el lado derecho de cada definición, mientras que la ruta al
igor@438: repositorio está a la derecha.  Note que no tiene que haber relación
igor@438: alguna entre la ruta virtual que elija y el lugar del repositorio en
jerojasro@516: su sistema de ficheros.
igor@438: 
igor@438: Si lo desea, puede usar los dos mecanismos \texttt{collections} y
jerojasro@516: \texttt{paths} simultáneamente en un sólo fichero de configuración.
igor@402: 
igor@402: \begin{note}
igor@438:   Si varios repositorios tienen la misma ruta virtual,
igor@438:   \sfilename{hgwebdir.cgi} no reportará error.  Pero se comportará
igor@438:   impredeciblemente.
igor@402: \end{note}
igor@402: 
igor@438: \subsection{Descarga de ficheros fuente}
igor@438: 
jerojasro@542: La interfaz web de Mercurial permite a los usuarios descargar
igor@438: un conjunto de cualquier revisión.  Este fichero contendrá una réplica
igor@438: del directorio de trabajo en la revisión en cuestión, pero no
igor@438: contendrá una copia de los datos del repositorio.
igor@438: 
igor@438: De forma predeterminada esta característica no está habilitada.  Para
igor@438: lograrlo adicione un \rcitem{web}{allow\_archive} a la sección \rcsection{web}
igor@438: de su fichero \hgrc.
igor@438: 
igor@438: \subsection{Opciones de configuración en Web}
igor@438: 
jerojasro@520: Las interfaces web de Mercurial (la orden \hgcmd{serve}, y los guiones
igor@438: \sfilename{hgweb.cgi} y \sfilename{hgwebdir.cgi}) tienen varias
igor@438: opciones de configuración para establecer. Todas ellas en la sección
igor@438: \rcsection{web}.
igor@402: \begin{itemize}
jerojasro@516: \item[\rcitem{web}{allow\_archive}] Determina cuáles tipos de ficheros
igor@438:   de descarga soportará Mercurial.  Si habilita esta característica,
igor@438:   los usuarios de la interfaz web podrán descargar una copia de la
igor@438:   revisión del repositorio que estén viendo. Para activar la
igor@438:   característica de descarga de fichero, el valor tendrá una secuencia
igor@438:   de palabras extraídas de la lista de abajo.
igor@402:   \begin{itemize}
igor@438:   \item[\texttt{bz2}] Un fichero \command{tar} con el método de
jerojasro@542:     compresión \texttt{bzip2}.  Tiene la mejor tasa de compresión,
igor@438:     pero usa más tiempo de procesamiento en el servidor.
igor@438:   \item[\texttt{gz}] Un fichero \command{tar}, comprimido con
igor@438:     \texttt{gzip}.
igor@438:   \item[\texttt{zip}] Un fichero \command{zip}, comprimido con LZW.
jerojasro@542:     Este formato posee la peor tasa de compresión, pero es muy usado en
igor@438:     el mundo Windows.
igor@402:   \end{itemize}
igor@438:   Si da una lista vacía o no tiene la entrada
igor@438:   \rcitem{web}{allow\_archive}, esta característica se deshabilitará.
igor@438:   A continuación un ejemplo de cómo habilitar los tres formatos soportados.
igor@402:   \begin{codesample4}
igor@402:     [web]
igor@402:     allow_archive = bz2 gz zip
igor@402:   \end{codesample4}
igor@438: \item[\rcitem{web}{allowpull}] Booleano.  Determina si la interfaz web
igor@438:   permite a los usuarios remotos emplear \hgcmd{pull} y \hgcmd{clone}
igor@438:   sobre el repositorio~HTTP.  Si se coloca \texttt{no} o
igor@438:   \texttt{false}, solamente la porción de los procesos
igor@440:   ``orientados-a-humanos'' se habilita de la interfaz web.
jerojasro@520: \item[\rcitem{web}{contact}] Cadena.  Una cadena en forma libre (pero
igor@440:   preferiblemente corta) que identifica a la persona o grupo a cargo
igor@440:   del repositorio.  Usualmente contiene el nombre y la dirección de
igor@440:   correo electrónico de una persona o de una lista de correo.  Aveces
igor@440:   tiene sentido colocar esta opción en el fichero \sfilename{.hg/hgrc}
igor@440:   del repositorio, pero en otras oportunidades en el \hgrc\ global si
igor@440:   todos los repositorios tienen un único mantenedor.
igor@440: \item[\rcitem{web}{maxchanges}] Entero.  La cantidad máxima de
igor@440:   conjuntos de cambios a mostrar de forma predeterminada en cada página.
igor@440: \item[\rcitem{web}{maxfiles}] Entero.  La cantidad máxima
igor@440:   predeterminada de ficheros modificados a desplegar en una página.
igor@440: \item[\rcitem{web}{stripes}] Entero.  Si la interfaz web despliega
igor@440:   ``franjas'' para facilitar la visualización alineada de filas cuando
igor@440:   se ve una tabla, este valor controla la cantidad de filas en cada
igor@440:   franja.
igor@440: \item[\rcitem{web}{style}] Controla la plantilla que Mercurial usa para
igor@440:   desplegar la interfaz web.  Mercurial viene con dos plantillas web,
igor@440:   llamadas \texttt{default} y \texttt{gitweb} (La primera es
igor@440:   visualmente más atractiva).  Puede especificar una plantilla propia;
igor@440:   consulte el capítulo~\ref{chap:template}.  A continuación mostramos
igor@440:   cómo habilitar el estilo \texttt{gitweb}.
igor@402:   \begin{codesample4}
igor@402:     [web]
igor@402:     style = gitweb
igor@402:   \end{codesample4}
igor@440: \item[\rcitem{web}{templates}] Ruta.  Directorio en el que se buscarán
jerojasro@516:   los ficheros plantilla.  De forma predeterminada, busca en el
igor@440:   directorio en el cual fue instalado.
igor@402: \end{itemize}
igor@440: Si usa \sfilename{hgwebdir.cgi}, puede añadir otras opciones de
igor@440: configuración en una sección \section{web} del fichero
igor@440: \sfilename{hgweb.config} en lugar del fichero \hgrc\, si lo considera
igor@440: más conveniente.  Estas opciones son \rcitem{web}{motd} y
igor@402: \rcitem{web}{style}.
igor@402: 
igor@440: \subsubsection{Opciones específicas para repositorios individuales}
igor@440: 
igor@440: Ciertas opciones de configuración de \rcsection{web} deben estar
igor@440: ubicadas en el \sfilename{.hg/hgrc} de un repositorio en lugar del
igor@440: fichero del usuario o el \hgrc global.
igor@402: \begin{itemize}
igor@440: \item[\rcitem{web}{description}] Cadena.  Una cadena de forma
jerojasro@520:   libre (preferiblemente corta) que describa los contenidos o el
igor@440:   propósito del repositorio.
igor@440: \item[\rcitem{web}{name}] Cadena.  El nombre para visualizar en la
igor@440:   interfaz web del repositorio. Sustituye el nombre predeterminado, el
igor@440:   cual es el último componente de la ruta del repositorio.
igor@402: \end{itemize}
igor@402: 
igor@440: \subsubsection{Opciones específicas a la orden \hgcmd{serve}}
igor@440: 
igor@440: Algunas opciones en la sección \rcsection{web} de un fichero \hgrc\
igor@440: son de uso exclusivo para la orden \hgcmd{serve}.
igor@402: \begin{itemize}
igor@440: \item[\rcitem{web}{accesslog}] Ruta.  El nombre del fichero en el cual
igor@440:   se escribe la bitácora de acceso.  En principio, la orden
igor@440:   \hgcmd{serve} escribe esta información a la salida estándar, no a un
igor@440:   fichero. Las líneas de la bitácora se escriben en un formato de
igor@440:   fichero ``combinado'' estándar, usado por casi todos los servidores
igor@440:   web.
igor@440: \item[\rcitem{web}{address}] Cadena.  La dirección local en la cual el
igor@440:   servidor debe escuchar peticiones entrantes.  En principio, el
igor@440:   servidor escucha en todas las direcciones.
igor@440: \item[\rcitem{web}{errorlog}] Ruta.  El nombre de un fichero en el
igor@440:   cual escribir la bitácora de error.  En principio, la orden
igor@440:   \hgcmd{serve} escribe esta información en la salida de error
igor@440:   estándar, no a un fichero.
igor@440: \item[\rcitem{web}{ipv6}] Booleano.  Si se usa o no el protocolo
igor@440:   IPv6. En principio, IPv6 no se usa.
igor@440: \item[\rcitem{web}{port}] Entero.  El número del puerto~TCP en el cuál
igor@440:   el servidor escuchará.  El puerto predeterminado es el~8000.
igor@402: \end{itemize}
igor@402: 
igor@440: \subsubsection{Elegir el fichero \hgrc\ correcto para las
igor@440:   configuraciones de \rcsection{web}}
igor@440: 
igor@440: Es importante recordar que un servidor web como Apache o
igor@440: \texttt{lighttpd} se ejecutarán bajo el usuario~ID que generalmente no
igor@440: es el suyo  Los guiones CGI ejecutados por su servidor, tales como
igor@440: \sfilename{hgweb.cgi}, se ejecutarán también con el usuario~ID.
igor@440: 
igor@440: Si añade opciones \rcsection{web} a su fichero personal \hgrc\, Los
igor@440: guiones CGI no leerán tal fichero \hgrc\.  Tales configuraciones
igor@440: solamente afectarán el comportamiento de la orden \hgcmd{serve} cuando
igor@440: usted lo ejecuta.  Para logar que los guiones CGI vean sus
igor@440: configuraciones, o bien cree un fichero \hgrc\ en el directorio hogar
igor@440: del usuario ID que ejecuta su servidor web, o añada tales
jerojasro@457: configuraciones al fichero global \hgrc.
igor@402: 
igor@402: 
igor@402: %%% Local Variables: 
igor@402: %%% mode: latex
igor@402: %%% TeX-master: "00book"
igor@402: %%% End: