<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Caio Romão</title>
  <link href="http://caioromao.com" rel="alternate" type="text/html"/>
  <link href="http://www.caioromao.com/atom.xml" rel="self"/>
  <id>http://www.caioromao.com/</id>
  <updated>2012-07-17T21:54:41+02:00</updated>
  <entry>
    <title>Vim Plugin: Query Command Complete</title>
    <link href="http://caioromao.com/blog/vim-plugin-query-command-complete/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/vim-plugin-query-command-complete/</id>
    <updated>2012-07-15T22:00:00+02:00</updated>
    <published>2012-07-15T22:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>A vim plugin to create completions from an external query command (addressbook command line application, for example)</summary>
    <content type="html">&lt;p&gt;I&amp;#8217;ve just released a new Vim plugin to improve how I&amp;#8217;ve been writing my e-mails. Every once in a while I remember I need to include someone in that e-mail I&amp;#8217;ve started writing a few minutes before and that&amp;#8217;s where using a normal text editor to write falls short: by default, there&amp;#8217;s no integration between it and any sort of address book.&lt;/p&gt;

&lt;p&gt;Note that I&amp;#8217;m not talking about the usual workflow imposed by the command line clients, where you select the recipients and &lt;em&gt;then&lt;/em&gt; you write your message. In this case, just setting up a &lt;a href='http://wiki.mutt.org/?QueryCommand'&gt;query command&lt;/a&gt; (or analogous on your MUA of choice. I&amp;#8217;m pretty sure it&amp;#8217;s a fairly standard feature).&lt;/p&gt;

&lt;p&gt;Well, this plugin&amp;#8217;s intention is setting up a completion system that queries an external command using the same kind of tools that are used for managing your address book. As long as the output of such command is easily parseable, you can use it with this plugin. Here is how it works:&lt;/p&gt;

&lt;p&gt;You setup the &lt;code&gt;g:qcc_query_command&lt;/code&gt; option to the call to your address book (say, &lt;code&gt;abook --mutt-query&lt;/code&gt;) and enable the completion on the filetype of your choice:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Standard setup for mutt
let g:qcc_query_command = &amp;#39;abook --mutt-query&amp;#39;
# You might consider using `omnifunc` if you have a completion
# system plugin like neocomplcache
au BufRead /tmp/mutt* setlocal completefunc=QueryCommandComplete&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now whenever you realise you have to fiddle with the headers that take e-mail addresses as parameters (From, To, Cc, etc), you can do it without leaving your Vim session. For example if you have the following in your line (&lt;code&gt;|&lt;/code&gt; being the cursor position):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;From: Foobar &amp;lt;foo@bar.com&amp;gt;, cai|&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then you trigger user completion (usually &lt;code&gt;C-x C-u&lt;/code&gt;), &lt;a href='http://www.vim.org/scripts/script.php?script_id=4132'&gt;Query Command Complete&lt;/a&gt; will go ahead and call &lt;code&gt;abook --mutt-query cai&lt;/code&gt; and present the results back to you in that glorious wildmenu we all know and love.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s some configuration goodness also, so one can even adapt it to work with the most bizarre things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;g:qcc_line_separator&lt;/code&gt;: Separator for each entry in the result from the query. Default: &lt;code&gt;&amp;#39;\n&amp;#39;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;g:qcc_field_separator&lt;/code&gt;: Separator for the fields of an entry from the result. Default: &lt;code&gt;&amp;#39;\t&amp;#39;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;g:qcc_pattern&lt;/code&gt;: Pattern used to match against the current line to decide whether to call the query command. Default: &lt;code&gt;&amp;#39;^\(To\|Cc\|Bcc\|From\|Reply-To\):&amp;#39;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, enough marketing. Give &lt;a href='http://www.vim.org/scripts/script.php?script_id=4132'&gt;Query Command Complete&lt;/a&gt; a go and if you find any issues or want to contribute, &lt;a href='https://github.com/caio/querycommandcomplete.vim'&gt;check the project at Github&lt;/a&gt;. Have fun!&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Exercise: CLI Fuzzy Clock</title>
    <link href="http://caioromao.com/blog/exercise-cli-fuzzy-clock/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/exercise-cli-fuzzy-clock/</id>
    <updated>2012-03-28T00:00:00+02:00</updated>
    <published>2012-03-28T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Announcement of a CLI fuzzy clock implementation I made for practice</summary>
    <content type="html">&lt;p&gt;While backing up stuff during preparations for my move abroad (more on that later), I found a couple of tiny projects using &lt;a href='http://www.gnu.org/software/automake/'&gt;Autotools&lt;/a&gt; and realized I remembered almost nothing about this build system and then I decided I should do a quick refresher project with it.&lt;/p&gt;

&lt;p&gt;Since remembering stuff is not as fun as learning, I jumped on the testing-in-c bandwagon and decided I&amp;#8217;d learn and use the &lt;a href='http://check.sourceforge.net'&gt;Check unit testing framework&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, why a fuzzy clock? No idea. It was the first really simple but not completely useless project that came to mind.&lt;/p&gt;

&lt;p&gt;You can &lt;a href='https://github.com/caio/fuzzyclock'&gt;check the source code&lt;/a&gt; and also &lt;a href='https://github.com/downloads/caio/fuzzyclock/fuzzyclock-1.0.tar.gz'&gt;download the initial release&lt;/a&gt; of this project.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>How "puts" works in Ruby</title>
    <link href="http://caioromao.com/blog/how-puts-works-in-ruby/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/how-puts-works-in-ruby/</id>
    <updated>2011-10-21T00:00:00+02:00</updated>
    <published>2011-10-21T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Lower level implementation details of the Ruby "puts" function.  Or: Y U NO call to_s on my Array subclass!?</summary>
    <content type="html">&lt;p&gt;Most object oriented programming languages provide an interface that an object can implement to describe itself as a string, so when it is given as an argument to a &amp;#8220;printing&amp;#8221; function, it gets converted/coerced to it&amp;#8217;s desired format.&lt;/p&gt;

