From 9534f4b73cdd99e588442cfcc2f592935ac53fb4 Mon Sep 17 00:00:00 2001
From: Mark Sonnabaum <mark@sonnabaum.com>
Date: Sat, 26 Feb 2011 20:43:55 -0600
Subject: [PATCH] Issue #1076302 by msonnabaum: Added local caching to git package handler.

---
 commands/pm/package_handler/git_drupalorg.inc |   56 +++++++++++++++++++++++++
 commands/pm/pm.drush.inc                      |    1 +
 2 files changed, 57 insertions(+), 0 deletions(-)

diff --git commands/pm/package_handler/git_drupalorg.inc commands/pm/package_handler/git_drupalorg.inc
index ca96390..9180b52 100644
--- commands/pm/package_handler/git_drupalorg.inc
+++ commands/pm/package_handler/git_drupalorg.inc
@@ -34,9 +34,27 @@ function package_handler_download_project(&$request, $release) {
   $repository = 'git://git.drupal.org/project/' . $request['name'] . '.git';
   $tag = $release['tag'];
 
+  if (drush_get_option('gitcache')) {
+    $gitcache = drush_server_home() . '/.drush/gitcache';
+    drush_gitcache_check($gitcache);
+
+    drush_shell_cd_and_exec($gitcache, 'git remote show'); 
+    $cached_modules = drush_shell_exec_output();
+
+    if (!in_array($request['name'], $cached_modules)) {
+      drush_gitcache_add_project($gitcache, $request, $repository);
+    }
+  }
+
   // Clone the repo into its appropriate target location.
   $command  = 'git clone';
   $command .= ' ' . drush_get_option('gitcloneparams');
+  if (drush_get_option('gitcache')) {
+    $command .= ' --reference ' . drush_escapeshellarg($gitcache);
+  }
+  if (drush_get_context('DRUSH_VERBOSE')) {
+    $command .= ' --verbose --progress';
+  }
   $command .= ' ' . drush_escapeshellarg($repository);
   $command .= ' ' . drush_escapeshellarg($request['full_project_path']);
   if (!drush_shell_exec($command)) {
@@ -144,3 +162,41 @@ function package_handler_post_download($project) {
   }
 }
 
+/**
+ * Check for gitcache directory or create it.
+ *
+ * @param $gitcache The location of the gitcache directory.
+ */
+function drush_gitcache_check($gitcache) {
+  if (is_dir(drush_server_home() . '/.drush')) {
+    drush_mkdir($gitcache);
+    if (!drush_shell_cd_and_exec($gitcache, 'test $(git rev-parse --is-bare-repository) == "true"')) {
+      drush_shell_cd_and_exec($gitcache, 'git init --bare');
+      drush_shell_cd_and_exec($gitcache, 'git config core.compression 1');
+    }
+  }
+}
+
+
+/**
+ * Add a project to the cache.
+ *
+ * @param $gitcache The location of the gitcache directory.
+ * @param $request The project array with name, base and full (final) paths.
+ * @param $release The release details array from drupal.org
+ */
+function drush_gitcache_add_project($gitcache, $request, $repository) {
+  $tmpdir = drush_tempdir();
+  $command = 'git clone --bare ';
+  if (drush_get_context('DRUSH_VERBOSE')) {
+    $command .= ' --verbose --progress ';
+  }
+  $command .= '%s';
+  if (drush_shell_cd_and_exec($tmpdir, $command, $repository)) {
+    // Then fetch from the temporary dir into our main repo.
+    drush_shell_cd_and_exec($gitcache, 'git remote add %s %s && git fetch %s --tags', $request['name'], $tmpdir, $request['name']);
+
+    // Then change the remote URL and fetch normally.
+    drush_shell_cd_and_exec($gitcache, 'git remote set-url %s %s && git fetch %s --tags', $request['name'], $repository, $request['name']); 
+  }
+}
diff --git commands/pm/pm.drush.inc commands/pm/pm.drush.inc
index 6015ec5..c6a1604 100644
--- commands/pm/pm.drush.inc
+++ commands/pm/pm.drush.inc
@@ -1904,6 +1904,7 @@ function pm_drush_engine_package_handler() {
           'gitfetchparams' => 'Add options to the `git fetch` command.',
           'gitpullparams' => 'Add options to the `git pull` command.',
           'gitsubmoduleaddparams' => 'Add options to the `git submodule add` command.',
+          'gitcache' => 'Use a local git cache and clone projects using --reference.',
         ),
       ),
     ),
-- 
1.7.4.1

