Práctica: Ejecución Controlada de Un Programa

Objetivos

Escriba un módulo Batch::Simple que provee:

  1. Un constructor new que recibe
    1. El comando: una cadena como 'sort'
    2. Posibles opciones para el comando, por ejemplo -n, etc.
    3. Un posible manejador de fichero para STDIN
    4. Un posible manejador de fichero para STDOUT
    5. Un posible manejador de fichero para STDERR
    Si el fichero input no se especifica se entenderá que es STDIN. Por ejemplo:

                  my $c = Batch::Simple->new(command => 'sort', stdin => $infile, options => $options);
    
    La llamada a new retorna un objeto de la clase Batch::Simple.
  2. Los objetos Batch::Simple disponen de un método run que ejecutará el programa. El método run devuelve un objeto Batch::Simple::Result que tiene los siguientes atributos:
    1. stdout: La salida por STDOUT del programa
    2. stderr: La salida por STDERR del programa
    3. status: El contenido de $?

Escriba métodos de acceso a los atributos implicados.

Una posible implementación de run consiste en redirigir los flujos de salida y de error durante la ejecución a ficheros utilizando la metodología vista en la sección Salvando Manejadores de Fichero 1.5. Si no se especificaron valores para STDOUT y STDERR es posible usar ficheros temporales (veanse File::Temp y File::Spec). Para repasar la programación orientada a objetos en Perl puede repasar el capítulo Programación Orientada a Objetos de los apuntes de LHP o mejor aún, usar Moose y leer los siguientes artículos:

Creación del Proyecto para la Elaboración del Módulo

Para repasar la creación de módulos véase el capítulo Módulos de los apuntes de LHP.

Cree la estructura de directorios usando h2xs o Module::Install (Véase Module::Install::Philosophy):

pp2@nereida:~/src$ h2xs -X -A -n Batch::Simple
Defaulting to backwards compatibility with perl 5.8.8
If you intend this module to be compatible with earlier perl versions, please
specify a minimum perl version with the -b option.

Writing Batch-Simple/lib/Batch/Simple.pm
Writing Batch-Simple/Makefile.PL
Writing Batch-Simple/README
Writing Batch-Simple/t/Batch-Simple.t
Writing Batch-Simple/Changes
Writing Batch-Simple/MANIFEST
Añada un directorio para el ejecutable e incluya su presencia dándolo de alta en el fichero Batch-Simple/MANIFEST y en la entrada EXE_FILES en la llamada a WriteMakefile en el fichero Batch-Simple/Makefile.PL:
pp2@nereida:~/src/Batch-Simple$ cat -n MANIFEST
     1  Changes
     2  Makefile.PL
     3  MANIFEST
     4  README
     5  script/batch.pl
     6  t/Batch-Simple.t
     7  lib/Batch/Simple.pm
pp2@nereida:~/src/Batch-Simple$ cat -n Makefile.PL
     1  use ExtUtils::MakeMaker;
     2  WriteMakefile(
     3      NAME              => 'Batch::Simple',
     4      VERSION_FROM      => 'lib/Batch/Simple.pm', # finds $VERSION
     5      PREREQ_PM         => {}, # e.g., Module::Name => 1.1
     6      EXE_FILES         => [ qw{script/batch.pl} ],
     7  );
Hay varias formas de garantizar que durante el periodo de desarrollo de una librería los ejecutables encuentran la librería. Uno es añadir use blib en el ejecutable:
pp2@nereida:~/src/Batch-Simple/script$ cat -n batch.pl
     1  #!/usr/local/bin/perl -w
     2   use strict;
     3   use Carp;
     4   use Getopt::Long;
     5   use Pod::Usage;
     6   use blib;
     7   use Batch::Simple;
     .   ....................
el módulo blib busca por un directorio de tipo blib hasta 5 niveles por encima del actual. Observa que eso significa que trabajas con la copia en blib y no el original en lib. Por tanto deberás hacer make para asegurarte la actualización de la copia. Otra forma de garantizar que la librería se encuentra es incluirla en la variable PERL5LIB.

Aplicación para Las Pruebas