&lt;p&gt;In Ruby, this is achieved by implementing the &lt;code&gt;to_s&lt;/code&gt; method, so if you define a class implementing this method, &lt;code&gt;puts&lt;/code&gt; will behave like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; class MyClass
&amp;gt;&amp;gt;   def to_s
&amp;gt;&amp;gt;     &amp;quot;&amp;lt;MyClass Instance&amp;gt;&amp;quot;
&amp;gt;&amp;gt;   end
&amp;gt;&amp;gt; end
=&amp;gt; nil
&amp;gt;&amp;gt; instance = MyClass.new
=&amp;gt; &amp;lt;MyClass Instance&amp;gt;
&amp;gt;&amp;gt; puts instance
&amp;lt;MyClass Instance&amp;gt;
=&amp;gt; nil&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So everything is well and works as expected until you suddenly decide to subclass the &lt;code&gt;Array&lt;/code&gt; or the &lt;code&gt;String&lt;/code&gt; class:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; class MyString &amp;lt; String
&amp;gt;&amp;gt;   def to_s
&amp;gt;&amp;gt;     &amp;quot;&amp;lt;MyString #{super}&amp;gt;&amp;quot;
&amp;gt;&amp;gt;   end
&amp;gt;&amp;gt; end
=&amp;gt; nil
&amp;gt;&amp;gt;
&amp;gt;&amp;gt; class MyArray &amp;lt; Array
&amp;gt;&amp;gt;   def to_s
&amp;gt;&amp;gt;     &amp;quot;&amp;lt;MyArray instance&amp;gt;&amp;quot;
&amp;gt;&amp;gt;   end
&amp;gt;&amp;gt; end
=&amp;gt; nil
&amp;gt;&amp;gt;
&amp;gt;&amp;gt; mystring = MyString.new(&amp;quot;Hello World!&amp;quot;)
=&amp;gt; &amp;quot;Hello World!&amp;quot;
&amp;gt;&amp;gt;
&amp;gt;&amp;gt; myarray = MyArray.new
=&amp;gt; []
&amp;gt;&amp;gt;
&amp;gt;&amp;gt; puts mystring
Hello World!
=&amp;gt; nil
&amp;gt;&amp;gt; puts myarray
=&amp;gt; nil&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wait, what!? As you can see, I&amp;#8217;ve implemented the &lt;code&gt;to_s&lt;/code&gt; function but it didn&amp;#8217;t get called when I passed the instances to the &lt;code&gt;puts&lt;/code&gt; function. That means I did something wrong, right?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; mystring.to_s
=&amp;gt; &amp;quot;&amp;lt;MyString Hello World!&amp;gt;&amp;quot;
&amp;gt;&amp;gt; myarray.to_s
=&amp;gt; &amp;quot;&amp;lt;MyArray instance&amp;gt;&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, apparently not. So what kind of trickery is going on here? I&amp;#8217;ve implemented the necessary method but it&amp;#8217;s not being called for those specific subclasses, so it&amp;#8217;s bound to be an implementation detail of the function we are calling. Let&amp;#8217;s take a look at how &lt;code&gt;puts&lt;/code&gt; is implemented in Ruby &lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Opening up the &lt;code&gt;io.c&lt;/code&gt; file and searching for &amp;#8220;puts&amp;#8221; we end up finding a declaration of the &lt;code&gt;rb_io_puts&lt;/code&gt; function:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;VALUE
rb_io_puts(int argc, VALUE *argv, VALUE out)
{
    int i;
    VALUE line;

    /* if no argument given, print newline. */
    if (argc == 0) {
        rb_io_write(out, rb_default_rs);
        return Qnil;
    }
    for (i=0; i&amp;lt;argc; i++) {
        if (TYPE(argv[i]) == T_STRING) {
            line = argv[i];
            goto string;
        }
        line = rb_check_array_type(argv[i]);
        if (!NIL_P(line)) {
            rb_exec_recursive(io_puts_ary, line, out);
            continue;
        }
        line = rb_obj_as_string(argv[i]);
    string:
        rb_io_write(out, line);
        if (RSTRING_LEN(line) == 0 ||
            !str_end_with_asciichar(line, &amp;#39;\n&amp;#39;)) {
            rb_io_write(out, rb_default_rs);
        }
    }

    return Qnil;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The comment block above the function definition already explains what happens, but let&amp;#8217;s understand the function and &lt;em&gt;why&lt;/em&gt; it behaves the way it does when we call it with our custom &lt;code&gt;Array&lt;/code&gt; and &lt;code&gt;String&lt;/code&gt; subclasses.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TYPE&lt;/code&gt; is a macro that expands to &lt;code&gt;rb_type&lt;/code&gt;, which ultimately checks the &lt;code&gt;.flags&lt;/code&gt; field from the object cast as &lt;code&gt;struct RBasic&lt;/code&gt; to identify it&amp;#8217;s type. So, for the string behavior it&amp;#8217;s simple:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TYPE(argv[i]) == T_STRING&lt;/code&gt; is True, which makes the code jump to the &lt;code&gt;string&lt;/code&gt; label and simply write it&amp;#8217;s contents.&lt;/p&gt;

&lt;p&gt;For the array case, the code calls &lt;code&gt;rb_check_array_type&lt;/code&gt; (from &lt;code&gt;array.c&lt;/code&gt;), which cascades to testing &lt;code&gt;TYPE(argv[i]) == T_ARRAY &amp;amp;&amp;amp; T_ARRAY != T_DATA&lt;/code&gt;. That results in true, so the code enters the &lt;code&gt;if (!NIL_P(line))&lt;/code&gt; block, calling &lt;code&gt;io_puts_ary&lt;/code&gt; (that ends up calling &lt;code&gt;rb_io_puts&lt;/code&gt; for each item of the array) and goes to handle the next parameter.&lt;/p&gt;

&lt;p&gt;Now, only if both tests above fails the interpreter ends up calling &lt;code&gt;rb_obj_as_string&lt;/code&gt;, which, as you may have guessed, is responsible for calling the higher level &lt;code&gt;to_s&lt;/code&gt; implementation.&lt;/p&gt;

&lt;p&gt;So now you might be thinking &amp;#8220;if I don&amp;#8217;t subclass Array nor String ruby will certainly call my &lt;code&gt;to_s&lt;/code&gt; implementation, right?&amp;#8221;. Well, wrong! :)&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;ve been following along what I&amp;#8217;ve written with Ruby&amp;#8217;s source code, you might have noticed the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;VALUE
rb_check_array_type(VALUE ary)
{
    return rb_check_convert_type(ary, T_ARRAY, &amp;quot;Array&amp;quot;, &amp;quot;to_ary&amp;quot;);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice the last parameter being given (&lt;code&gt;to_ary&lt;/code&gt;)? It&amp;#8217;s a well known friend of rubyists: it&amp;#8217;s a method that converts an object to array.&lt;/p&gt;

&lt;p&gt;Without digging deeper in the code, what might this mean? Let&amp;#8217;s do a little test. Remember our first example, the &lt;code&gt;MyClass&lt;/code&gt; implementation? We&amp;#8217;ll build up on that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; class MyClass
&amp;gt;&amp;gt;   def to_s
&amp;gt;&amp;gt;     &amp;quot;&amp;lt;MyClass Instance&amp;gt;&amp;quot;
&amp;gt;&amp;gt;   end
&amp;gt;&amp;gt; end
=&amp;gt; nil
&amp;gt;&amp;gt; instance = MyClass.new
=&amp;gt; &amp;lt;MyClass Instance&amp;gt;
&amp;gt;&amp;gt; puts instance
&amp;lt;MyClass Instance&amp;gt;
=&amp;gt; nil
&amp;gt;&amp;gt; class MyClass
&amp;gt;&amp;gt;   def to_ary
&amp;gt;&amp;gt;     %W(MyClass Instance as Array)
&amp;gt;&amp;gt;   end
&amp;gt;&amp;gt; end
=&amp;gt; nil
&amp;gt;&amp;gt; puts instance
MyClass
Instance
as
Array
=&amp;gt; nil&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Weird isn&amp;#8217;t it? Turns out that &lt;code&gt;rb_check_array_type&lt;/code&gt; returns a valid pointer if the parameter implements the &lt;code&gt;to_ary&lt;/code&gt; method. This means that whenever an object has this method implemented, it will be treated as an array by &lt;code&gt;puts&lt;/code&gt; and the &lt;code&gt;to_s&lt;/code&gt; method will never be called by it.&lt;/p&gt;

&lt;p&gt;And that&amp;#8217;s it, phew! To summarise: &lt;code&gt;puts&lt;/code&gt; does call &lt;code&gt;to_s&lt;/code&gt; as long as you don&amp;#8217;t:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Subclass from &lt;code&gt;String&lt;/code&gt; nor &lt;code&gt;Array&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;Implement the &lt;code&gt;to_ary&lt;/code&gt; method&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This post idea comes from a &lt;a href='http://goo.gl/ScUZr'&gt;question I&amp;#8217;ve answered&lt;/a&gt; on a Portuguese stackoverflow-like website some months ago.&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;I&amp;#8217;m using the C reference implementation for Ruby, version 1.9.2-p290, obtainable at &lt;a href='http://ruby-lang.org/'&gt;http://ruby-lang.org/&lt;/a&gt;.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Musings About RPM Upgrades</title>
    <link href="http://caioromao.com/blog/musings-about-rpm-upgrades/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/musings-about-rpm-upgrades/</id>
    <updated>2011-09-14T00:00:00+02:00</updated>
    <published>2011-09-14T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>On how the lack of proper knowledge of the inner workings of the upgrade process of a RPM package caused some critical issues and how we overcame them.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;TL;DR Version&lt;/strong&gt;: We&amp;#8217;ve screwed up for not really understanding how the packaging system we used worked internally.&lt;/p&gt;

&lt;p&gt;I currently work on a project where we have to go full stack: from planning, coding and testing to packaging, shipping and doing some legal paper work. One of the areas that gives the most headaches (besides the legal hassle, obviously) is the packaging (we&amp;#8217;re only dealing with &lt;a href='http://www.rpm.org'&gt;RPM&lt;/a&gt; for now). Here I&amp;#8217;ll describe an RPM default behavior which has bitten us recently and how we&amp;#8217;ve used it for our own good.&lt;/p&gt;

&lt;p&gt;RPM packages support scripting at some points during installation: before and after installation and removal - namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;%pre&lt;/code&gt;: kicks in before installing the package - this stage is commonly used to prepare the environment before the install, such as creating directories and setting permissions.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;%post&lt;/code&gt;: runs after the package has been installed, typically used to run configuration scripts, like creating the administrator credentials for a database or setting up the service to start at boot.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;%preun&lt;/code&gt;: happens before a package removal (or upgrade), used to stop dependant services and kill the application being uninstalled.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;%postun&lt;/code&gt;: the last step of a removal (or, again, an upgrade), sometimes used for some leftover cleanup like purging empty directories.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I won&amp;#8217;t go too deep on the workings of RPM as this is not the scope of this post, but if you&amp;#8217;re interested check out &lt;a href='http://www.rpm.org/max-rpm/'&gt;Maximum RPM&lt;/a&gt;: it&amp;#8217;s the most complete RPM guide you&amp;#8217;ll ever get. As a bare minimum, take a quick look &lt;a href='http://www.rpm.org/max-rpm/s1-rpm-specref-scripts.html'&gt;at here&lt;/a&gt; and &lt;a href='http://www.rpm.org/max-rpm/s1-rpm-specref-files-list.html'&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, what would happen behind the scenes during a package upgrade? It&amp;#8217;s natural (at least for me and my team) to think that the old version package will be removed and then the new version would be installed -meaning that the sections described previously would be called in the following order: &lt;code&gt;%preun&lt;/code&gt;, &lt;code&gt;%postun&lt;/code&gt;, &lt;code&gt;%pre&lt;/code&gt;, &lt;code&gt;%post&lt;/code&gt;. Well, turns out this is &lt;em&gt;not&lt;/em&gt; what happens and this is why we were bitten. Twice.&lt;/p&gt;

&lt;h2 id='bite_1_our_services_were_all_stopped_after_an_upgrade'&gt;Bite #1: Our Services Were All Stopped After An Upgrade&lt;/h2&gt;

&lt;p&gt;Following the &amp;#8220;natural&amp;#8221; chain of thought, we&amp;#8217;d included in our package&amp;#8217;s &lt;code&gt;%preun&lt;/code&gt; section instructions to stop the services we setup so that it wouldn&amp;#8217;t be running during the upgrade and risk breaking everything.&lt;/p&gt;

&lt;p&gt;This definitely didn&amp;#8217;t break anything and since we provide a front-end for upgrading our packages which triggers a restart after everything, we didn&amp;#8217;t spot the issue soon. Only when testing a command line upgrade it was noticed that our services were completely stopped.&lt;/p&gt;

&lt;p&gt;The fix for it was simple: we removed the commands to stop our services in the &lt;code&gt;%preun&lt;/code&gt; section during an upgrade and everything went better than expected.&lt;/p&gt;

&lt;h2 id='bite_2_files_generated_dynamically_were_being_removed'&gt;Bite #2: Files Generated Dynamically Were Being Removed&lt;/h2&gt;

&lt;p&gt;Due to some internal reasons one of the packages we ship switched from including some files statically in the RPM package (defined in the &lt;code&gt;%files&lt;/code&gt; section) to automatically generating them during the install process.&lt;/p&gt;

&lt;p&gt;With this change, after an upgrade from our old and more declarative package to this new dynamic one the files that were being generated ended up being removed after the upgrade (we had confirmed they were definitely being created during the setup).&lt;/p&gt;

&lt;p&gt;The rather-ugly-but-simple-fix was to create an intermediary package with static files with names different from the ones being auto generated.&lt;/p&gt;

&lt;h2 id='how_an_upgrade_really_works'&gt;How An Upgrade REALLY Works&lt;/h2&gt;

&lt;p&gt;So, how come those fixes worked and - more importantly - why the heck were they happening in the first place?&lt;/p&gt;

&lt;p&gt;Quoting from &lt;a href='http://www.ibm.com/developerworks/library/l-rpm2/'&gt;this developerWorks article&lt;/a&gt;, what happens during a package upgrade is the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Run the &lt;code&gt;%pre&lt;/code&gt; section of the RPM being installed.&lt;/li&gt;

&lt;li&gt;Install the files that the RPM provides.&lt;/li&gt;

&lt;li&gt;Run the &lt;code&gt;%post&lt;/code&gt; section of the RPM.&lt;/li&gt;

&lt;li&gt;Run the &lt;code&gt;%preun&lt;/code&gt; of the old package.&lt;/li&gt;

&lt;li&gt;Delete any old files not overwritten by the newer version. (This step deletes files that the new package does not require.)&lt;/li&gt;

&lt;li&gt;Run the &lt;code&gt;%postun&lt;/code&gt; hook of the old package.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;What this means is that the old package removal happens &lt;strong&gt;after&lt;/strong&gt; the installation of the new one. If you think about it, it &lt;em&gt;kind of&lt;/em&gt; makes sense since we don&amp;#8217;t want to touch the configuration files the user has changed (or rather, we don&amp;#8217;t want to force the user to reconfigure her service after simple updates). If it were up to me I wouldn&amp;#8217;t do it like this, but anyway.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s understand each issue and why the fix worked:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The issue with services being stopped (Bite #1) is fairly simple to understand once you read about the upgrade order above: you must &lt;strong&gt;not&lt;/strong&gt; stop services on the &lt;code&gt;%preun&lt;/code&gt; and &lt;code&gt;%postun&lt;/code&gt; sections during an update/upgrade.&lt;/li&gt;

&lt;li&gt;Issue #2 is the interesting one: since the files we were creating were described in the &lt;code&gt;%files&lt;/code&gt; section of the old package but not in the new one, the step 5 in the upgrade flow removes them. This, in my opinion, is a bug: the &lt;code&gt;mtime&lt;/code&gt; of the candidate files for removal should be checked to make sure no &lt;code&gt;scriptlet&lt;/code&gt; touched it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id='the_tasty_bite'&gt;The Tasty Bite&lt;/h2&gt;

&lt;p&gt;Enough of issues, let&amp;#8217;s take a look at a situation where this upgrade behavior actually helped us solve a production bug:&lt;/p&gt;

&lt;p&gt;In our first release some of our code depended on some filesystem data to work and we didn&amp;#8217;t cache such data for further use throughout the service lifetime; This caused a bug during an upgrade because the newer package version would replace some files which the old service depended on - so, after an upgrade through our UI, the application would crash since the filesystem data is different from what it expected (yeah, I&amp;#8217;m talking about templates - shame on us).&lt;/p&gt;

&lt;p&gt;Such an issue could be solved by simply releasing a new minor version of the product, however the bug would still show up if the user tried to upgrade from the original version, without going through the minor update, so this wasn&amp;#8217;t perfectly safe.&lt;/p&gt;

&lt;p&gt;By the time we caught this problem we were already aware of the real RPM upgrade flow, so we used that to work around the issue for any version: in the &lt;code&gt;%pre&lt;/code&gt; section of the new package we backed-up the old files which triggered the crash when changed and kept them at their original location after the upgrade finished - when the application restarts, it detects the presence of the old files and finally replaces them with the new ones: now the service is running with updated code aware of the filesystem changes and nothing really breaks.&lt;/p&gt;

&lt;p&gt;This is what one would call a really ugly hack in the wild and I&amp;#8217;d have to agree. However, the code was already in production and even worse than doing dirty hacks is letting the application crash in the face of the user.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Neat App of the Day: Taskwarrior</title>
    <link href="http://caioromao.com/blog/neat-app-of-the-day-taskwarrior/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/neat-app-of-the-day-taskwarrior/</id>
    <updated>2011-01-22T00:00:00+01:00</updated>
    <published>2011-01-22T00:00:00+01:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Continuation of the "Neat App of the Day" series, featuring Taskwarrior, a powerful command-line TODO-list manager</summary>
    <content type="html">&lt;h2 id='introduction'&gt;Introduction&lt;/h2&gt;

&lt;p&gt;&lt;a href='http://taskwarrior.org/projects/show/taskwarrior/'&gt;Taskwarrior&lt;/a&gt; isn&amp;#8217;t an application, it is a project. To quote from their website:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href='http://taskwarrior.org/projects/show/taskwarrior/'&gt;Taskwarrior&lt;/a&gt; is an ambitious project to supercharge &lt;strong&gt;task&lt;/strong&gt; with an interactive interface, GTD features, color themes, data synch, dependencies, custom reports, charts, and Lua plugins, all while our international team provides excellent support!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, yeah, the neat app I&amp;#8217;m talking about is actually called &lt;code&gt;task&lt;/code&gt;, but that&amp;#8217;s too hard to differentiate from anything else, since it&amp;#8217;s a dictionary word.&lt;/p&gt;

&lt;p&gt;Anyway, I&amp;#8217;ve been searching for a fast and easy to use TODO-list manager for a long time in order to move away from that dreaded-but-functional &lt;code&gt;TODO.txt&lt;/code&gt; plain-text file in my homedir. And for the past month or so, I could say I&amp;#8217;ve finally found a decent replacement.&lt;/p&gt;

&lt;h2 id='the_good'&gt;The Good&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It&amp;#8217;s a command-line app&lt;/li&gt;

&lt;li&gt;High programmability level&lt;/li&gt;

&lt;li&gt;Command abbreviation&lt;/li&gt;

&lt;li&gt;Batch processing&lt;/li&gt;

&lt;li&gt;Active development community&lt;/li&gt;

&lt;li&gt;On-demand eye candy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being able to quickly manage my tasks is a must-have for me, and by &amp;#8220;quickly&amp;#8221; I mean: without the need to use a mouse. Taskwarrior does just that, with added support for synchronization, tags, projects and calendaring. I can simply list my tasks for the day with &lt;code&gt;task ls due:today&lt;/code&gt; (or the overdue ones with &lt;code&gt;task overdue&lt;/code&gt;) and filter any kind of query command by project (&lt;code&gt;pro:&amp;lt;NAME&amp;gt;&lt;/code&gt;), priority (&lt;code&gt;pri:&amp;lt;H,M,L,N&amp;gt;&lt;/code&gt;), tags (&lt;code&gt;+&amp;lt;TAG&amp;gt;&lt;/code&gt;) and many other modifiers (check the &lt;code&gt;ATTRIBUTES AND METADATA&lt;/code&gt; section in the task manpage).&lt;/p&gt;

&lt;p&gt;I could write several paragraphs about how many interesting features Taskwarrior has, but I&amp;#8217;ll direct you to their &lt;a href='http://taskwarrior.org/wiki/taskwarrior/Tutorial'&gt;official tutorials&lt;/a&gt; instead. If you prefer watching over reading, make sure you check this introductory video out:&lt;/p&gt;
&lt;object height='505' width='640'&gt;&lt;param name='movie' value='http://www.youtube-nocookie.com/v/d-abs0s8uis?fs=1&amp;amp;hl=en_US&amp;amp;rel=0' /&gt;
&lt;param name='allowFullScreen' value='true' /&gt;
&lt;param name='allowscriptaccess' value='always' /&gt;
&lt;embed allowfullscreen='true' allowscriptaccess='always' height='385' src='http://www.youtube-nocookie.com/v/d-abs0s8uis?fs=1&amp;amp;hl=en_US&amp;amp;rel=0' type='application/x-shockwave-flash' width='480' /&gt;&lt;/object&gt;
&lt;h2 id='the_bad'&gt;The Bad&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It&amp;#8217;s &lt;strong&gt;only&lt;/strong&gt; a command-line app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being a command-line-only application, it&amp;#8217;s usage becomes &lt;em&gt;really&lt;/em&gt; limited and it&amp;#8217;s quite impossible to do any sort of productive task management on a mobile device without a (proper) physical keyboard. Luckily this is bound to change (otherwise this would be placed under a &amp;#8220;The Ugly&amp;#8221; section) since there are plans to decouple the UI from the engine (I believe this&amp;#8217;ll be on the next release: &lt;code&gt;1.9.4&lt;/code&gt;), which will allow lots of front-ends to be created, which is great for I&amp;#8217;ll be able to develop apps for all those cool smartphones and gadgets that I don&amp;#8217;t have (the prices are plain stupid here in Brazil).&lt;/p&gt;

&lt;h2 id='alternatives'&gt;Alternatives&lt;/h2&gt;

&lt;p&gt;There are plenty of TODO-list managers out there, some with really interesting features and great visuals. If having your list accessible off-line in an easy way is not a requirement, there are several web-based tools out there to try out - I&amp;#8217;ve used &lt;a href='http://google.com/tasks'&gt;Google Tasks&lt;/a&gt; for a couple of months and it&amp;#8217;s quite simple (maybe &lt;strong&gt;too&lt;/strong&gt; simple), a featureful alternative to Google&amp;#8217;s take on task management would be &lt;a href='http://www.rememberthemilk.com'&gt;Remember the Milk&lt;/a&gt;. If GUI applications are your thing, maybe &lt;a href='http://www.evernote.com/'&gt;Evernote&lt;/a&gt; or &lt;a href='http://gtg.fritalk.com/'&gt;Getting Things Gnome&lt;/a&gt; will be more to your liking.&lt;/p&gt;

&lt;p&gt;But if you&amp;#8217;re like me and utterly dislike using your mouse, but &lt;a href='http://taskwarrior.org/projects/show/taskwarrior/'&gt;Taskwarrior&lt;/a&gt; didn&amp;#8217;t suit your taste, another great option would be the more popular &lt;a href='http://ginatrapani.github.com/todo.txt-cli/'&gt;todo.txt&lt;/a&gt;, which has the advantage (not for long, I guess) of having mobile clients for IPhone and Android.&lt;/p&gt;

&lt;h2 id='conclusion'&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;At long last a task manager I can use without feeling uncomfortable or limited! I&amp;#8217;ve been using &lt;a href='http://taskwarrior.org/projects/show/taskwarrior/'&gt;Taskwarrior&lt;/a&gt; daily, coupled with some &lt;a href='/2011/01/11/Neat-App-of-the-Day-Sup-Mail.html'&gt;sup mail&lt;/a&gt; hooks to trigger task creation and syncing frequently with my personal tasks stored on &lt;a href='http://db.tt/KBMeY72'&gt;Dropbox&lt;/a&gt; and my work-related ones stored on my current job&amp;#8217;s cloud-like infrastructure. Make sure you try this one out if you&amp;#8217;re not completely satisfied with your current solution, even if you tend to prefer GUI apps.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Neat App of the Day: Sup Mail</title>
    <link href="http://caioromao.com/blog/neat-app-of-the-day-sup-mail/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/neat-app-of-the-day-sup-mail/</id>
    <updated>2011-01-11T00:00:00+01:00</updated>
    <published>2011-01-11T00:00:00+01:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>First post in a series of planned but not promised notes about the great applications I come by day by day. This one about sup, a neat command-line mail client written in ruby.</summary>
    <content type="html">&lt;p&gt;One of the things I really love about open source is that one can find new amazing software often and quite easily. I mean &lt;em&gt;real quality&lt;/em&gt; software, not that shitload of crapware/adware that&amp;#8217;s usually associated with &amp;#8220;free&amp;#8221; software.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m well know for using &amp;#8220;alternative&amp;#8221; apps, for changing (technical) opinions quite often and for breaking my system a lot (it figures, I have a &lt;a href='http://www.linuxfromscratch.org'&gt;LFS&lt;/a&gt;, &lt;a href='http://gentoo.org'&gt;Gentoo&lt;/a&gt; and - currently -&lt;a href='http://archlinux.org'&gt;Archlinux&lt;/a&gt; background). Turns out that this &lt;em&gt;beta&lt;/em&gt; (or rather, &lt;em&gt;alpha&lt;/em&gt;) nature of mine gives me the opportunity to try some promising software out way before it gets widely known.&lt;/p&gt;

&lt;h2 id='introduction'&gt;Introduction&lt;/h2&gt;

&lt;p&gt;This time I&amp;#8217;ll write about an application I&amp;#8217;ve been using since early 2010: &lt;a href='http://sup.rubyforge.org'&gt;sup&lt;/a&gt;. Sup is an e-mail client that works in the command line and has several neat features hardly found on major clients out there. It&amp;#8217;s already well known by the bleeding edgers, but surprisingly unknown by most of the nerd/geek/whatever circles I know.&lt;/p&gt;

&lt;h2 id='the_good'&gt;The Good&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Written in Ruby&lt;/li&gt;

&lt;li&gt;It&amp;#8217;s &lt;strong&gt;FAST&lt;/strong&gt;&lt;/li&gt;

&lt;li&gt;Full-text search&lt;/li&gt;

&lt;li&gt;Local storage&lt;/li&gt;

&lt;li&gt;Scriptable&lt;/li&gt;

&lt;li&gt;Tags!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are a &lt;a href='http://mail.google.com'&gt;gmail&lt;/a&gt; user, you should be aware of how much tagging helps organizing the flood of e-mails we receive every day. I use &lt;a href='http://sup.rubyforge.org'&gt;sup&lt;/a&gt; to deal with a couple of personal accounts and - mostly - with my job&amp;#8217;s e-mail and I couldn&amp;#8217;t be happier. Being able to search my e-mail using a gmail-like query language and get results in less than a second really helps out when you need to find that message you thought no one would care, or that meeting agenda you forgot to store in a better place.&lt;/p&gt;

&lt;p&gt;Being written in Ruby really eases the creation of hooks for several events and, since I have some experience with the language, even allowed me to hack on the code and create a useful feature for me: contact groups (&lt;a href='http://gitorious.org/~caio/sup/contactgroup-support'&gt;check my code&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id='the_bad'&gt;The Bad&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Written in Ruby&lt;/li&gt;

&lt;li&gt;Needs scripts for pretty basic things&lt;/li&gt;

&lt;li&gt;No (official) &lt;code&gt;maildir&lt;/code&gt; sync-back support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might be wondering how come being written in Ruby is listed here if it was listed in the section above. Well, if you&amp;#8217;ve ever maintained anything in Ruby long enough you&amp;#8217;ll probably know how things can break badly from version to version (even minors!). Using a bleeding-edge distribution doesn&amp;#8217;t help either: most of the packages are either &amp;#8220;too new&amp;#8221; or just don&amp;#8217;t work at all. Ever since Archlinux changed it&amp;#8217;s default Ruby version to the &lt;code&gt;1.9.x&lt;/code&gt; family, running &lt;a href='http://sup.rubyforge.org'&gt;sup&lt;/a&gt; became a pain so, to avoid any problems, I have to keep an exclusive &lt;a href='http://rvm.beginrescueend.com/'&gt;rvm&lt;/a&gt; setup for it and freeze updates on &lt;code&gt;xapian-core&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='alternatives'&gt;Alternatives&lt;/h2&gt;

&lt;p&gt;There are several console-based e-mail clients out there, but none with the power of sup. If getting over those Ruby issues or using a relatively young software bothers you (and you can live without tags), it might be worth checking out the most well-known and established MUA for the Linux terminal: &lt;a href='http://www.mutt.org/'&gt;mutt&lt;/a&gt;. Other than that, only &lt;a href='http://danielchoi.com/software/vmail.html'&gt;vmail&lt;/a&gt; comes to mind, which seems a good enough solution if you only use gmail (you gotta be a &lt;a href='http://www.vim.org'&gt;vim&lt;/a&gt; addict too, but who isn&amp;#8217;t :-).&lt;/p&gt;

&lt;h2 id='conclusion'&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Tired of those sluggish GUI-based e-mail clients out there? Can&amp;#8217;t find anything that fits your needs? Even grew tired of &lt;a href='http://sylpheed.sraoss.jp/en/'&gt;Sylpheed&lt;/a&gt;? Check out &lt;a href='http://sup.rubyforge.org'&gt;sup&lt;/a&gt;. If you manage to install it in your distro, I&amp;#8217;m sure you&amp;#8217;ll like it.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Custom Directory Completion for Zsh</title>
    <link href="http://caioromao.com/blog/custom-directory-completion-for-zsh/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/custom-directory-completion-for-zsh/</id>
    <updated>2010-12-26T00:00:00+01:00</updated>
    <published>2010-12-26T00:00:00+01:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>On how to setup a custom directory-based command-line completion on zsh.  And why I hate slow leg-less zombies.</summary>
    <content type="html">&lt;p&gt;I&amp;#8217;ve been planing on checking &lt;a href='http://www.zsh.org'&gt;zsh&lt;/a&gt; out ever since I found out about &lt;a href='https://github.com/robbyrussell/oh-my-zsh'&gt;oh-my-zsh&lt;/a&gt;. This weekend I finally had a little free time to do so. Besides a pretty informative prompt and useful command completion, one thing that I (now) find absolutely necessary in any shell I use daily it my custom &lt;code&gt;make_dir_complete&lt;/code&gt; function to generate shortcuts for any directory. I&amp;#8217;ve previously described how to implement it &lt;a href='/2010/10/10/Custom-directory-completion.html'&gt;here&lt;/a&gt;, if you&amp;#8217;re interested.&lt;/p&gt;

&lt;p&gt;Well, given zsh&amp;#8217;s fame of having a really complicated completion system, I was reluctant to go down the path of implementing it on my own and decided to check on &lt;code&gt;#zsh&lt;/code&gt; (at Freenode) if anyone had already done what I wanted or if I could at least get some decent directions (zsh&amp;#8217;s completion documentation is exactly like bash&amp;#8217;s. They both suck). Since the only answer I got was in the form of &amp;#8221;I&amp;#8217;ve asked that previously and got no answer&amp;#8221;, I decided to give it a shot.&lt;/p&gt;

&lt;p&gt;I went down the same chain of thought I had to use on bash: generate a completion function which would reply the next possible directories based on the first parameter. Turns out this was a really bad choice, since I soon got stuck at not getting consecutive completions and started feeling confused by the many glob options available.&lt;/p&gt;

&lt;p&gt;After messing around with existing system completions (basic ones, like the &lt;code&gt;man&lt;/code&gt; completion), I found some really interesting uses of &lt;code&gt;compctl&lt;/code&gt; and decided to delve deep into it&amp;#8217;s manpages and soon I came up with this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function jk() { cd ~/src/$@; };
compctl -/ -W ~/src jk&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;#8217;s it, it worked! I was impressed, even completing a directory with spaces worked out of the box. Now I just had to add the code generation part and would be all set:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;make_dir_complete() {
    local aliasname=$1
    local dirname=$(readlink -f $2)
    FUNC=&amp;quot;$aliasname () { cd $dirname/\$@ }&amp;quot;
    eval $FUNC
    compctl -/ -W $dirname $aliasname
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Short, concise and way easier to &amp;#8220;get it&amp;#8221; than it&amp;#8217;s bash&amp;#8217;s counterpart. I&amp;#8217;ve even created a oh-my-zsh plugin for using it, it&amp;#8217;s the same function, but with proper usage documentation and parameter verifications. You can &lt;a href='https://github.com/caio/oh-my-zsh/blob/master/plugins/make-dir-complete/make-dir-complete.plugin.zsh'&gt;check it here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, all my requirements were met and I was ready to ditch bash in favor of zsh, right? Unfortunately no. I&amp;#8217;ve spent the Sunday using it, was quite happy and everything was going smooth, until I decided to do a test-drive and check how it fared against my current job workflow, which involves a slightly large git repository (migrated from svn by yours truly). That&amp;#8217;s when I came back running to bash. A great part of my job involves reviewing code, and the shell completion helps me a &lt;strong&gt;lot&lt;/strong&gt; matching the branches I&amp;#8217;ll review and merge and zsh&amp;#8217;s git completion crawls like a zombie (a slow one, without legs).&lt;/p&gt;

&lt;p&gt;A fully migrated setup, with every important thing working properly, discarded without remorse. I&amp;#8217;m not willing to change shells &lt;em&gt;and&lt;/em&gt; lose productivity, even if the community behind oh-my-zsh is big and amazing. So long zsh, I&amp;#8217;ll be back (soon, I hope) when your git completion doesn&amp;#8217;t take more time to list possibilities than it takes me to remember and type a branch name.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Custom Directory Completion for Bash</title>
    <link href="http://caioromao.com/blog/custom-directory-completion-for-bash/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/custom-directory-completion-for-bash/</id>
    <updated>2010-10-10T00:00:00+02:00</updated>
    <published>2010-10-10T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>On how to setup a custom directory-based command-line completion on bash.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: Z-Shell users, check out the post detailing the &lt;a href='/2010/12/26/Custom-directory-completion-for-zsh.html'&gt;zsh version&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I really dislike writing tildes. I mean, since I use an international keyboard layout (In Portuguese we do some heavy usage of tilde and cedilla), I have to type &lt;code&gt;&amp;lt;SHIFT&amp;gt;~&amp;lt;SPACE&amp;gt;&lt;/code&gt; in order to get a single &lt;code&gt;~&lt;/code&gt; character.&lt;/p&gt;

&lt;p&gt;For that reason, I&amp;#8217;ve always used quick commands to change to directories nested from my homedir: first I used aliases, then some &lt;code&gt;pushd&lt;/code&gt;/&lt;code&gt;popd&lt;/code&gt; tickery and finally some proper bash completion usage. Up &amp;#8216;till a few weeks ago, I&amp;#8217;d only used a single command, which would complete the folders inside &lt;code&gt;~/src/&lt;/code&gt; - but this has changed. I felt the need to have quicker access do my downloads folder (&lt;code&gt;~/download/&lt;/code&gt;) and even for my homedir, so I hacked together a simple yet useful completion generator function which I though it might be worthwhile to share.&lt;/p&gt;

&lt;p&gt;Here it is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;make_dir_complete() {
    local aliasname=$1
    local dirname=$(readlink -f $2)
    local prgname=&amp;quot;__s_${aliasname}__&amp;quot;
    FUNC=&amp;quot;function $prgname() {
        local cur len wrkdir;
        local IFS=\$&amp;#39;\\n&amp;#39;
        wrkdir=\&amp;quot;$dirname\&amp;quot;
        cur=\${COMP_WORDS[COMP_CWORD]};
        len=\$((\${#wrkdir} + 2));
        COMPREPLY=( \$(compgen -S/ -d \$wrkdir/\$cur| cut -b \$len-) );
    }&amp;quot;
    ALIAS=&amp;quot;$aliasname () { cd \&amp;quot;$dirname/\$*\&amp;quot;; }&amp;quot;
    eval $FUNC
    eval $ALIAS
    complete -o nospace -F $prgname $aliasname
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The usage is simple: &lt;code&gt;make_dir_complete &amp;lt;shortcut_name&amp;gt; &amp;lt;directory&amp;gt;&lt;/code&gt;. So, in my case I&amp;#8217;d call &lt;code&gt;make_dir_complete jk ~/src&lt;/code&gt; and whenever I type &lt;code&gt;jk &amp;lt;TAB&amp;gt;&amp;lt;TAB&amp;gt;&lt;/code&gt; it will list to me the directories inside &lt;code&gt;~/src&lt;/code&gt;. More advanced completion like wildcard and partial matching (no fuzzy matching, though. Sorry) also work, thanks to bash&amp;#8217;s awesome &lt;code&gt;complete&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;There are probably better ways to achieve what I just did, so please let me know if you see any room for improvements :)&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>An IRC Bot for Managing Shared Machines</title>
    <link href="http://caioromao.com/blog/an-irc-bot-for-managing-shared-machines/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/an-irc-bot-for-managing-shared-machines/</id>
    <updated>2010-09-25T00:00:00+02:00</updated>
    <published>2010-09-25T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Announcement of MachineBot, or: I should really be studying.</summary>
    <content type="html">&lt;p&gt;This Saturday afternoon I had nothing (that I deemed) important to do, so I&amp;#8217;ve decided to check how rusty I had became with &lt;a href='http://ruby-lang.org'&gt;Ruby&lt;/a&gt;. I&amp;#8217;ve spent some fun hours coding a simple IRC bot to substitute the one that my team used at work since we&amp;#8217;ve lost it&amp;#8217;s source code.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s no technical reason for my decision of using Ruby instead of my &lt;a href='http://python.org'&gt;current favorite programming language&lt;/a&gt;. I just wanted to practice with another language for a change, but wasn&amp;#8217;t with enough disposition to learn a new one. I also had to bear in mind that (if used), this would be installed on a production machine, so keeping the external dependencies limited would be a good idea &lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Anyway, you can check it out &lt;a href='http://github.com/caio/machinebot'&gt;here&lt;/a&gt;. I&amp;#8217;ve included a basic README file with usage instructions. The fun part is over, so I don&amp;#8217;t plan on documenting nor creating help / debug output messages today.&lt;/p&gt;

&lt;p&gt;Using it is pretty straight-forward if you&amp;#8217;re familiarized with &lt;a href='http://github.com/injekt/cinch'&gt;cinch&lt;/a&gt;. If not, just check &lt;a href='http://github.com/injekt/cinch'&gt;their homepage&lt;/a&gt;. The good thing is that I&amp;#8217;ve done &lt;a href='http://github.com/caio/machinebot'&gt;MachineBot&lt;/a&gt; (yeah, the name is lame, I agree) as a plugin, so if you already have your own bot built with &lt;code&gt;cinch&lt;/code&gt;, integrating mine is just a matter of requiring it and adding to the plugin list.&lt;/p&gt;

&lt;p&gt;I should really start doing this more often, it&amp;#8217;s a great exercise. Too bad weekends like this are hard to come by nowadays. I&amp;#8217;ll make sure to keep track of how much time I spend doing it next time - It&amp;#8217;s been around 4 hours, but I&amp;#8217;d like to know precisely what&amp;#8217;s my pace.&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;Actually, I hadn&amp;#8217;t thought of that while coding. This came to my mind while writing this post.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Disgusted With C++ Build Errors</title>
    <link href="http://caioromao.com/blog/disgusted-with-c%2B%2B-build-errors/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/disgusted-with-c%2B%2B-build-errors/</id>
    <updated>2010-08-07T00:00:00+02:00</updated>
    <published>2010-08-07T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Personal thoughts on the lack of decent compilation facilities for C++.</summary>
    <content type="html">&lt;p&gt;Everybody knows C++ build errors are one of the most bizarre anyone will ever find in the compiled languages world and, by knowing that, it seems that the developers treat new introduced oddities as a normal thing.&lt;/p&gt;

&lt;p&gt;Don&amp;#8217;t get me wrong, I&amp;#8217;m not a C++ hater &lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt; and I didn&amp;#8217;t come here to rant about the well known and blatantly ugly compilation errors caused by any kind of incorrect Template and/or Overloading usage. What made me come home and write this post was &lt;a href='http://goo.gl/kzKuv'&gt;this question on Stackoverflow.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just reading the question and it&amp;#8217;s answer is enough to get sick. This is basically what goes on:&lt;/p&gt;

&lt;p&gt;A fella decides to try out C++0x&amp;#8217;s standard multithreading support and uses the following code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;thread&amp;gt;

void hello() {
    std::cout &amp;lt;&amp;lt; &amp;quot;Hello Concurrent World&amp;quot;;
}

int main(int argc, char *argv[]) {
    std::thread t(hello);
    t.join();
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;He says he compiled it with &lt;code&gt;g++ -std=c++0x -g -o executable source.cpp&lt;/code&gt; and there were no errors, but when running he got a weird Segmentation Fault:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Program received signal SIGSEGV, Segmentation fault.
_dl_fixup (l=0x7ffff7b0992c, reloc_arg=&amp;lt;value optimized out&amp;gt;) at ../elf/dl-runtime.c:147
147     ../elf/dl-runtime.c: No such file or directory.
        in ../elf/dl-runtime.c&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When trying his code on my box, I got this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;terminate called after throwing an instance of &amp;#39;std::system_error&amp;#39;
  what():
Aborted&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which is not as ugly, but still very weird and non informative. Examining the backtrace we get not even a single decent hint about what may be going on:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0xb7fe1424 in __kernel_vsyscall ()
0xb7d67d61 in raise () from /lib/libc.so.6
0xb7d695ee in abort () from /lib/libc.so.6
0xb7f7bcd5 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6
0xb7f79bd5 in ?? () from /usr/lib/libstdc++.so.6
0xb7f79c12 in std::terminate() () from /usr/lib/libstdc++.so.6
0xb7f79d81 in __cxa_throw () from /usr/lib/libstdc++.so.6
0xb7f1eee9 in std::__throw_system_error(int) () from /usr/lib/libstdc++.so.6
0xb7f721d0 in std::thread::_M_start_thread(std::shared_ptr&amp;lt;std::thread::_Impl_base&amp;gt;) ()
 from /usr/lib/libstdc++.so.6
0x08048dd2 in thread&amp;lt;void (*)()&amp;gt; (this=0xbffff53c, __f=0x8048b0f &amp;lt;hello()&amp;gt;)
 at /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/thread:135&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, if you&amp;#8217;re even a little bit used to programming with threads on C or C++ you might just have noted that there&amp;#8217;s no flag being given to &lt;code&gt;g++&lt;/code&gt; to link the binary against a threading library (&lt;code&gt;pthread&lt;/code&gt;, for example, on Linux) and that&amp;#8217;s &lt;strong&gt;exactly&lt;/strong&gt; the issue here. He should have compiled his code with &lt;code&gt;g++ -std=c++0x -g -pthread -o executable source.cpp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How fucked up is that? I mean, it&amp;#8217;s logical that one should need to link against a threading library (even though I believe that this should be automatically resolved by the compiler, being part of the standard and such), but no error at all while compiling? Wtf? That&amp;#8217;s not an unauthorized access to private memory, null-pointer dereference nor anything like that, it&amp;#8217;s a linking issue and must cause an error no matter what.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m obviously being too harsh with all this. C++0x is not a released standard yet and g++&amp;#8217;s implementation is based on the draft, which is constantly (not that much anymore) changing, so perhaps there was not enough time/interest to focus on these &amp;#8220;usability&amp;#8221; issues. I just hope this behavior changes. Soon.&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;Though, if given the choice and it sounds reasonable, I&amp;#8217;d definitely stick to plain C most of the cases. I&amp;#8217;d rather glue Python and C together if the only argument for using C++ is being able to &amp;#8220;properly&amp;#8221; use OOP.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Splitting Git Repositories</title>
    <link href="http://caioromao.com/blog/splitting-git-repositories/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/splitting-git-repositories/</id>
    <updated>2009-12-14T00:00:00+01:00</updated>
    <published>2009-12-14T00:00:00+01:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Pragmatic guide on how to create git repositories based on sub-folders from an existing tree. Useful when moving or separating created code into a new project.</summary>
    <content type="html">&lt;p&gt;Today I was doing some maintenance on my repositories and decided some of them were worth splitting into sub-projects. Since I couldn&amp;#8217;t find any information on &lt;a href='http://google.com'&gt;Google&lt;/a&gt; on how to do it the easy way, I dug up a method myself, which I&amp;#8217;ll describe bellow.&lt;/p&gt;

&lt;h2 id='background'&gt;Background&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s say you have a &lt;a href='http://git-scm.com/'&gt;git&lt;/a&gt; repository in which you store some toy codes, I&amp;#8217;ll call it &lt;code&gt;playground.git&lt;/code&gt;. If you keep it long enough, soon you&amp;#8217;ll see some of your toys growing too large and/or important to keep on a mixed messy repository.&lt;/p&gt;

&lt;p&gt;For illustration purposes, I&amp;#8217;ll assume your repository is structured this way:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;.
`-- playground.git/
    |-- subproject1/
    |   `-- ...
    |-- subproject2/
    |   `-- ...
    `-- important_project/
        |-- important_file
        `-- ...&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What we&amp;#8217;ll see here is how to migrate the folder &lt;code&gt;important_project&lt;/code&gt; to it&amp;#8217;s own repository (say, &lt;code&gt;new_project.git&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Chances are you&amp;#8217;re sharp enough to notice when a project is growing too important to be on your playground, so moving it away by simply copying shouldn&amp;#8217;t be such a loss, but if you find it&amp;#8217;s important to keep the commit history and/or just noticed your project was getting bigger several hours of work later, you may find this post useful.&lt;/p&gt;

&lt;h2 id='finding_the_correct_revision_number'&gt;Finding the Correct Revision Number&lt;/h2&gt;

&lt;p&gt;This may be quite obvious to some of you, but it&amp;#8217;s a rather useful command (flag, actually) which I don&amp;#8217;t see many people I know using.&lt;/p&gt;

&lt;p&gt;From &lt;code&gt;git-log&lt;/code&gt; &lt;a href='http://www.kernel.org/pub/software/scm/git/docs/git-log.html'&gt;manpage&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git log [&amp;lt;options&amp;gt;] [&amp;lt;since&amp;gt;..&amp;lt;until&amp;gt;] [[--] &amp;lt;path&amp;gt;...]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The useful parameter for our case is &amp;#8220;path&amp;#8221;, so if we want to see the logs pertaining to a given file/folder, we&amp;#8217;d use:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git log -- important_project&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, basically, if we want to find the first commit that happened inside our &lt;code&gt;important_project&lt;/code&gt; folder, we could issue the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git log --oneline -- important_project | tail -n 1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which would output a shortened commit-id followed by the commit message. What we want here is the commit-id, let&amp;#8217;s say it is &lt;code&gt;DEADBEEF&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, if we do a &lt;code&gt;git diff DEADBEEF&lt;/code&gt; we&amp;#8217;ll see the changes &lt;em&gt;since&lt;/em&gt; the commit-id &lt;code&gt;DEADBEEF&lt;/code&gt;. Since we&amp;#8217;re migrating everything inside &lt;code&gt;important_project&lt;/code&gt; we actually want to &lt;strong&gt;include&lt;/strong&gt; the first commit, so we&amp;#8217;ll be using &lt;code&gt;DEADBEEF^&lt;/code&gt;, which points to the commit before the one we found.&lt;/p&gt;

&lt;h2 id='generating_the_patches'&gt;Generating the Patches&lt;/h2&gt;

&lt;p&gt;Now comes the part where git shines: remember the &lt;code&gt;-- &amp;lt;path&amp;gt;&lt;/code&gt; option we used before? It&amp;#8217;s not explicit on &lt;code&gt;git-format-patch&lt;/code&gt; manpage, but you can use it here too! So creating patches is simply:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git format-patch DEADBEEF^ -o ~/Desktop --relative -- important_project&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&amp;#8217;s understand what&amp;#8217;s going on here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;-o ~/Desktop&lt;/code&gt; option is telling git to write the patches on my Desktop folder. I like to store them there so I don&amp;#8217;t forget to work with them later on.&lt;/li&gt;

&lt;li&gt;The &lt;code&gt;--relative&lt;/code&gt; switch is not really useful with this example, but it&amp;#8217;s useful if you&amp;#8217;re deeply nested inside your repository. This switch will instruct git to not include the full path (from the project&amp;#8217;s root, of course), but to use your relative path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href='http://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html'&gt;manpage for git-format-patch&lt;/a&gt; for some other useful options.&lt;/p&gt;

&lt;h2 id='creating_the_new_repository'&gt;Creating the New Repository&lt;/h2&gt;

&lt;p&gt;You&amp;#8217;ve probably done this before, so I&amp;#8217;ll be quick:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkdir new_project.git
cd new_project.git
git init&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='applying_the_patches'&gt;Applying the Patches&lt;/h2&gt;

&lt;p&gt;This part may get tricky (to understand, that is) if you&amp;#8217;ve generated patches for projects too nested on &lt;code&gt;playground.git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;ve managed a simple git repository before accepting incoming patches from third-parties, you may know the &lt;a href='http://www.kernel.org/pub/software/scm/git/docs/git-am.html'&gt;git am&lt;/a&gt; command. That&amp;#8217;s what we&amp;#8217;ll use, but with a little switch the people coming from the dark ages of VCSes probably know: the &lt;code&gt;-p&amp;lt;NUM&amp;gt;&lt;/code&gt; for relative patching.&lt;/p&gt;

&lt;p&gt;For you fellas who didn&amp;#8217;t have to mess with the &lt;code&gt;patch&lt;/code&gt; command by hand &amp;#8216;till now, a basic explanation of the &lt;code&gt;-p&amp;lt;NUM&amp;gt;&lt;/code&gt; option would be: the number of &amp;#8220;folders&amp;#8221; to go up when applying a patch, so, say a patch diffs the file &amp;#8220;/important_project/file.txt&amp;#8221; but you actually want to apply to &amp;#8220;./file.txt&amp;#8221;, you&amp;#8217;d use &lt;code&gt;-p2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Okay, time for the magic:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git am -p2 ~/Desktop/*.patch&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;#8217;s it. I&amp;#8217;m impressed with git. Again.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Watch out when using Python's urljoin</title>
    <link href="http://caioromao.com/blog/watch-out-when-using-python-s-urljoin/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/watch-out-when-using-python-s-urljoin/</id>
    <updated>2009-10-24T00:00:00+02:00</updated>
    <published>2009-10-24T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Python's urljoin function behaves differently on Python 2.5- and Python 2.6+. This Post describes it's behavior and suggests some measures to avoid future headaches.</summary>
    <content type="html">&lt;p&gt;While implementing some &lt;a href='http://github.com/caio/bizarrice/commit/3d284eb50ad6ba45c7b0f712c3398a1118f54bab'&gt;pinging functions&lt;/a&gt; I&amp;#8217;ve come around a weird behavior of the &lt;code&gt;urljoin&lt;/code&gt; method from &lt;code&gt;urlparse&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# weird_urljoin.py file
from urlparse import urljoin
print urljoin(&amp;#39;http://url.com/pathname&amp;#39;, &amp;#39;?q=joinable&amp;#39;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What do you think will be printed when this code is executed? Whatever you do, you probably wouldn&amp;#8217;t think the following would happen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;python weird_urjoin.py
&amp;quot;http://url.com/?q=joinable&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yeah, while testing if the urls would hit I was building them with &lt;code&gt;urljoin&lt;/code&gt; and getting a 400 status code every request without knowing why - I was actually printing the url I was trying to hit, but the change was so subtle that I didn&amp;#8217;t notice.&lt;/p&gt;

&lt;p&gt;Turns out that this behavior is expected, since the function clearly says it implements the &lt;a href='http://tools.ietf.org/html/rfc1808'&gt;rfc1808&lt;/a&gt; standard (and actually implements the &lt;a href='http://tools.ietf.org/html/rfc2396'&gt;rfc2396&lt;/a&gt;, if we check the implementation).&lt;/p&gt;

&lt;p&gt;Anyway, if you check the RFC I&amp;#8217;ve linked above, you will note that they&amp;#8217;ve both been obsoleted by &lt;a href='http://tools.ietf.org/html/rfc3986'&gt;rfc3986&lt;/a&gt;. So I decided to see if this was &amp;#8220;fixed&amp;#8221; in a newer python version &lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;, and well, it was! (if you&amp;#8217;re going to check it yourself, note that &lt;code&gt;urljoin&lt;/code&gt; is now part of &lt;code&gt;urllib.parse&lt;/code&gt;, which makes a lot more sense).&lt;/p&gt;

&lt;p&gt;After a quick investigation, I came across &lt;a href='http://bugs.python.org/issue1432'&gt;Issue 1432&lt;/a&gt;, which basically goes over all I&amp;#8217;ve just written here.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re a &lt;a href='http://www.python.org/download/releases/2.6.3/'&gt;Python 2.6&lt;/a&gt; user, you may be inclined to say that &lt;code&gt;urljoin(&amp;#39;http://url.com/pathname&amp;#39;, &amp;#39;?q=joinable&amp;#39;)&lt;/code&gt; works alright and it does. On 2.6. On Python 2.5 the result is the same as my first example. Check out this simple test and it&amp;#8217;s output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;try:
    from urlparse import urljoin
except ImportError:
    from urllib.parse import urljoin

print(urljoin(&amp;#39;http://url.com/pathname&amp;#39;, &amp;#39;?q=joinable&amp;#39;))
print(urljoin(&amp;#39;http://url.com/pathname?&amp;#39;, &amp;#39;q=joinable&amp;#39;))

# On Python 2.5.4:
# &amp;gt;&amp;gt;&amp;gt; http://url.com/?q=joinable
# &amp;gt;&amp;gt;&amp;gt; http://url.com/q=joinable
# On Python 2.6.3:
# &amp;gt;&amp;gt;&amp;gt; http://url.com/pathname?q=joinable
# &amp;gt;&amp;gt;&amp;gt; http://url.com/q=joinable
# On Python 3.1.1: &amp;quot;http://url.com/q=joinable&amp;quot;
# &amp;gt;&amp;gt;&amp;gt; http://url.com/pathname?q=joinable
# &amp;gt;&amp;gt;&amp;gt; http://url.com/q=joinable&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The behavior is the same with 2.6 and 3.1, but on 2.5 it get&amp;#8217;s slightly more messed up. It&amp;#8217;d be swell if the fix from Issue 1432 got backported to 2.5 or even better: AppEngine started working based on 2.6, so I&amp;#8217;d finally stop using 2.5. There are some &lt;a href='http://docs.python.org/whatsnew/2.6.html'&gt;great improvements&lt;/a&gt; that I&amp;#8217;d love to use here.&lt;/p&gt;

&lt;p&gt;Okay, what to do if I&amp;#8217;m developing for 2.6 but want to keep compatibility with 2.5? I&amp;#8217;d just use string formatting to join the urls and the parameters. Actually, I think that&amp;#8217;s the best approach even when not keeping compatibility with older versions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;endpoint = &amp;#39;%(url)s?%(data)s&amp;#39; % data_dict&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Seems way more readable to me than:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;endpoint = urljoin(url, &amp;#39;?%(data)s&amp;#39; % data_dict)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we don&amp;#8217;t need to care whether the url is fully-qualified. So, concluding this article, I&amp;#8217;m giving up one of my advices &lt;a href='http://caioromao.com/blog/how-to-read-json-data-from-an-appengine-app/'&gt;posted previously&lt;/a&gt;, at lest when doing quick coding, since you must pay great attention when using &lt;code&gt;urljoin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even with all these considerations, there&amp;#8217;s one thing you must &lt;em&gt;always&lt;/em&gt; do: test. A &lt;strong&gt;LOT&lt;/strong&gt;.&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;I&amp;#8217;ve been messing with &lt;a href='http://www.python.org/download/releases/3.1.1/'&gt;Python 3k&lt;/a&gt; for a long while now and whenever I have to do some quick tests in the interactive console, I go for Python3 instead of &lt;a href='http://www.python.org/download/releases/2.5.4/'&gt;Python 2.5&lt;/a&gt;, which is used on AppEngine. This is sub-optimal, I know, but I get to train my mind for the changes being introduced by the new python version.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Markdown Update</title>
    <link href="http://caioromao.com/blog/markdown-update/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/markdown-update/</id>
    <updated>2009-10-18T00:00:00+02:00</updated>
    <published>2009-10-18T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>An article with thoughts on two Markdown implementations written for Python and what led me to change the one used on Bizarrice blog engine.</summary>
    <content type="html">&lt;p&gt;If you&amp;#8217;re following the &lt;a href='http://github.com/caio/bizarrice/commits/master/'&gt;commit log&lt;/a&gt; for this blog engine, you&amp;#8217;ve probably noted that I&amp;#8217;ve just switched from &lt;a href='http://code.google.com/p/python-markdown2/'&gt;python-markdown2&lt;/a&gt; to the original &lt;a href='http://www.freewisdom.org/projects/python-markdown/'&gt;python-markdown&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a change that I&amp;#8217;ve already discussed with &lt;a href='http://victormblog.appspot.com/'&gt;Victor&lt;/a&gt;, who is a user from the &lt;a href='http://github.com/caio/bizarrice_old/'&gt;old version&lt;/a&gt; of this engine and has been helping me on this one with occasional commits. The main reason for the switch is &lt;em&gt;extendability&lt;/em&gt;. Extending &lt;a href='http://www.freewisdom.org/projects/python-markdown/'&gt;python-markdown&lt;/a&gt; is way easier, and it also comes with a few useful built-in extensions with aren&amp;#8217;t, AFAIK, available on &lt;a href='http://code.google.com/p/python-markdown2/'&gt;python-markdown2&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Abbreviations (I&amp;#8217;ve just used it! :-) tip: It&amp;#8217;s usually in uppercase)&lt;/li&gt;

&lt;li&gt;Definition Lists&lt;/li&gt;

&lt;li&gt;Tables&lt;/li&gt;

&lt;li&gt;Table of Contents (this one is additional, not included in the &amp;#8220;extra&amp;#8221; package)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aside from the extensions provided, it&amp;#8217;s on my plans creating a few hooks to ease the usage of this blog, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Image tag for &lt;strong&gt;uploaded&lt;/strong&gt; images, without the need to provide the full relative path&lt;/li&gt;

&lt;li&gt;LaTeX rendering (I&amp;#8217;ll leave this one for &lt;a href='http://victormblog.appspot.com/'&gt;Victor&lt;/a&gt;, since he&amp;#8217;s the one that suggested it :-)&lt;/li&gt;

&lt;li&gt;Anything that comes to mind&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;ve been seeing an increased usage of &lt;a href='http://code.google.com/p/python-markdown2/'&gt;python-markdown2&lt;/a&gt; in open source projects, and I think it&amp;#8217;s mostly based on it&amp;#8217;s advertised speed compared to the original, and on the fact that it&amp;#8217;s a simple &lt;code&gt;.py&lt;/code&gt; file. Actually, I wouldn&amp;#8217;t advise against it &amp;#8211; It&amp;#8217;s just that I &lt;em&gt;need&lt;/em&gt; to be able to extend it. Also, if you&amp;#8217;re interested in a comparison between both libraries, I&amp;#8217;d suggest reading &lt;a href='http://www.third-bit.com/pages/reviewing-markdown.html'&gt;Reviewing Markdown&lt;/a&gt; by &lt;a href='http://www.third-bit.com/'&gt;Greg Wilson&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Oh, and you may have noted already, but let me say it officially: syntax highlight with &lt;a href='http://pygments.org/'&gt;pygments&lt;/a&gt; was finally enabled.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Ditching PyTz</title>
    <link href="http://caioromao.com/blog/ditching-pytz/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/ditching-pytz/</id>
    <updated>2009-10-11T02:00:00+02:00</updated>
    <published>2009-10-11T02:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Thoughts on Timezone issues on Google AppEngine, the usage of PyTz for l10n support and it's replacement for a web-service providing a Timezone interface.</summary>
    <content type="html">&lt;p&gt;I&amp;#8217;ve just removed &lt;a href='http://pytz.sourceforge.net'&gt;pytz&lt;/a&gt; from this blog.&lt;/p&gt;

&lt;h2 id='the_reasoning'&gt;The Reasoning&lt;/h2&gt;

&lt;p&gt;There are a couple of reasons I&amp;#8217;d like to state:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It is too big.&lt;/li&gt;

&lt;li&gt;Loading the module takes too long.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You may say say we can get around the first issue (taking into account AppEngine&amp;#8217;s 1000-file-limitation) by zipping the &lt;code&gt;zoneinfo&lt;/code&gt; directory and patching the &lt;code&gt;open_resource&lt;/code&gt; function (since the &lt;a href='http://takashi-matsuo.blogspot.com/2008/07/using-zipped-pytz-on-gae.html'&gt;old workaround&lt;/a&gt; doesn&amp;#8217;t work anymore). Doing so brings us to the second issue.&lt;/p&gt;

&lt;p&gt;On my development server, hitting the homepage for the first time would take a few more seconds than what I like to wait when testing small changes and checking the logs it was clear that it got stuck loading the &lt;code&gt;zoneinfo.zip&lt;/code&gt; file. Also, checking the dashboard for this blog one could see some high &lt;em&gt;cputime&lt;/em&gt; raises from time to time and my cpu consumption was growing much faster than expected.&lt;/p&gt;

&lt;h2 id='the_solution'&gt;The Solution&lt;/h2&gt;

&lt;p&gt;Given one of the sayings from software development features best practices: &amp;#8220;Never take away a feature. Ever. Even if your users don&amp;#8217;t use it.&amp;#8221;, I&amp;#8217;ve started browsing for lighter and cheaper alternatives.&lt;/p&gt;

&lt;p&gt;Not long later, I find one of those useful services which I never heard about: &lt;a href='http://github.com/simonw/json-time'&gt;json-time&lt;/a&gt;, which given a timezone, returns it&amp;#8217;s current time. And that&amp;#8217;s decided! Took me a couple of minutes to find out about Django&amp;#8217;s &lt;a href='http://docs.djangoproject.com/en/dev/topics/serialization/'&gt;simplejson&lt;/a&gt;, which is available on AppEngine.&lt;/p&gt;

&lt;h2 id='the_conclusion'&gt;The Conclusion&lt;/h2&gt;

&lt;p&gt;Well, if you check json-time &lt;a href='http://github.com/simonw/json-time'&gt;source code&lt;/a&gt;, you&amp;#8217;ll see that it is a simple service based on &lt;a href='http://pytz.sourceforge.net'&gt;pytz&lt;/a&gt;, so one can say that I&amp;#8217;ve not completely ditched pytz and actually, I was hoping I wouldn&amp;#8217;t.&lt;/p&gt;

&lt;p&gt;Pytz still rocks, but it would be really nice if it was included on AppEngine&amp;#8217;s environment (or a library with the same functionality was added).&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>How to read JSON data from an AppEngine app</title>
    <link href="http://caioromao.com/blog/how-to-read-json-data-from-an-appengine-app/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/how-to-read-json-data-from-an-appengine-app/</id>
    <updated>2009-10-11T12:00:00+02:00</updated>
    <published>2009-10-11T12:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>A short-guide on interacting Google AppEngine based apps with Web Services that use JSON for their response.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I&amp;#8217;ve removed the &lt;code&gt;urljoin&lt;/code&gt; function usage since it &lt;a href='http://caioromao.com/blog/watch-out-when-using-python-s-urljoin/'&gt;does not work as expected&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since I had to figure it out myself, I may as well write it here, so it may help somebody else some day.&lt;/p&gt;

&lt;p&gt;In this post I&amp;#8217;ll write how to fetch and decode json data in an AppEngine application. It is really simple and involves using two modules: &lt;code&gt;simplejson&lt;/code&gt; and &lt;code&gt;urlfetch&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from django.utils import simplejson
from google.appengine.api import urlfetch&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Following best practices, and to avoid issues with joining two urls, we&amp;#8217;ll use the &lt;code&gt;urljoin&lt;/code&gt; method from &lt;code&gt;urlparse&lt;/code&gt; and &lt;code&gt;urlencode&lt;/code&gt; from &lt;code&gt;urllib&lt;/code&gt; and enable logging:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import logging
# urljoin follows rfc1808 and doesn&amp;#39;t work as a human would expect
# from urlparse import urljoin
from urllib import urlencode&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For this example, I&amp;#8217;ll use the &lt;a href='http://json-time.appspot.com'&gt;json-time&lt;/a&gt; service cited on my previous post, but it should work with any service which returns json data as content for requests.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SERVICE_ENDPOINT = &amp;#39;http://json-time.appspot.com/time.json&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To use &lt;a href='http://json-time.appspot.com'&gt;json-time&lt;/a&gt;, you must pass a &lt;code&gt;tz&lt;/code&gt; element as GET parameter, like &lt;code&gt;tz=America/Sao_Paulo&lt;/code&gt;. So let&amp;#8217;s build our url:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;encoded_data = urlencode({&amp;#39;tz&amp;#39;: &amp;#39;America/Sao_Paulo&amp;#39;})
# url = urljoin(SERVICE_ENDPOINT, encoded_data)
url = &amp;#39;%s?%s&amp;#39; % (SERVICE_ENDPOINT, encoded_data)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might be wondering why not just write the full url (&lt;code&gt;http://json-time.appspot.com/time.json?tz=America/Sao_Paulo&lt;/code&gt;) instead of messing around with all those libs. Well, in this case, it&amp;#8217;d really be easier, but consider a more complex service with many options, or one which would return the options after a first request. Using those modules makes it all more flexible and less human-error prone.&lt;/p&gt;

&lt;p&gt;Now we&amp;#8217;ll use google&amp;#8217;s &lt;code&gt;urlfetch&lt;/code&gt; to fetch our properly built url and check it&amp;#8217;s results:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;result = urlfetch.fetch(url)
if result.status_code != 200
    # Boo! It didn&amp;#39;t work
    logging.error(&amp;#39;json-time returned unexpected status code: %d&amp;#39;
                % result.status_code)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we&amp;#8217;ll create a JSON decoder and try to read the data:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;else:
    received_content = result.content
    json_decoder = simplejson.decoder.JSONDecoder()
    try:
        decoded_json = json_decoder.decode(received_content)
    except ValueError:
        logging.error(&amp;quot;json-time sent data which simplejson couldn&amp;#39;t parse&amp;quot;)
    else:
        logging.debug(&amp;#39;Decoded JSON from json-time: %s&amp;#39; % str(decoded_json))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;#8217;s it! You&amp;#8217;ll see on your app&amp;#8217;s console whether things worked alright or not &lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;. If it all went well, you&amp;#8217;ll be able to verify that &lt;code&gt;decoded_json&lt;/code&gt; is simply a &lt;code&gt;dict&lt;/code&gt; like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;decoded_json = {
    &amp;quot;tz&amp;quot;: &amp;quot;America\/Sao_Paulo&amp;quot;,
    &amp;quot;hour&amp;quot;: 1,
    &amp;quot;datetime&amp;quot;: &amp;quot;Sun, 11 Oct 2009 01:42:48 -0200&amp;quot;,
    &amp;quot;second&amp;quot;: 48,
    &amp;quot;error&amp;quot;: false,
    &amp;quot;minute&amp;quot;: 42
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using it is quite straigtforward and is completelly up to you. Hope it helped :)&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;I didn&amp;#8217;t really test this whole code in production, but I&amp;#8217;m using a variation of it for this blog - you can check it &lt;a href='http://github.com/caio/bizarrice/blob/master/filters.py'&gt;here&lt;/a&gt;, in the &lt;code&gt;tz_date&lt;/code&gt; filter.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Bazaar Weirdness</title>
    <link href="http://caioromao.com/blog/bazaar-weirdness/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/bazaar-weirdness/</id>
    <updated>2009-07-24T00:00:00+02:00</updated>
    <published>2009-07-24T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Complaints about Bazaar behavior and how slow it's been for me while developing the Bugzilla back-end for Ubuntu's Apport.</summary>
    <content type="html">&lt;p&gt;As you know (or at least should, if you read this blog), part of my work on Summer of Code involves hacking around Ubuntu&amp;#8217;s &lt;a href='http://launchpad.net/apport'&gt;Apport&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve just finished implementing the credentials API I&amp;#8217;ve submitted earlier (another branch merged, yay!) on the Bugzilla back-end and found myself with a weird issue related to the repository format. I didn&amp;#8217;t delve much on it, but it seems the upstream branch has migrated to a new format (to support bzr-svn and bzr-git, I guess) and now I have to migrate my branch in order to merge the changes from mainstream.&lt;/p&gt;

&lt;p&gt;This kind of issue is a real turn-down for me. I may be doing something wrong, but in my opinion this should &lt;strong&gt;never&lt;/strong&gt; happen, even more with Bazaar, which - like Mercurial - advocates a &amp;#8220;sane&amp;#8221; UI. I&amp;#8217;ve never had a single issue merging/rebasing/branching using either git nor hg, and I&amp;#8217;ve been using both for quite a while now.&lt;/p&gt;

&lt;p&gt;Nevertheless, this post is just a quick rant. I&amp;#8217;ve issued &lt;code&gt;bzr upgrade --rich-root-pack /path/to/remote/branch&lt;/code&gt; and it&amp;#8217;s already transferred 60MiB. For a format upgrade. And there is no option to disable the backup &amp;#8220;feature&amp;#8221;. How fucked up is that?&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m about to abort the upgrade and create a new branch, ignoring the historical value of the prior commit messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: The upgrade finished after \~75MiB (It erased the line when completed, so I didn&amp;#8217;t see the final value). I&amp;#8217;m just too afraid to do a &lt;code&gt;bzr get&lt;/code&gt; on my branch now to check if this upgrade reflected on the repository size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I&amp;#8217;ve just run a &lt;code&gt;bzr get&lt;/code&gt; and the download size was \~6.2MiB more than three times what it used to be.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>GSoC Midterm Roundup</title>
    <link href="http://caioromao.com/blog/gsoc-midterm-roundup/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/gsoc-midterm-roundup/</id>
    <updated>2009-07-13T00:00:00+02:00</updated>
    <published>2009-07-13T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Status report for the midterm evaluation period for Google Summer of Code 2009.</summary>
    <content type="html">&lt;p&gt;That&amp;#8217;s it. The midterm evaluation week is gone (actually, there are a few hours left, but it&amp;#8217;s gone for me, at least).&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m writing this up while I wait for my Univ&amp;#8217;s restaurant to open and it&amp;#8217;s quite cold here - I&amp;#8217;d usually like it if it weren&amp;#8217;t for my lack of sleep (too-much-coffe), I guess.&lt;/p&gt;

&lt;p&gt;So far I&amp;#8217;ve been on schedule, even though I feel like I could be way ahead of it if it weren&amp;#8217;t for some unexpected issues that came up.&lt;/p&gt;

&lt;p&gt;Well, the Bugzilla back-end has progressed little since last week: it&amp;#8217;s feature complete, but it needs a log-in mechanism which is on the way as I discuss with &lt;a href='http://martinpitt.wordpress.com/'&gt;Martin Pitt&lt;/a&gt; the best way to do it. PyBugz is going steady, I&amp;#8217;ve a new feature for reading cookies from the most common browsers (Firefox and Chrome at the time being) uncomitted yet - What worries me is the lack of response from PyBugz maintainer/author.&lt;/p&gt;

&lt;p&gt;On to following my schedule for the last term, I&amp;#8217;ve began mocking up (on paper) some user interfaces for the stand-alone bug reporting tool, which will probably use PyBugz and maybe fire-up apport when the user is reporting an application crash. I still haven&amp;#8217;t decided which way to go: power or simplicity. The best would be to put both together but it is quite hard to think of an intuitive user interface being a command-line addict myself.&lt;/p&gt;

&lt;p&gt;As always, I&amp;#8217;ll end promising to post more frequently, but I can&amp;#8217;t promise to keep my promise :)&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>GSoC Project Status</title>
    <link href="http://caioromao.com/blog/gsoc-project-status/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/gsoc-project-status/</id>
    <updated>2009-06-19T00:00:00+02:00</updated>
    <published>2009-06-19T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Status report for my Summer of Code project, with references to bazaar branches and git forks.</summary>
    <content type="html">&lt;p&gt;I haven&amp;#8217;t been using this blog to report my status on Summer of Code. Well, actually, I haven&amp;#8217;t been using this blog at all.&lt;/p&gt;

&lt;p&gt;So, um, okay&amp;#8230; I&amp;#8217;ll write what I&amp;#8217;ve been doing. That&amp;#8217;ll basically be a modified status report I sent to my mentor sooner.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Bugzilla back-end is finally feature complete! Every test (ported from Launchpad back-end) is passing when testing with 3.0 and 3.2 Bugzilla instances.&lt;/li&gt;

&lt;li&gt;To integrate Apport on Pardus, we&amp;#8217;re gonna need a &lt;a href='http://www.pardus.org.tr/eng/projeler/pisi/index.html'&gt;PiSi&lt;/a&gt; back-end implementation. Luckily, PiSi is written in python and it&amp;#8217;s interface is quite well defined, so I already have a partially working version. Finishing it shoudn&amp;#8217;t take as long as the Bugzilla back-end took.&lt;/li&gt;

&lt;li&gt;To correctly act when requested, I had to &lt;a href='http://github.com/caio/pybugz'&gt;fork PyBugz&lt;/a&gt; fixing some issues (check the &lt;a href='http://github.com/caio/pybugz/commits/master/'&gt;revision history&lt;/a&gt;, if interested) and implementing a new feature to modify attachments. The reason I forked it was due to the lack of reply from PyBugz original author - but since his branch is on GitHub too, I&amp;#8217;ve made a pull request, so my changes can get upstream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Talking about upstream, while testing the Bugzilla back-end, I&amp;#8217;ve talked to apport&amp;#8217;s maintainer regarding a python-apt API change issue, which culminated in &lt;a href='https://code.launchpad.net/~caioromao/apport/new-python-apt-version/'&gt;one of my branches&lt;/a&gt; being &lt;a href='http://bazaar.launchpad.net/~apport-hackers/apport/trunk/revision/1467'&gt;merged upstream&lt;/a&gt;. So that&amp;#8217;s actually my first real code contribution to a successfull open source project. Cool, huh? :)&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Sobre Brigas e Pirraças</title>
    <link href="http://caioromao.com/blog/sobre-brigas-e-pirracas" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/sobre-brigas-e-pirracas</id>
    <updated>2009-06-05T00:00:00+02:00</updated>
    <published>2009-06-05T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Divagações sobre a apatia brasileira e a fraqueza da atual força jovem revolucionária.</summary>
    <content type="html">&lt;p&gt;I&amp;#8217;d like to apologise to my English readers. The following post is completely in Portuguese (from Brazil) and I won&amp;#8217;t bother translating it since it&amp;#8217;s about issues in this country. Perhaps an &lt;a href='http://goo.gl/RjrCv'&gt;automated translation&lt;/a&gt; will help you if you&amp;#8217;re really interested.&lt;/p&gt;

&lt;p&gt;É comum ouvir em meio acadêmico que a &amp;#8220;geração coca-cola&amp;#8221; é mais acomodada, não luta por seus direitos e é extremamente individualista. Culpa-se, claro, nossa herança maldita, o meio em que nos desenvolvemos, a espelho de uma cultura extremamente consumista e apática.&lt;/p&gt;

&lt;p&gt;Apesar de acreditar que há sim uma parcela de &amp;#8220;culpa&amp;#8221; na desculturalização que vem ocorrendo, culpar somente isso, muitas vezes com algumas pitadas de teoria da conspiração, é errôneo.&lt;/p&gt;

&lt;p&gt;A massa de descontentes é notável. Basta visitar fóruns on-line sobre assuntos diversos que sempre há uma série de mensagens de insatisfação política - muitas delas pessimamente argumentadas e/ou infundadas, de fato, porém não é isso que importa. Saindo do meio da Internet, é só conversar com qualquer desconhecido que logo surge um assunto sobre o governo e o quanto ele está ruim ultimamente - não importa o ano nem a pessoa que está no poder.&lt;/p&gt;

&lt;p&gt;A &amp;#8220;geração atual&amp;#8221; perde muito seu tempo discutindo os problemas nacionais em fóruns de discussão, assinando petições on-line, encaminhando e-mails esclarecedores a seus amigos. Então, por quê nada acontece?&lt;/p&gt;

&lt;p&gt;A revolta e a revolução são vítimas da modernização. Os meios de comunicação evoluíram, mas as formas de fazer-se ouvir quando o alvo pouco se importa continua a mesma. Organiza-se um &lt;a href='http://pt.wikipedia.org/wiki/Flash_mob'&gt;FlashMob&lt;/a&gt; com centenas de pessoas em instantes, mas parece impossível reunir estudantes indignados para protestar contra o aumento absurdo das tarifas de Ônibus.&lt;/p&gt;

&lt;p&gt;Não é culpando a internet que faremos os gordinhos tetudos (afinal, quem frequenta fóruns on-line só pode ser gordo, não é mesmo?) levantarem-se e brigarem por seus direitos. A mídia mudou, os interesses mudaram, será que não é hora de o recrutamento mudar? - o que está enferrujado é a &amp;#8220;massa revolucionária&amp;#8221;, a força estudantil, que se precariza a cada ano com o excesso de politicagem, inúmeros jogos de interesse e influência partidária, que luta contra o &amp;#8220;imperialismo norte-americano&amp;#8221;, mas nem olha ao seu redor para ver o chiqueiro em que estão fazendo todo alvoroço.&lt;/p&gt;

&lt;p&gt;Deve-se lembrar que não é preciso concordar em tudo para que se lute em conjunto por uma causa e que hoje em dia temos acesso a um volume de informação absurdo, de forma que torna-se difícil confiar em qualquer organização. Não se briga por um plano completo, por uma pauta política, por um partido. Luta-se por mudança.&lt;/p&gt;

&lt;p&gt;Não entrarei nos (poucos) méritos da democracia, pois é uma área perigosa e cheia de pessoas com facas nas mãos e gigantescos dedos indicadores para lhe apontarem e rotularem com algum substantivo qualquer. O fato é que, no meio em que vivemos, jamais haverá uma idéia em uníssono, portanto reitero: lute por mudança, não por um ideal completo de quinhentas páginas. Se a mudança só piorou as coisas, lute novamente.&lt;/p&gt;

&lt;p&gt;Estamos recheados de derrotismo e egoísmo. Não importa de quem é a culpa, mas sim como e quando vamos mudar isso.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Branch Published!</title>
    <link href="http://caioromao.com/blog/branch-published/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/branch-published/</id>
    <updated>2009-05-24T00:00:00+02:00</updated>
    <published>2009-05-24T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>A quick note regarding the publishing of my Summer of Code modifications for apport into a public branch on Launchpad.</summary>
    <content type="html">&lt;p&gt;As promissed: I&amp;#8217;ve just published my branch from apport on Launchpad, &lt;a href='https://code.launchpad.net/~caioromao/apport/pardus-bugzilla'&gt;check it here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since I wasn&amp;#8217;t working directly on a bazaar branch, my first commit was quite a big blob (and I even forgot to pull from uptream before publishing) - I&amp;#8217;ll try to keep the next ones short and concise.&lt;/p&gt;

&lt;p&gt;A new task has appeared when I started coding the Bugzilla crash database for apport: I&amp;#8217;ll need to write a a PiSi backend for it to query for package info. There&amp;#8217;s already a preliminary working version of it thanks to the amazingly well-written and well-organized PiSi source code.&lt;/p&gt;

&lt;p&gt;Not much more to write about right now - The coding phase has officially stated but due to this new task I&amp;#8217;ve described, I&amp;#8217;m way behind what I expected, even though I&amp;#8217;m a bit advanced if compared with my official-and-private tasklist.&lt;/p&gt;

&lt;p&gt;As a reference: most of my commits will probably flow on weekends, tuesdays and fridays since that&amp;#8217;s when I have a little extra free time ;)&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Coding phase: START!</title>
    <link href="http://caioromao.com/blog/coding-phase-start/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/coding-phase-start/</id>
    <updated>2009-05-14T00:00:00+02:00</updated>
    <published>2009-05-14T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Kick-off post about my initial work for Google Summer of Code and the Pardus organization.</summary>
    <content type="html">&lt;p&gt;Actually, the official coding phase is scheduled to start on 23rd, but I decided to start a bit earlier since I don&amp;#8217;t have much free time.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve finally decided to go with &lt;a href='https://wiki.ubuntu.com/Apport'&gt;Apport&lt;/a&gt; and somehow follow the steps from my &lt;a href='http://caioromao.com/blog/on-summer-of-code/'&gt;original proposal&lt;/a&gt;. So now I&amp;#8217;ll be officially using three of the most well-known &lt;a href='http://en.wikipedia.org/wiki/Distributed_revision_control'&gt;DVCSs&lt;/a&gt;: &lt;a href='http://git-scm.org'&gt;git&lt;/a&gt;, &lt;a href='http://mercurial.selenic.com'&gt;mercurial&lt;/a&gt; and now Bazaar.&lt;/p&gt;

&lt;p&gt;The initial work is fairly simple since Apport is quite well modularized, so I expect to finish it before the oficial &amp;#8220;Coding Phase&amp;#8221; starts. As usual, when I decided to start working some problems started showing up (exams and projects scheduled for next week, new assignments, the flu), so all I could do up untill now was set-up a testing environment, play around with python-bugzilla functionalities and get to understand how apport will manage multiple crashdb implementations.&lt;/p&gt;

&lt;p&gt;I have yet to lean how to properly contribute using Bazaar, but it seems to be fairly easy. So, whenever I set-up a branch with my code I&amp;#8217;ll update here.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>On Summer of Code</title>
    <link href="http://caioromao.com/blog/on-summer-of-code/" rel="alternate" type="text/html"/>
    <id>http://www.caioromao.com/blog/on-summer-of-code/</id>
    <updated>2009-04-27T00:00:00+02:00</updated>
    <published>2009-04-27T00:00:00+02:00</published>
    <author>
      <name>Caio Romão</name>
      <email>caio@romao.me</email>
      <uri>http://caioromao.com</uri>
    </author>
    <summary>Google Summer of Code 2009 accepted proposal for creating a Bug Reporting System on KDE for the Pardus Linux Organization.</summary>
    <content type="html">&lt;p&gt;&amp;#8230; finally!&lt;/p&gt;

&lt;p&gt;The reason that made me try blogging again was my acceptance as a student on Summer of Code, so I guess I should be talking about it here.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll be working with &lt;a href='http://www.pardus.org.tr/eng/'&gt;Pardus&lt;/a&gt; folks with a project entitled &amp;#8220;Bug Reporting Tool for KDE4&amp;#8221;. I&amp;#8217;ll post the original proposal here, but bear in mind that we&amp;#8217;re in the middle of a discussion about what path to take given KDE&amp;#8217;s drKonqi &lt;a href='http://osdir.com/ml/general/2009-04/msg05544.html'&gt;current state&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='project_abstract'&gt;Project Abstract&lt;/h2&gt;

&lt;p&gt;A KDE 4 application to help non-technical users diagnose and report bugs and issues. This application will provide the following: a simple template-based bug-reporting assistant, a GUI front-end for crash reporting on Bugzilla and a &amp;#8220;Hardware Test&amp;#8221; wizard to check basic computer functionality.&lt;/p&gt;

&lt;p&gt;There are two notable projects that strive this functionality: &lt;a href='https://wiki.ubuntu.com/Apport'&gt;Apport&lt;/a&gt; and &lt;a href='https://fedorahosted.org/abrt/wiki'&gt;abrt&lt;/a&gt;. This project&amp;#8217;s goal is to improve on the usability and portability of either and further extend it to fill Pardus&amp;#8217;s view of the issue.&lt;/p&gt;

&lt;h2 id='project_detailed_description'&gt;Project Detailed Description&lt;/h2&gt;

&lt;p&gt;Based on the high-level description of the &lt;a href='http://en.pardus-wiki.org/SummerOfCode2009Ideas#Bugzilla_Applet_for_KDE4'&gt;idea&lt;/a&gt;, this project would involve the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decide which existing solution (Apport or abrt) is the most suitable.&lt;/li&gt;

&lt;li&gt;Develop a Bugzilla back-end if necessary.&lt;/li&gt;

&lt;li&gt;Define the simple Bug Report tool functionality: wizard-like interface or a simple dialog which would search for patterns on the text and suggest the inclusion of command dumps and configuration files (which would happen automatically).&lt;/li&gt;

&lt;li&gt;Create a simple front-end for the chosen crash handler with passive or intrusive behavior depending on the severity and user-configuration.&lt;/li&gt;

&lt;li&gt;Integrate the crash handler on Pardus.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, the whole proccess would be documented through a personal weblog and, if given the time, the creation of a &amp;#8220;Hardware Testing&amp;#8221; wizard would be studied and implemented.&lt;/p&gt;

&lt;p&gt;Given the steps defined above and some superficial study of the available solutions, I&amp;#8217;ve come up with some decisions (subject to changes after some discussion with the project mentor) which I enumerate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose Apport over abrt: Apport seems to have a more mature code base, mostly due to have been deployed on Ubuntu for a long time; It&amp;#8217;s modular interface and the fact that it&amp;#8217;s coded in Python would greatly improve the data-handling and development process.&lt;/li&gt;

&lt;li&gt;Develop the simple bug reporting tool first, mostly due to the fact that it would help testing the bugzilla backend.&lt;/li&gt;

&lt;li&gt;Use &lt;a href='https://fedorahosted.org/python-bugzilla/'&gt;python-bugzilla&lt;/a&gt; to develop a crashdb implementation of Bugzilla for Apport.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even though I&amp;#8217;ve attended to an Human-Computer Interaction course, I&amp;#8217;m no usability expert, so the GUI-related parts would probably involve a bunch of mock-ups and at least one brainstorming session do decide which path to follow.&lt;/p&gt;</content>
  </entry>
</feed>
