Node:Ver lo que Ud. (y otros) han hecho - comandos Update y Diff, Next:, Previous:Hacer un cambio, Up:Un día con CVS



Ver lo que Ud. (y otros) han hecho - comandos Update y Diff

Hasta ahora nos hemos referido a la "actualización" como una forma de traer a su copia de trabajo los cambios que se han realizado en el repositorio, es decir, como una manera de obtener los cambios hechos por otras personas. Sin embargo, la actualización es un proceso algo más complejo que esto, puesto que compara el estado global de su copia de trabajo con el estado del proyecto que se encuentra en el repositorio. Incluso si nada ha cambiado en el repositorio desde que se obtuvo la copia, puede que algo en la copia de trabajo sí lo haya hecho, y "update" también le mostrará esto:

floss$ cvs update
cvs update: Updating .
M hello.c
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
cvs update: Updating b-subdir

La "M" al lado de hello.c significa que el fichero ha sido modificado desde que se obtuvo la copia, y que las modificaciones no se han enviado aún al repositorio.

A veces, todo lo que necesita es simplemente saber qué ficheros ha editado. Sin embargo, si desea echar un vistazo más de cerca a los cambios, puede solicitar un informe detallado en formato diff. El comando diff compara los ficheros que puedan haberse modificado en la copia de trabajo con sus homónimos en el repositorio, mostrando a continuación cualquier posible diferencia:

floss$ cvs diff
cvs diff: Diffing .
Index: hello.c
===================================================================
RCS file: /usr/local/cvs/miproyecto/hello.c,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 hello.c
6a7
>   printf ("¡Adiós, mundo!\n");
cvs diff: Diffing a-subdir
cvs diff: Diffing a-subdir/subsubdir
cvs diff: Diffing b-subdir

Aunque un poco liosa, esta información es útil, si bien todavía hay un montón de ruido ahí. Para empezar, puede ignorar la mayor parte de las líneas del comienzo, dado que sólo hacen referencia al nombre del fichero del repositorio e indican el número de la última revisión enviada al mismo. Son datos útiles en otras circunstancias (las veremos en detalle más adelante), pero no las necesita cuando sólo quiere hacerse una idea de los cambios que se han hecho en la copia de trabajo.

Una molestia más seria a la hora de leer el diff es que CVS anuncia su entrada en escena a medida que va entrando en cada directorio durante la actualización. Esto puede ser útil durante largas actualizaciones en grandes proyectos, puesto que le da una idea del tiempo que va a necesitar el comando, pero ahora mismo lo único que hace es molestarle mientras intenta interpretar lo que está leyendo. Así pues, digámosle a CVS que no diga nada sobre su trabajo, con la opción global -Q (de "Que te calles", obviamente):

floss$ cvs -Q diff
Index: hello.c
===================================================================
RCS file: /usr/local/cvs/miproyecto/hello.c,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 hello.c
6a7
>   printf ("¡Adiós, mundo!\n");

Mejor - al menos, parte del ruido ha desaparecido. Sin embargo, el diff es aún difícil de leer. Le está diciendo que en la línea 6 se añadió una línea nueva (que se convirtió en la línea 7) cuyo contenido es:

printf ("¡Adiós, mundo!\n");

El signo ">" que precede a la línea en el diff le dice que esta línea está presente en la nueva versión del fichero, pero no en la antigua.

Sin embargo, el formato podría ser aún más legible. Muchas personas encuentran el formato "de contexto" de diff más fácil de leer, porque muestra menos líneas de contexto delimitando los cambios. Los diffs de contexto pueden generarse pasando a diff la opción -c:

floss$ cvs -Q diff -c
Index: hello.c
===================================================================
RCS file: /usr/local/cvs/miproyecto/hello.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 hello.c
*** hello.c     1999/04/18 18:18:22     1.1.1.1
--- hello.c     1999/04/19 02:17:07
***************
*** 4,7 ****
---4,8 --
  main ()
  {
    printf ("¡Hola, mundo!\n");
+   printf ("¡Adiós, mundo!\n");
  }

¡Esto sí está claro! Incluso si no está acostumbrado a leer diffs de contexto, un vistazo a esta información mostrará de forma bastante obvia lo que ha sucedido: se añadió una nueva línea (el + en la primera columna significa que se ha añadido una línea) entre la línea que imprime "¡Hola, mundo!" y la llave final.

No es necesario que seamos capaces de interpretar perfectamente los diffs de contexto (esto es trabajo para el programa "patch"), pero le será útil tomarse un tiempo para adquirir al menos una cierta familiaridad con el formato. Las primeras dos líneas (después del rollo del comienzo) son

*** hello.c     1999/04/18 18:18:22     1.1.1.1
--- hello.c     1999/04/19 02:17:07

