Overriding Drush make

Seems that Drush make is becoming the way to build distributions and sites. Especially the ability to use recursive make files to let each module pull in it's own dependencies allows for compartmentalisation of things is handy.

However, some times it can get a bit in the way of thing. Picture this:

We're building a distribution which consists of a lot of, more or less optional, modules, which all pull in their dependencies using make files, whether it's contrib modules or our own. For everybodys sanity, they're all specifying specific versions of their dependencies.

It's a bit of a bitch when developing, however. Developers just want the bleeding edge of all modules, not the latest stable release, and up until now it meant doing a git checkout master in each repository.

But Drush make has a hook that makes things easier. There's a hook_drush_make_validate_info() that will get the parsed info file, and can return a new version. So I added the following function into an existing drush command file:

  1. /**
  2.  * Implements hook_drush_make_validate_info
  3.  */
  4. function ding2_utils_drush_make_validate_info($info) {
  5.   if (drush_get_option('ding2-dev', FALSE)) {
  6.     drush_log(dt("Checking out HEAD revisions of Ding 2 repositories."), 'ok');
  7.  
  8.     foreach ($info['projects'] as $name => &$spec) {
  9.       // Only consider git repositories.
  10.       if (!empty($spec['download']['type']) && $spec['download']['type'] == 'git') {
  11.         // Only mess with repos from the right organisations on
  12.         // github. The [/:] makes this work with both http and git
  13.         // protocol specifications.
  14.         if (preg_match('{github\.com[/:](ding2|dbcdk)/}i', $spec['download']['url'])) {
  15.           $what = NULL;
  16.           // Unset any tag or revision specifications. We'll leave any
  17.           // branch specifications.
  18.           if (isset($spec['download']['tag'])) {
  19.             $what = 'tag';
  20.             unset($spec['download']['tag']);
  21.           }
  22.           if (isset($spec['download']['revision'])) {
  23.             $what = (empty($what) ? '' : ' and ') . 'revision';
  24.             unset($spec['download']['revision']);
  25.           }
  26.           if (!empty($what)) {
  27.             drush_log(dt('Unsetting @what for @who', array('@what' => $what, '@who' => $name)), 'debug');
  28.           }
  29.         }
  30.       }
  31.     }
  32.   }
  33.  
  34.   return $info;
  35. }

What it does is quite simple: if the argument --ding2-dev is passed to Drush make, it strips any tag or revision specifications from any git repo that matches our pattern, causing drush make to grab the HEAD of master in each repo.

What you can do with the hook is somewhat limited to what you can do with only the specification of the intent of drush make. While it's quite easy to make a function that checks that recursive make files that uses the same module, also uses the same version and patches, you can't examine a git checkout for the existence of a specific branch. Not without cloning the repository yourself (but then you can change the url to the local clone, to save some bandwidth).