Puedes usar como ejemplo de aplicación el tar.gz que implementa un producto de matrices en C en la página asociada con estos apuntes (fichero matrix.tar.gz)

Use Subversion: Creación de un Repositorio

You can think of every object in the repository as existing in a sort of two-dimensional coordinate system. The first coordinate is a particular revision tree, and the second coordinate is a path within that tree

Parece que en banot esta instalado subversion. Para crear un repositorio emita el comando svnadmin create:

-bash-3.1$ uname -a
Linux banot.etsii.ull.es 2.6.24.2 #3 SMP Fri Feb 15 10:39:28 WET 2008 i686 i686 i386 GNU/Linux
-bash-3.1$ svnadmin create /home/loginname/repository/
-bash-3.1$ ls -l repository/
total 28
drwxr-xr-x 2 loginname apache 4096 feb 28 11:58 conf
drwxr-xr-x 2 loginname apache 4096 feb 28 11:58 dav
drwxr-sr-x 5 loginname apache 4096 feb 28 12:09 db
-r--r--r-- 1 loginname apache    2 feb 28 11:58 format
drwxr-xr-x 2 loginname apache 4096 feb 28 11:58 hooks
drwxr-xr-x 2 loginname apache 4096 feb 28 11:58 locks
-rw-r--r-- 1 loginname apache  229 feb 28 11:58 README.txt

Una alternativa a considerar es ubicar el repositorio en un dispositivo de almacenamiento portable (pendriver)

Añadiendo Proyectos

Ahora esta en condiciones de añadir proyectos al repositorio creado usando svn import:

[loginname@tonga]~/src/perl/> uname -a
Linux tonga 2.6.24.2 #1 SMP Thu Feb 14 15:37:31 WET 2008 i686 i686 i386 GNU/Linux
[loginname@tonga]~/src/perl/> pwd
/home/loginname/src/perl
[loginname@tonga]~/src/perl/> ls -ld /home/loginname/src/perl/Grammar-0.02
drwxr-xr-x 5 loginname Profesor 4096 feb 28  2008 /home/loginname/src/perl/Grammar-0.02
[loginname@tonga]~/src/perl/> svn import -m 'Grammar Extended Module' \
                                        Grammar-0.02/ \
                                        svn+ssh://banot/home/loginname/repository/Grammar
Añadiendo      Grammar-0.02/t
Añadiendo      Grammar-0.02/t/Grammar.t
Añadiendo      Grammar-0.02/lib
Añadiendo      Grammar-0.02/lib/Grammar.pm
Añadiendo      Grammar-0.02/MANIFEST
Añadiendo      Grammar-0.02/META.yml
Añadiendo      Grammar-0.02/Makefile.PL
Añadiendo      Grammar-0.02/scripts
Añadiendo      Grammar-0.02/scripts/grammar.pl
Añadiendo      Grammar-0.02/scripts/Precedencia.yp
Añadiendo      Grammar-0.02/scripts/Calc.yp
Añadiendo      Grammar-0.02/scripts/aSb.yp
Añadiendo      Grammar-0.02/scripts/g1.yp
Añadiendo      Grammar-0.02/Changes
Añadiendo      Grammar-0.02/README

Commit de la revisión 2.

En general, los pasos para crear un nuevo proyecto son:

* mkdir /tmp/nombreProyecto
* mkdir /tmp/nombreProyecto/branches
* mkdir /tmp/nombreProyecto/tags
* mkdir /tmp/nombreProyecto/trunk
* svn mkdir file:///var/svn/nombreRepositorio/nombreProyecto -m 'Crear el proyecto nombreProyecto'
* svn import /tmp/nombreProyecto \
            file:///var/svn/nombreRepositorio/nombreProyecto \
            -m "Primera versión del proyecto nombreProyecto"

Obtener una Copia de Trabajo

La copia en Grammar-0.02 ha sido usada para la creación del proyecto, pero no pertenece aún al proyecto. Es necesario descargar la copia del proyecto que existe en el repositorio. Para ello usamos svn checkout:

