Москва’2011

Puede sonar típico este post, lo reconozco, al igual que todas esas frases de corta y pega y referencias al Club de los 27, pero es que me apetecía escribir los pensamientos que me rondan estos días en relación a la muerte de Amy Winehouse, aunque sobre todo a su música. Es más, reconozco que no había vuelto a escuchar un disco de ella completo desde hacía por lo menos un par de años.
Como suele ocurrir en estos casos, durante estos días la venta de discos se dispara, aparecen recopilatorios, libros, DVDs, nuevos fans, se suavizan las críticas extra-musicales y el artista pasa de ser una estrella, a ser un mito.
Pasando un poco por encima sobre su vida personal, al fin y al cabo, Amy Winehouse es una prueba más de que aquí cada uno puede, y en última instancia, debe, hacer con su vida lo que le da la gana. Como es lógico, opiniones existen para todos los gustos. En mi opinión, veo normal que sus más allegados (familia y amigos), intentaran influir de alguna forma en su vida. Cada uno quiere lo mejor para él y los suyos.
El caso de Amy Winehouse es un ejemplo más de un talento desperdiciado. Sólo había sacado dos discos. Como siempre, queda la duda de si lo mejor aún estaba por llegar. Quién sabe. Peor fue el caso de Jeff Buckley.
La conocí un poco tarde, por el 2008-2009, con el famoso Rehab y el superventas Back to Black retumbando por todos sitios. Y estos días, reescuchándolo, ocurre como en otras muchas ocasiones, que la música gana con el tiempo. He vuelto a escuchar temas que en su momento, no eran de mis preferidos, y que ahora me parecen sublimes. Hablo de Addicted, He Can Only Hold Her y sobre todo de Some Unholy War. Este último me parece una auténtica joya. El ritmo de la canción, los arreglos, la riqueza de tonos de la voz, su flow sobre la base. Apenas dos minutos, pero intensos. Además, el productor de esta canción, Salaam Remi, ha publicado estos días en su blog una versión de este tema no incluida originalmente en Back to Black (aunque sí en las últimas reediciones del álbum), algo que por lo visto le afectó bastante en su momento.
Otro tema que me parece genial, y que se sale de la línea soul que la caracterizó últimamente, es In My Bed, de nuevo producido por Salaam Remi, e incluido en su primer álbum Frank:
Y para terminar, cerraré este post con este magnífico directo interpretando Some Unholy War. Hasta siempre, Amy Winehouse.
Para CD:
dd if=/dev/cdrom of=/carpeta/destino/cd.iso
Para DVD:
dd if=/dev/dvd of=/carpeta/destino/dvd.iso
A raíz de los problemas técnicos que me he ido encontrando por el camino para conseguir confirmar el borrador de la declaración de la renta usando mi certificado digital, he hecho un resumen de los pasos que he ido dando para ello.
Por lo tanto, partimos de que tenemos ya instalado en el navegador (en mi caso, Firefox 4) nuestro certificado digital proporcionado por la FNMT. Además, se supone que ya hemos hecho la solicitud del borrador de la declaración de la renta, y estamos ya en el paso en que queremos enviar la confirmación. Por lo tanto, se supone que ya tendremos instalado en el navegador el certificado FNMT Clase 2 CA - FNMT, proporcionado automáticamente al entrar en la web de la Agencia Tributaria. En caso de no tenerlo instalado, se puede descargar aquí y luego importarlo en Firefox.
Pues bien, lo primero que necesitamos es instalar 2 certificados necesarios para realizar trámites en la web de la Agencia Tributaria. Son los siguientes:

En esta web oficial podéis encontrar estos y otros certificados.
A continuación, hay que editar la configuración de los certificados en Firefox. Para ello, abrimos el administrador de certificados, marcamos los 3 certificados y le damos a editar confianza. Marcamos las 3 casillas.

También hay que configurar un parámetro de Firefox para permitir la ejecución de scripts. Para ello, abrimos el menú de configuración poniendo en la barra de direcciones about:config. Una vez dentro, escribimos signed y hacemos doble clic sobre el único resultado que nos sale. Si nos fijamos en el campo Valor, ahora debería estar a true. Después de esto, reiniciamos Firefox.
Por último, nos dirigimos a la pantalla de entrada para confirmar el borrador, iniciando sesión mediante nuestro certificado digital, y realizamos todos los pasos necesarios.

El último paso será enviar la confirmación, en el que nuevamente, nos pedirá que escribamos una contraseña maestra para realizar la firma digital. Lo dejamos en blanco y le damos a aceptar. Listo.

