? .DS_Store
? awesome.patch
Index: drush_make.download.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush_make/Attic/drush_make.download.inc,v
retrieving revision 1.1.2.41
diff -u -p -r1.1.2.41 drush_make.download.inc
--- drush_make.download.inc	28 Jun 2010 15:37:02 -0000	1.1.2.41
+++ drush_make.download.inc	28 Jun 2010 18:13:02 -0000
@@ -1,28 +1,25 @@
 <?php
 // $Id: drush_make.download.inc,v 1.1.2.41 2010/06/28 15:37:02 dmitrig01 Exp $
 
-class DrushMakeDownload {
+function drush_make_download_factory($project) {
+  $class = 'DrushMakeDownload_' . $project->download['type'];
+  if (class_exists($class)) {
+    return new $class($project);
+  }
+  else {
+    return FALSE;
+  }
+}
+
+abstract class DrushMakeDownload {
   var $project;
   var $path;
 
   function __construct($project) {
     $this->project = $project;
-    $this->path = !empty($this->project->directory_name) ? $this->project->directory_name : $this->project->name;
   }
 
-  function factory($project) {
-    $class = 'DrushMakeDownload_' . $project->download['type'];
-    if (class_exists($class)) {
-      return new $class($project);
-    }
-    else {
-      return FALSE;
-    }
-  }
-
-  function download() {
-    return FALSE;
-  }
+  abstract function download();
 }
 
 class DrushMakeDownload_CVS extends DrushMakeDownload {
@@ -51,10 +48,13 @@ class DrushMakeDownload_CVS extends Drus
       }
 
       // Checkout or export the module. CVS can't use absolute paths for named
-      // directories, so change into the tmp directory before checking out. 
-      if (drush_make_cd($tmp_path, "cvs -d%s %s -d%s %s %s", $download['root'], $command, $name, $flags, $download['module'])) {
-        drush_log(dt('%project @command from %module.', array('%project' => $name, '@command' => $command, '%module' => $download['module'])), 'ok');
-        return $name;
+      // directories, so change into the directory just above the final
+      // destination for the checkout. 
+      $cd_to_directory = dirname($this->project->download_location);
+      $destination_directory = basename($this->project->download_location);
+      if (drush_make_cd($cd_to_directory, "cvs -d%s %s -d%s %s %s", $download['root'], $command, $destination_directory, $flags, $download['module'])) {
+         drush_log(dt('%project @command from %module.', array('%project' => $name, '@command' => $command, '%module' => $download['module'])), 'ok');
+        return $this->project->download_location;
       }
     }
     else {
@@ -65,116 +65,190 @@ class DrushMakeDownload_CVS extends Drus
   }
 }
 
