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: igor@412: Adicionalmente la interfaz provee feeds de RSS de los cambios de los igor@412: repositorios. Que le permite ``subscribirse''a un repositorio usando igor@412: su herramienta de lectura de feeds 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 igor@412: permitirlo) publicar cambios en el mismo. El protocolo de tunneling 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: igor@412: Los proyectos de cierta talla tienden naturlamente 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} igor@412: La rama principal contendtrá 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 igor@417: incluso rogar a otro desarrollador para que tome sus cabmios, 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 igor@417: acepten los cambios. Si usted es reconocido y matiene 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: igor@417: Tícamente 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 igor@417: puede moverse. A pesar de que está intimamente 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: igor@427: Si no está familizarizado 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 igor@427: está entrando al servidor. Puede omitirl 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 igor@427: directorio chasa 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: igor@427: Para evitar la necesidad de teclera 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: igor@428: Un agente de autentitcación es un daemonio 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 igor@428: clave, en alguntos 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 igor@428: el agente. Añade un ícono 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 igor@428: problemas potenciales occuren 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} igor@428: \item Si obitene un error de ``conexión rehusada'', es posible que no igor@428: haya un daemonio 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} igor@428: En resumen, si tiene problemas al comunicarse con el daemonio 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@520: puerto en el cual el daemonio de ssh está escuchando (usualmente el~22). igor@428: No trate de buscar otras posibilidades exóticas o configuraciones igor@428: erradas haste 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@516: escribir el fichero, el daemonio 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 igor@428: exitósamente, 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: igor@428: Si en su servidor tiene guión que se ejecuta a la entrada e imprimie 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 igor@428: otra forma estos letreros al menos llenarán la salida de Mercurial. igor@428: 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, igor@428: la forma usual de ver si un guión de script se ejecuta en un shell 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 igor@428: ruta en el guión de shell 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 igor@428: ruta a los módulos de Mercurial en Python. Puede que nisiquiera 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. igor@429: Use su discresió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 igor@429: por cualquiera, y que el ``grupo'' y los ``otros'' \emph{not} 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 igor@436: permiso para leer aquellos que estén adentro. A continúació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 igor@436: completamente en blanco cuando trata de cargar el script. 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 igor@436: script que tenga permisos de escritura para el group 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: igor@402: AllowOverride FileInfo AuthConfig Limit igor@402: Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec igor@402: igor@402: Order allow,deny igor@402: Allow from all igor@402: igor@402: igor@402: Order deny,allow igor@402: Deny from all igor@402: igor@402: 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: igor@436: Si resulta que Apache le muestra el texto del script 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 igor@436: de ejecutar su script 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} igor@436: y reemplaze 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: igor@438: \subsection{Compartir varios repositorios con un script 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 igor@438: \url{http://myhostname/~myuser/hgwebdir.cgi}. Debería mostar 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: igor@438: La interfaz web de Mercurial permite a los ususarios 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 igor@438: compresión \texttt{bzip2}. Tiene la mejor taza 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. igor@438: Este formato posee la peor tasa de compresió, 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: