Instalar wekan en Debian 9
https://www.osradar.com/how-to-install-wekan-in-debian-9/
Manejar varios PC con un único teclado y ratón
https://www.taringa.net/posts/linux/9589221/Compartir-un-mouse-teclado-entre-multiples-PCs.html
https://computers.tutsplus.com/es/tutorials/how-to-configure-synergy-to-use-one-keyboard-and-mouse-seamlessly--cms-27623
Recuperación de archivos borrados en Windows.
http://www.piriform.com/recuva
Referencia rápida de Git.
Crear un repositorio nuevo
Crea un directorio nuevo. Métete en el y ejecuta:
git init
Esto crea un nuevo directorio (.git) con la información necesaria para git.
Hacer checkout a un repositorio
Crea una copia local del repositorio ejecutando:
git clone /path/to/repository
Si utilizas un servidor remoto, ejecuta:
git clone username@host:/path/to/repository
Flujo de trabajo
Tu repositorio local esta compuesto por tres "árboles" administrados por git.
- El primero es tu Directorio de trabajo que contiene tus archivos.
- El segundo es el Index que actúa como una zona intermedia.
- El último es el HEAD que apunta al último commit realizado.
add & commit
Puedes registrar cambios (añadirlos al Index) ejecutando:
git add <filename>
git add .
Este es el primer paso en el flujo de trabajo básico.
Para hacer commit a estos cambios usa
git commit -m "Commit message"
Ahora el archivo esta incluído en el HEAD, pero aún no en tu repositorio remoto.
Envío de cambios
Tus cambios están ahora en el HEAD de tu copia local.
Para enviar estos cambios a tu repositorio remoto ejecuta:
git push origin master (Reemplaza master por la rama a la que quieres enviar tus cambios.)
Si no has clonado un repositorio ya existente y quieres conectar tu repositorio local a un repositorio remoto,ejecuta:
git remote add origin <server>
Ahora podrás subir tus cambios al repositorio remoto seleccionado.
Ramas
Las ramas son utilizadas para desarrollar funcionalidades aisladas unas de otras.
La rama master es la rama "por defecto" cuando creas un repositorio.
Crea nuevas ramas durante el desarrollo y fusiónalas a la rama principal cuando termines.
Crea una nueva rama llamada "feature_x" y cámbiate a ella ejecutando:
git checkout -b feature_x
Vuelve a la rama principal
git checkout master
y borra la rama
git branch -d feature_x
Una rama nueva no estará disponible para los demás a menos que subas (push) la rama a tu repositorio remoto
git push origin <branch>
actualiza & fusiona
Para actualizar tu repositorio local al commit más nuevo, ejecuta:
git pull
en tu directorio de trabajo para bajar y fusionar los cambios remotos.
Para fusionar otra rama a tu rama activa (por ejemplo master), utiliza
git merge <branch>
en ambos casos git intentará fusionar automáticamente los cambios. Desafortunadamente, no siempre será posible y se podrán producir conflictos.
Tú eres responsable de fusionar esos conflictos manualmente al editar los archivos mostrados por git.
Después de modificarlos, necesitas marcarlos como fusionados con
git add <filename>
Antes de fusionar los cambios, puedes revisarlos usando
git diff <source_branch> <target_branch>
Etiquetas
Se recomienda crear etiquetas para cada nueva versión publicada de un software.
Este concepto no es nuevo, ya que estaba disponible en SVN. Puedes crear una nueva etiqueta llamada 1.0.0 ejecutando :
git tag 1.0.0 1b2e1d63ff
1b2e1d63ff se refiere a los 10 caracteres del commit id al cual quieres referirte con tu etiqueta. Puedes obtener el commit id con
git log
también puedes usar menos caracteres que el commit id, pero debe ser un valor único.
Reemplaza cambios locales
En caso de que hagas algo mal (lo que seguramente nunca suceda ;) puedes reemplazar cambios locales usando el comando
git checkout -- <filename>
Este comando reemplaza los cambios en tu directorio de trabajo con el último contenido de HEAD.
Los cambios que ya han sido agregados al Index, así como también los nuevos archivos, se mantendrán sin cambio.
Por otro lado, si quieres deshacer todos los cambios locales y commits, puedes traer la última versión del servidor y apuntar a tu copia local principal de esta forma
git fetch origin
git reset --hard origin/master
Trucos
Interfaz gráfica por defecto:
gitk
Colores especiales para la consola:
git config color.ui true
Mostrar sólo una línea por cada commit en la traza:
git config format.pretty oneline
Agregar archivos de forma interactiva:
git add -i
Acceder a cuenta de Gmail con MUTT
1.- Editar el fichero de configuración de mutt (.muttrc) y copiar las líneas siguientes.
Los comentarios explican el uso.
_______________________________________________________________________________
#Fichero .muttrc
# Juego de caracteres de los mensajes que enviamos:
set send_charset = "utf-8"
set assumed_charset = "iso-8859-1"
# Asegurarse de que Vim sabe que Mutt es un cliente de correo electrónico
# y que queremos componer los mensajes usando UTF-8
# Si no tien vi entonces mutt leerá el contenido
# de la variable de entorno $EDITOR):
set editor = "vim -c 'set syntax=mail ft=mail enc=utf-8'"
set menu_scroll = "yes"
# Remitente de los mails:
set from = "usuario@gmail.com"
set realname = "Nombre Apellido"
# Configuraciones de servidor -->
# Configuraciones servidor IMAP:
set imap_user = "usuario@gmail.com"
set smtp_url = "smtp://usuario@smtp.gmail.com:587/"
# Opcional (no lo recomiendo porque queda almacenada la contraseña
# en texto plano):
set imap_pass = "contraseña"
set smtp_pass = "contraseña"
# En caso de no poner los dos valores anteriores, se nos pedirá ingresar
# la contraseña al enviar o recibir mails.
set folder = "imaps://imap.gmail.com:993"
# Ponemos el Inbox
set spoolfile = "+INBOX"
# Ponemos la carpeta de borradores (debe llamarse igual que en la web):
set postponed = "+[Gmail]/Borradores"
# Guardamos los mails en Enviados:
set record = "imaps://imap.gmail.com:993/[Gmail]/Enviados"
# Ajustes para la conexión IMAP:
set mail_check=100
set imap_keepalive=300
# Buzones extra que queremos comprobar.
mailboxes "+[Gmail]/Spam"
mailboxes "+[Gmail]/Papelera"
# Ordenamos los mensajes en orden inverso.
set sort=reverse-threads
set sort_aux= last-date-received
# Crear los directorios para no obtener errores,
#'mkdir -p ~/.mutt/cache/{bodies,headers}':
set message_cachedir = "~/.mutt/cache/bodies"
set header_cache = "~/.mutt/cache/headers"
# El siguiente archivo debe existir y contiene la firma, que va al pie de cada
# mail que escribamos:
set signature = ".mutt/.firma"
# Iluminar con colores, obtenido de:
# http://aperiodic.net/phil/configs/mutt/colors
#
#-*- muttrc -*-
#
# Color settings for mutt.
#----------------------------------------------------------------------------------------------------------------------------
# Default color definitions
color normal white default
color hdrdefault green default
color quoted green default
color quoted1 yellow default
color quoted2 red default
color signature cyan default
color indicator brightyellow red
color error brightred default
color status brightwhite blue
color tree brightmagenta default
color tilde blue default
color attachment brightyellow default
color markers brightred default
color message white default
color search brightwhite magenta
color bold brightyellow default
# Color definitions when on a mono screen
mono bold bold
mono underline underline
mono indicator reverse
mono error bold
# Colors for items in the reader
color header brightyellow default "^(From|Subject):"
color header brightcyan default ^To:
color header brightcyan default ^Cc:
mono header bold "^(From|Subject):"
# Many of these formulas were stolen from Jeremy Blosser
# These would be much simpler if colors were additive.
# regular new messages
color index black white "~N !~T !~F !~p !~P"
# regular tagged messages
color index black cyan "~T !~F !~p !~P"
# regular flagged messages
color index black red "~F !~p !~P"
# messages to me
color index yellow default "~p !~N !~T !~F !~P"
color index brightyellow white "~p ~N !~T !~F !~P"
color index yellow cyan "~p ~T !~F !~P"
color index yellow red "~p ~F !~P"
# messages from me
color index green default "~P !~N !~T !~F"
color index green white "~P ~N !~T !~F"
color index green cyan "~P ~T !~F"
color index green red "~P ~F"
# messages which mention my name in the body
color index yellow default "~b \"phil(_g|\!| gregory| gold)|pgregory\" !~N !~T !~F !~p !~P"
color index brightyellow white "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~N !~T !~F !~p !~P"
color index yellow cyan "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~T !~F !~p !~P"
color index yellow red "~b \"phil(_g|\!| gregory| gold)|pgregory\" ~F !~p !~P"
# messages which are in reference to my mails
color index magenta default "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" !~N !~T !~F !~p !~P"
color index magenta white "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~N !~T !~F !~p !~P"
color index magenta cyan "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~T !~F !~p !~P"
color index magenta red "~x \"(mithrandir|aragorn)\\.aperiodic\\.net|thorin\\.hillmgt\\.com\" ~F !~p !~P"
# messages to root, etc.
color index cyan default "~C \"(root|postmaster|abuse|mailer-daemon)@\" !~N !~P !~p"
color index cyan white "~C \"(root|postmaster|abuse|mailer-daemon)@\" ~N !~P !~p"
# big messages
color index brightred default "!~N ~z 102400-"
color index brightred cyan "~T !~F !~p !~P ~z 102400-"
color index brightred white "~N ~z 102400-"
# deleted messages
color index red default "!~N ~D"
color index red white "~N ~D"
# Highlights inside the body of a message.
# Attribution lines
color body magenta default "\\* [^<]+ <[^>]+> \\[[^]]+\\]:"
color body magenta default "(^|[^[:alnum:]])on [a-z0-9 ,]+( at [a-z0-9:,. +-]+)? wrote:"
# URLs
color body brightyellow default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
# email addresses
color body brightmagenta default "((@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]),)*@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]):)?[0-9a-z_.+%$-]+@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\])"
# PGP messages
color body brightyellow default "^gpg: Good signature .*"
color body white default "^gpg: "
color body brightwhite red "^gpg: BAD signature from.*"
mono body bold "^gpg: Good signature"
mono body bold "^gpg: BAD signature from.*"
# Various smilies and the like
color body brightwhite default "<[Gg]>" # <g>
color body brightwhite default "<[Bb][Gg]>" # <bg>
color body brightwhite default " [;:]-*[})>{(<|]" # :-) etc...
# *bold*
color body brightblue default "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)"
mono body bold "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)"
# _underline_
color body brightblue default "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)"
mono body underline "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)"
# /italic/ (Sometimes gets directory names)
#color body brightblue default "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)"
#mono body underline "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)"
# Border lines.
color body blue default "( *[-+=#*~_]){6,}"
#-----------------------------------------------------------------------------------------------------------------------
#Visualizar los ficheros html y no su código fuente.
auto_view text/html
_______________________________________________________________________________________
2.- Crear un fichero llamado .firma donde poner el texto que queremos que aparezca al final de cada mensaje que enviemos. Por ejemplo:
Saludos de Usuario
Jefe de ............ y .........
3.- Crear un fichero llamado .mailcap. Este fichero sirve para poder visualizar correctamente los ficheros de email en formato html mediante el uso de w3m. Su contenido será:
text/html; w3m %s; nametemplate=%s.html
text/html; w3m -dump %s; nametemplate=%s.html; copiousoutput
Tutorial Basico de SUBVERSION
Original de Santiago Romero
http://www.sromero.org/wiki/linux/servicios/subversion/basico
Minireceta: tutorial básico de SVN / subversion
A continuación una pequeña minireceta sobre cómo crear un pequeño repositorio de subversión en un sistema remoto, donde alojar tus pequeños proyectos de software o webs.
Este sistema te permitirá tener siempre online una copia actualizada tu código y evitar el tener que llevar .tar.gzs de las últimas versiones de un ordenador a otro. También puede servir como repositorio, en un entorno laboral, de webs, scripts o código de cualquier tipo.
Instalar subversion
Es tan sencillo como instalar el paquete correspondiente vía apt-get o yum
# apt-get install subversion subversion-tools
# yum install subversion
Ahora debemos optar entre 2 opciones:
1.- Levantamos el daemon de svnserve y creamos un repositorio global en el servidor para todos los usuarios (repositorio por defecto). Esto implica que la gestión de los usuarios se realizará a nivel de servidor (por ejemplo en un fichero de usuarios).
2.- Dejamos que cada usuario aloje sus proyectos en uno o varios repositorios propios en su HOME. Esto sólo necesita acceso SSH abierto en el servidor.
Crear repositorio por defecto (SVN)
Si vamos a ejecutar subversión sin SSH, directamente contra el servidor svn, necesitaremos un script de parada y arranque y un repositorio por defecto. Creamos el siguiente script:
# cat /etc/init.d/svnserve
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: svnserve
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start:
# Default-Stop:
# X-Interactive: true
# Short-Description: Start/stop svnserve
### END INIT INFO
test -f /usr/bin/svnserve || exit 0
### Podemos cambiar el puerto en el que escuchar:
OPTIONS="-d -r /var/svn/ --listen-port=3690"
case "$1" in
start)
echo -n "Starting subversion daemon:"
echo -n " svnserve"
start-stop-daemon --start --quiet --oknodo --user root --exec /usr/bin/svnserve -- $OPTIONS
echo "."
;;
stop)
echo -n "Stopping subversion daemon:"
echo -n " svnserve"
start-stop-daemon --stop --quiet --oknodo --exec /usr/bin/svnserve
echo "."
;;
reload)
;;
force-reload)
$0 restart
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: /etc/init.d/subversion {start|stop|reload|restart}"
exit 1
;;
esac
exit 0
Damos permisos de ejecución:
# chmod +x /etc/init.d/svnserve
Ahora lo introducimos en el arranque de la máquina:
Debian: # update-rc.d svnserve defaults
CentOS: # ntsysv
También debemos definir y crear el repositorio por defecto para el daemon que corre en memoria, y modificar los permisos de acceso autenticado (auth-access → permitimos escritura), anónimo (anon-access → no permitimos el accesos) y los usuarios/passwords de autenticación en fichero aparte:
# svnadmin create /var/svn/
# egrep -v "^#|^$" /var/svn/conf/svnserve.conf
[general]
auth-access = write
anon-access = none
password-db = passwd
# cat /var/svn/conf/passwd
[users]
miusuario = elpassword
Como luego veremos, nada impide que vía SSH cada usuario pueda tener sus propios repositorios adicionales.
Finalmente, arrancamos el servicio SVN:
# /etc/init.d/svnserve start
En algunos tutoriales se aconseja crear los siguientes directorios base:
# svn mkdir file:///var/svn/trunk -m "Crear trunk"
# svn mkdir file:///var/svn/tags -m "Crear tags"
# svn mkdir file:///var/svn/branches -m "Crear branches"
La ventaja de este sistema es que podemos dar acceso a múltiples usuarios gracias al fichero de passwords, así como dar acceso anónimo de sólo lectura.
Crear repositorios individuales para los usuario (SVN+SSH)
Podemos utilizar SVN por SSH si queremos un acceso “personal” a un repositorio a través de nuestra cuenta de trabajo de un servidor o host Linux sin necesitar acceso administrativo (siempre y cuando tenga instalado el paquete de subversion). Normalmente es la forma más utilizada para usuarios individuales (no trabajo en grupo) que quieren guardar sus proyectos o ficheros en un repositorio para evitar el traspaso de ficheros entre diferentes equipos de trabajo (ejemplo: tener la misma copia de código en casa o en el trabajo).
En el caso de utilizar SVN por ssh, no necesitamos arrancar el daemon ni crear este repositorio por defecto. En ese caso, crearemos uno o varios repositorios para nuestro usuario, ubicado donde queramos en el PATH, por ejemplo en /home/usuario/svn:
Si necesitamos acceso de múltiples usuarios vía SSH, lo mejor es crear un usuario común (no nuestro usuario personal) que alojará el/los repositorios.
En el caso de SVN+SSH se nos presentan 2 opciones relativas a la organización de los repositorios:
1.- Crear un único repositorio del que colgarán todos los proyectos:
Creamos un directorio único en el servidor (por ejemplo /home/usuario/svn), creado con “svnadmin create”, el cual alojará todos los proyectos. La raíz del repositorio será dicho directorio, para todos los proyectos. La ventaja de este sistema es la simplicidad del “setup”.
La desventaja de este sistema es que las revisiones del repositorio son comunes a todos los proyectos; es decir, si en un repositorio con 3 proyectos hacemos commit en cada proyecto, la revisión aumenta en 3, no es específica para cada proyecto.
Además, borrar un proyecto es “complicado”: implica regenerar el repositorio a partir de un dump con filtro extraído con “svndumpfilter exclude” (ver reposadmin.maint.filtering).
2.- Crear múltiples repositorios (un repositorio para cada proyecto):
Creamos un directorio único en el servidor (por ejemplo /home/usuario/svn), y dentro de dicho directorio creamos un repositorio para cada proyecto (con “svnadmin create nombreproyecto”). La raíz del repositorio ya no será /home/usuario/svn sino /home/usuario/svn/PROYECTO, según el proyecto con el que queramos trabajar.
La ventaja de este sistema es que cada proyecto tiene su propio sistema de revisiones, y sus propios tags y branches. También, el borrado de los proyectos (repositorios) es muy fácil y simple.
Yo personalmente me decanto por esta opción aunque veremos las 2.
La opción elegida sólo cambia la forma de CREAR EL REPOSITORIO y de hacer LA SUBIDA INICIAL DEL PROYECTO y la DESCARGA INICIAL DEL PROYECTO (digamos que los primeros 10 minutos de uso del repositorio). Después, el uso diario y regular de SVN es igual en ambas opciones.
Crear un único repositorio donde alojar todos los proyectos
Creamos el repositorio en el servidor:
$ mkdir /home/usuario/svn/
$ svnadmin create /home/usuario/svn
Una vez hecho esto, vía SSH podemos ya acceder al repositorio referenciándolo como:
$ export SVNROOT="svn+ssh://usuario@server.com/home/usuario/svn/"
De nuevo, se recomienda crear los siguientes subdirectorios:
$ svn mkdir file:///home/usuario/svn/trunk -m "Crear trunk"
$ svn mkdir file:///home/usuario/svn/tags -m "Crear tags"
$ svn mkdir file:///home/usuario/svn/branches -m "Crear branches"
Repositorio único: Subir por primera vez un proyecto al repositorio
Sea un directorio de código fuente denominado “miproyecto”. Nos situamos en el directorio padre de “miproyecto” y ejecutamos uno de los siguientes comandos:
$ svn import miproyecto svn://server.sromero.org/var/svn/miproyecto
$ svn import miproyecto svn+ssh://server.sromero.org/home/sromero/svn/miproyecto
$ svn import miproyecto ${SVNROOT}/miproyecto
$ svn import miproyecto ${SVNROOT}/miproyecto -m "Upload inicial del proyecto"
Al comando le decimos que importe un directorio específico (svn import miproyecto) y le decimos que lo haga sobre el SVNROOT añadiendo además el subdirectorio del repositorio que alojará el proyecto (miproyecto también en este caso). Esto permite tener múltiples proyectos en cada repositorio, gracias a este path “final” sobre el SVNROOT.
Se nos solicitará entonces la introducción de una línea de texto para “resumir” en qué consiste el cambio realizado. Todos los cambios en el repositorio tienen que tener este “summary” que luego podemos recuperar con “log”.
Como se puede ver en el último ejemplo, podemos agregar el resumen para el log en la línea de comandos (en modo no interactivo) con -m “Upload inicial del proyecto”.
Repositorio único: Descargar una copia del proyecto desde el repositorio
Una vez un repositorio está en un proyecto, podemos “descargar” una copia ya controlada por SVN. De hecho, deberíamos desechar (de momento renombrar) el directorio de proyecto original y trabajar con la copia versionada.
Nos situamos en el directorio de trabajo “padre” y (una vez renombrado el directorio original si existe) ejecutamos lo siguiente (una u otra opción según si tenemos definida o no la variable):
$ svn checkout svn://server.sromero.org/var/svn/miproyecto
$ svn checkout ${SVNROOT}/miproyecto
Esto descargará el proyecto “SVNROOT/miproyecto” recreando el directorio “miproyecto” en el directorio actual.
Usar un repositorio para cada proyecto
Esta puede ser la opción más habitual si no queremos mezclar revisiones y si queremos poder borrar un proyecto concreto.
Múltiples repositorios: creando los repositorios
- Creamos un directorio común del que colgarán todos los repositorios (proyectos). Por ejemplo: /home/usuario/svn/.
- Creamos un repositorio por cada proyecto, con “svnadmin create /home/usuario/svn/proyecto”.
- Preparamos cada proyecto para su subida, creando los subdirectorios trunk, branches y tags. Esta subida implicará un SVNROOT diferente para cada proyecto.
- Subimos cada proyecto a su propio repositorio.
- Ya podemos trabajar con los proyectos. Para esto ya no hará falta definir un SVNROOT diferente por proyecto ya que los directorios ocultos .svn de cada proyecto guardan esta información:
Empezamos creando el directorio común en el servidor SVN:
$ mkdir /home/usuario/svn/
Para cada proyecto a alojar hay después que crear su repositorio en el servidor SVN:
$ svnadmin create /home/usuario/svn/proyecto1
$ svnadmin create /home/usuario/svn/proyecto2
Múltiples repositorios: Subir por primera vez proyectos al repositorio
Supongamos que tenemos en nuestro sistema 2 proyectos bajo /home/usuario/code y queremos alojarlos en el servidor de SVN.
Primero preparamos el proyecto1, creando los 3 subdirectorios trunk, branches y tags:
- trunk → contiene el código fuente del proyecto.
- branches → donde se pueden crear ramas del proyecto.
- tags → donde se pueden alojar “snapshots” del código fuente en un momento dado.
$ cd /home/usuario/code/
$ cd proyecto1
$ mkdir trunk
$ mv * trunk
$ mkdir branches
$ mkdir tags
Una vez estructurado el directorio del proyecto, lo subimos al repositorio:
$ export SVNROOT="svn+ssh://server.sromero.org/home/sromero/svn/proyecto1"
$ svn import proyecto1 ${SVNROOT}/ -m "Agregamos proyecto1 a su propio repositorio"
Nótese que ahora el SVNROOT incluye el subdirectorio “proyecto1”, al contrario que en el caso de múltiples proyectos en un único repositorio.
Repetimos a continuación el proceso para nuestro segundo proyecto:
$ cd /home/usuario/code/
$ cd proyecto2
$ mkdir trunk
$ mv * trunk
$ mkdir branches
$ mkdir tags
$ export SVNROOT="svn+ssh://server.sromero.org/home/sromero/svn/proyecto2"
$ svn import proyecto1 ${SVNROOT}/ -m "Agregamos proyecto2 a su propio repositorio"
Múltiples repositorios: Descargar por primera vez el proyecto del repositorio
Importamos el proyecto “subversionado”, renombrando el directorio original y haciendo un checkout:
$ cd /home/usuario/code/
$ export SVNROOT="svn+ssh://server.sromero.org/home/sromero/svn/proyecto1"
$ mv proyecto1 proyecto1.orig
$ svn checkout $SVNROOT proyecto1
Y lo mismo para el otro proyecto:
mv proyecto2 proyecto2.orig
svn checkout $SVNROOT proyecto2
Ahora ya podríamos trabajar con normalidad dentro de cualquiera de los 2 proyectos (svn update, svn commit, etc), y cada uno de ellos estará alojado dentro de su propio repositorio sin compartir estructuras de SVN con otros proyectos.
Múltiples repositorios: Borrado de un proyecto del repositorio
El borrado de un proyecto, se realizará en el servidor con un simple:
$ rm -rf /home/usuario/svn/elproyecto
(sin afectar así al resto de proyectos, y pudiendo volver a generarlo de nuevo con un “svnadmin create” si fuera necesario).
Múltiples repositorios: Import y checkout inicial masivo
Veamos un pequeño “script” que subirá al repositorio todos los proyectos que tenemos bajo un mismo directorio:
En el servidor SVN:
cd /home/usuario/svn
for PROJECT in proyecto1 proyecto2 proyecto3 proyecto4;
do
svnadmin create $PROJECT
done
En nuestro equipo de trabajo:
cd /home/usuario/prog/code
for PROJECT in proyecto1 proyecto2 proyecto3 proyecto4;
do
export SVNROOT="svn+ssh://user@myserver.org/home/usuario/svn/${PROJECT}/"
cd ${PROJECT}
mkdir trunk
mv * trunk
mkdir tags
mkdir branches
cd ..
svn import $PROJECT ${SVNROOT} -m "Agregamos proyecto al repositorio"
done
Con esto hemos subido los diferentes proyectos al servidor SVN, cada uno en un repositorio diferente bajo la misma ruta.
Ahora tenemos que descargarnos los proyectos “subversionados” para trabajar con ellos en lugar de usar los directorios de código fuente originales (que no contienen el directorio oculto .svn):
cd /home/usuario/prog/code
for PROJECT in proyecto1 proyecto2 proyecto3 proyecto4;
do
# Movemos el directorio original como .orig
if [ -e $PROJECT ]; then mv $PROJECT ${PROJECT}.orig ; fi
export SVNROOT="svn+ssh://user@myserver.org/home/usuario/svn/${PROJECT}/"
svn checkout $SVNROOT $PROJECT
done
Esta operación es la misma que tendremos que realizar en otros equipos (ej: en casa) donde guardemos copia de estos proyectos, para tenerlos versionados y apuntando al repositorio desde este momento.
Un apunte final sobre el comando mv del script importador:
mv * trunk
Este comando no movera archivos ocultos a trunk/ si tu proyecto los tiene. En ese caso, se puede usar:
(shopt -s dotglob; mv -- * ..)
(con los paréntesis)
Usar subversion
Referenciar el repositorio:
La referencia del repositorio puede ser svn: o svn+ssh: :
- SVN puerto por defecto:
svn://server.sromero.org/var/svn/
- SVN puerto modificado:
svn://server.sromero.org:puerto/var/svn/
- SVN via SSH puerto estándar:
Repositorio único: svn+ssh://server.sromero.org/home/usuario/svn/
Múltiples repositorios: svn+ssh://server.sromero.org/home/usuario/svn/nombre_proyecto
- SVN via SSH puerto o usuario modificados:
Repositorio único: svn+ssh://server.sromero.org/home/usuario/svn/
Repositorio único: svn+ssh://usuario@server.sromero.org/home/usuario/svn/
Múltiples repositorios: svn+ssh://usuario@server.sromero.org/home/usuario/svn/nombre_proyecto
export SVN_SSH="ssh -p 24"
Repositorio único: svn+ssh://usuario@server.sromero.org/home/usuario/svn/
Múltiples repositorios: svn+ssh://usuario@server.sromero.org/home/usuario/svn/nombre_proyecto
En ocasiones puede ser útil declarar este valor en un “export SVNROOT” para usarlo después en las llamadas a svn.
SVN/SSH no nos pedirá password si utilizamos autenticación sin password por clave pública/privada. En el caso de SSH, en ocasiones se crea un usuario específico “svn” para que sea dueño específico del repositorio.
Subir cambios al repositorio
Cuando hacemos cambios en el código, debemos de subirlos al repositorio (hacer un commit de los cambios). Hay quien hace commit cada vez que hace un cambio acotado (para que gracias al comentario del commit podamos saber qué cambios se realizan cada vez), y hay quien hace un commit al final de largas sesiones de trabajo.
Una vez hayamos decidido hacer el commit, y estando dentro del directorio de trabajo del proyecto, ejecutamos:
$ svn commit
$ svn commit fichero_o_directorio
$ svn commit -m "Resumen de cambios"
Nótese que no necesitamos especificar el SVNROOT porque viene ya “pregrabado” en el directorio que hemos descargado (directorio oculto .svn).
Descargar cambios desde el repositorio
Si otros compañeros han subido cambios o bien queremos descargar en casa los cambios realizados en el trabajo, podemos hacer un update sobre nuestra copia local (que en algún momento fue descargada con checkout).
$ svn update
$ svn update fichero_o_directorio
Agregar/Crear/Mover/Borrar ficheros o directorios al proyecto
En SVN tenemos que “añadir” al repositorio los ficheros NUEVOS que creemos localmente, para que sean también subidos/descargados con los checkouts/updates. También hay que eliminar ficheros remotamente si queremos borrarlos localmente.
$ svn add fichero_o_directorio
$ svn mkdir nuevo-dir
$ svn move file_dir1 file_dir2
$ svn delete fichero_o_directorio
Ver las diferencias de nuestra copia respecto al repositorio
Si hemos hecho cambios en nuestra copia local “descargada”; podemos ver un diff de dichos cambios con:
$ svn diff
$ svn diff fichero_o_directorio
$ svn diff | less
$ svn diff | vim -
Descartar nuestros cambios locales
Es posible en algún momento que hayamos hecho cambios en algún fichero de nuestra copia local y queramos deshacerlos para empezar de cero con los datos que hay en el repositorio. En ese caso no es necesario realizar un checkout de nuevo, podemos hacer un:
$ svn revert fichero_o_directorio
O bien, si queremos revertir todos los cambios (.) o los de un directorio:
$ svn revert --recursive .
$ svn revert --recursive directorio
Ver historico de un fichero o del proyecto
Lo siguiente muestra todo el registro de cambios de un proyecto:
$ svn log
$ svn log fichero_o_directorio
Ver estado del proyecto
El siguiente comando proporciona un listado de nuevos ficheros, ficheros modificados, y ficheros a borrar en el próximo commit.
$ svn status
Resulta también muy útil para conocer si en el directorio actual hay ficheros sin versionar (a los que falta hacerle el svn add), porque estos aparecen con el prefijo ?:
$ touch new_file
$ svn status
? new_file
Flags opcionales para el comando "svn"
Si no estamos usando svn+ssh, puede ser interesante especificar user/pass en línea de comandos:
--username sromero --password XXXXXX
También, para el checkout y para el update, puede ser útil la opción –force.
Con –force podríamos hacer un checkout de un proyecto recién subido al repositorio con un import sobre el directorio “inicial” sin renombrarlo. Es decir, podríamos subir una web al repositorio y hacer un checkout –force en el directorio de la web para “descargar la copia remota” y crear las estructuras .svn sin tener que renombrar el directorio y hacer el checkout (que cortaría la web mientras hacemos el mv + checkout).
Mover un repositorio ya existente
Para mover un repositorio se puede usar switch:
$ svn switch --relocate old-url new-url
Tags y branches de proyectos
En subversion tenemos disponibles las siguientes funcionalidades:
- tags → “Snapshot” (foto ó backup) del código (trunk) en un momento dado, para marcar dicho momento en el tiempo del código como un estado concreto (por ejemplo: versión 0.1.0), o para hacer una copia del código antes de realizar alguna acción “invasiva” y de la que podríamos querer volver atrás. Los tags nos permiten así empaquetar el código en versiones específicas o bien volver atrás después de un cambio que no ha salido bien y que no se puede deshacer ya con un revert porque ha tenido commits al repositorio. Los tags son “versiones sólo lectura” del código.
- branches → “Ramas” del código. Es decir, “versiones paralelas” del código que otro equipo de desarrollo pueda querer explorar. Son parecidos a los tags, salvo que pueden modificarse. Por ejemplo, podríamos hacer un branch del código para que otro equipo de desarrollo pruebe a implementar soporte en nuestro programa para otro Sistema Operativo, y que si el desarrollo llega a buen puerto, se haga un “merge” de esta rama con el trunk.
Para crear un tag o un branch, lo haríamos con el comando “svn copy”
$ svn copy trunk tags/0.1.0 -m "Version 0.1.0 del proyecto"
$ svn commit -m "Version 0.1.0" tags/
$ svn copy trunk tags/0.1.0-antes-de-probar-SDL -m "Snapshot antes de probar SDL"
$ svn commit -m "Snapshot antes de probar SDL" tags/
$ svn copy trunk branches/soporte-android -m "Creamos branch pruebas Android"
$ svn commit -m "Branch pruebas de soporte para Android" branches/
También podemos crear un tag o branch no desde la rama de trunk sino desde nuestra copia local (directorio del proyecto), es decir, con cambios aún no subidos al repositorio:
$ svn copy miproyecto ${SVNROOT}/tags/android-funcional -m "Tag con codigo Android Funcional"Para borrar un tag o un branch, lo haríamos con “svn delete”:
$ svn delete tags/0.1.0-antes-de-probar-SDL -m "Eliminamos el tag: SDL implementado OK"
$ svn commit -m "Borrado tag 0.1.0-antes-de-probar-SDL"
$ svn delete branches/soporte-android
$ svn commit -m "Se borra la rama de soporte para Android"
En realidad, físicamente no se borra el código, sólo se marca el repositorio de forma que ya no “exista” en cuanto a actualizaciones. No obstante, podemos recuperar cualquier número de revisión en cualquier momento con:
$ svn copy ${SVNROOT}/branches/rama-android@15 \
${SVNROOT}/branches/rama-android \
-m "Restaurando revision 15"Podemos obtener un listado de tags o branches del proyecto con svn list (para restaurar revisiones puede sernos útil también svn log, svn info y svn status).
$ svn list ${SVNROOT}/tags
0.1.0/Y podemos hacer un checkout de un release concreto con:
$ svn checkout ${SVNROOT}/tags/0.1.0 Una de las pegas de los tags es que son parte del proyecto por lo que cada vez que hagamos checkouts o updates nos los vamos a descargar en ~/proyecto/tags . Si queremos evitar esto, podemos hacer checkout sólo del raíz del repositorio (no recursivamente, -N) y actualizar sólo el trunk:
$ svn checkout $SVNROOT -N PROYECTO
$ svn update PROYECTO/trunk
De esta forma sólo descargamos el trunk, y no tags ni branches, por lo que no desperdiciamos espacio en disco local.
Trabajando con ramas (branches)
Existen diferentes políticas al respecto de cómo trabajar con el código y las ramas.
Quizá la más extendida es trabajar sobre la rama principal (trunk) y cada cierto tiempo crear una rama denominada “estable”. El proyecto se continúa después sobre la rama principal y la estable sólo se modificará (durante el tiempo de vida de dicha versión) para corregir bugs (que también se deberán corregir en el trunk si le afectan); las nuevas características o funcionalidades sólo se implementarán en la rama principal.
Así, podemos crear una nueva rama y trabajar sólo sobre ella así:
$ svn info ${SVNROOT}/trunk | grep Revision
# (anotamos el numero de revision actual "REVISION_ACTUAL")
$ svn copy ${SVNROOT}/trunk ${SVNROOT}/branches/stable-1.0 \
-m "Rama estable LA_REVISION_ACTUAL"Ahora configuramos nuestra copia local como la nueva rama:
svn switch --relocate ${SVNROOT}/trunk ${SVNROOT}/branches/stable-1.0En este momento, podemos trabajar con nuestra copia local y ya no estaremos trabajando con el trunk sino con “stable-1.0”.
$ svn info | grep URL
$ svn update
# (hacemos cambios)
$ svn commit -m "Bug corregido en blah"
Estos pasos servirán incluso si tenemos cambios en nuestra copia local que todavía no hemos subido al trunk, porque hemos decidido que estén en la nueva rama y no en el trunk.
Convertir nuestra rama en la rama principal
También podemos haber querido crear una rama para explorar una alternativa al código (por ejemplo, cambiar de GTK a QT) y que los cambios hayan tenido éxito y queramos convertir esta rama en la versión principal:
Un primer método es borrar el trunk y convertir el código de nuestra rama en el trunk:
$ svn delete ${SVNSERVER}/trunk
$ svn move ${SVNSERVER}/branches/programa-con-qt ${SNVSERVER}/trunk
$ svn switch --relocate ${SVNSERVER}/branches/programa-con-qt ${SVNSERVER}/trunk
Hacer merge de los cambios de nuestra rama con la principal
El merge de una rama al trunk se realiza con:
$ svn merge -r XXX:YYY $SVNROOT/branches/la-rama
$ svn commit -m "Realizado merge de la-rama (XXX:YYY) al trunk"
Siendo XXX la revisión en la cual nació la rama y YYY la revisión actual del trunk.
Para obtener estos datos, podemos:
# hacer un checkout del trunk y de la rama en otro directorio:
$ cd ..
$ mkdir temp
$ cd temp
$ svn checkout $SVNSERVER/trunk trunk
$ svn checkout $SVNSERVER/branches/la-rama la-rama
$ cd la-rama
# encontrar la revisión donde se creó la rama (XXX):
$ cd la-rama
$ svn log --stop-on-copy
# encontrar la revisión actual del trunk ("At revision YYY"):
$ cd ..
$ cd trunk
$ svn update
Esto realizará un merge del código de la-rama sobre el trunk. Si hubiera conflictos de edición de ficheros (puede haberlos), los arreglamos localmente y hacemos un commit para subirlos:
$ vim fichero_que_da_conflictos.c
$ svn commit -m "Merge de
$ svn commit -m "Realizado merge de la-rama (XXX:YYY) al trunk"
Borrar un repositorio ya existente en el servidor
Simplemente, ejecutampos lo siguiente en el repositorio:
# TODO EL ARBOL DE PROYECTOS/REPOSITORIOS
$ rm -rf /home/sromero/svn/
# UN REPOSITORIO CONCRETO:
$ rm -rf /home/sromero/svn/PROYECTO/
Para volver a tenerlo operativo habría que seguir de nuevo el proceso de creación (mkdir, svnadmin create, editar conf/svnserve.conf, e importar en él proyectos).
Operativa inicial con SVN (cómo subir un proyecto)
Según si vamos a crear un repositorio común para todos los proyectos, o si vamos a crear un repositorio por cada proyecto, los comandos exactos son ligeramente diferentes (ver las correspondientes secciones al principio de este documento), pero generalizando, son:
1.- Crear el/los repositorios en el servidor.
2.- Establecer variables de entorno (SVNROOT y SVN_SSH si necesitamos cambiar el puerto).
3.- Preparar los directorios de nuestro proyecto (en el caso de múltiples repositorios, crear directorios trunk/branches/tags).
4.- Subir nuestro proyecto o web al repositorio.
5.- Renombrar el directorio antiguo.
6.- Descargar el mismo directorio pero con el control de versiones.
7.- Revisar que la descarga es correcta y que no faltan ficheros.
8.- “Archivar” (guardar, borrar) el directorio de código antiguo.
Operativa regular (trabajar con un proyecto)
A partir de ahora, debemos trabajar sobre el directorio de trabajo creado acordándonos de realizar “svn add” de nuevos ficheros, “svn delete” de ficheros que borremos, y de hacer los commits para subir nuestro trabajo y updates para recuperar el trabajo de los demás.
Aplicación práctica: ficheros específicos del HOME en SVN
Una cosa habitual para las personas que trabajamos con varios PCs (portátil, sobremesa casa, trabajo…) es tener gran cantidad de ficheros de configuración comunes entre todos ellos: .vimrc, .bashrc, .tmux.conf, así como directorios de notas, documentación, etc… En esos casos, cada vez que hacemos una mejora en uno de los ficheros, tenemos que distribuirlo manualmente a los otros equipos (vía correo, scp, o llavero USB).
En este ejemplo, vamos a mantener una copia selectiva de ficheros de nuestro HOME en un repositorio privado online de subversion, de forma que con un simple svn update (incluso podría ser automatizado en el login de nuestro usuario) podamos actualizar nuestro HOME local con las últimas copias de dichos ficheros. No sólo eso, sino que nos protege contra borrados accidentales de ficheros (podemos recuperarlos con un svn update) o para encontrar cambios en los ficheros que hayan producido algún problema (volviendo a revisiones anteriores, etc).
NOTA: nunca debemos subir ficheros con datos sensibles en cualquier caso, como una clave SSH, si no confiamos en la seguridad de dicho servidor.
Por ejemplo: estamos en el trabajo, encontramos una opción fantástica para el fichero .vimrc, la añadimos, hacemos un svn commit -m “Nueva opcion vimrc”, y luego en casa sólo hay que hacer svn update (o bien, como he dicho, ponerlo de forma automática en el arranque o el login del usuario).
Para montar este sistema, primero creamos el repositorio en el servidor:
$ svnadmin create /home/usuario/svn/home
Ahora ya en la parte cliente, creamos un directorio “home” ficticio, vacío, para subirlo al repositorio:
$ cd
$ mkdir home
$ export SVNROOT="svn+ssh://usuario@server.org/home/usuario/svn/home"
$ svn import home $SVNROOT -m "Creado homedir"
$ rm -rf ~/home
Finalmente, dentro de nuestro /home/usuario real, hacemos un checkout de “home” para que svn cree un directorio .svn de control en nuestro home.
$ cd /home/usuario
$ export SVNROOT="svn+ssh://usuario@server.org/home/usuario/svn/home"
$ svn checkout $SVNROOT . --force
Revisión obtenida: 0
Este checkout lo tenemos que realizar inicialmente en todos lo /home/usuario de los equipos donde queremos tener sincronizados los ficheros (por ejemplo, casa, trabajo, portátil)…
Ojo, –force sobreescribirá cualquier archivo ya existente, por lo que hay que revisar que no hayamos subido al SVN ninguno que no queramos tener idéntico entre los diferentes equipos (en cualquier caso, se recomienda hacer una copia previa a otro directorio “old” de los ficheros que se sobreescribirán la primera vez, por si acaso).
Desde este momento ya podemos subir ficheros a nuestro repositorio:
$ svn add .vimrc* .tmux.conf .gvimrc
A .vimrc
A .vimrc.common
A .tmux.conf
A .gvimrc
$ svn commit -m "Subidos ficheros iniciales"
Añadiendo .gvimrc
Añadiendo .tmux.conf
Añadiendo .vimrc
Añadiendo .vimrc.common
Transmitiendo contenido de archivos ..........
Commit de la revisión 1.
Con esto, cada vez que añadamos alguna funcionalidad nueva en el .vimrc, por ejemplo, en casa, podemos hacer un update en el trabajo y disfrutar de “contenidos sincronizados” sin andar enviando ficheros por correo o en unidades USB.
Simplemente tenemos que hacer un svn update en cada sitio para tener regularmente sincronizados los ficheros que tengamos en el repositorio.
# En otro sistema diferente,
$ export SVNROOT="svn+ssh://sromero@server.sromero.org/home/sromero/svn/home"
$ svn update --force
Además de ficheros podemos añadir directorios completos con sus subdirectorios:
$ svn add docs
A docs/notas_subversion.txt
A docs/comandos_utiles.txt
A docs/tutorial_truecrypt.txt
(...)
$ svn commit -m "Subido directorio docs"
Si queremos añadir sólo algunos ficheros de un directorio (es decir, ficheros selectivamente, pero no todo el contenido), bastará con que agreguemos el directorio con –non-recursive y luego los ficheros individuales. Esto puede ser útil por ejemplo si tenemos un directorio que tiene algún fichero que DEBE de ser diferente en ambos sistemas:
$ ls -1 bin
haz_backup.sh
sistema_backup.py
wxmylauncher.py
$ svn add bin --non-recursive
A bin
$ svn add bin/sistema_backup.py bin/wxmylauncher.py
A bin/sistema_backup.py
A bin/wxmylauncher.py
$ svn commit -m "Subidos algunos ficheros de bin/"
De esta forma, los updates sólo actualizarán los 2 scripts que hemos marcado, y podemos tener así scripts con el mismo nombre pero distinto contenido en las diferentes máquinas.
Podemos habilitar un script para facilitarnos el “svn update” del home:
$ cat bin/update_home_svn.sh
#!/bin/bash
# Update home directory from SVN
export SVNROOT="svn+ssh://usuario@server.org/home/usuario/svn/home"
cd $HOME
svn update
Siendo este script otro candidato a mantener en SVN (svn add bin/update_home_svn.sh + svn commit).
Etherpad - Editor web basado en la colaboración en tiempo real.
Permite a varios autores editar simultáneamente un documento de texto, y ver todos los participantes en las ediciones en tiempo real, con la capacidad de mostrar el texto de cada autor en diferente color. También hay una ventana de chat en la barra lateral para permitir la comunicación directa.
NGINX: una interesante alternativa a Apache.
Este antiguo servidor Web está ganando popularidad dentro del ámbito empresarial. NGINX es ahora el nuevo número dos de servidores Web, en gran parte porque es una alternativa rápida, ligera y de código abierto al todopoderoso Apache. He aquí el por qué atrae tanto la atención.
http://blog.desdelinux.net/nginx-una-interesante-alternativa-a-apache/
Cambiar codificaciones de caracteres de archivos. - iconv
iconv is a computer program and a standardized application programming interface (API) used to convert between different character encodings.
http://en.wikipedia.org/wiki/Iconv
Generador de instalaciones para programas Python ( y Windows)
py2Nsis is a Simple to Use, Nsis installers generator for python projects. It also make the setup.py for py2exe.
Nsis is a professional open source system to create Windows installers.
py2exe is a Python Distutils extension which converts Python scripts into executable Windows programs, able to run without requiring a Python installation.
py2Nsis combines the capabilities of these ones and generates directly a Windows installer with just a few information about your python code!
Discos de arranque
We offer a boot disk for everything from MS-DOS 3.3 to Windows XP Professional. These disks can be used to setup a new hard drive, scan an existing hard drive for errors, install or re-install Windows, upgrade your PC's BIOS, run DOS utilities and much more.
Ejecutar programas o archivos desde Delphi
http://delphi.about.com/od/windowsshellapi/a/executeprogram.htm