diff options
| -rw-r--r-- | crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs | 4 | ||||
| -rw-r--r-- | crates/shirabe-external-packages/src/seld/mod.rs | 2 | ||||
| -rw-r--r-- | crates/shirabe-external-packages/src/seld/phar_utils/linter.rs | 8 | ||||
| -rw-r--r-- | crates/shirabe-external-packages/src/seld/phar_utils/mod.rs | 5 | ||||
| -rw-r--r-- | crates/shirabe-external-packages/src/seld/phar_utils/timestamps.rs | 18 | ||||
| -rw-r--r-- | crates/shirabe-php-shim/src/lib.rs | 8 | ||||
| -rw-r--r-- | crates/shirabe/src/compiler.rs | 479 | ||||
| -rw-r--r-- | crates/shirabe/src/lib.rs | 1 |
8 files changed, 0 insertions, 525 deletions
diff --git a/crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs b/crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs index 3546056..31383e2 100644 --- a/crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs +++ b/crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs @@ -16,8 +16,4 @@ impl CaBundle { pub fn validate_ca_file(_ca_file: &str, _logger: ()) -> bool { todo!() } - - pub fn get_bundled_ca_bundle_path() -> String { - todo!() - } } diff --git a/crates/shirabe-external-packages/src/seld/mod.rs b/crates/shirabe-external-packages/src/seld/mod.rs index ea1253b..b7c12c4 100644 --- a/crates/shirabe-external-packages/src/seld/mod.rs +++ b/crates/shirabe-external-packages/src/seld/mod.rs @@ -1,7 +1,5 @@ pub mod json_lint; -pub mod phar_utils; pub mod signal; pub use json_lint::*; -pub use phar_utils::*; pub use signal::*; diff --git a/crates/shirabe-external-packages/src/seld/phar_utils/linter.rs b/crates/shirabe-external-packages/src/seld/phar_utils/linter.rs deleted file mode 100644 index 27238d3..0000000 --- a/crates/shirabe-external-packages/src/seld/phar_utils/linter.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[derive(Debug)] -pub struct Linter; - -impl Linter { - pub fn lint(_file: &str, _php_versions: &[String]) -> anyhow::Result<()> { - todo!() - } -} diff --git a/crates/shirabe-external-packages/src/seld/phar_utils/mod.rs b/crates/shirabe-external-packages/src/seld/phar_utils/mod.rs deleted file mode 100644 index fed35a8..0000000 --- a/crates/shirabe-external-packages/src/seld/phar_utils/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod linter; -pub mod timestamps; - -pub use linter::*; -pub use timestamps::*; diff --git a/crates/shirabe-external-packages/src/seld/phar_utils/timestamps.rs b/crates/shirabe-external-packages/src/seld/phar_utils/timestamps.rs deleted file mode 100644 index 0a25389..0000000 --- a/crates/shirabe-external-packages/src/seld/phar_utils/timestamps.rs +++ /dev/null @@ -1,18 +0,0 @@ -#[derive(Debug)] -pub struct Timestamps { - file: String, -} - -impl Timestamps { - pub fn new(_file: &str) -> Self { - todo!() - } - - pub fn update_timestamps(&mut self, _date: &str) -> anyhow::Result<()> { - todo!() - } - - pub fn save(&self, _file: &str, _format: i64) -> anyhow::Result<()> { - todo!() - } -} diff --git a/crates/shirabe-php-shim/src/lib.rs b/crates/shirabe-php-shim/src/lib.rs index 873f7f4..7aa3c4b 100644 --- a/crates/shirabe-php-shim/src/lib.rs +++ b/crates/shirabe-php-shim/src/lib.rs @@ -1683,14 +1683,6 @@ pub fn http_build_query(_data: &[(&str, &str)], _sep_str: &str, _sep: &str) -> S todo!() } -pub fn token_get_all(_source: &str) -> Vec<PhpMixed> { - todo!() -} - -pub const T_COMMENT: i64 = 315; -pub const T_DOC_COMMENT: i64 = 316; -pub const T_WHITESPACE: i64 = 317; - pub fn dirname_levels(_path: &str, _levels: i64) -> String { todo!() } diff --git a/crates/shirabe/src/compiler.rs b/crates/shirabe/src/compiler.rs deleted file mode 100644 index 05177d6..0000000 --- a/crates/shirabe/src/compiler.rs +++ /dev/null @@ -1,479 +0,0 @@ -//! ref: composer/src/Composer/Compiler.php - -use indexmap::IndexMap; -use shirabe_external_packages::composer::ca_bundle::CaBundle; -use shirabe_external_packages::composer::pcre::Preg; -use shirabe_external_packages::seld::phar_utils::Linter; -use shirabe_external_packages::seld::phar_utils::Timestamps; -use shirabe_external_packages::symfony::finder::Finder; -use shirabe_external_packages::symfony::finder::SplFileInfo; -use shirabe_php_shim::{ - Phar, PhpMixed, RuntimeException, T_COMMENT, T_DOC_COMMENT, T_WHITESPACE, - UnexpectedValueException, array_search, date_format_to_strftime, file_exists, - file_get_contents, strcmp, strtr, strtr_array, token_get_all, -}; - -use crate::json::JsonFile; -use crate::util::Git; -use crate::util::ProcessExecutor; - -#[derive(Debug)] -pub struct Compiler { - version: String, - branch_alias_version: String, - version_date: chrono::DateTime<chrono::Utc>, -} - -impl Compiler { - pub fn new() -> Self { - Self { - version: String::new(), - branch_alias_version: String::new(), - version_date: chrono::Utc::now(), - } - } - - /// Compiles composer into a single phar file - pub fn compile(&mut self, phar_file: &str) -> anyhow::Result<()> { - let phar_file = if phar_file.is_empty() { - "composer.phar" - } else { - phar_file - }; - - if file_exists(phar_file) { - shirabe_php_shim::unlink(phar_file); - } - - let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(None))); - - let command = Git::build_rev_list_command( - &process, - vec![ - "-n1".to_string(), - "--format=%H".to_string(), - "HEAD".to_string(), - ], - ); - let mut output = String::new(); - // PHP: dirname(__DIR__, 2) - going up 2 levels from src/Composer to the repo root - let repo_root = shirabe_php_shim::dirname_levels(file!(), 2); - if process - .borrow_mut() - .execute_args(&command, &mut output, Some(&repo_root)) - != 0 - { - return Err(RuntimeException { - message: "Can't run git rev-list. You must ensure to run compile from composer git repository clone and that git binary is available.".to_string(), - code: 0, - }.into()); - } - self.version = Git::parse_rev_list_output(&output, &process) - .trim() - .to_string(); - - let command = Git::build_rev_list_command( - &process, - vec![ - "-n1".to_string(), - "--format=%ci".to_string(), - "HEAD".to_string(), - ], - ); - let mut output = String::new(); - if process - .borrow_mut() - .execute_args(&command, &mut output, Some(&repo_root)) - != 0 - { - return Err(RuntimeException { - message: "Can't run git rev-list. You must ensure to run compile from composer git repository clone and that git binary is available.".to_string(), - code: 0, - }.into()); - } - - let version_date_str = Git::parse_rev_list_output(&output, &process); - self.version_date = - chrono::DateTime::parse_from_str(version_date_str.trim(), "%Y-%m-%d %H:%M:%S %z") - .map(|dt| dt.with_timezone(&chrono::Utc))?; - - let mut git_describe_output = String::new(); - if process.borrow_mut().execute_args( - &[ - "git".to_string(), - "describe".to_string(), - "--tags".to_string(), - "--exact-match".to_string(), - "HEAD".to_string(), - ], - &mut git_describe_output, - Some(&repo_root), - ) == 0 - { - self.version = git_describe_output.trim().to_string(); - } else { - // get branch-alias defined in composer.json for dev-main (if any) - let local_config_path = format!("{}/composer.json", repo_root); - let mut file = JsonFile::new(local_config_path.clone(), None, None)?; - let local_config = file.read()?; - if let Some(branch_alias) = local_config - .as_array() - .and_then(|m| m.get("extra")) - .and_then(|e| e.as_array()) - .and_then(|m| m.get("branch-alias")) - .and_then(|b| b.as_array()) - .and_then(|m| m.get("dev-main")) - .and_then(|v| v.as_string()) - { - self.branch_alias_version = branch_alias.to_string(); - } - } - - if self.version.is_empty() { - return Err(UnexpectedValueException { - message: "Version detection failed".to_string(), - code: 0, - } - .into()); - } - - let mut phar = Phar::new_phar(phar_file.to_string(), 0, "composer.phar"); - phar.set_signature_algorithm(Phar::SHA512); - - phar.start_buffering(); - - let finder_sort = |a: &SplFileInfo, b: &SplFileInfo| -> i64 { - strcmp( - &strtr(&a.get_real_path().unwrap_or_default(), "\\", "/"), - &strtr(&b.get_real_path().unwrap_or_default(), "\\", "/"), - ) - }; - - // Add Composer sources - let mut finder = Finder::new(); - finder - .files() - .ignore_vcs(true) - .name("*.php") - .not_name("Compiler.php") - .not_name("ClassLoader.php") - .not_name("InstalledVersions.php") - .r#in(&format!("{}/src/Composer/..", repo_root)) - .sort(finder_sort); - for file in finder.iter() { - self.add_file(&mut phar, &file, true)?; - } - // Add runtime utilities separately to make sure they retain the docblocks as these will get copied into projects - self.add_file( - &mut phar, - &SplFileInfo::new(&format!( - "{}/src/Composer/Autoload/ClassLoader.php", - repo_root - )), - false, - )?; - self.add_file( - &mut phar, - &SplFileInfo::new(&format!("{}/src/Composer/InstalledVersions.php", repo_root)), - false, - )?; - - // Add Composer resources - let mut finder = Finder::new(); - finder - .files() - .r#in(&format!("{}/res", repo_root)) - .sort(finder_sort); - for file in finder.iter() { - self.add_file(&mut phar, &file, false)?; - } - - // Add vendor files - let mut finder = Finder::new(); - finder - .files() - .ignore_vcs(true) - .not_path(r"/\/(composer\.(?:json|lock)|[A-Z]+\.md(?:own)?|\.gitignore|appveyor.yml|phpunit\.xml\.dist|phpstan\.neon\.dist|phpstan-config\.neon|phpstan-baseline\.neon|UPGRADE.*\.(?:md|txt))$/") - .not_path(r"/bin\/(jsonlint|validate-json|simple-phpunit|phpstan|phpstan\.phar)(\.bat)?$/") - .not_path("justinrainbow/json-schema/demo/") - .not_path("justinrainbow/json-schema/dist/") - .not_path("justinrainbow/json-schema/bin/") - .not_path("composer/pcre/extension.neon") - .not_path("composer/LICENSE") - .exclude("Tests") - .exclude("tests") - .exclude("docs") - .r#in(&format!("{}/vendor/", repo_root)) - .sort(finder_sort); - - let mut extra_files: IndexMap<String, String> = IndexMap::new(); - let extra_file_paths = vec![ - format!("{}/vendor/composer/installed.json", repo_root), - format!( - "{}/vendor/composer/spdx-licenses/res/spdx-exceptions.json", - repo_root - ), - format!( - "{}/vendor/composer/spdx-licenses/res/spdx-licenses.json", - repo_root - ), - CaBundle::get_bundled_ca_bundle_path(), - format!( - "{}/vendor/symfony/console/Resources/bin/hiddeninput.exe", - repo_root - ), - format!( - "{}/vendor/symfony/console/Resources/completion.bash", - repo_root - ), - ]; - for file_path in &extra_file_paths { - let real = shirabe_php_shim::realpath(file_path).unwrap_or_default(); - extra_files.insert(file_path.clone(), real); - if !file_exists(file_path) { - return Err(RuntimeException { - message: format!( - "Extra file listed is missing from the filesystem: {}", - file_path - ), - code: 0, - } - .into()); - } - } - let mut unexpected_files: Vec<String> = vec![]; - - for file in finder.iter() { - let real_path = file.get_real_path().unwrap_or_default(); - if let Some(index) = array_search(&real_path, &extra_files) { - extra_files.shift_remove(&index); - } else if !Preg::is_match(r"{(^LICENSE(?:\.txt)?$|\.php$)}", &file.get_filename())? { - unexpected_files.push(file.get_pathname()); - } - - if Preg::is_match(r"{\.php[\d.]*$}", &file.get_filename())? { - self.add_file(&mut phar, &file, true)?; - } else { - self.add_file(&mut phar, &file, false)?; - } - } - - if !extra_files.is_empty() { - return Err(RuntimeException { - message: format!( - "These files were expected but not added to the phar, they might be excluded or gone from the source package:\n{}", - shirabe_php_shim::var_export(&PhpMixed::Null, true) // TODO: var_export of extra_files - ), - code: 0, - } - .into()); - } - if !unexpected_files.is_empty() { - return Err(RuntimeException { - message: format!( - "These files were unexpectedly added to the phar, make sure they are excluded or listed in $extraFiles:\n{}", - shirabe_php_shim::var_export(&PhpMixed::Null, true) // TODO: var_export of unexpected_files - ), - code: 0, - } - .into()); - } - - // Add bin/composer - self.add_composer_bin(&mut phar)?; - - // Stubs - phar.set_stub(&self.get_stub()); - - phar.stop_buffering(); - - // disabled for interoperability with systems without gzip ext - // $phar->compressFiles(\Phar::GZ); - - let license_file = SplFileInfo::new(&format!("{}/LICENSE", repo_root)); - self.add_file(&mut phar, &license_file, false)?; - - drop(phar); - - // re-sign the phar with reproducible timestamp / signature - let mut util = Timestamps::new(phar_file); - util.update_timestamps( - &self - .version_date - .format(date_format_to_strftime("Y-m-d H:i:s")) - .to_string(), - )?; - util.save(phar_file, Phar::SHA512)?; - - Linter::lint( - phar_file, - &[ - "vendor/symfony/console/Attribute/AsCommand.php".to_string(), - "vendor/symfony/polyfill-intl-grapheme/bootstrap80.php".to_string(), - "vendor/symfony/polyfill-intl-normalizer/bootstrap80.php".to_string(), - "vendor/symfony/polyfill-mbstring/bootstrap80.php".to_string(), - "vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php".to_string(), - "vendor/symfony/service-contracts/Attribute/SubscribedService.php".to_string(), - "vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.php".to_string(), - "vendor/symfony/polyfill-php84/Resources/Deprecated.php".to_string(), - "vendor/symfony/polyfill-php84/Resources/RoundingMode.php".to_string(), - "vendor/symfony/polyfill-php84/bootstrap82.php".to_string(), - ], - )?; - - Ok(()) - } - - fn get_relative_file_path(&self, file: &SplFileInfo) -> String { - let real_path = file.get_real_path().unwrap_or_default(); - // PHP: dirname(__DIR__, 2) . DIRECTORY_SEPARATOR - repo root + separator - let repo_root = shirabe_php_shim::dirname_levels(file!(), 2); - let path_prefix = format!("{}/", repo_root); - - let relative_path = if let Some(stripped) = real_path.strip_prefix(&path_prefix) { - stripped.to_string() - } else { - real_path.clone() - }; - - strtr(&relative_path, "\\", "/") - } - - fn add_file(&self, phar: &mut Phar, file: &SplFileInfo, strip: bool) -> anyhow::Result<()> { - let path = self.get_relative_file_path(file); - let content = file_get_contents(&file.get_path()).unwrap_or_default(); - let mut content = if strip { - self.strip_whitespace(&content) - } else if file.get_filename() == "LICENSE" { - format!("\n{}\n", content) - } else { - content - }; - - if path == "src/Composer/Composer.php" { - let mut replacements: IndexMap<String, String> = IndexMap::new(); - replacements.insert("@package_version@".to_string(), self.version.clone()); - replacements.insert( - "@package_branch_alias_version@".to_string(), - self.branch_alias_version.clone(), - ); - replacements.insert( - "@release_date@".to_string(), - self.version_date - .format(date_format_to_strftime("Y-m-d H:i:s")) - .to_string(), - ); - content = strtr_array(&content, &replacements); - content = Preg::replace( - r"{SOURCE_VERSION = '[^']+';}", - "SOURCE_VERSION = '';", - &content, - )?; - } - - phar.add_from_string(&path, &content); - - Ok(()) - } - - fn add_composer_bin(&self, phar: &mut Phar) -> anyhow::Result<()> { - let repo_root = shirabe_php_shim::dirname_levels(file!(), 2); - let content = file_get_contents(&format!("{}/bin/composer", repo_root)).unwrap_or_default(); - let content = Preg::replace(r"{^#!/usr/bin/env php\s*}", "", &content)?; - phar.add_from_string("bin/composer", &content); - Ok(()) - } - - /// Removes whitespace from a PHP source string while preserving line numbers. - fn strip_whitespace(&self, source: &str) -> String { - if !shirabe_php_shim::function_exists("token_get_all") { - return source.to_string(); - } - - let mut output = String::new(); - for token in token_get_all(source) { - match &token { - PhpMixed::String(s) => { - output.push_str(s); - } - PhpMixed::List(arr) if arr.len() >= 2 => { - let token_type = arr[0].as_int().unwrap_or(0); - let token_value = arr[1].as_string().unwrap_or(""); - if token_type == T_COMMENT || token_type == T_DOC_COMMENT { - let newline_count = - shirabe_php_shim::substr_count(token_value, "\n") as usize; - output.push_str(&"\n".repeat(newline_count)); - } else if token_type == T_WHITESPACE { - // reduce wide spaces - let whitespace = Preg::replace(r"{[ \t]+}", " ", token_value) - .unwrap_or_else(|_| token_value.to_string()); - // normalize newlines to \n - let whitespace = Preg::replace(r"{(?:\r\n|\r|\n)}", "\n", &whitespace) - .unwrap_or(whitespace); - // trim leading spaces - let whitespace = - Preg::replace(r"{\n +}", "\n", &whitespace).unwrap_or(whitespace); - output.push_str(&whitespace); - } else { - output.push_str(token_value); - } - } - _ => {} - } - } - - output - } - - fn get_stub(&self) -> String { - let stub = r#"#!/usr/bin/env php -<?php -/* - * This file is part of Composer. - * - * (c) Nils Adermann <naderman@naderman.de> - * Jordi Boggiano <j.boggiano@seld.be> - * - * For the full copyright and license information, please view - * the license that is located at the bottom of this file. - */ - -// Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264 -if (extension_loaded('apc') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN) && filter_var(ini_get('apc.cache_by_default'), FILTER_VALIDATE_BOOLEAN)) { - if (version_compare(phpversion('apc'), '3.0.12', '>=')) { - ini_set('apc.cache_by_default', 0); - } else { - fwrite(STDERR, 'Warning: APC <= 3.0.12 may cause fatal errors when running composer commands.'.PHP_EOL); - fwrite(STDERR, 'Update APC, or set apc.enable_cli or apc.cache_by_default to 0 in your php.ini.'.PHP_EOL); - } -} - -if (!class_exists('Phar')) { - echo 'PHP\'s phar extension is missing. Composer requires it to run. Enable the extension or recompile php without --disable-phar then try again.' . PHP_EOL; - exit(1); -} - -Phar::mapPhar('composer.phar'); - -"#; - - // add warning once the phar is older than 60 days - let mut stub = stub.to_string(); - if Preg::is_match(r"{^[a-f0-9]+$}", &self.version).unwrap_or(false) { - let warning_time = self.version_date.timestamp() + 60 * 86400; - stub.push_str(&format!( - "define('COMPOSER_DEV_WARNING_TIME', {});\n", - warning_time - )); - } - - stub.push_str( - r#"require 'phar://composer.phar/bin/composer'; - -__HALT_COMPILER(); -"#, - ); - - stub - } -} diff --git a/crates/shirabe/src/lib.rs b/crates/shirabe/src/lib.rs index 9fb9f5f..1e17b72 100644 --- a/crates/shirabe/src/lib.rs +++ b/crates/shirabe/src/lib.rs @@ -2,7 +2,6 @@ pub mod advisory; pub mod autoload; pub mod cache; pub mod command; -pub mod compiler; pub mod composer; pub mod config; pub mod console; |
