#814174: Integrate Drush PM with Git repositories on drupal.org.

From: Damien Tournoud <damien@commerceguys.com>


---
 pm/package_handler/git_drupalorg.inc |   93 ++++++++++++++++++++++++++++++++++
 pm/pm.drush.inc                      |    5 ++
 2 files changed, 98 insertions(+), 0 deletions(-)
 create mode 100644 pm/package_handler/git_drupalorg.inc

diff --git commands/pm/package_handler/git_drupalorg.inc commands/pm/package_handler/git_drupalorg.inc
new file mode 100644
index 0000000..207609e
--- /dev/null
+++ commands/pm/package_handler/git_drupalorg.inc
@@ -0,0 +1,93 @@
+<?php
+// $Id$
+
+/**
+ * @file Drush PM drupal.org Git extension.
+ */
+
+/**
+ * Install a project.
+ *
+ * @param $project The project array with name, base and full (final) paths.
+ * @param $release The release details array from drupal.org
+ */
+function package_handler_install_project($project, $release) {
+  drush_log('Downloading project ' . $project['name'] . ' ...');
+
+  $project_name = strtok($project['name'], ' ');
+
+  if (isset($release['version_extra']) && $release['version_extra'] == 'dev') {
+    // Use the development repository, not supported yet.
+    $repository = 'git://git.drupal.org/contributions/' . $project_name . '.git';
+    $tag = $release['tag'];
+  }
+  else {
+    // Use a stable repository.
+    $repository = 'git://git.drupal.org/contributions-stable/' . $project_name . '.git';
+    $tag = $release['version'];
+  }
+
+  // Verify that we are in a Git repository.
+  if (drush_shell_exec("cd " . escapeshellarg($project['base_project_path']) . " ; git rev-parse --git-dir")) {
+    $output = drush_shell_exec_output();
+    if (isset($output[0])) {
+      $git_dir = $output[0];
+    }
+  }
+  if (!isset($git_dir)) {
+    drush_set_error('DRUSH_PM_GIT_CHECKOUT_PROBLEMS', dt('Unable to check out !project: !dir is not in a Git repository.', array('!project' => $project['name'], '!dir' => $project['base_project_path'])));
+    return FALSE;
+  }
+
+  // Create the project path and find its true location, git submodule doesn't
+  // like symbolic links.
+  mkdir($project['full_project_path']);
+  $full_project_path = realpath($project['full_project_path']);
+  rmdir($full_project_path);
+
+  // Check it out.
+  $commands = array();
+  $commands[] = 'cd ' . escapeshellarg($git_dir . '/..');
+  $commands[] = 'git submodule add ' . escapeshellarg($repository) . ' ' . escapeshellarg($full_project_path);
+  $commands[] = 'cd ' . escapeshellarg($project['full_project_path']);
+  $commands[] = 'git checkout ' . escapeshellarg($tag);
+
+  if (!drush_shell_exec(implode(' && ', $commands))) {
+    drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to checkout ' . $project['name'] . ' from git.drupal.org.');
+    return FALSE;
+  }
+  else {
+    return TRUE;
+  }
+}
+
+/**
+ * Update a project (so far, only modules are supported).
+ *
+ * @param $project The project array with name, base and full (final) paths.
+ * @param $release The release details array from drupal.org
+ */
+function package_handler_update_project($project, $release) {
+  drush_log('Updating project ' . $project['name'] . ' ...');
+
+  $commands = array();
+  $commands[] = 'cd ' . escapeshellarg($project['full_project_path']);
+
+  if ($release['version_extra'] == 'dev') {
+    // Update the branch of the development repository.
+    $commands[] = 'git pull';
+  }
+  else {
+    // Use a stable repository.
+    $commands[] = 'git fetch';
+    $commands[] = 'git checkout ' . escapeshellarg($release['version']);
+  }
+
+  if (!drush_shell_exec(implode(' ; ', $commands))) {
+    drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to update ' . $project['name'] . ' from git.drupal.org.');
+    return FALSE;
+  }
+  else {
+    return TRUE;
+  }
+}
diff --git commands/pm/pm.drush.inc commands/pm/pm.drush.inc
index 67cda8f..e59bda3 100644
--- commands/pm/pm.drush.inc
+++ commands/pm/pm.drush.inc
@@ -1202,6 +1202,11 @@ function pm_drush_engine_package_handler() {
           'drush [command] cck --cvsmethod=update' =>  'Will update the project, and try to merge changes, rather than overwriting them. Any conflicts will need to be resolved manually.',
       ),
     ),
+    'git_drupalorg' => array(
+      'options' => array(
+        '--package-handler=git_drupalorg' => 'Use git.drupal.org to checkout and update projects.',
+      ),
+    ),
   );
 }
 