Partimos de un disco duro en formato VMDK con Windows XP instalado.
Lo primero, como siempre, será guardar una copia por si acaso ocurriera algo. Por ejemplo, exportando la máquina.
A partir de la versión 4 de VirtualBox, ya es posible redimensionar los discos duros. Pero sólo si:
VBoxManage clonehd --format VDI winxp.vmdk winxp.vdi
VBoxManage modifyhd winxp.vdi --resize tamaño_en_megabytesPor último, sólo falta redimensionar la partición de Windows XP, usando GParted, por ejemplo.

Hacía tiempo que tenía pendiente escribir un post sobre Sammy.js, así que por fin me he decidido a hacerlo.
Sammy, además de ser el nombre de un multi-instrumentista y actor estadounidense, es el nombre de un potente y fascinante framework javascript que se ha convertido en una gran herramienta para desarrollar aplicaciones AJAX.
Creado por el genial Aaron Quint, Sammy.js actúa como una capa de abstracción sobre jQuery que sirve para mapear y responder a URLs específicas. Esto permite desarrollar aplicaciones AJAX donde cada link tiene asociada su propia URL, y donde el botón Atrás del navegador recupera su función original (que se había perdido con las primeras aplicaciones AJAX), lo que se traduce en una navegación más natural y en una mejor interacción con el usuario. Gmail y el nuevo Twitter son dos buenos ejemplos de este tipo de aplicaciones AJAX.
Todo lo que hay en Sammy.js gira en torno a rutas, callbacks y eventos. Básicamente, se trata de asignar callbacks a rutas predefinidas (patrones de URLs) de forma que se disparen cuando el navegador apunte a determinadas URLs. Por ejemplo, podríamos definir el siguiente patrón:
/libros/:id
y asignarle una función (callback) que se dispare cuando por ejemplo, el navegador apunte a la dirección:
/libros/1212
Esto en Sammy.js se haría de la siguiente manera:
$.sammy(function() {
this.get('#/libros/:id', function() {
// acción
});
});
Y así, iríamos definiendo callbacks para cada una de las posibles rutas de nuestra aplicación.
Sammy.js está orientado a REST, lo que hace que los callbacks se puedan definir usando los 4 verbos HTTP básicos: GET, PUT, UPDATE y DELETE. En el ejemplo de antes, hemos usado el más común de ellos: GET.
Sammy.js ofrece muchas otras posibilidades, pero eso lo dejaré para otro post.
Quora es una base de conocimiento bien organizada con preguntas y respuestas en forma de red social. Creada por ex-empleados de Facebook, está ganando audiencia rápidamente. Algunos de los puntos fuertes son que te puedes suscribir a un proyecto/persona al que le estés siguiendo la pista (p.e. Twitter, Facebook, jQuery, KDE,…) y estar al día de las mejores preguntas/respuestas que se están haciendo sobre ellos. Otro punto fuerte es que por ahora es bastante exclusivo y muchos de sus miembros son expertos en diferentes áreas, incluso los propios creadores, por lo que por ahora hay información de calidad.
(Vía Bitelia)
El otro día alguien preguntaba qué era la sinergia. Pues esta es una respuesta que se me ocurrió esta mañana mientras desayunaba:
Imagina el sabor del Huevo
el sabor del Azúcar
el sabor de la Harina
el sabor de la Leche
el sabor del Limón
el sabor de la Canela…
Ahora imagina el sabor de un tierno y delicioso bizcocho recién hecho, fruto de unir todos los ingredientes anteriores. Es mucho más apetitoso que los ingredientes por separado, ¿verdad? Pues eso es la sinergia.

Un sistema de control de versiones (SCV) es un software que nos permite llevar un historial de las distintas versiones por las que va atravesando el desarrollo de un producto, normalmente, software. Existen multitud de herramientas ahí afuera, aunque si hay que elegir alguna, Subversion es con diferencia la más usada. Por ahora.
Subversion es un SCV centralizado. Esto quiere decir que requiere de un servidor donde alojar el repositorio del proyecto, y al que los distintos desarrolladores acceden para recuperar o actualizar los cambios del producto en desarrollo. El esquema de un SCV centralizado sería el siguiente:

