Como Hacer Una Actividad Sugar

Añadir tus fuentes al control de versiones

¿Qué es el control de versiones?

"Si he visto más lejos es sólo por estar parado sobre los hombros de gigantes."

Isaac Newton, en una carta a Robert Hooke.

Escribir una Actividad es algo que normalmente no harías solo. Habitualmente tendrás colaboradores de una manera u otra. Cuando empecé a escribir Read Etexts (Leer Etextos) copié bastante del código de la Actividad Leer (Read). Cuando implementé la lectura sintetizada de texto, adapté una barra de herramientas de la Actividad Hablar (Speak). Cuando finalmente conseguí hacer funcionar la característica de compartir archivos, el autor de Image Viewer pensó que estaba buena para incorporarla a esa Actividad. Otro programador vio el trabajo que hice para la lectura sintetizada y pensó que podría hacerlo mejor. Tenía razón, y sus mejoras fueron combinadas con mi código. Cuando escribí Get Internet Archive Books alguien más tomó la interfaz que hice y realizó una Actividad más potente y versátil llamada Get Books. Al igual que Newton, todos se benefician del trabajo que los demás han hecho antes. 

Aunque quisiera escribir Actividades sin ayuda, necesitaría colaboradores para traducirlas a otros idiomas.

Para posibilitar la colaboración necesitas tener un lugar donde todos puedan colocar sus fuentes y compartirlas. Este lugar se llama repositorio de código. No es suficiente con compartir la última versión de tu código. Lo que realmente quieres es compartir todas las versiones de tu código. Cada vez que hagas un cambio significativo a tu código querrás tener la nueva versión y la anterior disponibles. No solo querrás tener todas las versiones de tu código disponibles sino que querrás ser capaz de comparar cualquier par de versiones entre sí para ver qué cambió entre ellas. Esto es lo que hace el software de control de versiones.

Las tres herramientas de control de versiones más populares son CVS, Subversion y Git. Git es la más nueva y la que se usa en Sugar Labs. Si bien no todas las Actividades tienen su código en el repositorio Git de Sugar Labs (existen otros), no hay buenas razones para no hacerlo y sí tiene bastantes ventajas. Si quieres que tu Actividad sea traducida a otras lenguas, tendrás que usar el repositorio Git de Sugar Labs.  

Git 1 

Git es un sistema de control de versiones distribuido. Esto quiere decir que hay copias de cada versión de tu código fuente en un repositorio central y además las mismas copias existen en la computadora de cada usuario. Esto significa que puedes actualizar tu repositorio local estando desconectado, y luego al estar conectado a la Internet, compartir todo de una vez.

Hay dos formas para interactuar con un repositorio Git: a través de comandos Git y a través del sitio web en http://git.sugarlabs.org/.   Veamos primero el sitio web

Dirígete a http://git.sugarlabs.org/  y haz clic sobre el enlace Projects (Proyectos) en la parte superior derecha:

git1.jpg

Encontrarás una lista de proyectos en el repositorio. Estarán ordenados del más reciente al más antiguo. También encontrarás el enlace New Project (Nuevo Proyecto), pero necesitarás abrir una cuenta para hacer eso y no estamos listos, todavía.

git2.jpg

Si eliges la opción Search (Buscar) en la esquina superior derecha de la página obtendrás un formulario de búsqueda. Úsalo para buscar "read etexts". Elíge ese proyecto cuando lo encuentres. Deberías ver algo así:

git3.jpg

Esta página lista algunas de las actividades para el proyecto pero yo no la encuentro particularmente útil. Para dar un mejor vistazo a tu proyecto inicia haciendo clic en el nombre del repositorio al lado derecho de la página. En este caso, el nombre del repositorio es mainline.

git4.jpg

Verás algo parecido a esto en la parte superior de la página:

git5.jpg

