Show the current git branch in your bash prompt

November 23rd, 2011

I stole the following code off the internet some time ago and now I can't live without it. It's a hack that make your bash prompt show which git branch you are in in its prompt, by setting the PS1 variable. If you are in a subdirectory of a cloned git project, your prompt will show the current branch, and depending on its color, whether you have uncommitted changes or not. It also shows the return code of the last executed shell command if different from 0.



#
# lots of blurb to show git status in prompt
#

function parse_git_branch() {
   local rc=$?

   if git rev-parse --git-dir >/dev/null 2>&1 ; then
      echo -ne $(git branch 2>/dev/null | sed -n '/^\*/ s/^\* //p') ; fi

   return $rc
}

function git_color() {
   local rc=$?
   if git rev-parse --git-dir >/dev/null 2>&1 ; then
      if git diff --quiet 2>/dev/null >&2 ; then
         if git diff --quiet --cached 2>/dev/null >&2 ; then
            tput setf 2
         else tput setf 6 ; fi
      else tput setf 4 ; fi ; fi
   return $rc
}

function git_prompt() {
   local rc=$?

   if git rev-parse --git-dir >/dev/null 2>&1 ; then
      local branch=$(git branch 2>/dev/null| sed -n '/^\*/s/^\* //p')
      local hist="origin/$branch...$branch"
      local ahead=$(git log --no-color --oneline -- $hist | wc -l)

      echo -n "[$branch"
      if (($ahead > 0)); then tput setf 1; echo -n "+${ahead}"; fi
      echo -n "]"
   fi
   return $rc
}

function ret_color {
   local rc=$?
   if [ $rc -gt 0 ] ; then tput setf 6; fi
   return $rc
}

function ret_code {
   local rc=$?
   if [ $rc -gt 0 ] ; then echo -ne " (rc:${rc})"; fi
   return $rc
}

PCOL=0
PS1=""
PS1="${PS1}\[\e[${PCOL}m\]"
PS1="${PS1}\u@\h:\w"
PS1="${PS1}\[\$(git_color)\]\$(git_prompt)\[\e[0;${PCOL}m\]"
PS1="${PS1}\[\$(ret_color)\]\$(ret_code)\[\e[0;${PCOL}m\]"
PS1="${PS1} \\$\[\e[0m\] "

Metaprogramming with Python

October 28th, 2011

The problem: I want to redefine some methods in a class and replace them with a methods that do the same (ie call the original method) plus a little more. Basically I want decorators, but without having to actually decorate :-)

Here is an answer:


import unittest
import re
import inspect

class VerboseTestCase(unittest.TestCase):
   '''Make all assertX methods verbose by default'''

   def __init__(self, *args, **kargs):
      unittest.TestCase.__init__(self, *args, **kargs)

      # A decorator creator that makes f verbose
      def make_verbose(f):
         def wrapper(*args):
            # TODO: print only if args[-1] is a string
            print "Assert: %s" % args[-1]
            return f(*args)
         return wrapper

      # Redefine all methods whose name starts with assert.*
      for name in dir(unittest.TestCase):
         obj = getattr(unittest.TestCase, name)
         if (inspect.ismethod(obj) or inspect.isfunction(obj)):
            if re.match('^assert[a-zA-Z]*$', name):
               setattr(VerboseTestCase, name, make_verbose(obj))

class Tests(VerboseTestCase):

   def test_foo(self):
      self.assertTrue(1, 'Testing 1 is true')


The beauty of it is the way calling 'make_verbose' localizes the value of the variable f into the scope of each instance of 'wrapper'. Of course, in Perl, that trick would not have been necessary: anonymous functions get localized variables by default, even when they were created outside of the scope of the function...

Output TAP while running debuild

June 16th, 2011

Warning: what follows is arcane knowledge, but since I could not find a straight answer to it when googling around I thought it worth writing a dedicated entry for it.