[loginname@tonga]~/src/perl/> rm -fR Grammar-0.02
[loginname@tonga]~/src/perl/> svn checkout svn+ssh://banot/home/loginname/repository/Grammar Grammar
A    Grammar/t
A    Grammar/t/Grammar.t
A    Grammar/MANIFEST
A    Grammar/META.yml
A    Grammar/lib
A    Grammar/lib/Grammar.pm
A    Grammar/Makefile.PL
A    Grammar/scripts
A    Grammar/scripts/grammar.pl
A    Grammar/scripts/Calc.yp
A    Grammar/scripts/Precedencia.yp
A    Grammar/scripts/aSb.yp
A    Grammar/scripts/g1.yp
A    Grammar/Changes
A    Grammar/README
Revisión obtenida: 2
Ahora disponemos de una copia de trabajo del proyecto en nuestra máquina local:
[loginname@tonga]~/src/perl/> tree Grammar
Grammar
|-- Changes
|-- MANIFEST
|-- META.yml
|-- Makefile.PL
|-- README
|-- lib
|   `-- Grammar.pm
|-- scripts
|   |-- Calc.yp
|   |-- Precedencia.yp
|   |-- aSb.yp
|   |-- g1.yp
|   `-- grammar.pl
`-- t
    `-- Grammar.t

3 directories, 12 files
[loginname@tonga]~/src/perl/>       
[loginname@tonga]~/src/perl/> cd Grammar
[loginname@tonga]~/src/perl/Grammar/> ls -la
total 44
drwxr-xr-x 6 loginname Profesor 4096 feb 28  2008 .
drwxr-xr-x 5 loginname Profesor 4096 feb 28  2008 ..
-rw-r--r-- 1 loginname Profesor  150 feb 28  2008 Changes
drwxr-xr-x 3 loginname Profesor 4096 feb 28  2008 lib
-rw-r--r-- 1 loginname Profesor  614 feb 28  2008 Makefile.PL
-rw-r--r-- 1 loginname Profesor  229 feb 28  2008 MANIFEST
-rw-r--r-- 1 loginname Profesor  335 feb 28  2008 META.yml
-rw-r--r-- 1 loginname Profesor 1196 feb 28  2008 README
drwxr-xr-x 3 loginname Profesor 4096 feb 28  2008 scripts
drwxr-xr-x 6 loginname Profesor 4096 feb 28  2008 .svn
drwxr-xr-x 3 loginname Profesor 4096 feb 28  2008 t
Observe la presencia de los subdirectorios de control .svn.

Actualización del Proyecto

Ahora podemos modificar el proyecto y hacer públicos los cambios mediante svn commit:

loginname@tonga]~/src/perl/Grammar/> svn rm META.yml
D         META.yml
[loginname@tonga]~/src/perl/Grammar/> ls -la
total 40
drwxr-xr-x 6 loginname Profesor 4096 feb 28  2008 .
drwxr-xr-x 5 loginname Profesor 4096 feb 28 12:34 ..
-rw-r--r-- 1 loginname Profesor  150 feb 28 12:34 Changes
drwxr-xr-x 3 loginname Profesor 4096 feb 28 12:34 lib
-rw-r--r-- 1 loginname Profesor  614 feb 28 12:34 Makefile.PL
-rw-r--r-- 1 loginname Profesor  229 feb 28 12:34 MANIFEST
-rw-r--r-- 1 loginname Profesor 1196 feb 28 12:34 README
drwxr-xr-x 3 loginname Profesor 4096 feb 28 12:34 scripts
drwxr-xr-x 6 loginname Profesor 4096 feb 28  2008 .svn
drwxr-xr-x 3 loginname Profesor 4096 feb 28 12:34 t
[loginname@tonga]~/src/perl/Grammar/> echo "Modifico README" >> README
[loginname@tonga]~/src/perl/Grammar/> svn commit -m 'Just testing ...'
Eliminando     META.yml
Enviando       README
Transmitiendo contenido de archivos .
Commit de la revisión 3.
Observe que ya no es necesario especificar el lugar en el que se encuentra el repositorio: esa información esta guardada en los subdirectorios de administración de subversion .svn