(Vía http://progit.org/book/)
El principal inconveniente de este esquema es que dependemos al 100% de la integridad del servidor. Un corte de conexión atrasaría el desarrollo del producto durante un tiempo. La pérdida de datos supondría la pérdida de todo el historial de desarrollo (algo que se podría evitar con copias de seguridad, claro).
Git es otro SCV, aunque a diferencia de Subversion, Git es un sistema de control de versiones distribuido.
En un SCV distribuido, el historial del proyecto no se aloja sólo en el servidor. En lugar de esto, cada desarrollador tiene su propia copia de todo el historial. Además, la existencia de un servidor donde alojar el historial se convierte en algo opcional. El esquema de un SCV sería el siguiente:

(Vía http://progit.org/book/)
Como se ve en el diagrama, el flujo de trabajo es diferente del que había con un sistema centralizado. Ahora, cada desarrollador dispone de una copia completa del repositorio, pudiendo además recuperar/actualizar los cambios entre dos o más repositorios. Además, cada desarrollador envía los commits a su propio repositorio local, con lo que puede trabajar sin necesidad de estar conectado.
Git nació en 2005 como un proyecto liderado por Linus Torvalds, creador del núcleo Linux. Entre sus objetivos estaba el de crear un SCV rápido y seguro que permitiera un desarrollo distribuido del kernel de linux. Hoy en día, son muchos los que colaboran en el desarrollo de esta gran herramienta, haciendo que Git se haya convertido en los últimos años en uno de los SCV más usados, gracias en otras cosas a github.
Entre las principales ventajas de Git están la rapidez, la eficiencia, la seguridad y sobre todo la flexibilidad. Aunque quizá ésta última pueda convertirse al principio en un inconveniente.
Y bueno, después de toda esta introducción y cúmulo de piropos, vamos al grano: voy a mostrar algunos de los principales comandos que puedes usar en Git.
Comenzando con Git
Recordemos que en Git se trabaja con un repositorio local. Para crearlo, sólo tendremos que situarnos en el directorio del proyecto y poner:
git init
Con eso, ya tendremos el repositorio creado y nuestro proyecto bajo revisión. A diferencia de Subversion, git sólo crea un directorio oculto (.git/) en la raíz del directorio. A partir de aquí, ya podremos enviar commits y movernos a través del historial.
Lo primero que tendremos que hacer será añadir todos los archivos de nuestro proyecto al repositorio recién creado, ya que éste inicialmente estará vacío. Por lo tanto, para añadir todos los archivos del proyecto hacemos:
git add *
Con esto, Git añade los archivos a una especie de almacén llamado index. El index es algo así como una agenda donde se van apuntando los archivos que se añaden y se borran en el repositorio.
Para ver el estado actual del repositorio ponemos:
git status
Y para grabar definitivamente los cambios en el repositorio hacemos el clásico:
git commit -am "primer commit"
Para ver el historial de commits que hemos hecho ponemos:
git log
Aunque existe una herramienta visual que nos permite ver el historial de una forma mucho más cómoda: gitk. En Ubuntu se puede instalar desde los repositorios.
A continuación voy a hablar un poco de los branches (ramas). En Git podemos trabajar con múltiples versiones de nuestro proyecto, lo que nos permite separar la versión principal de desarrollo, master, de las versiones más inestables o en pruebas. A diferencia de Subversion, Git está diseñado para trabajar con múltiples branches de una forma natural y sencilla, ofreciendo una amplia gama de comandos para manipularlos.
Para crear un nuevo branch de nuestro proyecto, al que llamaremos “experimental”, sólo hay que hacer:
git branch experimental
Si a continuación ponemos:
git branch
Git nos indicará que estamos actualmente en la rama “experimental”. A partir de ahora, todos los cambios y commits que hagamos se irán almacenando en esta rama del proyecto, sin afectar a la versión estable de desarrollo (master), teniendo, por tanto, dos líneas de desarrollo diferentes e independientes. Aunque podríamos tener muchas más.
Una vez que decidamos incluir en la versión estable todos los cambios introducidos en la versión experimental, sólo habrá que hacer una fusión de ambas ramas. Para ello, usaremos el comando merge.
Para hacer un merge de la rama experimental con la master, primero nos cambiamos a la rama master:
git checkout master
y a continuación, la fusionamos con la rama experimental:
git merge experimental
A partir de este momento, ambas ramas vuelven a ser exactamente iguales. Si queremos cambiarnos de nuevo a la versión experimental, ponemos:
git checkout experimental
Y si por contra, preferimos eliminarla:
git branch -d experimental

Y por último, para no extenderme demasiado con este artículo, ahí van dos magníficas referencias para aprender a manejar este potente sistema de control de versiones:
Ah! Y por si os resulta útil, ahí va una chuleta con los principales comandos que he ido usando con el tiempo:
[Actualización] Una versión más reciente de la chuleta la puedes encontrar en mi cuenta de Github: https://github.com/srus/taller-git/Configuración de git # Para configuración específica del proyecto, quitar --global # configuración del nombre git config --global user.name "John Doe" # configuración del email git config --global user.email johndoe@example.com # para activar el color en los diff git config --global color.diff auto
Configuración de un repositorio privado (acceso SSH) # situarse en el directorio del proyecto y poner: git clone --bare /home/usuario/proyecto/.git /home/usuario/repositorio/nombre-proyecto # ya tenemos un repositorio remoto # eliminar el proyecto y bajarse una copia del repositorio remoto git clone usuario@maquina:repositorio/nombre-proyecto/
gitignore (para ignorar archivos en git) Los archivos sólo se ignoran si previamente no se han añadido al index, es decir, deben aparecer como "Untracked files".
ejemplo de archivo .gitignore # Ignorar los siguientes archivos proyecto/archivo1.txt proyecto/archivo2.txt # Ignorar archivos ocultos de Eclipse .classpath .project # No ignorar este archivo !.gitignore # Ignorar un directorio completo directorio/*
Comandos generales en git # inicializar repositorio git init # commit sobre el repositorio local git commit -am "mensaje del commit" # estado del repositorio local git status # Añadir nuevos archivos al index git add * # Eliminar archivos del index git rm file1 file2 # Actualizar el index con los archivos eliminados. # Evita tener que hacer git rm file1 file2 file3 ... git add -u # diferencias entre versiones git diff --cached # traer los cambios de todas las ramas remotas, sin actualizar ninguna rama local git fetch # comparar los cambios entre una rama local y una remota git diff rama_local rama_remota # efectuar los cambios en la rama local actual git merge rama_remota # actualizar (fetch + merge) la rama actual del repo local con la rama remota "experimental" # (origin almacena la dirección del repositorio desde donde se hizo el clone) git pull origin experimental # o bien simplemente usar: git pull # Ejemplo: # actualizar la rama actual del repositorio local con los últimos cambios # de la rama "master" del repositorio remoto git pull usuario@maquina:/ruta/al/repositorio master # info del repositorio git config -l # info del repositorio remoto git remote show origin # "congelar" y poner los cambios actuales a salvo, sin hacer commit, para volver más tarde a ellos git stash # recuperar los cambios git stash apply # limpiar el stash git stash clear
Manejando ramas # crear un branch local git branch nuevo_branch # cambiar a otro branch git checkout nombre_branch # crear un branch y cambiarse a este inmediatamente git checkout -b nuevo_branch # crear un branch que apunte a uno remoto git branch nuevo_branch origin/nombre_branch # crear un branch que apunte a uno remoto y cambiarse a este inmediatamente git checkout -b nuevo_branch origin/nombre_branch # fusionar un branch con el actual git merge nuevo_branch # crear una rama remota o actualizarla: git push origin nuevo_branch # debe existir también una rama local "nuevo_branch" # listar los branch locales git branch # listar los branch remotos git branch -r # listar todos los branch git branch -a # eliminar un branch git branch -d nombre_branch # eliminar un branch remoto (en el repositorio remoto) git push origin :nombre_branch # eliminar un remote-tracking branch (origin/nombre_branch) git branch -r -d origin/nombre_branch # hacer que un branch local haga un seguimiento de una rama remota, # de forma que los push/pull sean más simples: ahora sólo sería # necesario hacer "git pull" o "git push" git branch --track nuevo_branch origin/nuevo_branch
Eliminación de archivos / Volviendo atrás # descartar cambios en un archivo y volver a la última versión git checkout -- ruta_archivo # volver a una versión concreta de un archivo git checkout HASH -- ruta_archivo # modificar un antiguo commit (se modifica sólo ese commit): git revert HASH # Descartar todos los cambios (eliminando/añadiendo archivos) y # volver a un estado concreto del proyecto: # ¡Cuidado! ¡Esto elimina todos los commits hechos! # No aplicarlo en commits anteriores a un git-push, ya que # no podremos hacer push sobre el repositorio remoto. git reset --hard HASH # Para forzar el push en el repositorio remoto (NO RECOMENDABLE): git push origin +master # recuperar commits eliminados: git reflog # una vez identificado el commit a recuperar, hacer: git reset --hard HASH # Por defecto, reflog almacena los commits de los últimos 90 días. # A partir de esa fecha, git-gc eliminará los commits de más de 90 días. # Para modificar la duración, hacemos: git config --add gc.reflogexpire [ 30.days | 30.minutes | 30.seconds ]
Manipulando commits # Modificar el último commit git commit --amend # Unir varios commits en uno. Se usa 'squash' para unir el commit con el anterior. # ¡¡Sólo en el caso de no haber hecho ya un push al repositorio remoto!! git rebase -i HASH
Git y Subversion (git-svn) # commit git svn dcommit # Subir nuevo proyecto con subversion svn import project http://host_name/svn_dir/repository_name/project -m "First Import" # inicializar git-svn git svn init http://host_name/svn_dir/repository_name/project # recuperar la versión git svn fetch -rREVISION # Hasta aquí, los pasos para iniciar un proyecto # actualizar proyecto local git svn rebase