Changeset 5147 for sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/zip/class-builder.php
- Timestamp:
- 03/13/2017 05:56:27 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/zip/class-builder.php
r4727 r5147 11 11 class Builder { 12 12 13 /** 14 * The base directory for the ZIP files. 15 * Zip files will be stored in a sub-directory, such as: 16 * /tmp/plugin-zipfiles/hello-dolly/hello-dolly.zip 17 */ 18 const ZIP_DIR = '/tmp/plugin-zipfiles'; 19 const SVN_URL = 'https://plugins.svn.wordpress.org'; 20 21 public $zip_file = ''; 22 public $md5_file = ''; 23 protected $tmp_build_file = ''; 13 const TMP_DIR = '/tmp/plugin-zip-builder'; 14 const SVN_URL = 'http://plugins.svn.wordpress.org'; 15 const ZIP_SVN_URL = PLUGIN_ZIP_SVN_URL; 16 17 protected $zip_file = ''; 24 18 protected $tmp_build_dir = ''; 25 26 27 /** 28 * Generate a ZIP for a provided Plugin Version. 29 * 30 * @param string $plugin_slug The Plugin slug 31 * @param string $version The version to build (tag, or trunk) 32 */ 33 public function __construct( $slug, $version ) { 34 if ( ! is_dir( self::ZIP_DIR ) ) { 35 mkdir( self::ZIP_DIR, 0777, true ); 36 chmod( self::ZIP_DIR, 0777 ); 37 } 38 if ( ! is_dir( self::ZIP_DIR . '/' . $slug ) ) { 39 mkdir( self::ZIP_DIR . '/' . $slug, 0777, true ); 40 chmod( self::ZIP_DIR . '/' . $slug, 0777 ); 41 } 42 43 $this->slug = $slug; 44 $this->version = $version; 45 46 if ( 'trunk' == $this->version ) { 47 $this->zip_file = self::ZIP_DIR . "/{$this->slug}/{$this->slug}.zip"; 19 protected $tmp_dir = ''; 20 21 protected $slug = ''; 22 protected $version = ''; 23 protected $context = ''; 24 25 /** 26 * Generate a ZIP for a provided Plugin versions. 27 * 28 * @param string $slug The plugin slug. 29 * @param array $versions The versions of the plugin to build ZIPs for. 30 * @param string $context The context of this Builder instance (commit #, etc) 31 */ 32 public function build( $slug, $versions, $context = '' ) { 33 // Bail when in an unconfigured environment. 34 if ( ! defined( 'PLUGIN_ZIP_SVN_URL' ) ) { 35 return false; 36 } 37 38 $this->slug = $slug; 39 $this->versions = $versions; 40 $this->context = $context; 41 42 // General TMP directory 43 if ( ! is_dir( self::TMP_DIR ) ) { 44 mkdir( self::TMP_DIR, 0777, true ); 45 chmod( self::TMP_DIR, 0777 ); 46 } 47 48 // Temp Directory for this instance of the Builder class. 49 $this->tmp_dir = $this->generate_temporary_directory( self::TMP_DIR, $slug ); 50 51 // Create a checkout of the ZIP SVN 52 $res_checkout = SVN::checkout( 53 self::ZIP_SVN_URL, 54 $this->tmp_dir, 55 array( 56 'depth' => 'empty', 57 'username' => PLUGIN_ZIP_SVN_USER, 58 'password' => PLUGIN_ZIP_SVN_PASS, 59 ) 60 ); 61 62 if ( $res_checkout['result'] ) { 63 64 // Ensure the plugins folder exists within svn 65 $plugin_folder = "{$this->tmp_dir}/{$this->slug}/"; 66 $res = SVN::up( 67 $plugin_folder, 68 array( 69 'depth' => 'empty' 70 ) 71 ); 72 if ( ! is_dir( $plugin_folder ) ) { 73 mkdir( $plugin_folder, 0777, true ); 74 $res = SVN::add( $plugin_folder ); 75 } 76 if ( ! $res['result'] ) { 77 throw new Exception( __METHOD__ . ": Failed to create {$plugin_folder}." ); 78 } 48 79 } else { 49 $this->zip_file = self::ZIP_DIR . "/{$this->slug}/{$this->slug}.{$this->version}.zip"; 50 } 51 $this->md5_file = $this->zip_file . '.md5'; 52 53 } 54 55 /** 56 * Generate a ZIP for the plugin + version 57 */ 58 public function build() { 59 try { 60 $this->tmp_build_file = $this->generate_temporary_filename( dirname( $this->zip_file ), "tmp-{$this->slug}.{$this->version}", '.zip' ); 61 $this->tmp_build_dir = $this->tmp_build_file . '-files'; 62 mkdir( $this->tmp_build_dir, 0777, true ); 63 64 $this->export_plugin(); 65 $this->fix_directory_dates(); 66 $this->generate_zip(); 67 $this->move_into_place(); 68 $this->generate_md5(); 69 70 $this->cleanup(); 71 72 return true; 73 } catch( Exception $e ) { 74 $this->cleanup(); 75 throw $e; 76 }/* finally { // PHP 5.5+, meta.svn is limited to PHP 5.4 code still. 77 $this->cleanup(); 78 }*/ 79 } 80 81 /** 82 * Generates a temporary unique file in a given directory 80 throw new Exception( __METHOD__ . ": Failed to create checkout of {$svn_url}." ); 81 } 82 83 // Build the requested ZIPs 84 foreach ( $versions as $version ) { 85 $this->version = $version; 86 87 if ( 'trunk' == $version ) { 88 $this->zip_file = "{$this->tmp_dir}/{$this->slug}/{$this->slug}.zip"; 89 } else { 90 $this->zip_file = "{$this->tmp_dir}/{$this->slug}/{$this->slug}.{$version}.zip"; 91 } 92 93 // Pull the ZIP file down we're going to modify, which may not already exist. 94 SVN::up( $this->zip_file ); 95 96 try { 97 98 $this->tmp_build_dir = $this->zip_file . '-files'; 99 mkdir( $this->tmp_build_dir, 0777, true ); 100 101 $this->export_plugin(); 102 $this->fix_directory_dates(); 103 $this->generate_zip(); 104 $this->cleanup_plugin_tmp(); 105 106 } catch( Exception $e ) { 107 // In event of error, skip this file this time. 108 $this->cleanup_plugin_tmp(); 109 110 // Perform an SVN up to revert any changes made. 111 SVN::up( $this->zip_file ); 112 continue; 113 } 114 115 // Add the ZIP file to SVN - This is only really needed for new files which don't exist in SVN. 116 SVN::add( $this->zip_file ); 117 } 118 119 $res = SVN::commit( 120 $this->tmp_dir, 121 $this->context ? $this->context : "Updated ZIPs for {$this->slug}.", 122 array( 123 'username' => PLUGIN_ZIP_SVN_USER, 124 'password' => PLUGIN_ZIP_SVN_PASS, 125 ) 126 ); 127 128 $this->invalidate_zip_caches( $versions ); 129 130 $this->cleanup(); 131 132 if ( ! $res['result'] ) { 133 if ( $res['errors'] ) { 134 throw new Exception( __METHOD__ . ': Failed to commit the new ZIPs: ' . $res['errors'][0]['error_message'] ); 135 } else { 136 throw new Exception( __METHOD__ . ': Commit failed without error, maybe there were no modified files?' ); 137 } 138 } 139 140 return true; 141 } 142 143 /** 144 * Generates a temporary unique directory in a given directory 83 145 * 84 146 * Performs a similar job to `tempnam()` with an added suffix and doesn't … … 92 154 * @param string $suffix The file suffix, optional. 93 155 * 94 * @return string Filename of unique temporary file.95 */ 96 protected function generate_temporary_ filename( $dir, $prefix, $suffix = '' ) {156 * @return string Path of unique temporary directory. 157 */ 158 protected function generate_temporary_directory( $dir, $prefix, $suffix = '' ) { 97 159 $i = 0; 98 160 do { … … 106 168 107 169 fclose( $fp ); 170 171 // Convert file to directory. 172 unlink( $filename ); 173 if ( ! mkdir( $filename, 0777, true ) ) { 174 throw new Exception( __METHOD__ . ': Could not convert temporary filename to directory.' ); 175 } 176 chmod( $filename, 0777 ); 108 177 109 178 return $filename; … … 168 237 ) ); 169 238 if ( ! $latest_file_modified_timestamp ) { 170 throw new Exception( _ METHOD__ . ': Unable to locate the latest modified files timestamp.', 503 );239 throw new Exception( __METHOD__ . ': Unable to locate the latest modified files timestamp.', 503 ); 171 240 } 172 241 … … 182 251 */ 183 252 protected function generate_zip() { 184 // We have to remove the temporary 0-byte file first as zip will complain about not being able to find the zip structures. 185 unlink( $this->tmp_build_file ); 253 // If we're building an existing zip, remove the existing file first. 254 if ( file_exists( $this->zip_file ) ) { 255 unlink( $this->zip_file ); 256 } 186 257 $this->exec( sprintf( 187 258 'cd %s && find %s -print0 | sort -z | xargs -0 zip -Xu %s 2>&1', 188 259 escapeshellarg( $this->tmp_build_dir ), 189 260 escapeshellarg( $this->slug ), 190 escapeshellarg( $this-> tmp_build_file )261 escapeshellarg( $this->zip_file ) 191 262 ), $zip_build_output, $return_value ); 192 263 … … 196 267 } 197 268 198 /** 199 * Moves the completed ZIP into it's real-life location. 200 */ 201 protected function move_into_place() { 202 $this->exec( sprintf( 203 'mv -f %s %s', 204 escapeshellarg( $this->tmp_build_file ), 205 escapeshellarg( $this->zip_file ) 206 ), $output, $return_value ); 207 208 if ( $return_value ) { 209 throw new Exception( __METHOD__ . ': Could not move ZIP into place.', 503 ); 210 } 211 } 212 213 /** 214 * Generates the MD5 for the ZIP file used for serving. 215 * 216 * This can also be used for generating a package signature in the future. 217 */ 218 protected function generate_md5() { 219 $this->exec( sprintf( 220 "md5sum %s | head -c 32 > %s", 221 escapeshellarg( $this->zip_file ), 222 escapeshellarg( $this->md5_file ) 223 ), $output, $return_code ); 224 225 if ( $return_code ) { 226 throw new Exception( __METHOD__ . ': Failed to create file checksum.', 503 ); 269 270 /** 271 * Purge ZIP caches after ZIP building. 272 * 273 * @param array $versions The list of plugin versions of modified zips. 274 * @return bool 275 */ 276 public function invalidate_zip_caches( $versions ) { 277 // TODO: Implement PURGE 278 return true; 279 if ( ! defined( 'PLUGIN_ZIP_X_ACCEL_REDIRECT_LOCATION' ) ) { 280 return true; 281 } 282 283 foreach ( $versions as $version ) { 284 if ( 'trunk' == $version ) { 285 $zip = "{$this->slug}/{$this->slug}.zip"; 286 } else { 287 $zip = "{$this->slug}/{$this->slug}.{$version}.zip"; 288 } 289 290 foreach ( $plugins_downloads_load_balancer /* TODO */ as $lb ) { 291 $url = 'http://' . $lb . PLUGIN_ZIP_X_ACCEL_REDIRECT_LOCATION . $zip; 292 wp_remote_request( 293 $url, 294 array( 295 'method' => 'PURGE', 296 ) 297 ); 298 } 227 299 } 228 300 } … … 232 304 */ 233 305 protected function cleanup() { 234 if ( $this->tmp_build_file && file_exists( $this->tmp_build_file ) ) { 235 unlink( $this->tmp_build_file ); 236 } 306 if ( $this->tmp_dir ) { 307 $this->exec( sprintf( 'rm -rf %s', escapeshellarg( $this->tmp_dir ) ) ); 308 } 309 } 310 311 /** 312 * Cleans up any temporary directories created by the ZIP builder for a specific build. 313 */ 314 protected function cleanup_plugin_tmp() { 237 315 if ( $this->tmp_build_dir ) { 238 316 $this->exec( sprintf( 'rm -rf %s', escapeshellarg( $this->tmp_build_dir ) ) );
Note: See TracChangeset
for help on using the changeset viewer.