joe di castrohttp://joedicastro.com2012-04-26T21:15:00+02:00Sincronizar Bitbucket y GitHub2012-04-26T21:15:00+02:00joe di castrohttp://joedicastro.com/sincronizar-bitbucket-y-github.html<p>Para mis proyectos empleo generalmente <a href="http://mercurial.selenic.com/">mercurial</a> (hg) como sistema de control de versiones, porque está hecho en Python y me parece más elegante y agradable de usar que <a href="http://git-scm.com/">git</a>, aunque empleo git para algunas tareas, como gestionar los plugins de <a href="http://www.vim.org">Vim</a>. Del mismo modo, el emplear hg como <a href="http://es.wikipedia.org/wiki/Programas_para_control_de_versiones">DCVS</a> me llevaba de forma natural a emplear <a href="http://bitbucket.org">Bitbucket</a> como alojamiento para mis repositorios públicos. </p> <p>Siempre me ha gustado <strong>Bitbucket</strong>, su estilo sencillo, pero muy potente y creo que tiene algunas características que son superiores a las de sus rivales (el <a href="http://blog.bitbucket.org/2011/12/08/pull-requests-with-side-by-side-diffs/">diff side-by-side</a>, por ejemplo<sup id="fnref:gt"><a href="#fn:gt" rel="footnote">1</a></sup>). Pero también tengo claro que si hay algún alojamiento de código en la red que destaca sobre todos los demás es <a href="http://github.com">GitHub</a>, "todo" el mundo está allí y de algún modo, estás "obligado" a estar. <strong>GitHub</strong> tiene algunas características muy potentes y en ciertos aspectos es muy superior a Bitbucket, aunque me sigue gustando más el <em>feeling</em> de este último. </p> <h2 id="hg__git">Hg != Git</h2> <p>Me planteé entonces hace unos días que lo mejor era mantener una replica de mis repositorios alojados en Bitbucket en GitHub, como dice el refrán, <em>Nunca tengas todos tus huevos en una misma cesta</em>. El problema es que aunque Bitbucket soporta repositorios tanto en mercurial como en git (para competir con GitHub), GitHub solo soporta repositorios en Git. Y dado el éxito que tienen, dudo mucho que tengan intención alguna de soportar otro sistema de versiones distinto a Git. </p> <p>Técnicamente es posible mantener un repositorio con los dos dcvs a la vez, pero maldita la gracia que me hacía, ademas de que no es nada aconsejable por el incremento de tamaño en disco que esto supondría. Entonces, ¿como hacer para poder alojar un repositorio mantenido con mercurial en un alojamiento que solo soporta Git? La solución, <strong>hg-git</strong>.</p> <h3 id="hg-git">hg-git</h3> <p><a href="http://hg-git.github.com/">hg-git</a> es un plugin para mercurial que permite sincronizar el repositorio local en hg con un repositorio en git, admitiendo tanto <em>push</em> como <em>pull</em> y sin perdidas de información. Gracias a este plugin, podemos alojar el repositorio en los dos sitios a la vez, empleando solo mercurial para gestionarlo.</p> <p>Instalarlo es muy fácil (desde <code>easy_install</code> o <code>pip</code>) y emplearlo también. Primero necesitas habilitarlo en el fichero <code>~/.hgrc</code>, así como la extensión bookmarks que necesita para trabajar.</p> <div class="codehilite"><pre><span class="k">[extensions]</span> <span class="na">hgext.bookmarks</span> <span class="o">=</span> <span class="na">hggit</span> <span class="o">=</span> </pre></div> <p>A continuación tienes que ir a tu repositorio y asignarle un <code>bookmark</code> a la rama que tengas por defecto (suele ser <code>default</code>) o a <code>tip</code> con el nombre de <code>master</code> (el nombre de las ramas por defecto en git), es decir:</p> <div class="codehilite"><pre><span class="gp">$</span> hg bookmark -r default master -f </pre></div> <p>Y luego emplearlo es tan sencillo como si fuera un repositorio de mercurial, por ejemplo un push:</p> <div class="codehilite"><pre><span class="gp">$</span> hg push git+ssh://git@github.com/joedicastro/joedicastro.com.git </pre></div> <h2 id="sincronizar_el_repositorio_con_bitbucket_y_github">Sincronizar el repositorio con Bitbucket y GitHub</h2> <p>Ahora, lo que tampoco me apetecía era tener que andar haciendo un push cada vez para cada alojamiento, lo ideal es que cada vez que hiciera un push a un sitio se sincronizara también el otro de forma automática. La solución pasa por emplear los <em>paths</em> para definir alias para los repositorios remotos y un <em>hook</em> para automatizar la sincronización. </p> <p>Definir los alias con <em>paths</em> es realmente sencillo, nos vamos al fichero <code>.hg/hgrc</code> del repositorio local y añadimos esto (e.g. el repo de este blog):</p> <div class="codehilite"><pre><span class="k">[paths]</span> <span class="na">github</span> <span class="o">=</span> <span class="s">git+ssh://git@github.com:joedicastro/joedicastro.com.git</span> <span class="na">bitbucket</span> <span class="o">=</span> <span class="s">ssh://hg@bitbucket.org/joedicastro/joedicastro.com</span> </pre></div> <p>De este modo, realizar un <code>push</code> es tan sencillo como:</p> <div class="codehilite"><pre><span class="gp">$</span> hg push bitbucket </pre></div> <p>Ahora necesitamos crear el <code>hook</code> que nos sincronice los dos alojamientos. Hay en la red varias soluciones para esto, por ejemplo <a href="http://morgangoose.com/blog/2010/09/29/github-and-bitbucket-hooks/">esta</a> y <a href="http://wiki.ddenis.com/index.php?title=Sync_BitBucket_and_GitHub">esta</a>, pero ninguna de las dos acababa de convencerme, la una por emplear un script bash que entraba muy fácilmente en un bucle infinito y la otra por necesitar otro modulo externo, que en mi caso no acababa de funcionar. Así que basándome en la idea del script bash del primero, decidí crearme uno en Python que funcionara correctamente y me solucionara el problema. </p> <p>El código del <code>hook</code> es el siguiente:</p> <div class="codehilite"><pre><span class="c">#!/usr/bin/env python</span> <span class="c"># encoding: utf-8</span> <span class="sd">&quot;&quot;&quot;</span> <span class="sd"> bb_gh_sync.py: Mercurial hook to keep synced a repo to Bitbucket &amp; GitHub.</span> <span class="sd">&quot;&quot;&quot;</span> <span class="c">#==============================================================================</span> <span class="c"># This script maintain synced a repository to booth github and bitbucket sites,</span> <span class="c"># using only a local mercurial repository. To do this, makes use of hg-git, the</span> <span class="c"># paths defined in my local hg repo and the environment variable given by hg, to</span> <span class="c"># push to the site non described in the command line argument. This way, it&#39;s</span> <span class="c"># irrelevant which site I decided to push every time, booth are done by this</span> <span class="c"># hook.</span> <span class="c">#===============================================================================</span> <span class="c">#==============================================================================</span> <span class="c"># Copyright 2012 joe di castro &lt;joe@joedicastro.com&gt;</span> <span class="c">#</span> <span class="c"># This program is free software: you can redistribute it and/or modify</span> <span class="c"># it under the terms of the GNU General Public License as published by</span> <span class="c"># the Free Software Foundation, either version 3 of the License, or</span> <span class="c"># (at your option) any later version.</span> <span class="c">#</span> <span class="c"># This program is distributed in the hope that it will be useful,</span> <span class="c"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span> <span class="c"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span> <span class="c"># GNU General Public License for more details.</span> <span class="c">#</span> <span class="c"># You should have received a copy of the GNU General Public License</span> <span class="c"># along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.</span> <span class="c">#==============================================================================</span> <span class="n">__author__</span> <span class="o">=</span> <span class="s">&quot;joe di castro &lt;joe@joedicastro.com&gt;&quot;</span> <span class="n">__license__</span> <span class="o">=</span> <span class="s">&quot;GNU General Public License version 3&quot;</span> <span class="n">__date__</span> <span class="o">=</span> <span class="s">&quot;23/04/2012&quot;</span> <span class="n">__version__</span> <span class="o">=</span> <span class="s">&quot;0.1&quot;</span> <span class="kn">import</span> <span class="nn">os</span> <span class="kn">from</span> <span class="nn">tempfile</span> <span class="kn">import</span> <span class="n">gettempdir</span> <span class="kn">from</span> <span class="nn">subprocess</span> <span class="kn">import</span> <span class="n">call</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Main section&quot;&quot;&quot;</span> <span class="n">tmp_dir</span> <span class="o">=</span> <span class="n">gettempdir</span><span class="p">()</span> <span class="n">lock_file</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">tmp_dir</span><span class="p">,</span> <span class="s">&quot;bb_gh_sync.lock&quot;</span><span class="p">)</span> <span class="c"># make sure that only runs once for each repository</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span> <span class="nb">open</span><span class="p">(</span><span class="n">lock_file</span><span class="p">,</span> <span class="s">&quot;w&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> <span class="c"># if pushed to bitbucket, push to github too</span> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;HG_ARGS&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s">&quot;push bitbucket&quot;</span><span class="p">:</span> <span class="n">call</span><span class="p">([</span><span class="s">&quot;/usr/bin/env&quot;</span><span class="p">,</span> <span class="s">&quot;hg&quot;</span><span class="p">,</span> <span class="s">&quot;push&quot;</span><span class="p">,</span> <span class="s">&quot;github&quot;</span><span class="p">])</span> <span class="c"># et viceversa...</span> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;HG_ARGS&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s">&quot;push github&quot;</span><span class="p">:</span> <span class="n">call</span><span class="p">([</span><span class="s">&quot;/usr/bin/env&quot;</span><span class="p">,</span> <span class="s">&quot;hg&quot;</span><span class="p">,</span> <span class="s">&quot;push&quot;</span><span class="p">,</span> <span class="s">&quot;bitbucket&quot;</span><span class="p">])</span> <span class="k">else</span><span class="p">:</span> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">lock_file</span><span class="p">)</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span> <span class="n">main</span><span class="p">()</span> </pre></div> <p>Ahora solo tenemos que editar nuestro fichero <code>~/.hgrc</code> para habilitarlo y ya estaría listo para funcionar. Editamos el fichero y le añadimos estas lineas:</p> <div class="codehilite"><pre><span class="k">[hooks]</span> <span class="na">post-push</span> <span class="o">=</span> <span class="s">$HOME/dotfiles/hg/bb_gh_sync.py</span> </pre></div> <p>Ahora, si hacemos un push a Bitbucket, el hace automáticamente un push también a GitHub al acabar el primero, y viceversa. De este modo, hacer un push a ambos alojamientos es tan sencillo como:</p> <div class="codehilite"><pre><span class="gp">$</span> hg push bitbucket <span class="go">pushing to ssh://hg@bitbucket.org/joedicastro/joedicastro.com</span> <span class="go">running ssh hg@bitbucket.org &#39;hg -R joedicastro/joedicastro.com serve --stdio&#39;</span> <span class="go">searching for changes</span> <span class="go">no changes found</span> <span class="go">running hook post-push: $HOME/dotfiles/hg/bb_gh_sync.py</span> <span class="go">pushing to git+ssh://git@github.com:joedicastro/joedicastro.com.git</span> <span class="go">creating and sending data</span> <span class="go">[&quot;git-receive-pack &#39;joedicastro/joedicastro.com.git&#39;&quot;]</span> <span class="go"> github::refs/heads/master =&gt; GIT:198e8cc9</span> <span class="go">running hook post-push: $HOME/dotfiles/hg/bb_gh_sync.py</span> <span class="gp">$</span> </pre></div> <p>De este modo puedo mantener copias de los repositorios locales en ambos sitios de manera automática y sincronizada, sin preocuparme, ni hacer un trabajo extra. Eso si, conviene prescindir de los wikis y documentarlo todo a través de ficheros <code>README.md</code> en formato Markdown para facilitar la integración de los dos sitios. Lo que por otro lado también ayuda a mantenerlos actualizados de manera más sencilla.</p> <div class="footnote"> <hr /> <ol> <li id="fn:gt"> <p>Bueno, algunos rivales como <a href="http://gitorious.org/">Gitorius</a>, también soportan esta característica &#160;<a href="#fnref:gt" rev="footnote" title="Jump back to footnote 1 in the text">&#8617;</a></p> </li> </ol> </div>Pelican - Repositorio2011-07-05T23:02:00+02:00joe di castrohttp://joedicastro.com/pelican-repositorio.html<p>Como complemento a la <a href="http://joedicastro.com/tag/pelican.html">serie de artículos</a> que he publicado sobre <a href="http://docs.notmyidea.org/alexis/pelican/">Pelican</a>, el software que genera este blog, añado el repositorio, <a href="http://joedicastro.com/pelican-configuracion-y-personalizacion.html">como había prometido</a>, del contenido del mismo. El repositorio empleaba el sistema de control de versiones <a href="http://mercurial.selenic.com/">Mercurial</a> y estába alojado en <a href="https://bitbucket.org/">Bitbucket</a>.</p> <p>Las ventajas de disponer del contenido del blog en un repositorio son las de poder enmendar un error con suma facilidad y en muy poco tiempo, además de la de poder trabajar con distintas versiones del mismo (pruebas y producción). Además el repositorio en Bitbucket me proporcionaba una copia de seguridad adicional del sitio sin esfuerzo alguno. Y si alguien está interesado en crear su propio blog con Pelican y quiere saber como he realizado el mio, ahí tiene las claves. Salvo el propio Pelican (que no tendría mucho sentido) todo el material empleado para generarlo está en el. Y disponiendo del fichero <strong>fabric</strong>, se pueden descargar Pelican e instalar el entorno virtual en un minuto. </p> <p>Para automatizar todas las tareas, incluso las más comunes del repositorio, he añadido al fichero fabric <em>fabfile.py</em> dos tareas más:</p> <div class="codehilite"><pre><span class="k">def</span> <span class="nf">commit</span><span class="p">(</span><span class="n">message</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;Make a commit to the local mercurial repository.&quot;&quot;&quot;</span> <span class="n">local</span><span class="p">(</span><span class="s">&quot;hg add&quot;</span><span class="p">)</span> <span class="n">local</span><span class="p">(</span><span class="s">&quot;hg commit -m &#39;{0}&#39;&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">message</span><span class="p">))</span> <span class="k">def</span> <span class="nf">push</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Make a push to the remote mercurial repository.&quot;&quot;&quot;</span> <span class="n">local</span><span class="p">(</span><span class="s">&quot;hg push ssh://hg@bitbucket.org/joedicastro/joedicastro.com&quot;</span><span class="p">)</span> </pre></div> <p>Con estas puedo hacer un <code>commit</code> y un <code>push</code> a Bitbucket en un solo paso, por ejemplo:</p> <div class="codehilite"><pre><span class="go">fab commit:&quot;Añadido articulo: Pelican - Repositorio&quot; push</span> </pre></div> <p>También he cambiado la página que generaba los archivos del blog, ya que no me gustaba el formato anterior: una fecha, un articulo. He pasado de esto:</p> <div class="codehilite"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&quot;base.html&quot;</span> <span class="cp">%}</span><span class="x"></span> <span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span><span class="x"></span> <span class="x">&lt;section id=&quot;content&quot; class=&quot;body&quot;&gt;</span> <span class="x">&lt;h1&gt;Archivos de </span><span class="cp">{{</span> <span class="nv">SITENAME</span> <span class="cp">}}</span><span class="x">&lt;/h1&gt;</span> <span class="x">&lt;dl&gt;</span> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">dates</span> <span class="cp">%}</span><span class="x"></span> <span class="x"> &lt;dt&gt;</span><span class="cp">{{</span> <span class="nv">article.locale_date</span> <span class="cp">}}</span><span class="x">&lt;/dt&gt;</span> <span class="x"> &lt;dd&gt;&lt;a href=&#39;</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="x">&#39;&gt;</span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="x">&lt;/a&gt;&lt;/dd&gt;</span> <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span><span class="x"></span> <span class="x">&lt;/dl&gt;</span> <span class="x">&lt;/section&gt;</span> <span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span><span class="x"></span> </pre></div> <p>a esto:</p> <div class="codehilite"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&quot;base.html&quot;</span> <span class="cp">%}</span><span class="x"></span> <span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span><span class="x"></span> <span class="x">&lt;section id=&quot;content&quot; class=&quot;body&quot;&gt;</span> <span class="x">&lt;h1&gt;Archivos de </span><span class="cp">{{</span> <span class="nv">SITENAME</span> <span class="cp">}}</span><span class="x">&lt;/h1&gt;</span> <span class="cp">{%</span>- <span class="k">set</span> <span class="nv">years_month</span> <span class="o">=</span> <span class="o">{}</span> -<span class="cp">%}</span><span class="x"></span> <span class="cp">{%</span>- <span class="k">set</span> <span class="nv">months</span> <span class="o">=</span> <span class="o">{</span><span class="m">1</span><span class="s1">:&#39;Enero&#39;</span><span class="o">,</span> <span class="m">2</span><span class="s1">:&#39;Febrero&#39;</span><span class="o">,</span> <span class="m">3</span><span class="s1">:&#39;Marzo&#39;</span><span class="o">,</span> <span class="m">4</span><span class="s1">:&#39;Abril&#39;</span><span class="o">,</span> <span class="m">5</span><span class="s1">:&#39;Mayo&#39;</span><span class="o">,</span> <span class="m">6</span><span class="s1">:&#39;Junio&#39;</span><span class="o">,</span> <span class="m">7</span><span class="s1">:&#39;Julio&#39;</span><span class="o">,</span> <span class="m">8</span><span class="s1">:&#39;Agosto&#39;</span><span class="o">,</span> <span class="m">9</span><span class="s1">:&#39;Septiembre&#39;</span><span class="o">,</span> <span class="m">10</span><span class="s1">:&#39;Octubre&#39;</span><span class="o">,</span> <span class="m">11</span><span class="s1">:&#39;Noviembre&#39;</span><span class="o">,</span> <span class="m">12</span><span class="s1">:&#39;Diciembre&#39;</span><span class="o">}</span> -<span class="cp">%}</span><span class="x"> </span> <span class="cp">{%</span>- <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">dates</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">if</span> <span class="nv">article.date.year</span> <span class="k">not</span> <span class="k">in</span> <span class="nv">years_month</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">do</span> <span class="nv">years_month.update</span><span class="o">({</span><span class="nv">article.date.year</span><span class="o">:[</span><span class="nv">article.date.month</span><span class="o">]})</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">else</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">if</span> <span class="nv">article.date.month</span> <span class="k">not</span> <span class="k">in</span> <span class="nv">years_month</span><span class="o">[</span><span class="nv">article.date.year</span><span class="o">]</span> -<span class="cp">%}</span><span class="x"> </span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">do</span> <span class="nv">years_month</span><span class="o">[</span><span class="nv">article.date.year</span><span class="o">]</span><span class="nv">.append</span><span class="o">(</span><span class="nv">article.date.month</span><span class="o">)</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">endif</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">endif</span> -<span class="cp">%}</span><span class="x"></span> <span class="cp">{%</span>- <span class="k">endfor</span> <span class="cp">%}</span><span class="x"></span> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">year</span> <span class="k">in</span> <span class="nv">years_month</span><span class="o">|</span><span class="nf">sort</span><span class="o">(</span><span class="nv">reverse</span><span class="o">=</span><span class="kp">True</span><span class="o">)</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> &lt;h2 class=&quot;year&quot;&gt;</span><span class="cp">{{</span> <span class="nv">year</span> <span class="cp">}}</span><span class="x">&lt;/h2&gt;&lt;dl&gt; </span> <span class="x"> </span><span class="cp">{%</span> <span class="k">for</span> <span class="nv">month</span> <span class="k">in</span> <span class="nv">years_month</span><span class="o">[</span><span class="nv">year</span><span class="o">]</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> &lt;dt class=&quot;month&quot;&gt;</span><span class="cp">{{</span> <span class="nv">months</span><span class="o">[</span><span class="nv">month</span><span class="o">]</span> <span class="cp">}}</span><span class="x">&lt;/dt&gt;</span> <span class="x"> </span><span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">dates</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span> <span class="k">if</span> <span class="nv">article.date.year</span> <span class="o">==</span> <span class="nv">year</span> <span class="k">and</span> <span class="nv">article.date.month</span> <span class="o">==</span> <span class="nv">month</span> -<span class="cp">%}</span><span class="x"></span> <span class="x"> &lt;dd&gt;&lt;span class=&quot;day&quot;&gt;</span><span class="cp">{{</span> <span class="nv">article.locale_date.split</span><span class="o">()[</span><span class="m">1</span><span class="o">]</span> <span class="cp">}}</span><span class="x">&lt;/span&gt; &lt;a href=&#39;</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="x">&#39;&gt;</span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="x">&lt;/a&gt;&lt;/dd&gt;</span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">endif</span> <span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span>- <span class="k">endfor</span> <span class="cp">%}</span><span class="x"></span> <span class="x"> </span><span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span><span class="x">&lt;/dl&gt;</span> <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span><span class="x"></span> <span class="x">&lt;/section&gt;</span> <span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span><span class="x"></span> </pre></div> <p>Donde los artículos están archivados por año, mes y día, con un formato que personalmente me agrada bastante más.</p> <p>El repositorio de este blog se puede encontrar en <a href="http://github.com/joedicastro/joedicastro.com">github</a>.</p>