El servicio de subversion parece funcionar desde fuera de la red del centro. Véase la conexión desde una maquina exterior:

pp2@nereida:/tmp$  svn checkout svn+ssh://loginname@banot.etsii.ull.es/home/loginname/repository/Grammar Grammar
loginname@banot.etsii.ull.es's password:
loginname@banot.etsii.ull.es's password:
A    Grammar/t
A    Grammar/t/Grammar.t
A    Grammar/MANIFEST
A    Grammar/lib
A    Grammar/lib/Grammar.pm
A    Grammar/Makefile.PL
A    Grammar/scripts
A    Grammar/scripts/grammar.pl
A    Grammar/scripts/Calc.yp
A    Grammar/scripts/Precedencia.yp
A    Grammar/scripts/aSb.yp
A    Grammar/scripts/g1.yp
A    Grammar/Changes
A    Grammar/README
Revisión obtenida: 3

Comandos Básicos

Autentificación Automática

Para evitar la solicitud de claves cada vez que se comunica con el repositorio establezca autentificación SSH automática. Para ver como hacerlo puede consultar las instrucciones en la sección 2.1.3 o en:

http://search.cpan.org/~casiano/GRID-Machine/lib/GRID/Machine.pod#INSTALLATION

Consulte también las páginas del manual Unix de ssh, ssh-key-gen, ssh_config, scp, ssh-agent, ssh-add, sshd

Especificadores de Revisisón

Véase la sección Revision Specifiers en el libro de Subversion

Repasando la Historia

Véase la sección Examining History en el libro de Subversion

Deshaciendo Cambios en la Copia de Trabajo

Véase la sección Undoing Working Changes en el libro de Subversion

Resolución de Conflictos

Ejercicio 1.9.1  

Usando vimdiff como programa de diferencias para subversion

Side by side diffs are much more legible and useful than those in unified format or any other linear diff. By default, the svn diff command presents output in the unified format, though it has an option, --diff-cmd, which allows you to specify the program that will perform the diff. Passing vimdiff as the diff command doesn't work as the options passed by svn diff are a bit complicated:

Veamos que es así. Escribimos el siguiente programa de prueba:

generaciondecodigos@nereida:~/bin$ cat -n ./foo.pl
     1  #!/usr/bin/perl
     2
     3  print "'$_' " for @ARGV;
     4  print "\n";

Ejecución:

$ svn diff --diff-cmd=/home/generaciondecodigos/bin/foo.pl overloading.tex -rPREV
Index: overloading.tex
===================================================================
'-u' '-L' 'overloading.tex      (revisión: 5112)' '-L' 'overloading.tex (copia de trabajo)' '.svn/tmp/tempfile.tmp' 'overloading.tex'
El argumento -u indica que se debe usar unified format y el argumento -L especifica la etiqueta que describe la correspondiente versión.

Es necesario escribir un wrapper que prescinda de esas opciones y que se quede con los nombres de los dos ficheros:

pp2@nereida:~$ cat -n bin/diffwrap.sh
 1  #!/bin/sh
 2
 3  # Configure your favorite diff program here.
 4  DIFF="/usr/bin/vimdiff"
 5
 6  # Subversion provides the paths we need as the sixth and seventh
 7  # parameters.
 8  LEFT=${6}
 9  RIGHT=${7}
10
11  # Call the diff command (change the following line to make sense for
12  # your merge program).
13  $DIFF $LEFT $RIGHT
14
15  # Return an errorcode of 0 if no differences were detected, 1 if some were.
16  # Any other errorcode will be treated as fatal.
Ahora podemos establecer que este programa sea nuestro comando diff para svn editando el fichero de configuración ~/.subversion/config:
pp2@nereida:~/Lbook$ grep 'diff' ~/.subversion/config
### Set diff-cmd to the absolute path of your 'diff' program.
###   Subversion's internal diff implementation.
# diff-cmd = diff_program (diff, gdiff, etc.)
### Set diff3-cmd to the absolute path of your 'diff3' program.
###   Subversion's internal diff3 implementation.
# diff3-cmd = diff3_program (diff3, gdiff3, etc.)
### Set diff3-has-program-arg to 'true' or 'yes' if your 'diff3'
###   program accepts the '--diff-program' option.
# diff3-has-program-arg = [true | false]
diff-cmd = /home/pp2/bin/diffwrap.sh