Esta página contiene informaciómn útil. Primero, echa un vistazo a la Public clone url [Url pública para clonación] y la HTTP clone url [Url para clonación HTTP]. Necesitas hacer clic en More info (Más info) para ver cualquiera de las dos. Si ejecutas cualquiera de estos comandos desde la consola, obtendrás una copia del repositorio git del proyecto en tu computador. Esta copia incluirá cada versión de cada fragmento de código en el proyecto. Vas a tener que modificarlo un poco antes de compartir tus cambios de vuelta en el repositorio principal, pero todo estará ahí.

La lista bajo Activities (Actividades) no es tan útil, pero si haces clic en Source Tree (Árbol de fuentes) verás algo realmente bueno:

git6.jpg

Aquí hay una lista de cada archivo en el proyecto, su última fecha de actualización, y un comentario sobre qué fue modificado. Haz clic en el enlace para ReadEtextsActivity.py y verás esto:

git7.jpg

Este es el código más reciente en ese archivo en formato embellecido. Las palabras clave de Python se muestran en colores, tienen números de línea, etc. Esta es una buena página para mirar el código en la pantalla pero no queda bien al imprimirlo y no sirve mucho para copiar fragmentos de código en ventanas del editor Eric. Para hacer estas cosas querrás hacer clic en raw blob data (data sin procesar) en la parte superior del listado:

git8.jpg

Aún no terminamos. Usa el botón Back (Atrás) para regresar al listado embellecido y haz clic en el enlace que dice Commits (Consignaciones). Este arrojará un listado de todo lo que ha cambiado cada vez que hemos consignado código en Git.

git9.jpg

Habrás notado una combinación extraña de letras y números después de las palabras James Simmons committed [James Simmons consignó]. Esto es un tipo de número de versión. La práctica habitual en sistemas de control de versiones es darle a cada versión de código ingresada al sistema un número de versión, habitualmente uno consecutivo. Git es distribuído, con varias copias separadas del repositorio que pueden ser modificadas independientemente y luego combinadas. Esto hace imposible usar un número secuencial para identificar las versiones. En cambio, Git le da a cada versión un número aleatorio realmente grande. Este número se expresa en base 16, usando los símbolos 0-9 y a-f. Lo que ves en verde es tan solo una parte pequeña del número completo. El número es un enlace, y si haces clic en él verás esto:

git10.jpg

Al inicio de la página veremos el número de versión completo utilizado para esta consignación. Debajo de la caja gris vemos los comentarios completos que fueron usados para consignar los cambios. Debajo de esto hay una lista de los archivos que fueron modificados. Si miramos más abajo en la página, veremos esto:

git11_1.jpg

Este es un reporte diff el cual muestra las líneas que han cambiado entre esta versión y la anterior. Para cada cambio muestra algunas líneas antes y después para dar una mejor idea de lo que el cambio hace. Cada cambio muestra también los números de línea.

Un reporte como éste es una gran ayuda para programar. Algunas veces, cuando estás trabajando en una mejora a tu programa, algo que ha estado funcionando, misteriosamente deja de hacerlo. Cuando esto pasa, te preguntarás qué cambio habrá causado el problema. Un reporte diff puede ayudarte a encontrar el origen del problema.

A estas alturas estarás convencido de poner el código de tu proyecto en Git. Antes de poder hacer esto necesitamos crear una cuenta en este sitio web. No es más difícil que en otros sitios, pero necesitamos información importante que todavía no tenemos. Obtener esta información será nuestra próxima tarea.

 

Preparando las claves SSH

Para enviar tu código al repositorio de Gitorious necesitas un par de claves públicas/privadas SSH. SSH es una manera de enviar datos a través de la red en formato encriptado. (en otras palabras, utiliza un código secreto para que nadie más que la persona que recibe los datos puede leerlos). El encriptamiento de claves públicas/privadas es una forma de encrirptar datos que provee de una forma de garantizar que la persona que esta enviando los datos es quien dice ser.

En términos simples, funciona así: el software SSH genera dos números muy grandes que son usados para codificar y decodificar la información que transita por la red. El primer número, llamado la clave privada, es mantenido en secreto y sólo usado para codificar datos. El segundo número, llamado clave pública, es dado a quien sea que necesite decodificar estos datos. También es posible usar la clave pública para codificar un mensaje para ser enviado a ti y tu podrás decodificarlo con tu clave privada.

