<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V4.5-Based Extension//EN" "../../../share/xml/freebsd45.dtd"> <article lang='es'> <title><application>Perforce</application> en el contexto del desarrollo de &os;</title> <articleinfo> <authorgroup> <author> <firstname>Scott</firstname> <surname>Long</surname> <affiliation> <address><email>scottl@FreeBSD.org</email> </address> </affiliation> </author> </authorgroup> <legalnotice id="trademarks" role="trademarks"> &tm-attrib.freebsd; &tm-attrib.cvsup; &tm-attrib.general; </legalnotice> <pubdate>$FreeBSD$</pubdate> <releaseinfo>$FreeBSD$</releaseinfo> </articleinfo> <sect1 id="intro"> <title>Introducción</title> <para>El proyecto &os; utiliza el sistema de control de versiones <application>Perforce</application> para gestionar proyectos experimentales que todavía no están listos para ser incluidos en el repositorio principal de CVS.</para> <sect2 id="resources"> <title>Disponibilidad, documentación y recursos</title> <para>Aunque que el producto <application>Perforce</application> es un producto comercial, el software cliente que se encarga de interactuar con el servidor se distribuye libremente. Pueden descargarse versiones binarias del mismo desde el sitio web de <application>Perforce</application>: <ulink url="http://www.perforce.com/perforce/loadprog.html"></ulink>. </para> <para>Existe un cliente gráfico, pero la mayoría de la gente utiliza la aplicación de línea de órdenes, <command>p4</command>. Este documento trata sobre el uso de dicha herramienta para la línea de órdenes.</para> <para>En <ulink url="http://www.perforce.com/perforce/technical.html"></ulink> encontrará documentación <quote>online</quote> detallada.</para> <para>Se recomienda encarecidamente leer la <quote>guía de usuario</quote> y el <quote>manual de Perforce</quote>. La aplicación <application>p4</application> dispone de una extensa ayuda <quote>online</quote> a la que puede accederse mediante la orden <command>p4 help</command>.</para> <para>El servidor &os; <application>Perforce</application> se encuentra en <hostid role="fqdn">perforce.freebsd.org</hostid>, puerto <literal>1666</literal>. Puede navegar por el repositorio desde <ulink url="http://perforce.freebsd.org"></ulink>. Ciertas partes del repositorio se exportan automáticamente hacia diversos servidores <application>CVSup</application>.</para> </sect2> </sect1> <sect1 id="start"> <title>Los comienzos</title> <para>El primer paso para utilizar <application>Perforce</application> consiste en obtener una cuenta en el servidor. Si ya dispone de una cuenta en <hostid role="domainname">FreeBSD.org</hostid> entre en <hostid role="hostname">freefall</hostid> y ejecute el siguiente comando utilizando una contraseña distinta del acceso de su &os; o de cualquier otro mecanismo de autenticación SSH:</para> <screen>&prompt.user; <userinput>/usr/local/bin/p4newuser</userinput></screen> <para>Por supuesto si no tiene una cuenta en <hostid role="domainname">FreeBSD.org</hostid> necesitará coordinarse con su mentor.</para> <para>El siguiente paso consiste en establecer las variables de entorno que necesita <command>p4</command> y en verificar que puede conectarse al servidor. Es necesario especificar la variable <envar>P4PORT</envar> para realizar cualquier operación. Dicha variable indica el servidor <application>Perforce</application> con el que se va a trabajar. En el caso del Proyecto &os;, créela con el siguiente valor:</para> <screen>&prompt.user; <userinput>export P4PORT=perforce.freebsd.org:1666</userinput></screen> <note> <para>Los usuarios con acceso <quote>shell</quote> al <quote>cluster</quote> <hostid role="domainname">FreeBSD.org</hostid> pueden querer encapsular el protocolo cliente-servidor de <application>Perforce</application> a través de un túnel SSH, en cuyo caso la variable de arriba debería establecerse al valor <literal>localhost</literal>.</para> </note> <para>El servidor &os; también necesita que se establezcan las variables <envar>P4PASSWD</envar> y <envar>P4USER</envar>. Utilice el nombre de usuario y la contraseña anteriores del siguiente modo:</para> <screen>&prompt.user; <userinput>export P4USER=<replaceable>nombre_de_usuario</replaceable></userinput> &prompt.user; <userinput>export P4PASSWD=<replaceable>contraseña</replaceable></userinput></screen> <para>Compruebe que todo funciona mediante la siguiente orden:</para> <screen>&prompt.user; <userinput>p4 info</userinput></screen> <para>A resultas de esta orden debería ver información referente al servidor. Si no es así compruebe que la variable <envar>P4PORT</envar> tiene el valor correcto. </para> </sect1> <sect1 id="clients"> <title>Clientes</title> <para>El sistema <application>Perforce</application> proporciona acceso al repositorio y mantiene el estado del cliente de forma individualizada. En términos de <application>Perforce</application>, un cliente es una especificación que asocia <footnote><para> Este término, que también puede traducirse como asociar o asignar, suele aparecer en la jerga de la administración de sistemas como <quote>mapear</quote>. </para></footnote> ficheros y directorios desde el repositorio hasta la máquina local. Cada usuario puede poseer varios clientes, y cada cliente puede acceder a distintas partes del repositorio (incluso a varias partes que se solapan entre sí). El cliente también especifica el directorio raíz del árbol de directorios sobre el que se realiza la asociación y la máquina donde efectivamente está dicho árbol. Es por esto que si pretende trabajar en varias máquinas tendrá que usar varios clientes. </para> <para>Puede acceder a los clientes mediante <command>p4 client</command>. Si se ejecuta esta orden sin argumentos aparece una plantilla del cliente dentro de un editor, permitiendo de esta forma crear un nuevo cliente. Los campos importantes de esta plantilla se explican a continuación:</para> <variablelist> <varlistentry> <term><literal>Client:</literal></term> <listitem> <para>Este es el nombre de la especificación del cliente. Puede ser cualquier cosa, pero debe ser una cadena única dentro del servidor <application>Perforce</application>. Suelen usarse nombres como <literal><replaceable>nombre_de_usuario</replaceable>_<replaceable>nombre_de_máquina</replaceable></literal>, que permite identificar fácilmente a los clientes cuando se navega por ellos. Por defecto hay ya un nombre, que se corresponde con el nombre de la máquina.</para> </listitem> </varlistentry> <varlistentry> <term><literal>Description:</literal></term> <listitem> <para>Este campo suele consistir en un breve texto descriptivo que ayude a identificar al cliente.</para> </listitem> </varlistentry> <varlistentry> <term><literal>Root:</literal></term> <listitem> <para>Se trata del directorio local que actuará como directorio raíz para todos los ficheros dentro de la asociación en el cliente. Debe ser una localización única dentro del sistema de ficheros que no se solape con otros ficheros o clientes <application>Perforce</application>.</para> </listitem> </varlistentry> <varlistentry> <term><literal>Options:</literal></term> <listitem> <para>La mayoría de las opciones por defecto son correctas y válidas para todo el mundo, aunque suele ser recomendable comprobar que estén activadas las opciones <option>compress</option> y <option>rmdir</option> y que no tienen el prefijo <literal>no</literal>. Los detalles de cada una de estas opciones están en la documentación de <application>Perforce</application>. </para> </listitem> </varlistentry> <varlistentry> <term><literal>LineEnd:</literal></term> <listitem> <para>Este parámetro gestiona las conversiones CR-LF y debe dejarse tal cual salvo que sus necesidades específicas requieran cambiarlo.</para> </listitem> </varlistentry> <varlistentry> <term><literal>View:</literal></term> <listitem> <para>Aquí es donde están las asociaciones de ficheros servidor-a-local. El valor por defecto es:</para> <programlisting>//depot/... //<replaceable>cliente</replaceable>/...</programlisting> <para>Esto asociará por completo el repositorio <application>Perforce</application> al directorio <filename class="directory">Root</filename> del cliente. <emphasis>NO USE ESTE VALOR POR DEFECTO</emphasis>. El repositorio de &os; es enorme e intentar asociarlo y sincronizarse con dicho repositorio tardará muchísimo y consumirá enormes recursos. Asocie sólamente la sección del repositorio en la que va a trabajar. Por ejemplo, hay un árbol para el proyecto smpng en <filename class="directory">//depot/projects/smpng</filename>. Una asociación en ese caso sería algo así:</para> <programlisting>//depot/projects/smpng/... //<replaceable>cliente</replaceable>/...</programlisting> <para>Los <literal>...</literal> deben tomarse literalmente tal cual están. Es un dialecto de <application>Perforce</application> para decir <quote>este directorio y todos los ficheros y directorios por debajo de él.</quote>.</para> <para>Una <quote>vista</quote> (View) puede contener múltiples asociaciones. Vamos a suponer que quiere asociar los árboles de SMPng y de NFS. Su <quote>View</quote> sería algo así:</para> <programlisting>//depot/projects/smpng/... //<replaceable>cliente</replaceable>/smpng/... //depot/projects/nfs/... //<replaceable>cliente</replaceable>/nfs/...</programlisting> <para>Recuerde que <replaceable>cliente</replaceable> es el nombre del cliente que se especificó en la sección <literal>Client</literal>, pero en la sección <literal>View</literal> además se utiliza para resolver al directorio especificado en la sección <literal>Root</literal>.</para> <para>También tenga en cuenta que el mismo fichero o directorio no puede asociarse más de una vez dentro de una única vista. La orden del siguiente ejemplo no es correcta y producirá resultados imprevistos: </para> <programlisting>//depot/projects/smpng/... //<replaceable>cliente</replaceable>/smpng-esto/... //depot/projects/smpng/... //<replaceable>cliente</replaceable>/smpng-lo_otro/...</programlisting> <para>Las <quote>vistas</quote> son la parte compleja del proceso de aprendizaje de <application>Perforce</application>, así que no tenga miedo de hacer tantas preguntas como estime oportunas.</para> </listitem> </varlistentry> </variablelist> <para>Puede listar los clientes existentes mediante <command>p4 clients</command>. Puede listarlos sin que sufran modificaciones mediante <command>p4 client -o <replaceable>nombre_cliente</replaceable></command>.</para> <para>Siempre que se interactue con ficheros en <application>Perforce</application> la variable de entorno <envar>P4CLIENT</envar> debe contener al nombre del cliente que se está utilizando, es decir:</para> <screen>&prompt.user; <userinput>export P4CLIENT=<replaceable>nombredemicliente</replaceable></userinput></screen> <para>Fíjese en que las asociaciones del cliente en el repositorio no son exclusivos; varios clientes pueden estar asociados en la misma zona del respositorio. Esto permite el trabajo en equipo sobre el mismo código, permitiendo que distintas personas accedan y modifiquen la misma parte del respositorio. </para> </sect1> <sect1 id="syncing"> <title>Sincronizaciones</title> <para>Una vez definida la especificación del cliente y una vez establecida la variable de entorno <envar>P4CLIENT</envar>, el siguiente paso consiste en recuperar los ficheros para el cliente en cuestión desde el servidor hasta la máquina local. Esto se realiza con <command>p4 sync</command>, el cual indica a <application>Perforce</application> que sincronice los ficheros locales con los del repositorio. La primera vez que se ejecuta descargará todos los ficheros. Las siguientes ejecuciones sólo descargarán aquellos ficheros que hayan cambiado desde la última ejecución de la orden. Gracias a esto es posible sincronizar sus fuentes con las de otras personas con las que esté trabajando.</para> <para>Las operaciones de sincronización sólo atañen a aquellos ficheros cuyas modificaciones han sido transmitidas a <application>Perforce</application>. Si se modifica o borra un fichero en local sin informar de ello al servidor la ejecución de un <quote>sync</quote> no reflejará dichos cambios. No obstante, la ejecución de <command>p4 sync -f</command> sincrozará incondicionalmente todos los ficheros, sin que importe su estado. Esto resulta útil para solucionar problemas cuando se cree que el árbol pueda haber sufrido algún tipo de corrupción.</para> <para>Puede sincronizarse parte del árbol o del cliente especificando una ruta relativa a la orden <quote>sync</quote>. Por ejemplo, para sincronizar sólo el directorio <filename class="directory">ufs</filename> del proyecto <literal>smpng</literal> ejecute lo siguiente:</para> <screen>&prompt.user; <userinput>cd <replaceable>raizdelproyecto</replaceable>/smpng</userinput> &prompt.user; <userinput>p4 sync src/sys/ufs/...</userinput></screen> <para>El uso de rutas locales relativas funciona en muchas otras órdenes <command>p4</command>.</para> </sect1> <sect1 id="branches"> <title>Ramas</title> <para>Una de las características más interesantes de <application>Perforce</application> es la posibilidad de crear ramas. Las ramas son muy sencillas de crear y también resulta muy fácil mover cambios entre distintas ramas (como se verá más adelante). Las ramas también nos permiten realizar trabajos muy experimentales dentro de un entorno de <quote>sandbox</quote>, sin necesidad de tener que preocuparnos por las colisiones con otros usuarios o por desestabilizar el árbol principal. Además, las ramas proporcionan el aislamiento necesario frente a los errores que se cometen cuando se aprende a manejar el sistema <application>Perforce</application>. Vistas estas ventajas es lógico que cada proyecto disponga de su propia rama y en &os; recomendamos encarecidamente este esquema. También se recomienda la aplicación frecuente de los cambios realizados.</para> <para>El repositorio <application>Perforce</application> (conocido como el <quote>depósito</quote>, o <quote>depot</quote> en la jerga de <application>Perforce</application>) es un único árbol plano. Se accede a cada fichero a través de una sencilla ruta bajo el directorio <filename class="directory">//depot</filename>, tanto si se trata de un fichero de nueva creación como si proviene de una ramificación. Esto supone una gran diferencia con respecto a sistemas como CVS, donde cada rama se encuentra en la misma ruta que su rama padre. En <application>Perforce</application> el servidor mantiene las relaciones entre los ficheros padre e hijo, pero los ficheros en sí están bajo sus propias rutas.</para> <para>El primer para para crear una rama consiste en crear una especificación de rama. Es similar a la especificación de un cliente, pero se crea mediante la orden <command>p4 branch <replaceable>nombre_de_rama</replaceable></command>.</para> <para>Veamos los campos más importantes:</para> <variablelist> <varlistentry> <term><literal>Branch</literal></term> <listitem> <para>El nombre de la rama. Puede ser cualquier nombre, pero debe ser único en el repositorio. La convención que se usa en &os; es <replaceable>nombre_de_usuario</replaceable>_<replaceable>nombre_del_proyecto</replaceable>.</para> </listitem> </varlistentry> <varlistentry> <term><literal>Description</literal></term> <listitem> <para>Puede poner aquí un texto simple que describa la rama.</para> </listitem> </varlistentry> <varlistentry> <term><literal>View</literal></term> <listitem> <para>Esto es la asociación de la rama. En lugar de asociar desde el <quote>depósito</quote> hacia la máquina local como una asociación de cliente, se crea una asociación entre la rama padre y la rama hija dentro del <quote>depósito</quote>. Por ejemplo, puede querer crear una rama del proyecto smpng. La asociación resultaría en algo parecido a esto:</para> <programlisting>//depot/projects/smpng/... //depot/projects/mi-super-smpng/...</programlisting> <para>O puede crear una rama totalmente nueva a partir de las fuentes de &os;:</para> <programlisting>//depot/vendor/freebsd/... //depot/projects/mi-nuevo-proyecto/...</programlisting> <para>Esto asociará el HEAD del árbol de &os; a su nueva rama.</para> </listitem> </varlistentry> </variablelist> <para>La creación de la especificación de rama únicamente graba la especificación en sí misma dentro del servidor. No modifica el <quote>depósito</quote> ni cambia ningún fichero. El directorio que se declara en la rama permanece vacío en el servidor hasta que se comience a llenar. </para> <para>Para rellenar la rama primero debemos editar el cliente con la orden <command>p4 client</command> y asegurarnos de que el directorio de rama está asociado en el cliente. Puede ser necesario añadir una línea <literal>View</literal> como esta:</para> <programlisting>//depot/projects/mi-nuevo-proyecto/... //<replaceable>micliente</replaceable>/mi-nuevo-proyecto/...</programlisting> <para>El siguiente paso consiste en ejecutar <command>p4 integrate</command>, como se describe en la siguiente sección.</para> </sect1> <sect1 id="Integrations"> <title>Integraciones</title> <para><quote>Integración</quote> es el término que se utiliza en <application>Perforce</application> para describir la acción de mover cambios desde una parte del <quote>depósito</quote> a otra. Se suele realizar junto con las órdenes creación y mantenimiento de ramas. Una integración es necesaria cuando se quiere rellenar inicialmente una rama y cuando se quieren mover cambios realizados en la rama padre hacia la rama hija, o de la la rama hija a la padre. Un caso muy común es la integración periódica desde el árbol original de &os; hacia la rama hija propia del usuario. El servidor <application>Perforce</application> mantiene el estado de los cambios en cada rama y sabe cuándo hay cambios que pueden integrarse de una rama a otra.</para> <para>La forma más común de hacer una integración se muestra en la siguiente orden: </para> <screen>&prompt.user; <userinput>p4 integrate -b <replaceable>nombrederama</replaceable></userinput></screen> <para><replaceable>nombrederama</replaceable> es el nombre que se ha dado a la especificación de rama, tal y como se explicó en la sección anterior. Esta orden indica a <application>Perforce</application> que busque cambios en la rama padre que todavía no se hayan aplicado a la rama hija. En base a los cambios encontrados se prepara un listado de diferencias a aplicar. Si la integración se realiza por primera vez sobre una rama (por ejemplo cuando se realiza una operación de rellenado inicial) los ficheros de la rama padre simplemente se copiarán en la ubicación en la rama hija de la máquina local.</para> <para>Una vez que la operación de integración ha finalizado se debe ejecutar <command>p4 resolve</command>, que aplicará los cambios y resolverá posibles conflictos. Los conflictos puede surgir debido a cambios que se solapan al encontrarse tanto en fichero de la rama padre como en la copia del fichero de la rama hija. Normalmente no suelen aparecer conflictos y <application>Perforce</application> puede calcular rápidamente cómo unir los cambios. Para ejecutar una operación de resolución (<quote>resolve</quote>) utilice las siguientes órdenes:</para> <screen>&prompt.user; <userinput>p4 resolve -as</userinput> &prompt.user; <userinput>p4 resolve</userinput></screen> <para>La primera invocación indica a <application>Perforce</application> que una automáticamente los cambios y que acepte aquellos ficheros que no den conflictos. La segunda invocación permite inspeccionar cada fichero con conflictos y resolver de forma manual dichas incompatiblidades.</para> <para>Una vez hecha la integración de los ficheros llega el momento de aplicar los cambios al repositorio. Para ello se emplearemos la orden <command>p4 submit</command>, cuyo uso se explica en la siguiente sección.</para> </sect1> <sect1 id="submit"> <title>Aplicación de cambios en el repositorio</title> <para>Los cambios que se han realizado en local se deben aplicar en el contenido del servidor <application>Perforce</application> para mayor seguridad frente a pérdidas y para que otras personas puedan acceder a dichos cambios; esto se hace con la orden <command>p4 submit</command>. Cuando se ejecuta esta orden se abre una plantilla (<quote>submit template</quote>) en el editor. &os; dispone de una platilla personalizada, de la que a continuación se explican los campos más importantes:</para> <programlisting>Description: <enter description here> PR: Submitted by: Reviewed by: Approved by: Obtained from: MFP4 after:</programlisting> <para>es decir</para> <programlisting>Descripción: <Introduzca una descripción> PR: Enviado por: Revisado por: Aprobado por: Obtenido de: MFP4 tras:</programlisting> <para>Se considera una buena práctica proporcionar al menos dos o tres frases que describan los cambios entregados. Debería declarar aquí qué hacen dichos cambios, por qué se han hecho de esa forma o qué problemas intenta resolver con ellos. También conviene explicar qué APIs cambian y qué otros efectos secundarios pueden tener. Este texto debe sustituir a la línea <literal><enter description here></literal> que aparece en la plantilla. Debe recubrir las líneas y comenzar cada línea con una tabulación. Las etiquetas de más abajo son específicas de &os; y puede eliminarlas si no resultan útiles o apropiadas en su contexto.</para> <programlisting>Files:</programlisting> <para>Este campo se rellena automáticamente con todos los ficheros que el cliente etiquetó en el servidor con estados de adición, borrado, integración o edición. Le aconsejamos que revise esta lista y elimine de ella los ficheros que todavía no esten listos.</para> <para>Una vez guardada la sesión de su editor tiene lugar la entrega de los datos al servidor. Esto significa que las copias locales de los ficheros entregados se enviarán al servidor. Si algo va mal durante este proceso se cancelará la entrega y se avisará al usuario de que la entrega se ha convertido en una lista de cambios que deben corregirse y reenviarse. Las entregas son atómicas, es decir, si un fichero falla la entrega se cancela en su totalidad.</para> <para>Los cambios efectuados en el servidor no pueden cancelarse una vez hechos, pero sí que pueden cancelarse si, dentro aún del editor, se sale de él sin cambiar el texto del campo <literal>Description</literal>. <application>Perforce</application> se quejará la primera vez que intente salir y le devolverá al editor. Si sale por segunda vez el editor cancelará la operación. Devolver el repositorio al estado anterior a un cambio ya efectuado es un proceso muy complicado y no hay un procedimiento estándar, por lo que depende del caso concreto.</para> </sect1> <sect1 id="editing"> <title>Edición</title> <para>En el servidor se almacena y mantiene el estado de cada fichero del cliente. Para evitar colisiones entre distintas personas trabajando al mismo tiempo en el mismo fichero <application>Perforce</application> presta atención a qué ficheros están abiertos en modo de edición, y utiliza esa información para poder gestionar posteriormente las operaciones de entrega, las sincronizaciones y las integraciones.</para> <para>Para abrir un fichero para editarlo utilice <command>p4 edit</command> de la siguiente forma:</para> <screen>&prompt.user; <userinput>p4 edit <replaceable>nombredefichero</replaceable></userinput></screen> <para>Esto marca el fichero en el servidor con el estado de edición, lo que permite entregar el fichero posteriormente una vez realizados los cambios oportunos, o lo etiqueta como de tratamiento especial cuando se está efectuando una operación de integración o sincronización. Tenga en cuenta que la edición no es exclusiva en <application>Perforce</application>. Varias personas pueden tener el mismo fichero en estado de edición (será informado de ello si es necesario cuando ejecute <command>edit</command>), pero podrá entregar sus cambios incluso cuando haya otras personas que tengan ese fichero en estado de edición.</para> <para>Cuando alguien entregue un cambio de un fichero que usted esté editando necesitará cotejar sus modificaciones con las de la otra u otras personas para poder aplicar correctamente sus modifaciones al repositorio. La forma más sencilla de hacerlo es ejecutar <command>p4 sync</command> o <command>p4 submit</command> y dejar que el programa encuentre algún conflicto, y a continuación ejecutar <command>p4 resolve</command> para <quote>resolver</quote> manualmente los conflictos y aceptar los cambios de la otra persona en su copia del fichero. Hecho esto, utilice <command>p4 submit</command> para aplicar sus cambios en el repositorio.</para> <para>Si posee un fichero abierto para su edición y quiere descartar los cambios y devolverlo a su estado original ejecute <command>p4 revert</command> de la siguiente forma:</para> <screen>&prompt.user; <userinput>p4 revert <replaceable>nombredefichero</replaceable></userinput></screen> <para>Esto resincroniza el fichero con el contenido del servidor y elimina en el servidor el atributo de edición para ese fichero. Se perderá cualquier cambio que haya hecho en local. Esto resulta muy útil cuando se han efectuado una serie de cambios en un determinado fichero y se decide posteriormente que no se desean aplicar dichos cambios en el servidor.</para> <para>Cuando se sincroniza un fichero se marca como sólo lectura en el sistema de ficheros. Aunque se pueden sobreescribir fácilmente dichos permisos se aplican para recordar al usuario de una forma educada que para ello se debe utilizar <command>p4 edit</command>. Los ficheros modificados en local pero que no están en estado de edición pueden sobreescribirse al ejecutar <command>p4 sync</command>.</para> </sect1> <sect1 id="changes"> <title>Cambios, descripciones e historial</title> <para>Puede ver el historial de cambios realizados al <quote>depósito</quote> de <application>Perforce</application> puede consultarse mediante <command>p4 changes</command>. Esta orden proporciona una breve descripción de cada cambio, quién la realizó y cúal es el número de modificación. Si lo que se quiere son los detalles de un cambio en concreto utilice <command>p4 describe <replaceable>numero_de_cambio</replaceable></command>. Esta orden proporciona el <quote>log</quote> y los <quote>diffs</quote> de dicho cambio. Normalmente se utilizan las opciones <option>-du</option> o <option>-dc</option> para generar <quote>diffs</quote> unificados o contextuales, respectivamente, en lugar del formato del <quote>diff</quote> nativo.</para> <para><command>p4 filelog <replaceable>nombre_de_fichero</replaceable></command> muestra el historial de un fichero, incluyendo todas sus modificaciones, integraciones y ramas que contenga.</para> </sect1> <sect1 id="diffs"> <title><quote>diffs</quote></title> <para>Existen dos formas de generar <quote>diffs</quote> de ficheros en <application>Perforce</application>, bien entre cambios locales que todavía no se han entregado o bien entre dos árboles (o dentro de una misma rama) del <quote>depósito</quote>. Estos <quote>diffs</quote> se generan mediante órdenes distintas, <option>diff</option> y <option>diff2</option>:</para> <variablelist> <varlistentry> <term><command>p4 diff</command></term> <listitem> <para>Ese comando genera un <quote>diff</quote> entre los cambios locales y los cambios de ficheros en estado de edición. Los parámetros <option>-du</option> y <option>-dc</option> permiten crear <quote>diffs</quote> unificados o contextuales, respectivamente. También se puede establecer la variable <envar>P4DIFF</envar> para que apunte a un <quote>diff</quote> local. Le recomendamos encarecidamente usar esta orden para revisar sus cambios antes de aplicarlos en el servidor.</para> </listitem> </varlistentry> <varlistentry> <term><command>p4 diff2</command></term> <listitem> <para>Esta orden crea un <quote>diffs</quote> entre ficheros dados en el <quote>depósito</quote>, o entre ficheros especificados en una especificación de rama. La operación tiene lugar en el servidor, así que la variable <envar>P4DIFF</envar> no surte ningún efecto, aunque las opciones <option>-du</option> y <option>-dc</option> sí pueden usarse. Las dos formas de esta orden son:</para> <screen>&prompt.user; <userinput>p4 diff2 -b <replaceable>nombrederama</replaceable></userinput></screen> <para>y</para> <screen>&prompt.user; <userinput>p4 diff2 //depot/<replaceable>ruta1</replaceable> //depot/<replaceable>ruta2</replaceable></userinput></screen> </listitem> </varlistentry> </variablelist> <para>En todos los casos los <quote>diffs</quote> se muestran en la salida estándar. Por desgracia <application>Perforce</application> usa un formato de <quote>diffs</quote> que resulta ser ligeramente incompatible con las herramientas Unix estándar <command>diff</command> y <command>patch</command>. La utilización de la variable <envar>P4DIFF</envar> para que apunte al verdadero &man.diff.1; puede paliar este problema, o al menos en ciertos casos, puesto sólo funciona con la orden <command>p4 diff</command>. La salida de <option>diff2</option> debe procesarse para que sea de alguna utilidad (la opción <option>-u</option> de <option>diff2</option> producirá <quote>diffs</quote> unificados que serán <emphasis>más o menos compatibles</emphasis>, pero no esto no incluye ficheros nuevos o borrados. Este <quote>script</quote> puede serle de utilidad para este <quote>proceso necesario</quote>: <ulink url="http://people.freebsd.org/~scottl/awkdiff"></ulink>.</para> </sect1> <sect1 id="add-rm-files"> <title>Añadir o eliminar ficheros</title> <para>La integración de una rama hará que se añadan ficheros existentes en el servidor en su árbol, pero quizás sea necesario añadir nuevos ficheros o eliminar alguno de los ya existentes. Para añadir ficheros no tiene más que crear el fichero y ejecutar <command>p4 add</command> de la siguiente forma:</para> <screen>&prompt.user; <userinput>p4 add <replaceable>nombredefichero</replaceable></userinput></screen> <para>Si quiere añadir un árbol completo de ficheros ejecute:</para> <screen>&prompt.user; <userinput>find . -type f |xargs p4 add</userinput></screen> <para>Al ejecutar <command>p4 submit</command> se copiarán los ficheros al <quote>depósito</quote> del servidor. Es muy importante añadir sólo ficheros y no directorios. Si se añade explícitamente un directorio, <application>Perforce</application> lo tratará como fichero, lo cual seguramente no es lo que usted tenía previsto.</para> <para>Borrar un fichero es igualmente sencillo mediante <command>p4 delete</command>:</para> <screen>&prompt.user; <userinput>p4 delete <replaceable>nombredefichero</replaceable></userinput></screen> <para>Esta orden marcará el fichero para que sea borrado del <quote>depósito</quote> la siguiente vez que se ejecute una entrega. También borrará la copia local del fichero, así que sea cauteloso cuando la use.</para> <para>Por supuesto que borrar un fichero no significa que se borre realmente del repositorio.</para> <para>Los ficheros borrados se pueden <quote>resucitar</quote> mediante la sincronización con una versión previa. La única forma de borrar de forma permanente un fichero es mediante la orden <command>p4 obliterat</command>. Dicha orden es irreversible y costosa, así que sólo está al alcance del personal que administra el repositorio.</para> </sect1> <sect1 id="working-with-diffs"> <title>El trabajo con <quote>diffs</quote></title> <para>Algunas veces puede ser necesario aplicar un <quote>diff</quote> al árbol de <application>Perfoce</application> que provenga de otra aplicación. Si se trata de un <quote>diff</quote> de gran tamaño y que afecta a muchos ficheros, puede resultar tedioso ejecutar manualmente <command>p4 edit</command> sobre cada fichero. Hay un truco para hacerlo de una forma más sencilla. En primer lugar, asegúrese de que no hay ficheros abiertos en su cliente y de que su árbol está sincronizado y actualizado a la última versión. A continuación aplique sus cambios mediante las herramientas habituales, y forzando los permisos de los ficheros en caso de ser necesario. Después ejecute lo siguiente:</para> <screen>&prompt.user; <userinput>p4 diff -se ... |xargs p4 edit</userinput> &prompt.user; <userinput>p4 diff -sd ... |xargs p4 delete</userinput> &prompt.user; <userinput>find . -type f |xargs p4 add</userinput></screen> <para>La primera orden le dice a <application>Perforce</application> que busque los ficheros que han cambiado, incluso si no están abiertos. La segunda orden le dice a <application>Perforce</application> que busque los ficheros que no existen en la máquina local pero que sí están en el servidor. La tercera orden intenta añadir todos los ficheros que están en local. Es un método de fuerza bruta, pero funciona bien porque <application>Perforce</application> sólo añadirá los ficheros que le resulten desconocidos. El resultado de estas órdenes es un conjunto de ficheros abiertos para edición, borrado o para ser añadidos, según el caso. Hecho esto solo nos queda ejecutar <command>p4 submit</command> para entregar los cambios.</para> </sect1> <sect1 id="renaming-files"> <title>Cambiar nombres de ficheros</title> <para><application>Perforce</application> no dispone de una forma predefinida de cambiar nombres a ficheros o de moverlos a otra parte del árbol. Si se copia el fichero en cuestión a una nueva ubicación mediante <command>p4 add</command>, y posteriormente <command>p4 delete</command> en la versión anterior, se obtiene algo muy parecido a lo que se quería, pero tiene el inconveniente de que no se preserva el historial de cambios de ese fichero. Esto puede perjudicar futuras integraciones entre padres e hijos. Hay otro método más recomendable, que consiste en efectuar una integración dentro del mismo árbol y de una sola vez. Veamos un ejemplo:</para> <screen>&prompt.user; <userinput>p4 integrate -i <replaceable>ficheroprevio</replaceable> <replaceable>ficheronuevo</replaceable></userinput> &prompt.user; <userinput>p4 resolve</userinput> &prompt.user; <userinput>p4 delete <replaceable>ficheroprevio</replaceable></userinput> &prompt.user; <userinput>p4 submit</userinput></screen> <para>La integración fuerza a <application>Perforce</application> a mantener un registro de las relaciones entre los nombres antiguos y los nuevos, lo cual será muy útil en futuras integraciones. La opción <option>-i</option> indica que se trata de una integración <quote>sin base</quote>, es decir, que no existe un historial de ramas al que recurrir en la integración. Este parámetro tiene sentido en el presente ejemplo, pero no debería utilizarse en integraciones basadas en ramas.</para> </sect1> <sect1 id="freebsd-cvs-and-p4"> <title>Interacciones entre el CVS de &os; y Perforce</title> <para>Los repositorios de <application>Perforce</application> y de CVS de &os; están completamente separados. No obstante, los cambios que se producen en CVS se reflejan casi en tiempo real en <application>Perforce</application>. Cada 2 minutos se pregunta al servidor de CVS sobre cambios realizados en la rama HEAD, y dichos cambios se entregan a <application>Perforce</application> dentro del árbol <filename class="directory">//depot/vendor/freebsd/...</filename>. De este modo este árbol permite la ramificación y la integración de proyectos derivados. Cualquier proyecto que implique la modificación del código fuente de &os; debería tener este árbol como su rama padre (o rama <quote>abuela</quote>, dependiendo de las necesidades concretas de cada proyecto), y deberían tener lugar integraciones periódicas y sincronizaciones para que el árbol esté en consonancia con el desarrollo de &os; y evitar conflictos en la medida de lo posible.</para> <para>El puente entre CVS y <application>Perforce</application> es de un sólo sentido; los cambios del CVS se reflejarán en <application>Perforce</application>, pero los cambios en <application>Perforce</application> no se reflejarán en el CVS. Si es necesario, se pueden exportar partes del repositorio de <application>Perforce</application> al <application>CVSup</application> y que así se puedan distribuir. Por favor, contacte con los administradores de <application>Perforce</application> de &os; si ese es su caso.</para> </sect1> <sect1 id="offline-ops"> <title>Funcionamiento sin conexión de red</title> <para>Uno de los inconvenientes de <application>Perforce</application> es que supone que siempre es posible acceder al servidor a través de la red. La mayoría de los estados, el historial y los metadatos se almacenan en el servidor y no existe mecanismo alguno para replicar el servidor como los hay en CVS/<application>CVSup</application>. Es posible ejecutar un servidor proxy, pero solamente ayuda un poco si se quiere trabajar sin conexión al servidor.</para> <para>La mejor forma de trabajar sin conexión de red es comprobando que el cliente no tiene ningún fichero abierto y que está totalmente sincronizado antes de dejar de estar conectado. Cuando se edite un fichero se deberán cambiar manualmente los permisos a lectura-escritura. Cuando vuelva a estar conectado ejecute la orden que se mostraba en la <xref linkend="working-with-diffs"/> para identificar automáticamente los ficheros que se han editado, añadido o eliminado. Es bastante común encontrarse con la sorpresa de que <application>Perforce</application> ha sobreescrito un fichero modificado en local que no se abrió en modo edición, así que tenga especial cuidado con esto.</para> </sect1> <sect1 id="soc"> <title>Consideraciones finales para el <quote>Google Summer of Code</quote></title> <para>La mayoría de los proyectos de &os; dentro del programa <quote>Google Summer of Code</quote> están en <filename class="directory">//depot/projects/soc2005/<replaceable>nombre_del_proyecto</replaceable>/...</filename> en el servidor &os; de <application>Perforce</application>.</para> <para>Entre las responsabilidades del mentor del proyecto está seleccionar un nombre adecuado para dicho proyecto y hacer que el estudiante sea capaz de trabajar con <application>Perforce</application>.</para> <para>El acceso al servidor &os; de <application>Perforce</application> no implica pasar a ser miembro de la comunidad de committers del CVS de &os;, aunque animamos de todo corazón a todos los estudiantes que consideren la posibilidad de unirse al proyecto cuando estén listos para ello.</para> </sect1> </article>