+
 class DrushMakeDownload_Get extends DrushMakeDownload {
-  protected function unpack($filename) {
-    if (drush_get_context('DRUSH_SIMULATE')) {
-      // Return a fake directory name so our simulation makes more sense.
-      return 'simulated_project';
+  function download() {
+    if ($filename = $this->downloadFile()) {
+      $this->filename = $filename;
+      return $this->unpack();
     }
+    return FALSE;
+  }
 
-    $extension = array_pop(explode('.', $filename));
+  protected function downloadFile() {
+    $name = $this->project->name;
+    $tmp_path = $this->project->tmp_path;
+    $filename = dt('file');
+    if (!empty($this->project->download['url'])) {
+      $url = $this->project->download['url'];
+      $filename = "$tmp_path/" . basename($url);
+      // Download the project -- try wget, fall back to curl.
+      if (drush_get_context('DRUSH_SIMULATE') || drush_shell_exec('wget %s -O %s', $url, $filename) || drush_shell_exec('curl -L -o %s %s', $filename, $url)) {
+        drush_log(dt('%project downloaded from %url.', array('%project' => $name, '%url' => $url)), 'ok');
+        return $filename;
+      }
+    }
+    else {
+      $url = dt("unspecified location");
+    }
+    drush_make_error('DOWNLOAD_ERROR', dt('Unable to download %filename from %url.', array('%filename' => $filename, '%url' => $url)));
+    return FALSE;
+  }
+
+  function unpack() {
+    $extension = array_pop(explode('.', $this->filename));
+    $gzip = FALSE;
     switch ($extension) {
       case 'gz':
       case 'tgz':
-        return $this->unpackGz($filename);
+        // I'd like to just use tar -z, but apparently it breaks on windoze. Why do they always have to ruin everything?
+        $this->unpackGzip();
+        break;
       case 'tar':
-        return $this->unpackTar($filename);
+        $this->unpackTar();
+        break;
       case 'zip':
-        return $this->unpackZip($filename);
+        $this->unpackZip();
+        break;
       default:
-        drush_make_error('DOWNLOAD_ERROR', dt('Unable to unpack %file', array('%file' => $filename)));
+        drush_make_error('DOWNLOAD_ERROR', dt('Unable to unpack %file', array('%file' => $this->filename)));
     }
   }
 
-  protected function unpackTar($filename) {
-    // Untar it and then delete the tar file.
-    drush_shell_exec('tar -tf %s', $filename);
-    $info = drush_shell_exec_output();
-    if ($info) {
-      list($first_line) = drush_shell_exec_output();
-      list($directory) = explode('/', $first_line);
-      drush_make_cd($this->project->tmp_path, 'tar -xf %s', $filename);
-      drush_op('unlink', $filename);
-
-      return $directory;
+  protected function unpackTar() {
+    // Tarbomb detection.
+    drush_shell_exec('tar -tf %s', $this->filename);
+    $lines = drush_shell_exec_output();
+    if ($lines && !$this->protectBomb($lines)) {
+      $strip = '';
+    }
+    else {
+      // Detect whether the user uses --strip-path or --strip-components
+      $strip_option = drush_get_option('strip-option', FALSE);
+      if (!$strip_option) {
+        drush_shell_exec("man tar | grep strip-component");
+        $info = drush_shell_exec_output();
+        if ($info) {
+          $strip_option = 'component';
+        }
+        else {
+          drush_shell_exec("tar --help | grep strip-path");
+          $info = drush_shell_exec_output();
+          if ($info) {
+            $strip_option = 'path';
+          }
+          else {
+            drush_make_error('CONFIGURATION_ERROR', dt('Unable to find a strip option in your version of tar'));
+          }
+        }
+        drush_set_option('strip-option', $strip_option);
+      }
+      $strip = '--strip-' . $strip_option . ' 1';
     }
 
-    drush_make_error('PACKAGE_ERROR', dt('Could not retrieve package information for %filename.', array('%filename' => $filename)));
-    return;
+
+    // Untar directly to final resting place -- allows tarballs to be
+    // unpacked directly over an existing structure.
+    drush_shell_exec('tar -x ' . $strip . ' -C %s -f %s', $this->project->download_location, $this->filename);
+
+    // Remove the tarball.
+    if (file_exists($this->filename)) {
+      drush_shell_exec('rm %s', $this->filename);
+    }
   }
 
-  protected function unpackGz($filename) {
+  protected function unpackGzip() {
     // Find out where contents will end up. Retrieve last column of output using awk.
-    drush_shell_exec("gzip --list %s | awk '{print $4;}'", $filename);
+    drush_shell_exec("gzip --list %s | awk '{print $4;}'", $this->filename);
     $info = drush_shell_exec_output();
     if ($info) {
       $info = array_pop($info);
       $matches = array();
       preg_match('/[a-zA-Z0-9.\-_,]*.tar/', $info, $matches);
       if (isset($matches[0])) {
-        $file = $this->project->tmp_path . '/' . $matches[0];
+        $file = dirname($this->filename) . '/' . $matches[0];
         // Unzip it and then delete the tar file.
-        drush_shell_exec('gzip -d %s', $filename);
-        return $this->unpackTar($file);
+        drush_shell_exec('gzip -d %s', $this->filename);
+        $this->filename = $file;
+        return $this->unpackTar();
       }
     }
-    drush_make_error('PACKAGE_ERROR', dt('Could not retrieve package information for %filename.', array('%filename' => $filename)));
+    drush_make_error('PACKAGE_ERROR', dt('Could not retrieve package information for %filename.', array('%filename' => $this->filename)));
     return;
   }
 
-  protected function unpackZip($filename) {
-    // Find out where contents will end up.
-    drush_shell_exec("unzip -l %s", $filename);
+  protected function unpackZip() {
+    // Find the main directory in the zip file.
+    drush_shell_exec("unzip -l %s", $this->filename);
     $info = drush_shell_exec_output();
     if ($info) {
       foreach ($info as $line) {
         $matches = array();
         preg_match('/^\s+[0-9]+\s+[0-9-]+\s+[0-9:]+\s+(.*)$/', $line, $matches);
         if (isset($matches[1])) {
-          $directory = $matches[1];
-          break;
+          $lines[] = $matches[1];
         }
       }
-      if (isset($directory)) {
-        drush_shell_exec("unzip %s -d %s", $filename, $this->project->tmp_path);
-        if (file_exists($filename)) {
-          drush_shell_exec('rm %s', $filename);
+      $directory = $this->protectBomb($lines);
+      if ($directory) {
+        list($main_directory) = array_reverse(explode('/', $this->project->download_location));
+        if ($main_directory == $directory) {
+          // Directory names match up.
+          drush_shell_exec("unzip %s -d %s", $this->filename, dirname($this->project->download_location));
         }
-        if (is_dir($this->project->tmp_path . '/__MACOSX')) {
-          drush_shell_exec('rm -r %s', $this->project->tmp_path . '/__MACOSX');
+        else {
+          // Directories don't match up. Use cp.
+          drush_shell_exec('mkdir -p %s', $this->project->tmp_path . '/__unzip__');
+          drush_shell_exec('unzip %s -d %s', $this->filename, $this->project->tmp_path . '/__unzip__');
+          if (file_exists($this->filename)) {
+            drush_shell_exec('rm %s', $this->filename);
+          }
+          if (is_dir($this->project->tmp_path . '/__unzip__' . $directory . '/__MACOSX')) {
+            drush_shell_exec('rm -r %s', $this->project->tmp_path . '/__unzip__' . $directory . '/__MACOSX');
+          }
+          drush_shell_exec('mv %s %s', $this->project->tmp_path . '/__unzip__/' . $directory, $this->project->tmp_path . '/__unzip__/' . $main_directory);
+          drush_shell_exec('cp -Rf %s %s', $this->project->tmp_path . '/__unzip__/' . $main_directory, dirname($this->project->download_location));
+          drush_shell_exec('rm -r %s', $this->project->tmp_path . '/__unzip__');
         }
-        return $directory;
+      }
+      else {
+        // It's a bomb, so we can just unpack it right at its destination
+        // (warning: don't ever do this in real life).
+        drush_shell_exec("unzip %s -d %s", $this->filename, $this->project->download_location);
+      }
+      if (file_exists($this->filename)) {
+        drush_shell_exec('rm %s', $this->filename);
+      }
+      if (is_dir($this->project->download_location . '/__MACOSX')) {
+        drush_shell_exec('rm -r %s', $this->project->download_location . '/__MACOSX');
       }
     }
-    drush_make_error('PACKAGE_ERROR', dt('Could not retrieve package information for %filename.', array('%filename' => $filename)));
-    return;
-  }
-
-  function download() {
-    if ($filename = $this->downloadFile()) {
-      return $this->unpack($filename);
+    else {
+      drush_make_error('PACKAGE_ERROR', dt('Could not retrieve package information for %filename.', array('%filename' => $this->filename)));
     }
-    return FALSE;
+    return;
   }
 
-  protected function downloadFile() {
-    $name = $this->project->name;
-    $tmp_path = $this->project->tmp_path;
-    $filename = dt('file');
-    if (!empty($this->project->download['url'])) {
-      $url = $this->project->download['url'];
-      $filename = "$tmp_path/" . basename($url);
-      // Download the project -- try wget, fall back to curl.
-      if (drush_get_context('DRUSH_SIMULATE') || drush_shell_exec('wget %s -O %s', $url, $filename) || drush_shell_exec('curl -L -o %s %s', $filename, $url)) {
-        drush_log(dt('%project downloaded from %url.', array('%project' => $name, '%url' => $url)), 'ok');
-        return $filename;
+  protected function protectBomb($lines) {
+    $directory = FALSE;
+    foreach ($lines as $line) {
+      if (strpos($line, '/') !== FALSE) {
+        list($dir) = explode('/', $line);
+        if (!$directory) {
+          $directory = $dir;
+        }
+        elseif ($dir != $directory) {
+          // More than one root-level item detected. We're not safe - BOMB!
+          return FALSE;
+        }
       }
     }
-    else {
-      $url = dt("unspecified location");
+    if (!$directory) {
+      // If we didn't come upon anything, that is to say, they were only
+      // root-level files, it's a bomb.
+      return FALSE;
     }
-    drush_make_error('DOWNLOAD_ERROR', dt('Unable to download %filename from %url.', array('%filename' => $filename, '%url' => $url)));
-    return FALSE;
+    return $directory;
   }
 }
 
@@ -187,6 +261,8 @@ class DrushMakeDownload_Post extends Dru
       $url = $this->project->download['url'];
       $post_data = $this->project->download['post_data'];
       $file_type = $this->project->download['file_type'];
+      $filename = "$tmp_path/" . basename($url);
+      // Download the project -- try wget, fall back to curl.
       $filename = (empty($file_type)) ? "$tmp_path/" . basename($url) : "$tmp_path/" . basename($url) . ".$file_type";
       // Download the project -- try wget, fall back to curl.
       if (drush_get_context('DRUSH_SIMULATE') || drush_shell_exec('wget --post-data=%s %s -O %s', $post_data, $url, $filename) || drush_shell_exec('curl -d %s -o %s %s', $post_data, $filename, $url)) {
@@ -249,7 +325,7 @@ class DrushMakeDownload_Git extends Drus
       }
 
       // clone the given repository
-      if (drush_shell_exec("git clone %s %s/%s", $url, $tmp_path, $name)) {
+      if (drush_shell_exec("git clone %s %s", $url, $this->project->download_location)) {
         drush_log(dt('%project cloned from %url.', array('%project' => $name, '%url' => $url)), 'ok');
 
         // GIT Checkout only work on a ready cloned repo. So we switch to branch or to tag (only if we have no branch) after cloneing.
@@ -258,7 +334,7 @@ class DrushMakeDownload_Git extends Drus
           // get current directory (for move back later)
           $cwd = getcwd();
           // change path to working copy of cloned repo
-          chdir($tmp_path .'/'. $name);
+          chdir($this->project->download_location);
 
           // Progress branch / tag / revision download. Ensure that only one option ist set (branch OR tag OR revision)
           // check if branch a other than master
@@ -299,8 +375,8 @@ class DrushMakeDownload_Git extends Drus
         }
 
         // Remove .git/ directory if working-copy flag was not specified.
-        if (!$wc && file_exists($tmp_path .'/'. $name .'/.git')) {
-          drush_shell_exec("rm -rf %s/%s/.git", $tmp_path, $name);
+        if (!$wc && file_exists($this->project->download_location . '/.git')) {
+          drush_shell_exec("rm -rf %s/.git", $this->project->download_location);
         }
         return $name;
       }
@@ -350,7 +426,6 @@ class DrushMakeDownload_Bzr extends Drus
   function download() {
     // @TODO implement revisions, tags
     $name = $this->project->name;
-    $tmp_path = $this->project->tmp_path;
     $download = $this->project->download;
     $command = 'export';
     if (!empty($download['url'])) {
@@ -378,7 +453,6 @@ class DrushMakeDownload_Bzr extends Drus
 class DrushMakeDownload_SVN extends DrushMakeDownload {
   function download() {
     $name = $this->project->name;
-    $tmp_path = $this->project->tmp_path;
     $download = $this->project->download;
     $command = 'export';
     if (!empty($download['url'])) {
@@ -389,21 +463,23 @@ class DrushMakeDownload_SVN extends Drus
       $flags = isset($download['revision']) ? "-r{$download['revision']}" : '';
 
       if (!empty($download['username'])) {
-        $result = drush_shell_exec("svn --non-interactive %s %s %s %s/%s --username %s --password %s", $command, $flags, $download['url'], $tmp_path, $name, $download['username'], $download['password']);
+        $result = drush_shell_exec("svn --non-interactive %s %s %s --username %s --password %s", $command, $download['url'], $this->project->download_location, $download['username'], $download['password']);
       }
       else {
-        $result = drush_shell_exec("svn --non-interactive %s %s %s %s/%s", $command, $flags, $download['url'], $tmp_path, $name);
+        $result = drush_shell_exec("svn --non-interactive %s %s %s", $command, $download['url'], $this->project->download_location);
       }
       if ($result) {
         drush_log(dt('%project @command from %url.', array('%project' => $name, '@command' => $command, '%url' => $download['url'])), 'ok');
-        return $this->project->name;
+        return $this->project->download_location;
+      }
+      else {
+        $download['url'] = dt("unspecified location");
       }
     }
     else {
-      $download['url'] = dt("unspecified location");
+      drush_make_error('DOWNLOAD_ERROR', dt('Unable to @command %project from %url.', array('%project' => $name, '@command' => $command, '%url' => $download['url'])));
+      return FALSE;
     }
-    drush_make_error('DOWNLOAD_ERROR', dt('Unable to @command %project from %url.', array('%project' => $name, '@command' => $command, '%url' => $download['url'])));
-    return FALSE;
   }
 }
 
@@ -414,12 +490,12 @@ class DrushMakeDownload_Hg extends Drush
     $tmp_path = $this->project->tmp_path;
     $download = $this->project->download;
     if (!empty($download['url'])) {
-      if (drush_shell_exec("hg clone %s %s/%s", $download['url'], $tmp_path, $name)) {
+      if (drush_shell_exec("hg clone %s %s", $download['url'], $this->project->download_location)) {
         if (!drush_get_option('working-copy')) {
-          drush_shell_exec('rm -r %s/%s/.hg', $tmp_path, $name);
+          drush_shell_exec('rm -r %s/.hg', $this->project->download_location);
         }
         drush_log(dt('%project cloned from %url.', array('%project' => $name, '%url' => $download['url'])), 'ok');
-        return $name;
+        return $this->project->download_location;
       }
     }
     else {
@@ -429,4 +505,3 @@ class DrushMakeDownload_Hg extends Drush
     return FALSE;
   }
 }
-
Index: drush_make.project.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush_make/Attic/drush_make.project.inc,v
retrieving revision 1.1.2.24
diff -u -p -r1.1.2.24 drush_make.project.inc
--- drush_make.project.inc	21 Jun 2010 14:39:24 -0000	1.1.2.24
+++ drush_make.project.inc	28 Jun 2010 18:13:02 -0000
@@ -13,7 +13,7 @@ class DrushMakeProject {
     foreach ($project as $key => $value) {
       $this->{$key} = $value;
     }
-    $this->downloadClass = DrushMakeDownload::factory($this);
+    $this->downloadClass = drush_make_download_factory($this);
     if (!$this->downloadClass) {
       drush_make_error('BUILD_ERROR', dt('Could not find download type %type', array('%type' => $this->download['type'])));
     }
@@ -24,24 +24,28 @@ class DrushMakeProject {
    */
   function make() {
     if (empty($this->made)) {
-      $directory = $this->queue->addItem(array($this->downloadClass, 'download'));
-      $full_path = $this->queue->addItem(array($this, 'makePath'), array(), $directory);
-      $move = $this->queue->addItem(array($this, 'move'), array(), array($directory, $full_path));
-      $this->queue->addItem(array($this, 'applyPatches'), array(), array($move));
-      $this->queue->addItem(array($this, 'recurse'), array(), array($move, $directory));
+      $download_location = $this->queue->addItem(array($this, 'findDownloadLocation'));
+      $this->queue->addItem(array($this->downloadClass, 'download'), array(), array($download_location));
+      $this->queue->addItem(array($this, 'applyPatches'), array(), array($download_location));
+      $this->queue->addItem(array($this, 'recurse'), array(), array($download_location));
       $this->made = TRUE;
     }
     return FALSE;
   }
 
-  function makePath($directory) {
+  function findDownloadLocation($directory) {
     $this->path = $this->generatePath();
-    drush_shell_exec('mkdir -p %s', $this->path);
-    if (is_dir($this->path . '/' . $directory)) {
-      drush_set_error(dt('Directory not empty: %directory', array('%directory' => $directory)));
-      drush_shell_exec('rm -r %s', $directory);
+    $this->project_directory = !empty($this->directory_name) ? $this->directory_name : $this->name;
+    $this->download_location = $this->path . '/' . $this->project_directory;
+    // This directory shouldn't exist yet -- if it does, stop.
+    if (is_dir($this->download_location)) {
+      drush_set_error(dt('Directory not empty: %directory', array('%directory' => $this->download_location)));
+      $this->queue->terminate();
     }
-    return $this->path;
+    else {
+      drush_shell_exec("mkdir -p %s", $this->download_location);
+    }
+    return $this->download_location;
   }
 
   /**
@@ -78,26 +82,10 @@ class DrushMakeProject {
   }
 
   /**
-   * Move a project to its final resting place.
-   */
-  function move($project_directory) {
-    if (empty($this->directory_name)) {
-      drush_shell_exec("mv %s/%s %s", $this->tmp_path, $project_directory, $this->path);
-    }
-    else {
-      list($project_directory) = array_reverse(explode('/', trim($project_directory, '/')));
-      drush_shell_exec("mv %s/%s %s/%s", $this->tmp_path, $project_directory, $this->path, $this->directory_name);
-      $project_directory = $this->directory_name;
-    }
-    return $this->path . '/' . $project_directory;
-  }
-
-  /**
    * Generate the proper path for this project type.
    *
-   * @param $absolute
-   *   Whether to generate an absolute path, including the temporary directory path.
-   *   Defaults to true.
+   * @param $base
+   *   Whether include the base part (tmp dir). Defaults to TRUE.
    */
   protected function generatePath($base = TRUE) {
     $path = array();
@@ -149,26 +137,17 @@ class DrushMakeProject_Core extends Drus
     $this->install_path = '';
   }
 
-  function makePath($directory) {
-    $this->path = $this->generatePath();
-    drush_shell_exec('mkdir -p %s', dirname($this->path));
-    if (is_dir($this->path . '/' . $directory)) {
-      drush_set_error(dt('Directory not empty: %directory', array('%directory' => $directory)));
-      drush_shell_exec('rm -r %s', $directory);
-      return FALSE;
+  function findDownloadLocation() {
+    $this->path = $this->download_location = $this->generatePath();
+    $this->project_directory = '';
+    if (is_dir($this->download_location)) {
+      drush_set_error(dt('Directory not empty: %directory', array('%directory' => $this->download_location)));
+      $this->queue->terminate();
     }
-    return $this->path;
-  }
-
-  /**
-   * The core project will always be the base of the build, so it needs to move
-   * itself into place a little differently.
-   *
-   * @TODO ensure that the core project is always created first.
-   */
-  function move($project_directory) {
-    drush_shell_exec("mv %s/%s %s/__build__", $this->tmp_path, $project_directory, $this->tmp_path);
-    return $this->tmp_path . '/__build__';
+    else {
+      drush_shell_exec("mkdir -p %s", $this->download_location);
+    }
+    return $this->download_location;
   }
 }
 
