Backport drush_tarball_extract() for use by wget handler and archive-restore.
authorMoshe Weitzman
Thu, 7 Jul 2011 20:52:24 +0000 (16:52 -0400)
committerMoshe Weitzman
Thu, 7 Jul 2011 20:52:24 +0000 (16:52 -0400)
commands/pm/package_handler/wget.inc
includes/drush.inc

index daa9070..956236a 100644 (file)
@@ -45,14 +45,10 @@ function package_handler_download_project(&$request, $release) {
       }
     }
   }
-  
+
   $filename = explode('/', $release['download_link']);
   $filename = array_pop($filename);
 
-  // Chdir to the download location.
-  $olddir = getcwd();
-  drush_op('chdir', $request['base_project_path']);
-
   // Download the project.
   if (!drush_shell_exec("wget -P . %s", $release['download_link'])) {
     drush_shell_exec("curl -O %s", $release['download_link']);
@@ -61,7 +57,6 @@ function package_handler_download_project(&$request, $release) {
     drush_log("Downloading " . $filename . " was successful.");
   }
   else {
-    drush_op('chdir', $olddir);
     return drush_set_error('DRUSH_PM_DOWNLOAD_FAILED', 'Unable to download ' . $filename . ' to ' . $request['base_project_path'] . ' from '. $release['download_link']);
   }
 
@@ -69,38 +64,26 @@ function package_handler_download_project(&$request, $release) {
   if (drush_op('md5_file', $filename) != $release['mdhash'] && !drush_get_context('DRUSH_SIMULATE')) {
     drush_set_error('DRUSH_PM_FILE_CORRUPT', "File $filename is corrupt (wrong md5 checksum).");
     drush_op('unlink', $filename);
-    drush_op('chdir', $olddir);
     return FALSE;
   }
   else {
     drush_log("Md5 checksum of $filename verified.");
   }
 
-  // Decompress and untar in two steps as tar -xzf does not work on windows.
-  drush_shell_exec("gzip -d %s", $filename);
-  $tarpath = basename($filename, '.tar.gz');
-  $tarpath = basename($tarpath, '.tgz');
-  $tarpath .= '.tar';
-  drush_shell_exec("tar -xf %s", $tarpath);
+  // Extract the tarball.
+  $file_list = drush_tarball_extract($filename, $request['base_project_path'], TRUE);
 
   // Move untarred directory to project_dir, if distinct.
   if (($request['project_type'] == 'core') || (($request['project_type'] == 'profile') && (drush_get_option('variant', 'core') == 'core'))) {
     // Obtain the dodgy project_dir for drupal core.
-    // We use a separate tar -tf instead of -xvf above because
-    // the output is not the same in Mac.
-    drush_shell_exec("tar -tf %s", $tarpath);
-    $output = drush_shell_exec_output();
-    $project_dir = rtrim($output[0], DIRECTORY_SEPARATOR);
+
+    $project_dir = rtrim($file_list[0], DIRECTORY_SEPARATOR);
     if ($request['project_dir'] != $project_dir) {
       $path = $request['base_project_path'];
       drush_move_dir($path . '/'. $project_dir, $path . '/' . $request['project_dir']);
     }
   }
 
-  // Cleanup. Remove the tar file and set previous working directory.
-  drush_op('unlink', $tarpath);
-  drush_op('chdir', $olddir);
-
   return TRUE;
 }
 
@@ -118,4 +101,3 @@ function package_handler_update_project(&$request, $release) {
  */
 function package_handler_post_download($project) {
 }
-
index c06d546..748fdf4 100644 (file)
@@ -1523,6 +1523,69 @@ function _drush_download_file($url) {
 }
 
 /**
+ * Extract a tarball.
+ *
+ * @param string $path
+ *   The name of the .tar.gz or .tgz file to be extracted.
+ * @param string $destination
+ *   The destination directory the tarball should be extracted into.
+ *   Optional, if ommitted the tarball directory will be used as destination.
+ * @param boolean $listing
+ *   If TRUE, a listing of the tar contents will be returned on success.
+ *
+ * @return string
+ *   TRUE on success, FALSE on fail. If $listing is TRUE, a file listing of the
+ *   tarball is returned if the extraction reported success, instead of TRUE.
+ */
+function drush_tarball_extract($path, $destination = FALSE, $listing = FALSE) {
+  if (!file_exists($path)) {
+    return drush_set_error('TARBALL_EXTRACT_NOT_FOUND', dt('Tarball !path could not be found.', array('!path' => $path)));
+  }
+  $olddir = getcwd();
+  if (!$destination) {
+    $destination = dirname($path);
+  }
+  if (!is_writeable($destination)) {
+    return drush_set_error('TARBALL_EXTRACT_DESTINATION', dt('Extracting !path failed, as the destination directory !dest was not found or could not be written to.', array('!path' => $path, '!dest' => $dest)));
+  }
+  // If we are not on Windows, then try to do "tar" in a single operation.
+  if ((!drush_is_windows()) && (drush_shell_cd_and_exec(dirname($path), "tar -C %s -xzf %s", $destination, basename($path)))) {
+    if ($listing) {
+      // We use a separate tar -tf instead of -xvf above because
+      // the output is not the same in Mac.
+      drush_shell_cd_and_exec(dirname($path), "tar -tf %s", basename($path));
+      return drush_shell_exec_output();
+    }
+    return TRUE;
+  }
+  // If we could not get the single-op tar to work, do it in three steps.
+  // Copy the source tarball to the destination directory.  Rename to a temp name in case the destination directory == dirname($path)
+  $paths_basename = basename(basename($path, '.tar.gz'), '.tgz');
+  $tarball = drush_tempnam($paths_basename, $destination) . ".tar.gz";
+  drush_register_file_for_deletion($tarball);
+  drush_copy_dir($path, $tarball);
+  $unzipped = $destination . '/' . basename($tarball, ".tar.gz") . ".tar";
+  // We used to use gzip --decompress in --stdout > out, but the output redirection sometimes failed on Windows for some binary output
+  drush_shell_cd_and_exec(dirname($tarball), "gzip --decompress %s", $tarball);
+  if (file_exists($unzipped)) {
+    drush_register_file_for_deletion($unzipped);
+    if (drush_shell_cd_and_exec(dirname($unzipped), "tar -xf %s", basename($unzipped))) {
+      if ($listing) {
+        // We use a separate tar -tf instead of -xf above because
+        // the output is not the same in Mac.
+        drush_shell_cd_and_exec(dirname($unzipped), "tar -tf %s", basename($unzipped));
+        return drush_shell_exec_output();
+      }
+      return TRUE;
+    }
+    return drush_set_error('TARBALL_EXTRACT_TAR_FAIL', dt('Extracting !path using the tar command failed.', array('!path' => $path)));
+  }
+  else {
+    return drush_set_error('TARBALL_EXTRACT_GZIP_FAIL', dt('Uncompressing !path using  the gzip command failed.', array('!path' => $path)));
+  }
+}
+
+/**
  * @} End of "defgroup commandwrappers".
  */