Index: release/package-release-nodes.php =================================================================== RCS file: /Users/wright/drupal/local_repo/contributions/modules/project/release/package-release-nodes.php,v retrieving revision 1.68 diff -u -p -r1.68 package-release-nodes.php --- release/package-release-nodes.php 30 Jul 2010 20:42:27 -0000 1.68 +++ release/package-release-nodes.php 13 Nov 2010 01:33:18 -0000 @@ -79,6 +79,7 @@ $dest_rel = 'files/projects'; // the script will find these tools in your PATH. $tar = '/usr/bin/tar'; $gzip = '/usr/bin/gzip'; +$zip = '/usr/bin/zip'; $cvs = '/usr/bin/cvs'; $ln = '/bin/ln'; $rm = '/bin/rm'; @@ -314,7 +315,7 @@ function package_releases($type, $projec function package_release_core($type, $nid, $project_short_name, $version, $tag) { global $tmp_dir, $repositories, $dest_root, $dest_rel; - global $cvs, $tar, $gzip, $rm; + global $cvs, $tar, $gzip, $zip, $rm; if (!drupal_chdir($tmp_dir)) { return 'error'; @@ -324,6 +325,8 @@ function package_release_core($type, $ni $release_node_view_link = l(t('view'), 'node/' . $nid); $file_path_tgz = $dest_rel . '/' . $release_file_id . '.tar.gz'; $full_dest_tgz = $dest_root . '/' . $file_path_tgz; + $file_path_zip = $dest_rel . '/' . $release_file_id . '.zip'; + $full_dest_zip = $dest_root . '/' . $file_path_zip; // Remember if the tar.gz version of this release file already exists. $tgz_exists = is_file($full_dest_tgz); @@ -353,12 +356,19 @@ function package_release_core($type, $ni } } + convert_line_endings("$tmp_dir/$release_file_id", 'UNIX'); if (!drupal_exec("$tar -c --file=- $release_file_id | $gzip -9 --no-name > $full_dest_tgz")) { return 'error'; } $files[] = $file_path_tgz; - // As soon as the tarball exists, we want to update the DB about it. + convert_line_endings("$tmp_dir/$release_file_id", 'DOS'); + if (!drupal_exec("$zip -rq $full_dest_zip $release_file_id")) { + return 'error'; + } + $files[] = $file_path_zip; + + // As soon as the files exist, we want to update the DB about it. package_release_update_node($nid, $files); if ($tgz_exists) { @@ -375,7 +385,7 @@ function package_release_core($type, $ni function package_release_contrib($type, $nid, $project_short_name, $version, $tag, $release_dir) { global $tmp_dir, $repositories, $dest_root, $dest_rel; - global $cvs, $tar, $gzip, $rm, $ln; + global $cvs, $tar, $gzip, $zip, $rm, $ln; global $drush, $drush_make_dir; global $license, $trans_install; @@ -395,6 +405,8 @@ function package_release_contrib($type, $release_node_view_link = l(t('view'), 'node/' . $nid); $file_path_tgz = $dest_rel . '/' . $release_file_id . '.tar.gz'; $full_dest_tgz = $dest_root . '/' . $file_path_tgz; + $file_path_zip = $dest_rel . '/' . $release_file_id . '.zip'; + $full_dest_zip = $dest_root . '/' . $file_path_zip; // Remember if the tar.gz version of this release file already exists. $tgz_exists = is_file($full_dest_tgz); @@ -438,8 +450,10 @@ function package_release_contrib($type, return 'error'; } // Do we want a subdirectory in the tarball or not? + $is_translation = FALSE; $tarball_needs_subdir = TRUE; if ($contrib_type == 'translations' && $project_short_name != 'drupal-pot') { + $is_translation = TRUE; // Translation projects are packaged differently based on core version. if (intval($version) > 5) { if (!($to_tar = package_release_contrib_d6_translation($project_short_name, $version, $release_node_view_link))) { @@ -464,12 +478,21 @@ function package_release_contrib($type, } } + convert_line_endings("$tmp_dir/$release_file_id", 'UNIX'); // 'h' is for dereference, we want to include the files, not the links if (!drupal_exec("$tar -ch --file=- $to_tar | $gzip -9 --no-name > $full_dest_tgz")) { return 'error'; } $files[] = $file_path_tgz; + if (!$is_translation) { + convert_line_endings("$tmp_dir/$release_file_id", 'DOS'); + if (!drupal_exec("$zip -rq $full_dest_zip $to_tar")) { + return 'error'; + } + $files[] = $file_path_zip; + } + // Start with no package contents, since this is only valid for profiles. $package_contents = array(); @@ -519,9 +542,12 @@ function package_release_contrib($type, // NO-CORE DISTRIBUTION. $no_core_id = "$release_file_id-no-core"; - // Build the drupal file path and the full file path. - $no_core_file_path = "$dest_rel/$no_core_id.tar.gz"; - $no_core_full_dest = "$dest_root/$no_core_file_path"; + + // Build the drupal file path and the full file path for tgz and zip. + $no_core_file_path_tgz = "$dest_rel/$no_core_id.tar.gz"; + $no_core_full_dest_tgz = "$dest_root/$no_core_file_path_tgz"; + $no_core_file_path_zip = "$dest_rel/$no_core_id.zip"; + $no_core_full_dest_zip = "$dest_root/$no_core_file_path_zip"; // Run drush_make to build the profile's contents. // --drupal-org: Invoke drupal.org specific validation/processing. @@ -550,11 +576,18 @@ function package_release_contrib($type, } // Package the no-core distribution. + convert_line_endings($project_short_name, 'UNIX'); // 'h' is for dereference, we want to include the files, not the links - if (!drupal_exec("$tar -ch --file=- $project_short_name | $gzip -9 --no-name > $no_core_full_dest")) { + if (!drupal_exec("$tar -ch --file=- $project_short_name | $gzip -9 --no-name > $no_core_full_dest_tgz")) { + return 'error'; + } + $files[] = $no_core_file_path_tgz; + + convert_line_endings($project_short_name, 'ZIP'); + if (!drupal_exec("$zip -rq $no_core_full_dest_tgz $project_short_name")) { return 'error'; } - $files[] = $no_core_file_path; + $files[] = $no_core_file_path_zip; // CORE DISTRIBUTION. @@ -577,16 +610,26 @@ function package_release_contrib($type, } $core_id = "$release_file_id-core"; - // Build the drupal file path and the full file path. - $core_file_path = "$dest_rel/$core_id.tar.gz"; - $core_full_dest = "$dest_root/$core_file_path"; + + // Build the drupal file path and the full file path for tgz and zip. + $core_file_path_tgz = "$dest_rel/$core_id.tar.gz"; + $core_full_dest_tgz = "$dest_root/$core_file_path_tgz"; + $core_file_path_zip = "$dest_rel/$core_id.zip"; + $core_full_dest_zip = "$dest_root/$core_file_path_zip"; // Package the core distribution. + convert_line_endings($core_build_dir, 'UNIX'); // 'h' is for dereference, we want to include the files, not the links - if (!drupal_exec("$tar -ch --file=- $core_build_dir | $gzip -9 --no-name > $core_full_dest")) { + if (!drupal_exec("$tar -ch --file=- $core_build_dir | $gzip -9 --no-name > $core_full_dest_tgz")) { return 'error'; } - $files[] = $core_file_path; + $files[] = $core_file_path_tgz; + + convert_line_endings($core_build_dir, 'ZIP'); + if (!drupal_exec("$zip -rq $core_full_dest_zip $core_build_dir")) { + return 'error'; + } + $files[] = $core_file_path_zip; // Development releases may have changed package contents -- clear out // their package item summary so a fresh item summary will be inserted. @@ -606,6 +649,7 @@ function package_release_contrib($type, // Retrieve the package contents for the release. $package_contents_file = "$project_build_root/package_contents.txt"; if (file_exists($package_contents_file)) { + convert_file($package_contents_file, 'UNIX'); $lines = file($package_contents_file, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); foreach ($lines as $line) { if (is_numeric($line)) { @@ -624,7 +668,7 @@ function package_release_contrib($type, } } - // As soon as the tarball exists, update the DB + // Now that all the files exist, update the DB about them. package_release_update_node($nid, $files, $package_contents); if ($tgz_exists) { @@ -1217,6 +1261,126 @@ function translation_number_of_strings($ return $number_of_strings[$version]; } + +// ------------------------------------------------------------ +// Functions: Line ending conversion +// ------------------------------------------------------------ + + +/** + * Recursively convert line endings on all text files in a directory tree. + * + * @param $dir + * The root of the directory tree to traverse. + * @param $target_type + * The kind of line endings to convert the files to (can be 'UNIX' or 'DOS'). + * @param $exclude + * Optional array of filenames to exclude. + */ +function convert_line_endings($dir, $target_type, $exclude = array('.', '..')) { + if (is_dir($dir)) { + $fp = opendir($dir); + while (FALSE !== ($file = readdir($fp))) { + if (!in_array($file, $exclude)) { + $full_path = "$dir/$file"; + if (is_dir($full_path)) { + convert_line_endings($full_path, $target_type, $exclude); + } + elseif (needs_line_ending_conversion($full_path)) { + convert_file($full_path, $target_type); + } + } + } + closedir($fp); + } +} + +/** + * Helper function that decides if a given file needs line ending conversion. + * + * @param $filename + * Full path to the file to test. + * @param $whitelist + * Optional array of filename extensions to always convert. + * @param $blacklist + * Optional array of filename extensions to never convert. + * + * @return + * TRUE if the file should have line endings converted, otherwise FALSE. + */ +function needs_line_ending_conversion($filename, $whitelist = array('info'), $blacklist = array()) { + $path_info = pathinfo($filename); + if (in_array($path_info['extension'], $blacklist)) { + return FALSE; + } + if (in_array($path_info['extension'], $whitelist)) { + return TRUE; + } + + // If we don't know explicitly from the file extension, try the mime_type. + $mime_type = file_get_mimetype($filename); + $mime_parts = split('/', $mime_type); + + // text/* should always be converted + if ($mime_parts[0] == 'text') { + return TRUE; + } + // Otherwise, check the 2nd part of the mime_type. + switch ($mime_parts[1]) { + case 'x-httpd-php': + case 'x-httpd-php-source': + case 'x-httpd-php3': + case 'x-httpd-php3-preprocessed': + case 'x-httpd-php4': + case 'x-httpd-php5': + case 'x-httpd-php6': + case 'x-javascript': + case 'xml': + return TRUE; + } + // Otherwise, better be safe and not convert. + return FALSE; +} + +/** + * Converts line endings on a single file to the requested target file type. + * + * @param $file + * Full path to the file to convert. + * @param $target_type + * The kind of line endings to convert the file to (can be 'UNIX' or 'DOS'). + */ +function convert_file($file, $target_type) { + rename($file, "$file.convert-orig"); + $data = file_get_contents("$file.convert-orig"); + if ($target_type == 'UNIX') { + // Converting to UNIX is easy, since we just want everything to end with a + // single "\n". So, we convert "\r\n" (DOS) to "\n", then any single "\r" + // (Mac) and we're done. If the file is already UNIX endings, these are + // no-ops. + $data = str_replace(array("\r\n", "\r"), "\n", $data); + } + elseif ($target_type == 'DOS') { + // Converting to DOS is more complicated. If the file already has DOS + // line endings, the attempts to replace UNIX or Mac would break them. + // Therefore, we first convert any existing DOS line endings ("\r\n") to + // UNIX ("\n"). + $data = str_replace("\r\n", "\n", $data); + // After that, we can replace either UNIX ("\n") or Mac ("\r") with DOS: + $trans = array( + "\n" => "\r\n", + "\r" => "\r\n", + ); + $data = strtr($data, $trans); + } + file_put_contents($file, $data); + unlink("$file.convert-orig"); +} + +// ------------------------------------------------------------ +// Functions: Packaged distribution helper funcitons +// ------------------------------------------------------------ + /** * Construct a .make file which will build Drupal core. *