Git usa SSH como una firma electrónica para verificar que los cambios de código que supuestamente son tuyos, de hecho lo sean. Le daremos tu clave pública al repositorio Git. Sabrá entonces que cualquier cosa que pueda decodificar con esta clave habrá sido enviada por tí, porque solo tú tienes la clave privada correspondiente para codificarlo.

Estaremos usando una herramienta llamada OpenSSH para generar las claves públicas/privadas. Ésta está incluída con cada versión de Linux así que no necesitas verificar que haya sido instalada. Luego utiliza la utilidad ssh-keygen que viene con OpenSSH para generar las claves:

[jim@olpc2 ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/jim/.ssh/id_rsa):

Por defecto ssh-keygen genera una clave RSA, que es el tipo que requerimos. También por defecto pone lo archivos de claves en un directorio llamado /tudirectorio/.ssh y esto también lo queremos, de manera que NO ingreses nombre de archivo alguno cuando lo pida. Sólo oprime la tecla Enter para continuar.

[jim@olpc2 ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/jim/.ssh/id_rsa):
Created directory '/home/jim/.ssh'.
Enter passphrase (empty for no passphrase):

Ahora bien, SÍ queremos una passphrase (frase de paso) aquí. Esta frase de paso es como una contraseña que es usada con las claves públicas y privadas para efectuar la encriptación. Cuando la escribas no podrás ver las letras. Por ello se te pedirá escribirla dos veces y así confirmar que ambas veces la has escrito de la misma forma.

[jim@olpc2 ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/jim/.ssh/id_rsa):
Created directory '/home/jim/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/jim/.ssh/id_rsa.
Your public key has been saved in /home/jim/.ssh/id_rsa.pub.
The key fingerprint is:
d0:fe:c0:0c:1e:72:56:7a:19:cd:f3:85:c7:4c:9e:18
jim@olpc2.simmons
The key's randomart image is:
+--[ RSA 2048]----+
|        oo  E=.  |
|       + o+ .+=. |
|    . B +  o.oo  |
|     = O    .    |
|      . S        |
|         o       |
|          .      |
|                 |
|                 |
+-----------------+

Cuando selecciones la frase de paso o contraseña recuerda que debe ser algo que puedas escribir confiablemente sin verlo y será mas efectivo si no escojes una palabra que se encuentre en el diccionario, pues estas son fácilmente quebrantables. Cuando yo necesito generar una contraseña utilizo la herramienta que puedes encontrar en http://www.multicians.org/thvv/gpw.html.  Esta herramienta genera una cantidad de palabras pronunciables sin sentido. Escoje una que te guste y utilízala.

Ahora echa una mirada dentro del directorio .ssh. Por convención, cada archivo o directorio que empieza con un punto es considerado oculto por Linux, así que no se mostrará en el gestor de archivos de GNOME a menos que uses la opción Mostrar Archivos Ocultos en el menú Ver. Cuando veas los contenidos de este directorio observarás dos archivos: id_rsa e id_rsa.pub. La clave pública estará en id_rsa.pub. Intenta abrir ese archivo con gedit (Abrir con editor de texto) y verás algo así:

git12.jpg

Al crear tu cuenta en git.sugarlabs.orghabrá un casillero para colocar tu clave SSH pública. Para hacer eso elije Select All (Seleccionar Todo) del menú Edit (Editar) de gedit, luego Copy and Paste (Copia y pega) en el campo provisto en el formulario web.

Crear un proyecto nuevo

Voy a crear un proyecto nuevo en Git para los ejemplos de este libro. Necesito ingresar con mi nueva cuenta y hacer clic en el enlace New Project (Proyecto nuevo) que vimos anteriormente. Obtengo el siguiente formulario, que ya comencé a llenar:

git13.jpg