y le dicen qué se está comparando con qué. En este caso, la revisión 1.1.1.1 de hello.c se está comparando con una versión modificada del mismo fichero (motivo por el cual no aparece número alguno de revisión en la segunda línea, porque los cambios de la copia de trabajo no se han enviado todavía al repositorio). Las líneas de asteriscos y guiones identifican secciones situadas más adelante en el fichero de diferencias. Más adelante, una línea de asteriscos seguida de una franja de valores precede a una sección del fichero original. Después, una línea de guiones, con una franja de números de línea nuevos y potencialmente distintos, precede a una sección del fichero modificado. Estas secciones están organizadas por pares: por un lado la parte del fichero antiguo, y por otro lado la parte del fichero nuevo.

Nuestro fichero de diferencias tiene uno de estos pares:

***************
*** 4,7 ****
--- 4,8 --
  main ()
  {
    printf ("¡Hola, mundo!\n");
+   printf ("¡Adiós, mundo!\n");
  }

La primera sección del par está vacía, lo que significa que no se ha eliminado nada del fichero original. La segunda sección indica que, en el lugar correspondiente del nuevo fichero, se ha añadido una nueva línea, que aparece marcada con un signo "+". (Cuando el diff cita partes de ficheros, se reserva las primeras dos columnas a la izquierda para códigos especiales, como el "+", así que el trozo entero aparenta estar justificado a la izquierda con dos espacios. Esta justificación extra desaparece, por supuesto, cuando se aplica el fichero de diferencias.)

La franja de números de líneas muestra el alcance del par de diferencias, incluyendo líneas de contexto. En el fichero original, el par estaba en las líneas 4 a la 7; en el nuevo fichero, son las líneas 4 a la 8 debido a la nueva línea que se ha añadido. Fíjese en que el fichero de diferencias no necesita enseñar ninguna cosa del fichero original puesto que no se ha eliminado nada; sólo nos ha mostrado la franja afectada y ha continuación ha saltado a la segunda sección del par de diferencias.

Aquí hay otro diff de contexto, procedente esta vez de un proyecto real mío:

floss$ cvs -Q diff -c
Index: cvs2cl.pl
===================================================================
RCS file: /usr/local/cvs/kfogel/code/cvs2cl/cvs2cl.pl,v
retrieving revision 1.76
diff -c -r1.76 cvs2cl.pl
*** cvs2cl.pl   1999/04/13 22:29:44     1.76
--- cvs2cl.pl   1999/04/19 05:41:37
***************
*** 212,218 ****
          # can contain uppercase and lowercase letters, digits, '-',
          # and '_'. However, it's not our place to enforce that, so
          # we'll allow anything CVS hands us to be a tag:
!         /^\s([^:]+): ([0-9.]+)$/;
          push (@{$symbolic_names{$2}}, $1);
        }
      }
-- 212,218 --
          # can contain uppercase and lowercase letters, digits, '-',
          # and '_'. However, it's not our place to enforce that, so
          # we'll allow anything CVS hands us to be a tag:
!         /^\s([^:]+): ([\d.]+)$/;
          push (@{$symbolic_names{$2}}, $1);
        }
      }

El signo de exclamación indica que la línea marcada difiere del fichero antiguo al nuevo. Dado que no hay ningún signo "+" o "-", sabemos que el número total de líneas del fichero sigue siendo el mismo.

Éstas son otras diferencias de contexto del mismo proyecto, esta vez un poco más complejas:

floss$ cvs -Q diff -c
Index: cvs2cl.pl
===================================================================
RCS file: /usr/local/cvs/kfogel/code/cvs2cl/cvs2cl.pl,v
retrieving revision 1.76
diff -c -r1.76 cvs2cl.pl
*** cvs2cl.pl   1999/04/13 22:29:44     1.76
--- cvs2cl.pl   1999/04/19 05:58:51
***************
*** 207,217 ****
}
        else    # we're looking at a tag name, so parse & store it
        {
-         # According to the Cederqvist manual, in node "Tags", "Tag
-         # names must start with an uppercase or lowercase letter and
-         # can contain uppercase and lowercase letters, digits, '-',
-         # and '_'. However, it's not our place to enforce that, so
-         # we'll allow anything CVS hands us to be a tag:
          /^\s([^:]+): ([0-9.]+)$/;
          push (@{$symbolic_names{$2}}, $1);
        }
- 207,212 --
***************
*** 223,228 ****
--- 218,225 --
      if (/^revision (\d\.[0-9.]+)$/) {
        $revision = "$1";
      }
+
+     # Esta línea ha sido añadida, lo admito, sólo para este ejemplo de diff.

      # If have file name but not time and author, and see date or
      # author, then grab them:

Este fichero diff tiene dos pares de diferencias. En el primero se han eliminado cinco líneas (estas líneas se muestran sólo en la primera sección del par, y la cuenta de líneas de la segunda sección indica que tiene menos líneas). Una línea continua de asteriscos hace las veces de delimitador entre pares, y en el segundo par vemos que se han añadido dos líneas: una línea en blanco y un comentario inútil. Observe cómo los números de línea compensan el efecto del par anterior. En el fichero original, la franja del segundo par iba desde 223 hasta 228; en el nuevo fichero, dado que la eliminación tuvo lugar en el primer par, la franja de líneas abarca desde la 218 hasta la 225.

Enhorabuena, en este momento tiene posiblemente toda la experiencia que necesita para poder interpretar ficheros de diferencias.