The situation: I am building a debian package using debuild. The package itself is mostly a perl module with a Makefile.PL, surrounded by debian/* files generated by dh-make-perl. When running debuild, the perl tests are executed and their result displayed in short format to stdout (what you see when running 'prove' or 'make test').

The problem: I want to see the perl tests' output in TAP format when running debuild. Because higher up in the continuous integration server, I have a TAP parser that will interrupt the build script if it sees test failing.

One solution: set the TEST_VERBOSE variable to 1 in the Makefile generated by 'perl Makefile.PL'. To do that, alter your Makefile.PL to look something like:


#!/usr/bin/perl

use 5.8.0;

use strict;
use warnings;

use ExtUtils::MakeMaker;

WriteMakefile(
   NAME => "module_name",
   ABSTRACT => '',
   VERSION_FROM => 'some/file',
   PREREQ_PM => { # some modules
   },
   AUTHOR => 'me ',
);

# Here comes the ugly magic: we let MakeMaker generate the Makefile for us but
# hijack the part of the Makefile defining the test targets and set the
# TEST_VERBOSE flag in it.

package MY;

sub test {
   package MY; # so that "SUPER" works right
   my $inherited = shift->SUPER::test(@_);
   $inherited =~ s/TEST_VERBOSE=0/TEST_VERBOSE=1/;
   $inherited;
}



Now, this solution is not optimal since it affects the behavior of 'make test' even when not running debuild. A more appropriate solution would have been to set the TEST_VERBOSE variable from the debian/rules file but I just couldn't find a way to do it :-)

At last!

June 14th, 2011

At last! A graphical editor for pure ascii charts :-)
http://www.asciiflow.com

The cost of technical debt

March 22nd, 2011

I was doing a bit of research lately on the issue of 'technical debt'. This post will just summarize some of the more interesting things I came across.

Of first interest was a classification written by Jimmy Janlen identifying 4 kinds of technical debt:

* Programming debt: The debt induced by low quality code, poorly written, redundant, fragile to change or side cases, not self-explaining, etc.

* Design debt: bad or no design. Unflexible architecture. Unclear or lack of layering in the application. Spaghetti plate of classes and modules. Hard to understand and build upon.

* Test debt: when parts of the application haven't been tested well enough. Unknown test coverage. When failed tests do not necessarily indicate fault in the application.

* Knowledge debt: when there is isolated and undocumented knowledge. No comments in the code. No learning from previous mistakes. Isolated knowledge typically create bottle necks. New team members have a harder time becoming productive. Troubleshooting is a pain in the ass.

An interesting fact about technical debt is that payback time comes with a high interest rate. The longer you wait to level the debt, the more exponentially expensive it gets, until you reach a point of non-return at which payback is no longer technically possible. That's when your software decays :-)

The accepted best practice when handling technical debt is, just as in finance, to accumulate as little of it as possible and to pay it back quickly.

Building on that, some people tried to estimate the cost of technical debt. As nearly all time or cost estimation techniques applied to software development, that one should be taken with a pinch of salt.

Egoless programming

February 19th, 2011

I keep getting hurt at work because I put too much of my self into the code I write. Lately, I stumbled upon the ten commandments of egoless programming. They have been around for a while, since the seventies in fact, almost an eternity for the computer age, but they are still strikingly relevant. Here they are, once more reproduced to spread the wisdom:

1. Understand and accept that you will make mistakes.

2. You are not your code.

3. No matter how much "karate" you know, someone else will always know more.

4. Don't rewrite code without consultation.

5. Treat people who know less than you with respect, deference, and patience.

6. The only constant in the world is change. Be open to it and accept it with a smile.

7. The only true authority stems from knowledge, not from position.

8. Fight for what you believe, but gracefully accept defeat.

9. Don't be "the guy in the room."

10. Critique code instead of people -- be kind to the coder, not to the code.

For a more detailed description of each commandment, have a look at http://www.codinghorror.com/blog/2006/05/the-ten-commandments-of-egoless-programming.html.

Reverse-engineering the oyo ereader

December 12th, 2010

I bought an oyo ebook reader a few weeks ago. This reader has recently appeared on the market in many countries across Europe and comes bound to a webshop (chapitre.com, thalia.de, you name it), a bit like the amazon kindle.

I chose the oyo for its hardware and its design, so I wasn't strongly surprised (nor disappointed) to find the preloaded software quite buggy and lacking many features. But the oyo has a few great advantages: it runs linux, its kernel has been made available, it can start with a serial console over usb and its firmware is really easy to upgrade.

All that makes a great combination: you can modify the latest firmware and add a user with root privileges and a known password, log with this user over the serial usb console and dive into the live ereader :-) Debian binaries are available pre-compiled for this architecture so you can even install a good bunch of things. An ssh server for example ;-)

And if your oyo gets sick after an os upgrade, you can still flash it again with a more stable firmware! The thing is practically impossible to brick!

The result: in just a few weeks, people around Europe have started reverse engineering the oyo. Most of the information is currently available on Frank Wallenwein's wiki at http://www.fwma.de/pmwiki/pmwiki.php?n=Main.OYO, to which I have contributed a number of edits.

I recently replaced the original os of my oyo (from chapitre.com) with the latest Thalia upgrade in order to be able to gain root access on it, using one of the methods listed on Frank's site.

I have been roaming into the oyo's runtime a while and came upon the file /rwdata/settings/QBookApp.ini, which contains parameters that customize the oyo's main application (QBookApp is what you see and interact with when the oyo is turned on).

So now I got a very personal oyo front page, without any webshop icon eating up half of my screen space :-)



Ok, it's not impressive, but that wasn't the point. It's just for fun, really!

The art of commit messages

December 10th, 2010

A beautiful peace of wisdom on how to write good commit messages:
http://who-t.blogspot.com/2009/12/on-commit-messages.html

"Any software project is a collaborative project. It has at least two developers, the original developer and the original developer a few weeks or months later when the train of thought has long left the station.
[...]
a commit message shows whether a developer is a good collaborator"

And another one on the same topic: http://wildbit.com/blog/2008/11/11/the-importance-of-commit-messages/

"Without good communication skills you're nothing but a lone 'hacker' doing stuff for yourself."

Writing a universal test runner with Test::Harness

August 26th, 2010

Perl comes with a fantastic tool: prove. Prove searches for all the test files under a directory, runs them and reports the results. Anyone used to developing code and tests in parallel ends up running prove all the time, or at least after every code change. It is also an essential component of a continuous integration setup for perl projects.

Yet, through my years of addicted prove usage, I have encountered two limitations with it:

* by default, prove does not support running more than one type of test file. It can run perl test files ending with .t, or it can run python tests with the appropriate Test::Harness source handler, or pgTAP test with yet another source handler, and so on as long as the test script outputs TAP. But you can't have one project containing both perl, python and pgTAP tests and run prove to execute all of them at once.

* a need often arises for doing some generic pre- and post-execution setup around the executed tests (such as initializing a database or kicking up a daemon). It would be very nice to make prove handle that in some way instead of having to explicitly handle it in every test file.

As of version 3.22 of Test::Harness (the latest at the time of writing), those limitations are gone. It is now possible to write a universal test runner based on prove and Test::Harness. The code below does just that:


package TAP::Parser::SourceHandler::Universal;

use strict;
use warnings;
use Data::Dumper;
use Carp qw(confess);

use TAP::Parser::IteratorFactory ();
use TAP::Parser::Iterator::Process ();
use TAP::Parser::SourceHandler::pgTAP;

use base qw( TAP::Parser::SourceHandler );
TAP::Parser::IteratorFactory
   ->register_handler(__PACKAGE__);

# We handle everything :-)
sub can_handle { return 1 }

# Dispatch to the right kind of iterator,
# depending on what file it is
sub make_iterator {
   my ( $class, $source ) = @_;

   confess "Source is not a file"
      unless $source->meta->{is_file};

   my $ext = $source->meta->{file}{lc_ext};
   my $file = ref $source->raw ? ${ $source->raw } : $source->raw;

   # Do some test setup here. May be parse
   # some optional metadata in the test file
   # header, and apply the corresponding setup?

   # Look at the file's extension
   if ($ext eq '.pg') {

      # This is a pgTAP test file.
      # Return a source handler for pgTAP
      # that connects to our local test
      # database
      $source->{config}->{pgTAP} = {
         username => 'foo',
         host => '127.0.0.1',
         port => 5432,
         dbname => 'test',
      };

      return TAP::Parser::SourceHandler::pgTAP::make_iterator( $class, $source );

   } elsif ($ext eq '.t') {

      # This is a standard perl test file...
      return TAP::Parser::Iterator::Process->new({
         command => [ 'perl', $file ],
         merge => $source->merge
      });

   } else {
      confess "Do not know how to handle ".
         "test file $file of type $ext";
   }
}

END {
   # Cleanup after the tests
}

42;


The code above is basically a custom TAP source handler that says it supports any kind of test file (though it does not really) and just returns a native TAP source handler when passed a perl or pgTAP test file.

To run prove with this Universal source handler on all files ending with .t or .pg, just do:


$ prove --source Universal --ext .t --ext .pg


Now, this is just a skeleton: you will have to flesh it up according to your specific needs and to add support for more file formats. But it does what I needed: it let me define a TAP source handler for every type of test file I want to support and it gives me a place where to do some setup/cleaning before and after running every test file. From there on, the sky is the limit :-)

Timestamps in bash

February 16th, 2010

This is common knowledge but I found it so useful that I have to make sure it spreads even more :)

You can make bash register timestamps in its history:


export HISTTIMEFORMAT='[%F %T] '


And you can even alter the bash prompt to show timestamps as well, using the variable PROMPT_COMMAND:


export PROMPT_COMMAND="echo -n \[\$(date +%H:%M:%S)\]\ "


Voila! No more problem trying to figure out when things happened and how long time they took.

Of course, those 2 lines should be added to your ~/.bash_profile or equivalent for persistence.