El Title (Título) es usado en el sitio web; el Slug (Abreviatura) es una versión breve del título sin espacios, la cual será usada como nombre del repositorio Git. Las Categories (Categorías) son opcionales. La License (Licencia) es GPL v2 para mis proyectos. Puedes elegir entre las licencias ofrecidas en la lista para tus proyectos, y puedes cambiar la licencia posteriormente si quieres. También necesitarás ingresar una Description (Descripción) para tu proyecto.

Una vez que hayas hecho esto, podrás hacer clic en el entrada mainline para el proyecto (como hicimos con Read Etexts antes) y ver algo así:

git14.jpg

El próximo paso es convertir nuestro proyecto en un repositorio local de Git, añadirle los archivos, y luego subirlos al repositorio en git.sugarlabs.org. Necesitamos hacer esto porque no es posible clonar un repositorio vacío, y nuestro repositorio remoto ahora se encuentra vacío. Para superar este problema enviaremos nuestro repositorio local hacia el nuevo repositorio remoto que acabamos de crear, luego clonaremos el repositorio remoto y borraremos nuestro proyecto y su repositorio Git. A partir de entonces haremos todo nuestro trabajo desde el repositorio clonado.

Este proceso puede recordarles la cita de Edward Albee, "Algunas veces una persona debe desviarse bastante de su rumbo para desandar correctamente una pequeña distancia".2  Afortunadamente solo necesitamos hacerlo una vez por proyecto. Ingresa los comandos que aparecen en negritas después de cambiarte al directorio de tu proyecto:


git init
Initialized empty Git repository in
/home/jim/olpc/bookexamples/.git/
git add *.py
git add activity
git add MANIFEST
git add .gitignore
git commit -a -m "Create repository and load"
[master (root-commit) 727bfe8] Create repository and load
 9 files changed, 922 insertions(+), 0 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 MANIFEST
 create mode 100755 ReadEtexts.py
 create mode 100644 ReadEtextsActivity.py
 create mode 100644 ReadEtextsActivity2.py
 create mode 100644 activity/activity.info
 create mode 100644 activity/read-etexts.svg
 create mode 100755 setup.py
 create mode 100644 toolbar.py

Lo que hice fue crear un repositorio Git local vacio con git init, luego usé git add para añadir los archivos importantes a él. (De hecho git add no añade nada por sí mismo, sólo le dice a Git que añada el archivo en el siguiente git commit). Finalmente git commit con las opciones mostradas colocará la última versión de estos archivos en mi nuevo repositorio local.

Para subir este repositorio local a git.sugarlabs.org  usamos los comandos de la página web:

git remote add origin \
gitorious@git.sugarlabs.org:\
myo-sugar-activities-examples/mainline.git
git push origin master
Counting objects: 17, done.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (15/15), 7.51 KiB, done.
Total 15 (delta 3), reused 0 (delta 0)
To gitorious@git.sugarlabs.org:myo-sugar-activities-examples/
mainline.git
   2cb3a1e..700789d  master -> master
=> Syncing Gitorious...
Heads up: head of  changed to
700789d3333a7257999d0a69bdcafb840e6adc09 on master
Notify cia.vc of 727bfe819d5b7b70f4f2b31d02f5562709284ac4  on
myo-sugar-activities-examples
Notify cia.vc of 700789d3333a7257999d0a69bdcafb840e6adc09  on
myo-sugar-activities-examples
[OK]
rm *
rm activity -rf
rm .git -rf
cd ~
rm Activity/ReadEtextsII
mkdir olpc
cd olpc
mkdir bookexamples
cd bookexamples
git clone \
git://git.sugarlabs.org/\
myo-sugar-activities-examples/mainline.git
Initialized empty Git repository in
/home/jim/olpc/bookexamples/mainline/.git/
remote: Counting objects: 18, done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 18 (delta 3), reused 0 (delta 0)
Receiving objects: 100% (18/18), 8.53 KiB, done.
Resolving deltas: 100% (3/3), done.