Properties and Externals

Tracking Systems

Sustitución de Palabras Clave

Véase la sección Keyword Substitution en el libro de Subversion

Protocolos y Esquemas

Subversion admite una variedad de protocolos de red para conectarse con el repositorio. Con subversion viene el programa svnserve que escucha por conexiones de red y soporta un modo de autentificación simple. Sólo debe usarse si esta en una LAN privada. En el siguiente ejemplo arranco el daemon svnserve en banot:

bash-3.2$ uname -a
Linux banot.etsii.ull.es 2.6.18-128.1.16.el5 #1 SMP Tue Jun 30 06:10:28 EDT 2009 i686 i686 i386 GNU/Linux
-bash-3.2$ svnserve --listen-port=4040 -d -r repository
-bash-3.2$ ps -fA | grep svn
casiano  11876     1  0 11:16 ?        00:00:00 svnserve --listen-port=4040 -d -r repository
casiano  12036 11698  0 11:22 pts/0    00:00:00 grep svn

Ahora puedo acceder al proyecto vía svn desde otra máquina:

casiano@tonga:~$ svn co svn://banot:4040/acme-svn/trunk chuchu
A    chuchu/t
A    chuchu/t/00.load.t
A    chuchu/t/perlcritic.t
A    chuchu/t/pod.t
A    chuchu/t/pod-coverage.t
A    chuchu/MANIFEST
A    chuchu/lib
A    chuchu/lib/Acme
A    chuchu/lib/Acme/SVN.pm
A    chuchu/Makefile.PL
A    chuchu/Changes
A    chuchu/Build.PL
A    chuchu/README
Revisión obtenida: 6

Aunque no tengo permisos de ejecución:

casiano@tonga:~$ cd chuchu
casiano@tonga:~/chuchu$ echo prueba > prueba.txt
casiano@tonga:~/chuchu$ svn add prueba.txt
A         prueba.txt
casiano@tonga:~/chuchu$ svn commit prueba.txt -m 'added prueba.txt'
svn: Falló el commit (detalles a continuación):
svn: falló la autorización

Habría que dar permisos de escritura al repositorio y crear usuarios (véase svnserve, a custom server y svnserve.conf para los detalles)

Referencias

Consulte

  1. http://svnbook.red-bean.com/en/1.5/ .
  2. Vea la página de la ETSII http://cc.etsii.ull.es/svn .
  3. Vea los capítulos disponibles del libro Subversion in Action de la editorial Manning
  4. Practical Subversion de APress
  5. La hoja de referencia en http://www.digilife.be/quickreferences/QRC/Subversion%20Quick%20Reference%20Card.pdf

En KDE puede instalar el cliente gráfico KDEsvn.

Ejercicio: Copiando un Repositorio

Ejercicio 1.9.2   Copie su repositorio a un archivo, preferiblemente un dispositivo portable como un pen-driver.
casiano@europa:/media/UDISK 2.0$ rsync -aue ssh banot:repository svnrepositories
casiano@europa:/media/UDISK 2.0$ cd svnrepositories/
casiano@europa:/media/UDISK 2.0/svnrepositories$ ls -ltra
total 24
drwxr-xr-x 7 casiano root  4096 2009-03-05 15:50 repository
drwxr-xr-x 3 casiano root  4096 2009-03-18 13:11 .
drwxr-xr-x 6 casiano root 16384 2009-03-18 13:12 ..
casiano@europa:/media/UDISK 2.0/svnrepositories$ mv repository/ banotrepository
Intente comunicarse con él usando el protocolo file//
casiano@europa:/tmp$ svn ls file:///media/UDISK\ 2.0/svnrepositories/banotrepository
acme-svn/
casiano@europa:/tmp$ svn ls file:///media/UDISK\ 2.0/svnrepositories/banotrepository/acme-svn
branches/
trunk/



Subsecciones
Casiano Rodríguez León
2010-03-22