@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 203 lines 5.0 kB view raw
1<?php 2 3final class JavelinPeastLibrary extends Phobject { 4 5 /** 6 * The expected Peast version 7 * 8 * This is the version that would be obtained by downloading and including an 9 * up-to-date Peast. The //actual// Peast version may vary. 10 */ 11 const EXPECTED_VERSION = '1.17.4'; 12 13 const REPO = 'https://github.com/mck89/peast'; 14 15 /** 16 * The expected md5 hash of the PHP-parser packages listed above. 17 */ 18 private static $hashes = array( 19 // v1.17.4.tar.gz 20 'b6fe4a3345ec7653adae94cedb1b5405', 21 // v1.17.4.zip 22 'e8056c15c52de1dc2a2318462a0a4a61', 23 ); 24 25 private static $version; 26 27 public static function build() { 28 $root = phutil_get_library_root('phorge'); 29 $path = Filesystem::resolvePath($root.'/../support/peast'); 30 $target = self::getPath(); 31 $version = self::EXPECTED_VERSION; 32 33 if (extension_loaded('zip')) { 34 $target_path = $path.'/peast-'.$version.'.zip'; 35 36 id(new PhutilGitHubReleaseDownloader(self::REPO, $target_path)) 37 ->setDownloadFormat('zip') 38 ->setVersion($version) 39 ->validateDownload(self::$hashes) 40 ->download(); 41 42 $zip = new ZipArchive(); 43 $result = $zip->open($target_path); 44 if (!$result) { 45 throw new Exception( 46 pht( 47 'Opening %s failed! %s.', 48 $target_path, 49 $result === false ? 'Unknown Error' : (string)$result)); 50 } 51 52 $zip->extractTo($target); 53 54 // Renames fail if the target directory exists. 55 Filesystem::remove("{$target}/Peast"); 56 57 Filesystem::rename( 58 "{$target}/peast-{$version}/lib/Peast", 59 "{$target}/Peast"); 60 61 Filesystem::remove("{$target}/peast-{$version}"); 62 } else if ( 63 extension_loaded('phar') && 64 extension_loaded('zlib')) { 65 66 $target_path = $path.'/peast-'.$version.'.tar.gz'; 67 68 id(new PhutilGitHubReleaseDownloader(self::REPO, $target_path)) 69 ->setDownloadFormat('tar.gz') 70 ->setVersion($version) 71 ->validateDownload(self::$hashes) 72 ->download(); 73 74 id(new PharData($target_path))->extractTo($target, null, true); 75 76 // Renames fail if the target directory exists. 77 Filesystem::remove("{$target}/Peast"); 78 79 Filesystem::rename( 80 "{$target}/peast-{$version}/lib/Peast", 81 "{$target}/Peast"); 82 83 Filesystem::remove("{$target}/peast-{$version}"); 84 } else if (Filesystem::binaryExists('git')) { 85 execx( 86 'git clone --single-branch --depth 1 --branch %s %s %s', 87 'v'.self::EXPECTED_VERSION, 88 self::REPO, 89 $path.'/git'); 90 91 // Renames fail if the target directory exists. 92 Filesystem::remove("{$path}/Peast"); 93 94 Filesystem::rename( 95 "{$path}/git/lib/Peast", 96 "{$path}/Peast"); 97 98 Filesystem::remove($path.'/git'); 99 } else { 100 throw new Exception( 101 pht('No viable means to download Peast is available.')); 102 } 103 104 Filesystem::writeFile($target.'/version', $version); 105 } 106 107 /** 108 * Returns human-readable instructions for building PHP-parser. 109 * 110 * @return string 111 */ 112 public static function getBuildInstructions() { 113 $root = phutil_get_library_root('phorge'); 114 $script = Filesystem::resolvePath( 115 $root.'/../support/peast/build-peast.php'); 116 117 return phutil_console_format( 118 "%s:\n\n \$ %s\n", 119 pht( 120 "Your version of '%s' is unbuilt or out of date. Run this ". 121 "script to build it.", 122 'peast'), 123 $script); 124 } 125 126 private static function peastAutoloader($classname) { 127 $lib = self::getPath(); 128 129 if (strncmp($classname, 'Peast', 5)) { 130 return false; 131 } 132 133 $path = $lib.'/'.str_replace('\\', '/', $classname).'.php'; 134 135 if (!Filesystem::pathExists($path)) { 136 return false; 137 } 138 139 require $path; 140 141 return true; 142 } 143 144 public static function loadLibrary() { 145 static $loaded = false; 146 147 if (!$loaded) { 148 if (!self::isAvailable()) { 149 try { 150 self::build(); 151 } catch (Throwable $ex) { 152 throw new Exception(self::getBuildInstructions(), 0, $ex); 153 } 154 } 155 156 spl_autoload_register('JavelinPeastLibrary::peastAutoloader'); 157 } 158 } 159 160 /** 161 * Returns the path to the Peast library. 162 * 163 * @return string 164 */ 165 public static function getPath() { 166 static $path = null; 167 168 if (!$path) { 169 $root = phutil_get_library_root('phorge'); 170 $path = Filesystem::resolvePath($root.'/../support/peast/lib'); 171 } 172 173 return $path; 174 } 175 176 /** 177 * Returns the Peast version. 178 * 179 * @return string 180 */ 181 public static function getVersion() { 182 if (self::$version === null) { 183 $lib = self::getPath(); 184 185 if (Filesystem::pathExists($lib.'/version')) { 186 self::$version = trim(Filesystem::readFile($lib.'/version')); 187 } 188 } 189 190 return self::$version; 191 } 192 193 /** 194 * Checks if PHP-parser is built and up-to-date. 195 * 196 * @return bool 197 */ 198 public static function isAvailable() { 199 $version = self::getVersion(); 200 return $version === self::EXPECTED_VERSION; 201 } 202 203}