Las líneas en negritas son comandos para ingresar, y todo lo demás son mensajes que Git envía a la consola. He dividido algunos de los comandos Git más largos con la barra invertida (\) para que luzcan mejor en una página impresa, así como algunas líneas largas que normalmente se mostrarían en una línea, por el mismo motivo. Probablemente no esté claro lo que estamos haciendo o por qué, así que vayamos paso a paso:

  • El primer comando git remote add origin le dice al repositorio remoto de Git que le estaremos enviando cosas desde nuestro repositorio local.
  • El segundo comando git push origin master envía realmente el repositorio Git local al remoto y sus contenidos se copiarán. Cuando ingreses este comando se te pedirá la frase de paso (contraseña) de la clave SSH que creaste en la sección anterior. Si lo deseas, GNOME puede recordar esta frase y luego la ingresarla automáticamente para cada comando Git. Seguirá así hasta que cierres la sesión o apagues la máquina.
  • El siguiente paso es borrar nuestros archivos existentes y nuestro repositorio local de Git (el cual está contenido en el directorio oculto .git). rm .git -rf quiere decir "Borra el directorio .git y todo lo que encuentres en él". rm es un comando Unix, no un comando de Git. Si lo deseas puedes borrar los archivos existentes después de crear el repositorio clonado en el paso siguiente. Nota que el comando rm Activity/ReadEtextsII, el cual borra el enlace simbólico del proyecto viejo que creamos al ejecutar ./setup.py dev. Necesitaremos ir al directorio clonado de nuestro proyecto y ejecutar esto nuevamente antes de poder probar nuestra Actividad otra vez.
  • Ahora ejecutamos el comando git clone de la página web. Esto toma el repositorio Git remoto al cual acabamos de añadirle el archivo MANIFEST, y crea un nuevo repositorio local en el directorio /tudirectorio/olpc/bookexamples/mainline.

Finalmente tenemos un repositorio local que podemos usar. Bueno, no del todo. Podemos consignar nuestro código en él, pero no podemos subir nada de vuelta al repositorio remoto porque nuestro repositorio local no se encuentra correctamente configurado.

Lo que necesitamos hacer es editar el archivo config en el directorio .git de /tudirectorio/olpc/bookexamples/mainline. Podemos usar gedit para ello. Necesitamos cambiar la línea que comienza con url= para apuntar a la Push url (Url para subir) la cual se muestra en la página web de mainline. Cuando termines el archivo config lucirá algo así:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = gitorious@git.sugarlabs.org:
myo-sugar-activities-examples/mainline.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master

La línea en negrita es la única que se modifica. Está separada aquí para hacerla entrar en una página impresa. En tus propios archivos debe estar todo en una línea sin espacios entre los dos puntos (:) al final de la primera línea y el principio de la segunda línea.

De ahora en adelante quien quiera trabajar sobre tu proyecto puede obtener una copia local del repositorio Git haciendo esto desde el directorio donde quiere que vaya el repositorio:

git clone git://git.sugarlabs.org/\
myo-sugar-activities-examples/mainline.git

Necesitará cambiar su archivo .git/config igual como acabamos de hacer, y luego estará listo para empezar.

Uso habitual de Git

Aunque configurar los repositorios para comenzar es tedioso, el uso habitual no lo es. Hay tan solo algunos comandos con los que necesitarás trabajar. Cuando interrumpimos teníamos un repositorio en /tudirectorio/olpc/bookexamples/mainline con nuestros archivos en él. Necesitaremos añadir también cualquier archivo nuevo que creemos.

Usamos el comando git add para decirle a Git que queremos que guarde un archivo en particular. Esto no guarda nada, sólo le comunica a Git nuestras intenciones. El formato del comando es simplemente:

git add nombre_archivo_o_directorio

Hay archivos que no queremos añadir a Git, para empezar aquellos que terminan en .pyc. Si nunca les hacemos git add entonces nunca serán añadidos, pero Git constantemente nos preguntará por qué no los añadimos. Afortunadamente hay una forma de decirle a Git que realmente, absolutamente no queremos añadir esos archivos. Necesitamos crear un archivo llamado .gitignore usando gedit y colocar entradas así:

*.pyc
*.e4p
*.zip
.eric4project/
.ropeproject/

Estas entradas también ignorarán archivos de proyectos de Eric, archivos zip y archivos que contengan libros electrónicos3 . Una vez que tenemos este archivo en el directorio de mainline, podemos añadirlo al repositorio:

git add .gitignore
git commit -a -m "Add .gitignore file"

De ahora en adelante Git no insistirá en añadir archivos .pyc u otros archivos no deseados que coincidan con los patrones de búsqueda. Si hay otros archivos que no queremos en el repositorio, podemos añadirlos a .gitignore sea con sus nombres completos o con patrones de búsqueda como *.pyc.

 Además de añadir archivos a Git también los podemos eliminar:

git rm archivo

Nótese que esto sólo le dice a Git que de ahora en adelante no le hará seguimiento a este archivo, lo cual tomará efecto en la siguiente consignación (commit). Las versiones anterires del archivo seguirán en el repositorio.

Si deseas ver qué cambios serán aplicados en la próxima consignación, ejecuta esto:

git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will
#   be committed)
#
#       modified:   ReadEtextsActivity.py
#
no changes added to commit (use "git add" and/or
"git commit -a")

 

Finalmente, para colocar los últimos cambios en el repositorio, haz esto:

git commit -a -m "Change use of instance directory to tmp"
Created commit a687b27: Change use of instance
directory to tmp
 1 files changed, 2 insertions(+), 2 deletions(-)

Si omites la opción -m, un editor aparecerá y podrás escribir un comentario, luego grabar y salir. Desafortunadamente el editor por omisión es vi, un editor antiguo de modo texto que no es tan amigable como gedit.

Cuando hayamos hecho todos nuestros cambios podemos enviarlos al repositorio central usando git push:

git push
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 322 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To gitorious@git.sugarlabs.org:
myo-sugar-activities-examples/mainline.git
   700789d..a687b27  master -> master
=> Syncing Gitorious...
Heads up: head of  changed to
a687b27e2f034e5a17d2ca2fe9f2787c7f633e64 on master
Notify cia.vc of a687b27e2f034e5a17d2ca2fe9f2787c7f633e64
on myo-sugar-activities-examples
[OK]

Podemos obtener los últimos cambios de otros desarrolladores haciendo git pull:

git pull
remote: Counting objects: 17, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 15 (delta 3), reused 0 (delta 0)
Unpacking objects: 100% (15/15), done.
From gitorious@git.sugarlabs.org:
myo-sugar-activities-examples/mainline
   2cb3a1e..700789d  master     -> origin/master
Updating 2cb3a1e..700789d
Fast forward
 .gitignore               |    6 +
 MANIFEST                 |  244 +--------------------------
---------
 ReadEtexts.py            |  182 +++++++++++++++++++++++++++
 ReadEtextsActivity.py    |  182 +++++++++++++++++++++++++++
 ReadEtextsActivity2.py   |  311 +++++++++++++++++++++++++++
+++++++++++++++++++
 activity/activity.info   |    9 ++
 activity/read-etexts.svg |   71 +++++++++++
 setup.py                 |   21 +++
 toolbar.py               |  136 ++++++++++++++++++++
 9 files changed, 921 insertions(+), 241 deletions(-)
 create mode 100644 .gitignore
 create mode 100755 ReadEtexts.py
 create mode 100644 ReadEtextsActivity.py
 create mode 100644 ReadEtextsActivity2.py
 create mode 100644 activity/activity.info
 create mode 100644 activity/read-etexts.svg
 create mode 100755 setup.py
 create mode 100644 toolbar.py 
.4 
  1. NT: En el texto en inglés Git Along Little Dogies - la traducción sería muévanse pequeños terneros, fuera. Git Along, Little Dogies es una balada tradicional de los vaqueros. ^
  2. NT: En el texto en inglés: "Sometimes a person has to go a very long distance out of his way to come back a short distance correctly".^
  3. NT: ebooks en el original^^
  4. Traducido Sebastián Silva y Laura Vargas proyectomalla@somosazucar.org<
    .^


your comment:
name :
comment :

If you can't read the word, click here
word :