diff options
Diffstat (limited to 'crates')
173 files changed, 4365 insertions, 4475 deletions
diff --git a/crates/shirabe-external-packages/src/symfony/console/command/command.rs b/crates/shirabe-external-packages/src/symfony/console/command/command.rs index 2040f95..e737b58 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/command.rs @@ -178,16 +178,13 @@ impl CommandData { description.to_string(), default.clone(), )?)?; - if self.full_definition.is_some() { - self.full_definition - .as_mut() - .unwrap() - .add_argument(InputArgument::new( - name.to_string(), - mode, - description.to_string(), - default, - )?)?; + if let Some(full_definition) = self.full_definition.as_mut() { + full_definition.add_argument(InputArgument::new( + name.to_string(), + mode, + description.to_string(), + default, + )?)?; } Ok(self) @@ -214,17 +211,14 @@ impl CommandData { description.to_string(), default.clone(), )?)?; - if self.full_definition.is_some() { - self.full_definition - .as_mut() - .unwrap() - .add_option(InputOption::new( - name, - shortcut, - mode, - description.to_string(), - default, - )?)?; + if let Some(full_definition) = self.full_definition.as_mut() { + full_definition.add_option(InputOption::new( + name, + shortcut, + mode, + description.to_string(), + default, + )?)?; } Ok(self) diff --git a/crates/shirabe-external-packages/src/symfony/console/command/complete_command.rs b/crates/shirabe-external-packages/src/symfony/console/command/complete_command.rs index 522bb78..80186a3 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/complete_command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/complete_command.rs @@ -373,7 +373,7 @@ impl Command for CompleteCommand { } } - completion_output.write(&suggestions, &mut *output.borrow_mut()); + completion_output.write(&suggestions, &*output.borrow_mut()); Ok(0) })(); diff --git a/crates/shirabe-external-packages/src/symfony/console/command/dump_completion_command.rs b/crates/shirabe-external-packages/src/symfony/console/command/dump_completion_command.rs index c8947b8..cb76ff8 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/dump_completion_command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/dump_completion_command.rs @@ -34,6 +34,12 @@ impl DerefMut for DumpCompletionCommand { } } +impl Default for DumpCompletionCommand { + fn default() -> Self { + Self::new() + } +} + impl DumpCompletionCommand { pub const DEFAULT_NAME: &'static str = "completion"; pub const DEFAULT_DESCRIPTION: &'static str = "Dump the shell completion script"; diff --git a/crates/shirabe-external-packages/src/symfony/console/command/help_command.rs b/crates/shirabe-external-packages/src/symfony/console/command/help_command.rs index d98152f..2346258 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/help_command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/help_command.rs @@ -39,6 +39,12 @@ impl DerefMut for HelpCommand { } } +impl Default for HelpCommand { + fn default() -> Self { + Self::new() + } +} + impl HelpCommand { pub fn new() -> Self { let mut command = HelpCommand { diff --git a/crates/shirabe-external-packages/src/symfony/console/command/list_command.rs b/crates/shirabe-external-packages/src/symfony/console/command/list_command.rs index bfaece7..1d467ae 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/list_command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/list_command.rs @@ -38,6 +38,12 @@ impl DerefMut for ListCommand { } } +impl Default for ListCommand { + fn default() -> Self { + Self::new() + } +} + impl ListCommand { pub fn new() -> Self { let mut command = ListCommand { diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs index 1fad8f8..a32c95d 100644 --- a/crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs +++ b/crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs @@ -149,11 +149,13 @@ impl ProcessHelper { .write(&[stopped], false, output_interface::OUTPUT_NORMAL); } - if !process.is_successful() && error.is_some() { + if !process.is_successful() + && let Some(error) = error + { output.borrow().writeln( &[format!( "<error>{}</error>", - shirabe_php_shim::PhpMixed::String(self.escape_string(error.unwrap()),), + shirabe_php_shim::PhpMixed::String(self.escape_string(error),), )], output_interface::OUTPUT_NORMAL, ); diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs index 3b91f3b..1c01d70 100644 --- a/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs +++ b/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs @@ -465,7 +465,7 @@ impl QuestionHelper { None, ); output.borrow().write( - &[remaining_characters.clone()], + std::slice::from_ref(&remaining_characters), false, output_interface::OUTPUT_NORMAL, ); @@ -518,9 +518,11 @@ impl QuestionHelper { } let cur = c.clone().unwrap_or_default(); - output - .borrow() - .write(&[cur.clone()], false, output_interface::OUTPUT_NORMAL); + output.borrow().write( + std::slice::from_ref(&cur), + false, + output_interface::OUTPUT_NORMAL, + ); ret.push_str(&cur); full_choice.push_str(&cur); i += 1; diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/table_cell.rs b/crates/shirabe-external-packages/src/symfony/console/helper/table_cell.rs index b737cbc..a967d0e 100644 --- a/crates/shirabe-external-packages/src/symfony/console/helper/table_cell.rs +++ b/crates/shirabe-external-packages/src/symfony/console/helper/table_cell.rs @@ -78,11 +78,6 @@ impl TableCell { Self::new(value, options).expect("TableCell options built internally are always valid") } - /// Returns the cell value. - pub fn to_string(&self) -> String { - self.value.clone() - } - /// Gets number of colspan. pub fn get_colspan(&self) -> i64 { match self.options["colspan"] { diff --git a/crates/shirabe-external-packages/src/symfony/console/input/argv_input.rs b/crates/shirabe-external-packages/src/symfony/console/input/argv_input.rs index 80105e9..c614f88 100644 --- a/crates/shirabe-external-packages/src/symfony/console/input/argv_input.rs +++ b/crates/shirabe-external-packages/src/symfony/console/input/argv_input.rs @@ -240,7 +240,7 @@ impl ArgvInput { if let Some(key) = &first_key { let input_argument = &all[key]; if input_argument.get_name() == "command" { - symfony_command_name = self.inner.arguments.get("command").map(|v| v.clone()); + symfony_command_name = self.inner.arguments.get("command").cloned(); all.shift_remove(key); } } diff --git a/crates/shirabe-external-packages/src/symfony/console/question/choice_question.rs b/crates/shirabe-external-packages/src/symfony/console/question/choice_question.rs index 9de2d05..e1368e5 100644 --- a/crates/shirabe-external-packages/src/symfony/console/question/choice_question.rs +++ b/crates/shirabe-external-packages/src/symfony/console/question/choice_question.rs @@ -120,7 +120,10 @@ impl ChoiceQuestion { ) { return Err(InvalidArgumentException( shirabe_php_shim::InvalidArgumentException { - message: shirabe_php_shim::sprintf(&error_message, &[selected.clone()]), + message: shirabe_php_shim::sprintf( + &error_message, + std::slice::from_ref(&selected), + ), code: 0, }, )); @@ -198,7 +201,10 @@ impl ChoiceQuestion { if matches!(result, PhpMixed::Bool(false)) { return Err(InvalidArgumentException( shirabe_php_shim::InvalidArgumentException { - message: shirabe_php_shim::sprintf(&error_message, &[value.clone()]), + message: shirabe_php_shim::sprintf( + &error_message, + std::slice::from_ref(value), + ), code: 0, }, )); diff --git a/crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs b/crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs index 3f0406a..3a04885 100644 --- a/crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs +++ b/crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs @@ -477,7 +477,7 @@ impl SymfonyStyle { for message in messages { let message = Self::php_string(&message); - self.inner.writeln(&[message.clone()], r#type); + self.inner.writeln(std::slice::from_ref(&message), r#type); self.write_buffer(&message, true, r#type); } } @@ -493,7 +493,8 @@ impl SymfonyStyle { for message in messages { let message = Self::php_string(&message); - self.inner.write(&[message.clone()], newline, r#type); + self.inner + .write(std::slice::from_ref(&message), newline, r#type); self.write_buffer(&message, newline, r#type); } } @@ -696,8 +697,7 @@ impl StyleInterface for SymfonyStyle { choices: Vec<PhpMixed>, default: Option<PhpMixed>, ) -> PhpMixed { - let default = if default.is_some() { - let default = default.unwrap(); + let default = if let Some(default) = default { let values = shirabe_php_shim::array_flip(&PhpMixed::List( choices.iter().cloned().map(Box::new).collect(), )); @@ -705,7 +705,7 @@ impl StyleInterface for SymfonyStyle { let _ = values; Some(default) } else { - default + None }; // PHP: return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); diff --git a/crates/shirabe-php-shim/src/lib.rs b/crates/shirabe-php-shim/src/lib.rs index d643260..609d320 100644 --- a/crates/shirabe-php-shim/src/lib.rs +++ b/crates/shirabe-php-shim/src/lib.rs @@ -1459,8 +1459,8 @@ pub fn glob(_pattern: &str) -> Vec<String> { pub fn basename(path: &str) -> String { // PHP basename(): the trailing name component, after stripping trailing directory separators. - let trimmed = path.trim_end_matches(|c| matches!(c, '/' | '\\')); - match trimmed.rfind(|c| matches!(c, '/' | '\\')) { + let trimmed = path.trim_end_matches(['/', '\\']); + match trimmed.rfind(['/', '\\']) { Some(index) => trimmed[index + 1..].to_string(), None => trimmed.to_string(), } @@ -1933,7 +1933,7 @@ pub fn dirname_levels(_path: &str, _levels: i64) -> String { // re-scanned. Empty keys are ignored. pub fn strtr_array(s: &str, pairs: &IndexMap<String, String>) -> String { let mut keys: Vec<&String> = pairs.keys().filter(|k| !k.is_empty()).collect(); - keys.sort_by(|a, b| b.len().cmp(&a.len())); + keys.sort_by_key(|k| std::cmp::Reverse(k.len())); let bytes = s.as_bytes(); let mut result: Vec<u8> = Vec::with_capacity(bytes.len()); diff --git a/crates/shirabe-php-shim/src/preg.rs b/crates/shirabe-php-shim/src/preg.rs index 46d9428..6bf8900 100644 --- a/crates/shirabe-php-shim/src/preg.rs +++ b/crates/shirabe-php-shim/src/preg.rs @@ -99,7 +99,7 @@ pub fn preg_match_all_set_order( count } -pub fn preg_grep(pattern: &str, input: &Vec<String>) -> Vec<String> { +pub fn preg_grep(pattern: &str, input: &[String]) -> Vec<String> { let re = compile_php_pattern(pattern).unwrap_or_else(|e| panic!("invalid regex: {e}")); input.iter().filter(|s| re.is_match(s)).cloned().collect() } diff --git a/crates/shirabe/src/advisory/audit_config.rs b/crates/shirabe/src/advisory/audit_config.rs index 1feff3f..bcd0763 100644 --- a/crates/shirabe/src/advisory/audit_config.rs +++ b/crates/shirabe/src/advisory/audit_config.rs @@ -23,6 +23,7 @@ pub struct AuditConfig { } impl AuditConfig { + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn new( audit: bool, audit_format: String, diff --git a/crates/shirabe/src/advisory/auditor.rs b/crates/shirabe/src/advisory/auditor.rs index 0c4d80f..5a41b30 100644 --- a/crates/shirabe/src/advisory/auditor.rs +++ b/crates/shirabe/src/advisory/auditor.rs @@ -72,16 +72,7 @@ impl Auditor { pub const STATUS_VULNERABLE: i64 = 1; pub const STATUS_ABANDONED: i64 = 2; - /// @param PackageInterface[] $packages - /// @param self::FORMAT_* $format The format that will be used to output audit results. - /// @param bool $warningOnly If true, outputs a warning. If false, outputs an error. - /// @param array<string, string|null> $ignoreList List of advisory IDs, remote IDs, CVE IDs or package names that reported but not listed as vulnerabilities. - /// @param self::ABANDONED_* $abandoned - /// @param array<string, string|null> $ignoredSeverities List of ignored severity levels - /// @param array<string, string|null> $ignoreAbandoned List of abandoned package name that reported but not listed as vulnerabilities. - /// - /// @return int-mask<self::STATUS_*> A bitmask of STATUS_* constants or 0 on success - /// @throws InvalidArgumentException If no packages are passed in + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn audit( &self, io: &mut dyn IOInterface, @@ -166,7 +157,7 @@ impl Auditor { } let error_or_warn = if warning_only { "warning" } else { "error" }; - if affected_packages_count > 0 || ignored_advisories.len() > 0 { + if affected_packages_count > 0 || !ignored_advisories.is_empty() { let passes: Vec<( &IndexMap<String, Vec<AnySecurityAdvisory>>, String, @@ -237,7 +228,7 @@ impl Auditor { advisories: &IndexMap<String, Vec<AnySecurityAdvisory>>, ignore_list: &IndexMap<String, Option<String>>, ) -> bool { - if advisories.len() == 0 { + if advisories.is_empty() { return false; } @@ -268,7 +259,7 @@ impl Auditor { ignore_abandoned: &IndexMap<String, Option<String>>, ) -> anyhow::Result<Vec<CompletePackageInterfaceHandle>> { let mut filter: Option<String> = None; - if ignore_abandoned.len() != 0 { + if !ignore_abandoned.is_empty() { filter = Some(base_package::package_names_to_regexp( &array_keys(ignore_abandoned), "{^(?:%s)$}iD", @@ -325,22 +316,22 @@ impl Auditor { } if let Some(full) = advisory.as_security_advisory() { - if let Some(severity) = &full.severity { - if array_key_exists(severity, ignored_severities) { - is_active = false; - ignore_reason = ignored_severities - .get(severity) - .cloned() - .flatten() - .or_else(|| Some(format!("{} severity is ignored", severity))); - } + if let Some(severity) = &full.severity + && array_key_exists(severity, ignored_severities) + { + is_active = false; + ignore_reason = ignored_severities + .get(severity) + .cloned() + .flatten() + .or_else(|| Some(format!("{} severity is ignored", severity))); } - if let Some(cve) = &full.cve { - if array_key_exists(cve, ignore_list) { - is_active = false; - ignore_reason = ignore_list.get(cve).cloned().flatten(); - } + if let Some(cve) = &full.cve + && array_key_exists(cve, ignore_list) + { + is_active = false; + ignore_reason = ignore_list.get(cve).cloned().flatten(); } for source in &full.sources { @@ -356,7 +347,7 @@ impl Auditor { if is_active { advisories .entry(package.clone()) - .or_insert_with(Vec::new) + .or_default() .push(advisory); continue; } @@ -370,10 +361,7 @@ impl Auditor { advisory }; - ignored - .entry(package.clone()) - .or_insert_with(Vec::new) - .push(advisory); + ignored.entry(package.clone()).or_default().push(advisory); } } @@ -624,10 +612,10 @@ impl Auditor { fn get_package_name_with_link(&self, package: PackageInterfaceHandle) -> String { let package_url = PackageInfo::get_view_source_or_homepage_url(package.clone()); - if package_url.is_some() { + if let Some(package_url) = package_url { format!( "<href={}>{}</>", - OutputFormatter::escape(&package_url.unwrap()) + OutputFormatter::escape(&package_url) .expect("OutputFormatter::escape does not fail"), package.get_pretty_name() ) diff --git a/crates/shirabe/src/advisory/ignored_security_advisory.rs b/crates/shirabe/src/advisory/ignored_security_advisory.rs index fa1f8ae..7bcb823 100644 --- a/crates/shirabe/src/advisory/ignored_security_advisory.rs +++ b/crates/shirabe/src/advisory/ignored_security_advisory.rs @@ -16,6 +16,7 @@ pub struct IgnoredSecurityAdvisory { } impl IgnoredSecurityAdvisory { + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn new( package_name: String, advisory_id: String, diff --git a/crates/shirabe/src/advisory/security_advisory.rs b/crates/shirabe/src/advisory/security_advisory.rs index 7c258ee..78a2562 100644 --- a/crates/shirabe/src/advisory/security_advisory.rs +++ b/crates/shirabe/src/advisory/security_advisory.rs @@ -30,6 +30,7 @@ pub struct SecurityAdvisory { } impl SecurityAdvisory { + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn new( package_name: String, advisory_id: String, diff --git a/crates/shirabe/src/autoload/autoload_generator.rs b/crates/shirabe/src/autoload/autoload_generator.rs index 6ceb02c..c69cd34 100644 --- a/crates/shirabe/src/autoload/autoload_generator.rs +++ b/crates/shirabe/src/autoload/autoload_generator.rs @@ -104,6 +104,7 @@ impl AutoloadGenerator { self.platform_requirement_filter = platform_requirement_filter; } + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn dump( &mut self, config: &Config, @@ -137,10 +138,10 @@ impl AutoloadGenerator { )?; if installed_json.exists() { let installed_json_data = installed_json.read()?; - if let Some(arr) = installed_json_data.as_array() { - if let Some(dev) = arr.get("dev") { - self.dev_mode = dev.as_bool(); - } + if let Some(arr) = installed_json_data.as_array() + && let Some(dev) = arr.get("dev") + { + self.dev_mode = dev.as_bool(); } } } @@ -310,7 +311,7 @@ impl AutoloadGenerator { && main_autoload .get("psr-0") .and_then(|v| v.as_array()) - .map_or(false, |a| !a.is_empty()) + .is_some_and(|a| !a.is_empty()) { let levels = substr_count( &filesystem.normalize_path(&root_package.get_target_dir().unwrap_or_default()), @@ -341,13 +342,12 @@ impl AutoloadGenerator { if let Some(ex) = autoloads .get("exclude-from-classmap") .and_then(|v| v.as_list()) + && !ex.is_empty() { - if !ex.is_empty() { - excluded = ex - .iter() - .filter_map(|v| v.as_string().map(|s| s.to_string())) - .collect(); - } + excluded = ex + .iter() + .filter_map(|v| v.as_string().map(|s| s.to_string())) + .collect(); } let classmap_list = autoloads @@ -383,7 +383,7 @@ impl AutoloadGenerator { entry.insert("type".to_string(), PhpMixed::String(psr_type.to_string())); namespaces_to_scan .entry(namespace.clone()) - .or_insert_with(Vec::new) + .or_default() .push(entry); } } @@ -487,7 +487,7 @@ impl AutoloadGenerator { for (class_name, path) in class_map.get_map() { let path_code = format!( "{},\n", - self.get_path_code(&filesystem, &base_path, &vendor_path, &path) + self.get_path_code(&filesystem, &base_path, &vendor_path, path) ); classmap_file.push_str(&format!( " {} => {}", @@ -608,7 +608,7 @@ impl AutoloadGenerator { platform_check_content = self.get_platform_check( &package_map, config.get("platform-check").clone(), - &dev_package_names, + dev_package_names, ); if platform_check_content.is_none() { check_platform = false; @@ -750,7 +750,7 @@ impl AutoloadGenerator { if autoload .get("psr-4") .and_then(|v| v.as_array()) - .map_or(false, |a| !a.is_empty()) + .is_some_and(|a| !a.is_empty()) && package.get_target_dir().is_some() { let name = package.get_name(); @@ -883,13 +883,12 @@ impl AutoloadGenerator { if let Some(ex) = autoloads .get("exclude-from-classmap") .and_then(|v| v.as_list()) + && !ex.is_empty() { - if !ex.is_empty() { - excluded = ex - .iter() - .filter_map(|v| v.as_string().map(|s| s.to_string())) - .collect(); - } + excluded = ex + .iter() + .filter_map(|v| v.as_string().map(|s| s.to_string())) + .collect(); } let mut class_map_generator = ClassMapGenerator::new(vec![ @@ -943,11 +942,11 @@ impl AutoloadGenerator { }; let mut install_path = install_path; - if let Some(target_dir) = package.get_target_dir() { - if !target_dir.is_empty() { - let suffix_to_remove = format!("/{}", target_dir); - install_path = substr(&install_path, 0, Some(-(suffix_to_remove.len() as i64))); - } + if let Some(target_dir) = package.get_target_dir() + && !target_dir.is_empty() + { + let suffix_to_remove = format!("/{}", target_dir); + install_path = substr(&install_path, 0, Some(-(suffix_to_remove.len() as i64))); } for include_path in package.get_include_paths() { @@ -1077,7 +1076,7 @@ impl AutoloadGenerator { &self, package_map: &Vec<(PackageInterfaceHandle, Option<String>)>, check_platform: PhpMixed, - dev_package_names: &Vec<String>, + dev_package_names: &[String], ) -> Option<String> { let mut lowest_php_version = Bound::zero(); let mut required_php_64bit = false; @@ -1092,13 +1091,13 @@ impl AutoloadGenerator { let links = array_merge_map(package.get_replaces(), package.get_provides()); for (_k, link) in &links { let mut matches: IndexMap<CaptureKey, String> = IndexMap::new(); - if Preg::match3("{^ext-(.+)$}iD", link.get_target(), Some(&mut matches)) { - if let Some(ext) = matches.get(&CaptureKey::ByIndex(1)).cloned() { - extension_providers - .entry(ext) - .or_insert_with(Vec::new) - .push(link.get_constraint().clone()); - } + if Preg::match3("{^ext-(.+)$}iD", link.get_target(), Some(&mut matches)) + && let Some(ext) = matches.get(&CaptureKey::ByIndex(1)).cloned() + { + extension_providers + .entry(ext) + .or_default() + .push(link.get_constraint().clone()); } } } @@ -1144,7 +1143,7 @@ impl AutoloadGenerator { // skip extension checks if they have a valid provider/replacer if let Some(provided_list) = extension_providers.get(&ext_key) { for provided in provided_list { - if provided.matches(&*link.get_constraint()) { + if provided.matches(link.get_constraint()) { continue 'outer; } } @@ -1299,6 +1298,7 @@ impl AutoloadGenerator { } /// Note: vendor_path_code and app_base_dir_code are unused in this method + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub(crate) fn get_autoload_real_file( &self, _use_class_map: bool, @@ -1413,7 +1413,7 @@ impl AutoloadGenerator { } else { vec![] }; - loader.set(&namespace, paths); + loader.set(namespace, paths); } } @@ -1428,20 +1428,21 @@ impl AutoloadGenerator { } else { vec![] }; - loader.set_psr4(&namespace, paths).unwrap_or(()); + loader.set_psr4(namespace, paths).unwrap_or(()); } } let class_map = shirabe_php_shim::php_require(&format!("{}/autoload_classmap.php", target_dir)); - if class_map.as_bool() != Some(false) && !class_map.is_null() { - if let Some(cm) = class_map.as_array() { - let cm_str: IndexMap<String, String> = cm - .iter() - .map(|(k, v)| (k.clone(), v.as_string().unwrap_or("").to_string())) - .collect(); - loader.add_class_map(cm_str); - } + if class_map.as_bool() != Some(false) + && !class_map.is_null() + && let Some(cm) = class_map.as_array() + { + let cm_str: IndexMap<String, String> = cm + .iter() + .map(|(k, v)| (k.clone(), v.as_string().unwrap_or("").to_string())) + .collect(); + loader.add_class_map(cm_str); } let filesystem = Filesystem::new(None); @@ -1564,7 +1565,7 @@ impl AutoloadGenerator { { continue; } - maps.insert(substr(&prop, prefix_len as i64, None), value); + maps.insert(substr(&prop, prefix_len, None), value); } for (prop, value) in &maps { @@ -1905,10 +1906,8 @@ impl AutoloadGenerator { paths.insert(name, path.clone()); } - let sorted_packages = PackageSorter::sort_packages( - packages.values().map(|p| p.clone()).collect(), - IndexMap::new(), - ); + let sorted_packages = + PackageSorter::sort_packages(packages.values().cloned().collect(), IndexMap::new()); let mut sorted_package_map: Vec<(PackageInterfaceHandle, Option<String>)> = vec![]; diff --git a/crates/shirabe/src/autoload/class_loader.rs b/crates/shirabe/src/autoload/class_loader.rs index 083e1c3..918b319 100644 --- a/crates/shirabe/src/autoload/class_loader.rs +++ b/crates/shirabe/src/autoload/class_loader.rs @@ -134,7 +134,7 @@ impl ClassLoader { if prefix.is_empty() { if prepend { let mut new_dirs = paths.clone(); - new_dirs.extend(self.fallback_dirs_psr0.drain(..)); + new_dirs.append(&mut self.fallback_dirs_psr0); self.fallback_dirs_psr0 = new_dirs; } else { self.fallback_dirs_psr0.extend(paths); @@ -144,10 +144,7 @@ impl ClassLoader { } let first = prefix.chars().next().unwrap_or('\0').to_string(); - let entry = self - .prefixes_psr0 - .entry(first.clone()) - .or_insert_with(IndexMap::new); + let entry = self.prefixes_psr0.entry(first.clone()).or_default(); if !entry.contains_key(prefix) { entry.insert(prefix.to_string(), paths); return; @@ -155,7 +152,7 @@ impl ClassLoader { let existing = entry.get_mut(prefix).unwrap(); if prepend { let mut new_dirs = paths.clone(); - new_dirs.extend(existing.drain(..)); + new_dirs.append(existing); *existing = new_dirs; } else { existing.extend(paths); @@ -176,7 +173,7 @@ impl ClassLoader { // Register directories for the root namespace. if prepend { let mut new_dirs = paths.clone(); - new_dirs.extend(self.fallback_dirs_psr4.drain(..)); + new_dirs.append(&mut self.fallback_dirs_psr4); self.fallback_dirs_psr4 = new_dirs; } else { self.fallback_dirs_psr4.extend(paths); @@ -195,14 +192,14 @@ impl ClassLoader { let first = prefix.chars().next().unwrap_or('\0').to_string(); self.prefix_lengths_psr4 .entry(first) - .or_insert_with(IndexMap::new) + .or_default() .insert(prefix.to_string(), length); self.prefix_dirs_psr4.insert(prefix.to_string(), paths); } else if prepend { // Prepend directories for an already registered namespace. let existing = self.prefix_dirs_psr4.get_mut(prefix).unwrap(); let mut new_dirs = paths.clone(); - new_dirs.extend(existing.drain(..)); + new_dirs.append(existing); *existing = new_dirs; } else { // Append directories for an already registered namespace. @@ -221,7 +218,7 @@ impl ClassLoader { let first = prefix.chars().next().unwrap_or('\0').to_string(); self.prefixes_psr0 .entry(first) - .or_insert_with(IndexMap::new) + .or_default() .insert(prefix.to_string(), paths); } } @@ -246,7 +243,7 @@ impl ClassLoader { let first = prefix.chars().next().unwrap_or('\0').to_string(); self.prefix_lengths_psr4 .entry(first) - .or_insert_with(IndexMap::new) + .or_default() .insert(prefix.to_string(), length); self.prefix_dirs_psr4.insert(prefix.to_string(), paths); } @@ -327,11 +324,8 @@ impl ClassLoader { pub fn unregister(&self) { spl_autoload_unregister(Box::new(|_class: &str| -> PhpMixed { PhpMixed::Null })); - if self.vendor_dir.is_some() { - REGISTERED_LOADERS - .lock() - .unwrap() - .shift_remove(self.vendor_dir.as_ref().unwrap()); + if let Some(vendor_dir) = &self.vendor_dir { + REGISTERED_LOADERS.lock().unwrap().shift_remove(vendor_dir); } } @@ -360,12 +354,9 @@ impl ClassLoader { if self.class_map_authoritative || self.missing_classes.contains_key(class) { return None; } - if self.apcu_prefix.is_some() { + if let Some(apcu_prefix) = &self.apcu_prefix { let mut hit = false; - let file = apcu_fetch( - &format!("{}{}", self.apcu_prefix.as_ref().unwrap(), class), - &mut hit, - ); + let file = apcu_fetch(&format!("{}{}", apcu_prefix, class), &mut hit); if hit { return file.as_string().map(String::from); } @@ -378,9 +369,9 @@ impl ClassLoader { file = self.find_file_with_extension(class, ".hh"); } - if self.apcu_prefix.is_some() { + if let Some(apcu_prefix) = &self.apcu_prefix { apcu_add( - &format!("{}{}", self.apcu_prefix.as_ref().unwrap(), class), + &format!("{}{}", apcu_prefix, class), match file.as_ref() { Some(s) => PhpMixed::String(s.clone()), None => PhpMixed::Bool(false), @@ -483,10 +474,10 @@ impl ClassLoader { } // PSR-0 include paths. - if self.use_include_path { - if let Some(file) = stream_resolve_include_path(&logical_path_psr0) { - return Some(file); - } + if self.use_include_path + && let Some(file) = stream_resolve_include_path(&logical_path_psr0) + { + return Some(file); } None diff --git a/crates/shirabe/src/cache.rs b/crates/shirabe/src/cache.rs index 636a8ed..532de41 100644 --- a/crates/shirabe/src/cache.rs +++ b/crates/shirabe/src/cache.rs @@ -45,7 +45,7 @@ impl Cache { read_only: bool, ) -> Self { let allowlist = allowlist.unwrap_or("a-z0-9._").to_string(); - let root = format!("{}/", cache_dir.trim_end_matches(|c| c == '/' || c == '\\')); + let root = format!("{}/", cache_dir.trim_end_matches(['/', '\\'])); let filesystem = filesystem .unwrap_or_else(|| std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(None)))); let mut this = Self { @@ -305,10 +305,10 @@ impl Cache { if self.is_enabled() { let file = Preg::replace(&format!("{{[^{}]}}i", self.allowlist), "-", file); let full_path = format!("{}{}", self.root, file); - if file_exists(&full_path) { - if let Some(mtime) = filemtime(&full_path) { - return Some(abs(time() - mtime)); - } + if file_exists(&full_path) + && let Some(mtime) = filemtime(&full_path) + { + return Some(abs(time() - mtime)); } } diff --git a/crates/shirabe/src/command/about_command.rs b/crates/shirabe/src/command/about_command.rs index e476bb6..8ca44db 100644 --- a/crates/shirabe/src/command/about_command.rs +++ b/crates/shirabe/src/command/about_command.rs @@ -25,6 +25,12 @@ pub struct AboutCommand { base_command_data: BaseCommandData, } +impl Default for AboutCommand { + fn default() -> Self { + Self::new() + } +} + impl AboutCommand { pub fn new() -> Self { let mut command = AboutCommand { diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs index cd5fa04..1a043af 100644 --- a/crates/shirabe/src/command/archive_command.rs +++ b/crates/shirabe/src/command/archive_command.rs @@ -40,6 +40,12 @@ pub struct ArchiveCommand { base_command_data: BaseCommandData, } +impl Default for ArchiveCommand { + fn default() -> Self { + Self::new() + } +} + impl ArchiveCommand { const FORMATS: &'static [&'static str] = &["tar", "tar.gz", "tar.bz2", "zip"]; @@ -201,6 +207,7 @@ impl BaseCommand for ArchiveCommand { } impl ArchiveCommand { + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn archive( &mut self, io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>, @@ -239,7 +246,7 @@ impl ArchiveCommand { Some(process), ))); owned_archive_manager = - factory.create_archive_manager(&*config.borrow(), &download_manager, &loop_)?; + factory.create_archive_manager(&config.borrow(), &download_manager, &loop_)?; &mut owned_archive_manager }; @@ -299,12 +306,7 @@ impl ArchiveCommand { let repository_manager = repository_manager.borrow(); let local_repo = repository_manager.get_local_repository(); let mut repos: Vec<crate::repository::RepositoryInterfaceHandle> = vec![local_repo]; - repos.extend( - repository_manager - .get_repositories() - .iter() - .map(|r| r.clone()), - ); + repos.extend(repository_manager.get_repositories().iter().cloned()); repo = CompositeRepository::new(repos); min_stability = composer.get_package().get_minimum_stability().to_string(); } else { @@ -368,7 +370,7 @@ impl ArchiveCommand { None, shirabe_php_shim::PhpMixed::Bool(true), )?; - let p = best.unwrap_or_else(|| packages.into_iter().next().unwrap().into()); + let p = best.unwrap_or_else(|| packages.into_iter().next().unwrap()); io.write_error(&format!( "<info>Found multiple matches, selected {}.</info>", @@ -378,8 +380,7 @@ impl ArchiveCommand { io.write_error("<comment>Please use a more specific constraint to pick a different package.</comment>"); p } else if packages.len() == 1 { - let p: crate::package::PackageInterfaceHandle = - packages.into_iter().next().unwrap().into(); + let p: crate::package::PackageInterfaceHandle = packages.into_iter().next().unwrap(); io.write_error(&format!( "<info>Found an exact match {}.</info>", p.get_pretty_string() diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs index 4677b40..3014736 100644 --- a/crates/shirabe/src/command/audit_command.rs +++ b/crates/shirabe/src/command/audit_command.rs @@ -34,6 +34,12 @@ pub struct AuditCommand { base_command_data: BaseCommandData, } +impl Default for AuditCommand { + fn default() -> Self { + Self::new() + } +} + impl AuditCommand { pub fn new() -> Self { let mut command = AuditCommand { @@ -147,7 +153,7 @@ impl Command for AuditCommand { } let audit_config = AuditConfig::from_config( - &mut *composer.get_config().borrow_mut(), + &mut composer.get_config().borrow_mut(), true, Auditor::FORMAT_SUMMARY, )?; diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs index 24c1bbf..c6b5550 100644 --- a/crates/shirabe/src/command/base_command.rs +++ b/crates/shirabe/src/command/base_command.rs @@ -287,20 +287,20 @@ impl BaseCommand for BaseCommandData { disable_plugins: Option<bool>, disable_scripts: Option<bool>, ) -> Option<PartialComposerHandle> { - if self.composer.is_none() { - if let Some(application) = self.get_application() { - let result = { - let mut app_ref = application.borrow_mut(); - let app_dyn: &mut dyn shirabe_external_packages::symfony::console::application::Application = &mut *app_ref; - let app = app_dyn - .as_any_mut() - .downcast_mut::<Application>() - .expect("a Composer command's application is a shirabe Application"); - app.get_composer(false, disable_plugins, disable_scripts) - }; - if let Ok(composer) = result { - self.composer = composer; - } + if self.composer.is_none() + && let Some(application) = self.get_application() + { + let result = { + let mut app_ref = application.borrow_mut(); + let app_dyn: &mut dyn shirabe_external_packages::symfony::console::application::Application = &mut *app_ref; + let app = app_dyn + .as_any_mut() + .downcast_mut::<Application>() + .expect("a Composer command's application is a shirabe Application"); + app.get_composer(false, disable_plugins, disable_scripts) + }; + if let Ok(composer) = result { + self.composer = composer; } } @@ -399,7 +399,7 @@ impl BaseCommand for BaseCommandData { "dist" => { prefer_dist = true; } - "auto" | _ => { + _ => { // noop } } @@ -523,21 +523,18 @@ impl BaseCommand for BaseCommandData { .into()); } - if true - == input - .borrow() - .get_option("ignore-platform-reqs")? - .as_bool() - .unwrap_or(false) + if input + .borrow() + .get_option("ignore-platform-reqs")? + .as_bool() + .unwrap_or(false) { return Ok(PlatformRequirementFilterFactory::ignore_all()); } let ignores = input.borrow().get_option("ignore-platform-req")?; if count(&ignores) > 0 { - return Ok(PlatformRequirementFilterFactory::from_bool_or_list( - ignores, - )?); + return PlatformRequirementFilterFactory::from_bool_or_list(ignores); } Ok(PlatformRequirementFilterFactory::ignore_nothing()) @@ -664,7 +661,7 @@ impl BaseCommand for BaseCommandData { let audit_config = AuditConfig::from_config(config, audit, &audit_format)?; if Platform::get_env("COMPOSER_NO_SECURITY_BLOCKING") - .map_or(false, |s| !s.is_empty() && s != "0") + .is_some_and(|s| !s.is_empty() && s != "0") || (input.borrow().has_option("no-security-blocking") && input .borrow() @@ -777,41 +774,38 @@ pub fn base_command_initialize( .collect(); for (env_name, option_names) in &env_options { for option_name in option_names { - if true == input.borrow().has_option(option_name) { - if false - == input - .borrow() - .get_option(option_name)? - .as_bool() - .unwrap_or(false) - && Platform::get_env(env_name).map_or(false, |s| !s.is_empty() && s != "0") - { - input - .borrow_mut() - .set_option(option_name, PhpMixed::Bool(true)); - } + if input.borrow().has_option(option_name) + && !input + .borrow() + .get_option(option_name)? + .as_bool() + .unwrap_or(false) + && Platform::get_env(env_name).is_some_and(|s| !s.is_empty() && s != "0") + { + input + .borrow_mut() + .set_option(option_name, PhpMixed::Bool(true)); } } } - if true == input.borrow().has_option("ignore-platform-reqs") { - if !input + if input.borrow().has_option("ignore-platform-reqs") + && !input .borrow() .get_option("ignore-platform-reqs")? .as_bool() .unwrap_or(false) - && Platform::get_env("COMPOSER_IGNORE_PLATFORM_REQS") - .map_or(false, |s| !s.is_empty() && s != "0") - { - input - .borrow_mut() - .set_option("ignore-platform-reqs", PhpMixed::Bool(true)); + && Platform::get_env("COMPOSER_IGNORE_PLATFORM_REQS") + .is_some_and(|s| !s.is_empty() && s != "0") + { + input + .borrow_mut() + .set_option("ignore-platform-reqs", PhpMixed::Bool(true)); - io.write_error("<warning>COMPOSER_IGNORE_PLATFORM_REQS is set. You may experience unexpected errors.</warning>"); - } + io.write_error("<warning>COMPOSER_IGNORE_PLATFORM_REQS is set. You may experience unexpected errors.</warning>"); } - if true == input.borrow().has_option("ignore-platform-req") + if input.borrow().has_option("ignore-platform-req") && (!input.borrow().has_option("ignore-platform-reqs") || !input .borrow() @@ -823,7 +817,7 @@ pub fn base_command_initialize( let ignore_str = ignore_platform_req_env.clone().unwrap_or_default(); if 0 == count(&input.borrow().get_option("ignore-platform-req")?) && ignore_platform_req_env.is_some() - && "" != ignore_str + && !ignore_str.is_empty() { input.borrow_mut().set_option( "ignore-platform-req", diff --git a/crates/shirabe/src/command/base_config_command.rs b/crates/shirabe/src/command/base_config_command.rs index 5e77715..00098f2 100644 --- a/crates/shirabe/src/command/base_config_command.rs +++ b/crates/shirabe/src/command/base_config_command.rs @@ -56,7 +56,7 @@ pub trait BaseConfigCommand: BaseCommand { config_rc.borrow_mut().set_base_dir(Some(home)); } - let config_file = self.get_composer_config_file(input.clone(), &*config_rc.borrow())?; + let config_file = self.get_composer_config_file(input.clone(), &config_rc.borrow())?; // Create global composer.json if invoked using `composer global [config-cmd]` if (config_file == "composer.json" || config_file == "./composer.json") diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs index 5424dd1..98a2622 100644 --- a/crates/shirabe/src/command/base_dependency_command.rs +++ b/crates/shirabe/src/command/base_dependency_command.rs @@ -90,8 +90,8 @@ pub trait BaseDependencyCommand: BaseCommand { let local_repo = repository_manager.get_local_repository(); let root_pkg = composer.get_package(); - if local_repo.get_packages()?.len() == 0 - && (root_pkg.get_requires().len() > 0 || root_pkg.get_dev_requires().len() > 0) + if local_repo.get_packages()?.is_empty() + && (!root_pkg.get_requires().is_empty() || !root_pkg.get_dev_requires().is_empty()) { output.borrow().writeln( &["<warning>No dependencies installed. Try running composer install or update, or use --locked.</warning>".to_string()], @@ -451,7 +451,7 @@ pub trait BaseDependencyCommand: BaseCommand { "" }; self.write_tree_line( - &format!( + format!( "{}{}{} ({}) {}", prefix, if is_last { "└──" } else { "├──" }, @@ -459,8 +459,7 @@ pub trait BaseDependencyCommand: BaseCommand { link_text, circular_warn ) - .trim_end() - .to_string(), + .trim_end(), ); if let Some(children_vec) = children { self.print_tree( diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs index faa1ea7..1d5a81d 100644 --- a/crates/shirabe/src/command/bump_command.rs +++ b/crates/shirabe/src/command/bump_command.rs @@ -37,6 +37,12 @@ pub struct BumpCommand { base_command_data: BaseCommandData, } +impl Default for BumpCommand { + fn default() -> Self { + Self::new() + } +} + impl BumpCommand { const ERROR_GENERIC: i64 = 1; const ERROR_LOCK_OUTDATED: i64 = 2; @@ -72,7 +78,7 @@ impl BumpCommand { } let mut composer_json = JsonFile::new(composer_json_path.clone(), None, None)?; - let contents = match file_get_contents(&composer_json.get_path()) { + let contents = match file_get_contents(composer_json.get_path()) { Some(c) => c, None => { io.write_error3( @@ -146,7 +152,7 @@ impl BumpCommand { let contents_data = composer_json.read()?; if !contents_data .as_array() - .map_or(false, |m| m.contains_key("type")) + .is_some_and(|m| m.contains_key("type")) { io.write_error3( "If your package is not a library, you can explicitly specify the \"type\" by using \"composer config type project\".", @@ -301,7 +307,7 @@ impl BumpCommand { json: &JsonFile, updates: &indexmap::IndexMap<&str, indexmap::IndexMap<String, String>>, ) -> Result<bool> { - let contents = match file_get_contents(&json.get_path()) { + let contents = match file_get_contents(json.get_path()) { Some(c) => c, None => { return Err(shirabe_php_shim::RuntimeException { @@ -322,7 +328,7 @@ impl BumpCommand { } } - match file_put_contents(&json.get_path(), manipulator.get_contents().as_bytes()) { + match file_put_contents(json.get_path(), manipulator.get_contents().as_bytes()) { Some(_) => Ok(true), None => Err(shirabe_php_shim::RuntimeException { message: format!("Unable to write new {} contents.", json.get_path()), diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs index 23d2240..bfd8b99 100644 --- a/crates/shirabe/src/command/check_platform_reqs_command.rs +++ b/crates/shirabe/src/command/check_platform_reqs_command.rs @@ -40,6 +40,12 @@ pub struct CheckPlatformReqsCommand { base_command_data: BaseCommandData, } +impl Default for CheckPlatformReqsCommand { + fn default() -> Self { + Self::new() + } +} + impl CheckPlatformReqsCommand { pub fn new() -> Self { let mut command = CheckPlatformReqsCommand { @@ -253,7 +259,7 @@ impl Command for CheckPlatformReqsCommand { for (require, link) in composer.get_package().get_dev_requires() { requires .entry(require.to_string()) - .or_insert_with(Vec::new) + .or_default() .push(link.clone()); } } @@ -273,7 +279,7 @@ impl Command for CheckPlatformReqsCommand { for (require, link) in package.get_requires() { requires .entry(require.to_string()) - .or_insert_with(Vec::new) + .or_default() .push(link.clone()); } } diff --git a/crates/shirabe/src/command/clear_cache_command.rs b/crates/shirabe/src/command/clear_cache_command.rs index 31ba953..a414c11 100644 --- a/crates/shirabe/src/command/clear_cache_command.rs +++ b/crates/shirabe/src/command/clear_cache_command.rs @@ -26,6 +26,12 @@ pub struct ClearCacheCommand { base_command_data: BaseCommandData, } +impl Default for ClearCacheCommand { + fn default() -> Self { + Self::new() + } +} + impl ClearCacheCommand { pub fn new() -> Self { let mut command = ClearCacheCommand { diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs index 0752052..556dbdd 100644 --- a/crates/shirabe/src/command/config_command.rs +++ b/crates/shirabe/src/command/config_command.rs @@ -70,6 +70,12 @@ impl ConfigCommand { ]; } +impl Default for ConfigCommand { + fn default() -> Self { + Self::new() + } +} + impl ConfigCommand { pub fn new() -> Self { let mut command = ConfigCommand { @@ -157,7 +163,7 @@ impl Command for ConfigCommand { )?; let auth_config_file = - self.get_auth_config_file(input.clone(), &*self.config.as_ref().unwrap().borrow())?; + self.get_auth_config_file(input.clone(), &self.config.as_ref().unwrap().borrow())?; let auth_config_file_jf = std::rc::Rc::new(std::cell::RefCell::new(JsonFile::new( auth_config_file, @@ -299,7 +305,7 @@ impl Command for ConfigCommand { let config_rc = self.config.as_ref().unwrap().clone(); self.get_io() .borrow_mut() - .load_configuration(&mut *config_rc.borrow_mut())?; + .load_configuration(&mut config_rc.borrow_mut())?; } // List the configuration of the file settings @@ -407,12 +413,7 @@ impl Command for ConfigCommand { let bits = explode(".", &setting_key); // PHP: $data here is the mixed dot-segment cursor; the rest of the loop walks it. let mut cursor: PhpMixed = if bits[0] == "extra" || bits[0] == "suggest" { - PhpMixed::Array( - raw_data - .as_array() - .map(|a| a.clone()) - .unwrap_or_else(IndexMap::new), - ) + PhpMixed::Array(raw_data.as_array().cloned().unwrap_or_else(IndexMap::new)) } else { data.get("config").cloned().unwrap_or(PhpMixed::Null) }; @@ -425,12 +426,12 @@ impl Command for ConfigCommand { }; key_acc = Some(new_key.clone()); r#match = false; - if let Some(arr) = cursor.as_array() { - if let Some(v) = arr.get(&new_key) { - r#match = true; - cursor = (**v).clone(); - key_acc = None; - } + if let Some(arr) = cursor.as_array() + && let Some(v) = arr.get(&new_key) + { + r#match = true; + cursor = (**v).clone(); + key_acc = None; } } @@ -564,7 +565,7 @@ impl Command for ConfigCommand { }; let boolean_normalizer = |val: &PhpMixed| -> PhpMixed { let s = val.as_string().unwrap_or(""); - PhpMixed::Bool(s != "false" && s != "" && s != "0") + PhpMixed::Bool(s != "false" && !s.is_empty() && s != "0") }; // handle config values @@ -1133,7 +1134,7 @@ impl Command for ConfigCommand { .unwrap() .add_config_setting(&key, PhpMixed::Array(obj)); } else if matches[1] == "custom-headers" { - if values.len() == 0 { + if values.is_empty() { return Err(RuntimeException { message: "Expected at least one argument (header), got none".to_string(), code: 0, @@ -1279,7 +1280,7 @@ impl ConfigCommand { &mut self, key: &str, callbacks: &(ValidatorFn, NormalizerFn), - values: &Vec<String>, + values: &[String], method: &str, ) -> anyhow::Result<()> { let (validator, normalizer) = callbacks; @@ -1349,7 +1350,7 @@ impl ConfigCommand { &mut self, key: &str, callbacks: &(ValidatorFn, NormalizerFn), - values: &Vec<String>, + values: &[String], method: &str, ) -> anyhow::Result<()> { let (validator, normalizer) = callbacks; @@ -1551,7 +1552,7 @@ fn boolean_validator(val: &PhpMixed) -> PhpMixed { fn boolean_normalizer(val: &PhpMixed) -> PhpMixed { let s = val.as_string().unwrap_or(""); - PhpMixed::Bool(s != "false" && s != "" && s != "0") + PhpMixed::Bool(s != "false" && !s.is_empty() && s != "0") } fn build_unique_config_values() -> IndexMap<String, (ValidatorFn, NormalizerFn)> { @@ -1624,7 +1625,7 @@ fn build_unique_config_values() -> IndexMap<String, (ValidatorFn, NormalizerFn)> if s == "prompt" { PhpMixed::String("prompt".to_string()) } else { - PhpMixed::Bool(s != "false" && s != "" && s != "0") + PhpMixed::Bool(s != "false" && !s.is_empty() && s != "0") } }), ), @@ -1772,7 +1773,7 @@ fn build_unique_config_values() -> IndexMap<String, (ValidatorFn, NormalizerFn)> if s == "stash" { PhpMixed::String("stash".to_string()) } else { - PhpMixed::Bool(s != "false" && s != "" && s != "0") + PhpMixed::Bool(s != "false" && !s.is_empty() && s != "0") } }), ), @@ -1845,7 +1846,7 @@ fn build_unique_config_values() -> IndexMap<String, (ValidatorFn, NormalizerFn)> if s == "dev" || s == "no-dev" { val.clone() } else { - PhpMixed::Bool(s != "false" && s != "" && s != "0") + PhpMixed::Bool(s != "false" && !s.is_empty() && s != "0") } }), ), @@ -1924,7 +1925,7 @@ fn build_unique_config_values() -> IndexMap<String, (ValidatorFn, NormalizerFn)> if s == "php-only" { PhpMixed::String("php-only".to_string()) } else { - PhpMixed::Bool(s != "false" && s != "" && s != "0") + PhpMixed::Bool(s != "false" && !s.is_empty() && s != "0") } }), ), @@ -1949,7 +1950,7 @@ fn build_unique_config_values() -> IndexMap<String, (ValidatorFn, NormalizerFn)> if s == "prompt" { PhpMixed::String("prompt".to_string()) } else { - PhpMixed::Bool(s != "false" && s != "" && s != "0") + PhpMixed::Bool(s != "false" && !s.is_empty() && s != "0") } }), ), @@ -2197,10 +2198,10 @@ fn key_first_key(value: &PhpMixed) -> Option<String> { if let Some(arr) = value.as_array() { return arr.keys().next().cloned(); } - if let Some(list) = value.as_list() { - if !list.is_empty() { - return Some("0".to_string()); - } + if let Some(list) = value.as_list() + && !list.is_empty() + { + return Some("0".to_string()); } None } diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs index 99f73e9..3322008 100644 --- a/crates/shirabe/src/command/create_project_command.rs +++ b/crates/shirabe/src/command/create_project_command.rs @@ -61,6 +61,12 @@ pub struct CreateProjectCommand { Option<std::rc::Rc<std::cell::RefCell<SuggestedPackagesReporter>>>, } +impl Default for CreateProjectCommand { + fn default() -> Self { + Self::new() + } +} + impl CreateProjectCommand { pub fn new() -> Self { let mut command = CreateProjectCommand { @@ -178,7 +184,7 @@ impl Command for CreateProjectCommand { let repository_url_opt = input.borrow().get_option("repository-url")?; let repositories = if repository_opt .as_list() - .map(|l| l.len() > 0) + .map(|l| !l.is_empty()) .unwrap_or(false) { Some(repository_opt) @@ -321,7 +327,7 @@ impl CreateProjectCommand { // we need to manually load the configuration to pass the auth credentials to the io interface! io.borrow_mut() - .load_configuration(&mut *config.borrow_mut())?; + .load_configuration(&mut config.borrow_mut())?; self.suggested_packages_reporter = Some(std::rc::Rc::new(std::cell::RefCell::new( SuggestedPackagesReporter::new(io.clone()), @@ -363,61 +369,61 @@ impl CreateProjectCommand { )?; // add the repository to the composer.json and use it for the install run later - if let Some(repos) = repositories.as_ref() { - if add_repository { - for (index, repo) in repos.iter().enumerate() { - let config = crate::command::composer_full(&composer_handle).get_config(); - let repo_config = - RepositoryFactory::config_from_string(io.clone(), &config, repo, true)?; - let composer_json_repositories_config = - crate::command::composer_full(&composer_handle) - .get_config() - .borrow() - .get_repositories(); - let name = RepositoryFactory::generate_repository_name( - &PhpMixed::Int(index as i64), - &repo_config, - &composer_json_repositories_config, - ); - let mut config_source = JsonConfigSource::new( - std::rc::Rc::new(std::cell::RefCell::new(JsonFile::new( - "composer.json".to_string(), - None, - None, - )?)), - false, - ); - - let is_packagist_disabled = (repo_config.contains_key("packagist") - && repo_config.len() == 1 - && repo_config.get("packagist").and_then(|v| v.as_bool()) == Some(false)) - || (repo_config.contains_key("packagist.org") - && repo_config.len() == 1 - && repo_config.get("packagist.org").and_then(|v| v.as_bool()) - == Some(false)); - if is_packagist_disabled { - config_source.add_repository("packagist.org", PhpMixed::Bool(false), false); - } else { - config_source.add_repository( - &name, - PhpMixed::Array( - repo_config - .iter() - .map(|(k, v)| (k.clone(), Box::new(v.clone()))) - .collect(), - ), - false, - ); - } - - composer_handle = self.create_composer_instance( - input.clone(), - io.clone(), + if let Some(repos) = repositories.as_ref() + && add_repository + { + for (index, repo) in repos.iter().enumerate() { + let config = crate::command::composer_full(&composer_handle).get_config(); + let repo_config = + RepositoryFactory::config_from_string(io.clone(), &config, repo, true)?; + let composer_json_repositories_config = + crate::command::composer_full(&composer_handle) + .get_config() + .borrow() + .get_repositories(); + let name = RepositoryFactory::generate_repository_name( + &PhpMixed::Int(index as i64), + &repo_config, + &composer_json_repositories_config, + ); + let mut config_source = JsonConfigSource::new( + std::rc::Rc::new(std::cell::RefCell::new(JsonFile::new( + "composer.json".to_string(), None, - disable_plugins, None, - )?; + )?)), + false, + ); + + let is_packagist_disabled = (repo_config.contains_key("packagist") + && repo_config.len() == 1 + && repo_config.get("packagist").and_then(|v| v.as_bool()) == Some(false)) + || (repo_config.contains_key("packagist.org") + && repo_config.len() == 1 + && repo_config.get("packagist.org").and_then(|v| v.as_bool()) + == Some(false)); + if is_packagist_disabled { + config_source.add_repository("packagist.org", PhpMixed::Bool(false), false); + } else { + config_source.add_repository( + &name, + PhpMixed::Array( + repo_config + .iter() + .map(|(k, v)| (k.clone(), Box::new(v.clone()))) + .collect(), + ), + false, + ); } + + composer_handle = self.create_composer_instance( + input.clone(), + io.clone(), + None, + disable_plugins, + None, + )?; } } @@ -444,12 +450,12 @@ impl CreateProjectCommand { // use the new config including the newly installed project let config = composer.get_config(); let (ps, pd) = - self.get_preferred_install_options(&*config.borrow(), input.clone(), false)?; + self.get_preferred_install_options(&config.borrow(), input.clone(), false)?; prefer_source = ps; prefer_dist = pd; // install dependencies of the created project - if no_install == false { + if !no_install { composer .get_installation_manager() .borrow_mut() @@ -487,7 +493,7 @@ impl CreateProjectCommand { None, ) .set_audit_config( - self.create_audit_config(&mut *config.borrow_mut(), input.clone())?, + self.create_audit_config(&mut config.borrow_mut(), input.clone())?, ); if !composer.get_locker().borrow_mut().is_locked() { @@ -654,16 +660,17 @@ impl CreateProjectCommand { } // if no directory was specified, use the 2nd part of the package name - let mut directory = if directory.is_none() { - let mut parts = explode_with_limit("/", &name, 2); - format!( - "{}{}{}", - Platform::get_cwd(false)?, - DIRECTORY_SEPARATOR, - array_pop(&mut parts).unwrap_or_default() - ) - } else { - directory.unwrap() + let mut directory = match directory { + None => { + let mut parts = explode_with_limit("/", &name, 2); + format!( + "{}{}{}", + Platform::get_cwd(false)?, + DIRECTORY_SEPARATOR, + array_pop(&mut parts).unwrap_or_default() + ) + } + Some(directory) => directory, }; directory = rtrim(&directory, Some("/\\")); @@ -679,7 +686,7 @@ impl CreateProjectCommand { directory ); } - if "" == directory { + if directory.is_empty() { return Err(UnexpectedValueException { message: "Got an empty target directory, something went wrong".to_string(), code: 0, @@ -806,21 +813,8 @@ impl CreateProjectCommand { indexmap::IndexMap::new(), indexmap::IndexMap::new(), ); - if repositories.is_none() { - repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new( - CompositeRepository::new( - RepositoryFactory::default_repos( - Some(io.clone()), - Some(config.clone()), - Some(&mut rm.borrow_mut()), - )? - .into_iter() - .map(|(_, v)| v) - .collect(), - ), - ))?; - } else { - for repo in repositories.unwrap() { + if let Some(repositories) = repositories { + for repo in repositories { let mut repo_config = RepositoryFactory::config_from_string(io.clone(), &config, repo, true)?; let is_packagist_disabled = (repo_config.contains_key("packagist") @@ -860,6 +854,19 @@ impl CreateProjectCommand { None, )?); } + } else { + repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new( + CompositeRepository::new( + RepositoryFactory::default_repos( + Some(io.clone()), + Some(config.clone()), + Some(&mut rm.borrow_mut()), + )? + .into_iter() + .map(|(_, v)| v) + .collect(), + ), + ))?; } let platform_overrides = config.borrow_mut().get("platform"); @@ -965,10 +972,10 @@ impl CreateProjectCommand { } // avoid displaying 9999999-dev as version if default-branch was selected - if let Some(alias) = package.as_alias() { - if package.get_pretty_version() == VersionParser::DEFAULT_BRANCH_ALIAS { - package = alias.get_alias_of().into(); - } + if let Some(alias) = package.as_alias() + && package.get_pretty_version() == VersionParser::DEFAULT_BRANCH_ALIAS + { + package = alias.get_alias_of().into(); } io.write_error(&format!( diff --git a/crates/shirabe/src/command/depends_command.rs b/crates/shirabe/src/command/depends_command.rs index bc9dd27..133f8b2 100644 --- a/crates/shirabe/src/command/depends_command.rs +++ b/crates/shirabe/src/command/depends_command.rs @@ -28,6 +28,12 @@ pub struct DependsCommand { colors: Vec<String>, } +impl Default for DependsCommand { + fn default() -> Self { + Self::new() + } +} + impl DependsCommand { pub fn new() -> Self { let mut command = DependsCommand { diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs index 252208d..7f1aec5 100644 --- a/crates/shirabe/src/command/diagnose_command.rs +++ b/crates/shirabe/src/command/diagnose_command.rs @@ -69,6 +69,12 @@ pub struct DiagnoseCommand { pub(crate) exit_code: i64, } +impl Default for DiagnoseCommand { + fn default() -> Self { + Self::new() + } +} + impl DiagnoseCommand { pub fn new() -> Self { let mut command = DiagnoseCommand { @@ -158,7 +164,7 @@ impl Command for DiagnoseCommand { if strpos(file!(), "phar:") == Some(0) { io.write_no_newline("Checking pubkeys: "); - let r = self.check_pub_keys(&*config.borrow())?; + let r = self.check_pub_keys(&config.borrow())?; self.output_result(r); io.write_no_newline("Checking Composer version: "); @@ -172,7 +178,7 @@ impl Command for DiagnoseCommand { )); io.write_no_newline("Checking Composer and its dependencies for vulnerabilities: "); - let r = self.check_composer_audit(&*config.borrow())?; + let r = self.check_composer_audit(&config.borrow())?; self.output_result(r); let platform_overrides = config @@ -194,14 +200,14 @@ impl Command for DiagnoseCommand { )? .unwrap(); let mut php_version = php_pkg.get_pretty_version().to_string(); - if let Some(cp) = php_pkg.as_complete() { - if str_contains(&cp.get_description().unwrap_or_default(), "overridden") { - php_version = format!( - "{} - {}", - php_version, - cp.get_description().unwrap_or_default() - ); - } + if let Some(cp) = php_pkg.as_complete() + && str_contains(&cp.get_description().unwrap_or_default(), "overridden") + { + php_version = format!( + "{} - {}", + php_version, + cp.get_description().unwrap_or_default() + ); } io.write(&format!("PHP version: <comment>{}</comment>", php_version)); @@ -298,11 +304,11 @@ impl Command for DiagnoseCommand { self.output_result(PhpMixed::String(r)); io.write_no_newline("Checking http connectivity to packagist: "); - let r = self.check_http("http", &*config.borrow())?; + let r = self.check_http("http", &config.borrow())?; self.output_result(r); io.write_no_newline("Checking https connectivity to packagist: "); - let r = self.check_http("https", &*config.borrow())?; + let r = self.check_http("https", &config.borrow())?; self.output_result(r); for repo in config.borrow().get_repositories() { @@ -317,7 +323,7 @@ impl Command for DiagnoseCommand { let composer_repo = ComposerRepository::new( repo_arr_unboxed, self.get_io().clone(), - &*config.borrow(), + &config.borrow(), self.http_downloader.clone().unwrap(), None, ) @@ -339,7 +345,7 @@ impl Command for DiagnoseCommand { .and_then(|v| v.as_string()) .unwrap_or("") )); - let r = self.check_composer_repo(&url, &*config.borrow())?; + let r = self.check_composer_repo(&url, &config.borrow())?; self.output_result(r); } } @@ -375,11 +381,7 @@ impl Command for DiagnoseCommand { self.output_result(if is_string(&status) { status } else { - PhpMixed::String(format!( - "<error>[{}] {}</error>", - get_class_err(&e), - e.to_string() - )) + PhpMixed::String(format!("<error>[{}] {}</error>", get_class_err(&e), e)) }); } else { return Err(e); @@ -426,14 +428,14 @@ impl Command for DiagnoseCommand { self.output_result(PhpMixed::String(format!( "<error>[{}] {}</error>", get_class_err(&e), - e.to_string() + e ))); } } else { self.output_result(PhpMixed::String(format!( "<error>[{}] {}</error>", get_class_err(&e), - e.to_string() + e ))); } } @@ -441,7 +443,7 @@ impl Command for DiagnoseCommand { } io.write_no_newline("Checking disk free space: "); - let r = self.check_disk_space(&*config.borrow()); + let r = self.check_disk_space(&config.borrow()); self.output_result(r); Ok(self.exit_code) @@ -519,7 +521,7 @@ impl DiagnoseCommand { let mut output = String::new(); let _ = self.process.as_mut().unwrap().borrow_mut().execute( - &vec![ + vec![ "git".to_string(), "config".to_string(), "color.ui".to_string(), @@ -588,7 +590,7 @@ impl DiagnoseCommand { result_list.push(Box::new(PhpMixed::String(w))); } - if result_list.len() > 0 { + if !result_list.is_empty() { return Ok(PhpMixed::List(result_list)); } @@ -639,7 +641,7 @@ impl DiagnoseCommand { result_list.push(Box::new(PhpMixed::String(w))); } - if result_list.len() > 0 { + if !result_list.is_empty() { return Ok(PhpMixed::List(result_list)); } @@ -759,18 +761,18 @@ impl DiagnoseCommand { ))) } Err(e) => { - if let Some(te) = e.downcast_ref::<TransportException>() { - if te.get_code() == 401 { - return Ok(PhpMixed::String(format!( - "<comment>The oauth token for {} seems invalid, run \"composer config --global --unset github-oauth.{}\" to remove it</comment>", - domain, domain - ))); - } + if let Some(te) = e.downcast_ref::<TransportException>() + && te.get_code() == 401 + { + return Ok(PhpMixed::String(format!( + "<comment>The oauth token for {} seems invalid, run \"composer config --global --unset github-oauth.{}\" to remove it</comment>", + domain, domain + ))); } Ok(PhpMixed::String(format!( "<error>[{}] {}</error>", get_class_err(&e), - e.to_string() + e ))) } } @@ -913,7 +915,7 @@ impl DiagnoseCommand { return Ok(PhpMixed::String(format!( "<error>[{}] {}</error>", get_class_err(&e), - e.to_string() + e ))); } }; @@ -1006,7 +1008,7 @@ impl DiagnoseCommand { Err(e) => { return Ok(PhpMixed::String(format!( "<highlight>Failed performing audit: {}</>", - e.to_string() + e ))); } }; @@ -1102,8 +1104,7 @@ impl DiagnoseCommand { let mut had_warning = false; let mut result = result; // PHP: $result instanceof \Exception → already converted to string at call sites here - if !result.as_bool().unwrap_or(true) && !result.as_string().is_some() && !is_array(&result) - { + if !result.as_bool().unwrap_or(true) && result.as_string().is_none() && !is_array(&result) { // falsey results should be considered as an error, even if there is nothing to output had_error = true; } else { @@ -1334,7 +1335,7 @@ impl DiagnoseCommand { return Err(InvalidArgumentException { message: format!( "DiagnoseCommand: Unknown error type \"{}\". Please report at https://github.com/composer/composer/issues/new.", - other.to_string(), + other, ), code: 0, } @@ -1413,7 +1414,7 @@ impl DiagnoseCommand { return Err(InvalidArgumentException { message: format!( "DiagnoseCommand: Unknown warning type \"{}\". Please report at https://github.com/composer/composer/issues/new.", - other.to_string(), + other, ), code: 0, } @@ -1429,7 +1430,7 @@ impl DiagnoseCommand { } let composer_ipresolve = Platform::get_env("COMPOSER_IPRESOLVE").unwrap_or_default(); - if vec!["4".to_string(), "6".to_string()].contains(&composer_ipresolve) { + if ["4".to_string(), "6".to_string()].contains(&composer_ipresolve) { warnings.insert("ipresolve".to_string(), PhpMixed::Bool(true)); out_fn( &format!( @@ -1441,7 +1442,7 @@ impl DiagnoseCommand { ); } - Ok(if warnings.len() == 0 && errors.len() == 0 { + Ok(if warnings.is_empty() && errors.is_empty() { PhpMixed::Bool(true) } else { PhpMixed::String(output) diff --git a/crates/shirabe/src/command/dump_autoload_command.rs b/crates/shirabe/src/command/dump_autoload_command.rs index a1e50f5..9369267 100644 --- a/crates/shirabe/src/command/dump_autoload_command.rs +++ b/crates/shirabe/src/command/dump_autoload_command.rs @@ -27,6 +27,12 @@ pub struct DumpAutoloadCommand { base_command_data: BaseCommandData, } +impl Default for DumpAutoloadCommand { + fn default() -> Self { + Self::new() + } +} + impl DumpAutoloadCommand { pub fn new() -> Self { let mut command = DumpAutoloadCommand { @@ -269,7 +275,7 @@ impl Command for DumpAutoloadCommand { &config_ref, local_repo, package, - &mut *installation_manager_ref, + &mut installation_manager_ref, "composer", optimize, None, diff --git a/crates/shirabe/src/command/exec_command.rs b/crates/shirabe/src/command/exec_command.rs index aef22a3..c4a1e94 100644 --- a/crates/shirabe/src/command/exec_command.rs +++ b/crates/shirabe/src/command/exec_command.rs @@ -26,6 +26,12 @@ pub struct ExecCommand { base_command_data: BaseCommandData, } +impl Default for ExecCommand { + fn default() -> Self { + Self::new() + } +} + impl ExecCommand { pub fn new() -> Self { let mut command = ExecCommand { @@ -61,10 +67,10 @@ impl ExecCommand { let mut binaries: Vec<String> = Vec::new(); let mut previous_bin: Option<String> = None; for bin in bins.iter().chain(local_bins.iter()) { - if let Some(prev) = &previous_bin { - if bin == &format!("{}.bat", prev) { - continue; - } + if let Some(prev) = &previous_bin + && bin == &format!("{}.bat", prev) + { + continue; } previous_bin = Some(bin.clone()); binaries.push(basename(bin)); @@ -201,13 +207,13 @@ impl Command for ExecCommand { // Application handle (deferred with the Application shared-ownership work). Until then the // working-directory restore is skipped. let initial_working_directory: Option<String> = None; - if let Some(ref iwd) = initial_working_directory { - if getcwd().as_deref() != Some(iwd.as_str()) { - chdir(iwd).map_err(|e| RuntimeException { - message: format!("Could not switch back to working directory \"{}\"", iwd), - code: 0, - })?; - } + if let Some(ref iwd) = initial_working_directory + && getcwd().as_deref() != Some(iwd.as_str()) + { + chdir(iwd).map_err(|e| RuntimeException { + message: format!("Could not switch back to working directory \"{}\"", iwd), + code: 0, + })?; } let args = input @@ -221,12 +227,12 @@ impl Command for ExecCommand { }) .unwrap_or_default(); - Ok(dispatcher.borrow_mut().dispatch_script( + dispatcher.borrow_mut().dispatch_script( "__exec_command", true, args, indexmap::IndexMap::new(), - )?) + ) } fn initialize( diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs index 1e26fc0..4b58a7a 100644 --- a/crates/shirabe/src/command/fund_command.rs +++ b/crates/shirabe/src/command/fund_command.rs @@ -38,6 +38,12 @@ pub struct FundCommand { base_command_data: BaseCommandData, } +impl Default for FundCommand { + fn default() -> Self { + Self::new() + } +} + impl FundCommand { pub fn new() -> Self { let mut command = FundCommand { @@ -60,7 +66,7 @@ impl FundCommand { for funding_option in package.get_funding() { let url_val = funding_option.get("url").and_then(|v| v.as_string()); - if url_val.map_or(true, |s| s.is_empty()) { + if url_val.is_none_or(|s| s.is_empty()) { continue; } let mut url = url_val.unwrap().to_string(); @@ -68,14 +74,12 @@ impl FundCommand { .get("type") .and_then(|v| v.as_string()) .unwrap_or(""); - if r#type == "github" { - if let Some(matches) = + if r#type == "github" + && let Some(matches) = Preg::is_match_with_indexed_captures(r"^https://github.com/([^/]+)$", &url) - { - if let Some(sponsor) = matches.into_iter().nth(1) { - url = format!("https://github.com/sponsors/{}", sponsor); - } - } + && let Some(sponsor) = matches.into_iter().nth(1) + { + url = format!("https://github.com/sponsors/{}", sponsor); } fundings .entry(vendor.to_string()) @@ -115,13 +119,8 @@ impl Command for FundCommand { let repository_manager = composer.get_repository_manager().clone(); let repository_manager = repository_manager.borrow(); let repo = repository_manager.get_local_repository(); - let mut remote_repos = CompositeRepository::new( - repository_manager - .get_repositories() - .iter() - .map(|r| r.clone()) - .collect(), - ); + let mut remote_repos = + CompositeRepository::new(repository_manager.get_repositories().to_vec()); let mut fundings: IndexMap<String, IndexMap<String, Vec<String>>> = IndexMap::new(); let mut packages_to_load: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); @@ -149,14 +148,13 @@ impl Command for FundCommand { for (_, package) in &result.packages { if package.as_alias().is_none() { // TODO: check for CompleteAliasPackage as well - if let Some(complete_pkg) = package.as_complete() { - if complete_pkg.is_default_branch() - && !complete_pkg.get_funding().is_empty() - && packages_to_load_names.contains(&complete_pkg.get_name()) - { - Self::insert_funding_data(&mut fundings, &complete_pkg)?; - packages_to_load_names.shift_remove(&complete_pkg.get_name()); - } + if let Some(complete_pkg) = package.as_complete() + && complete_pkg.is_default_branch() + && !complete_pkg.get_funding().is_empty() + && packages_to_load_names.contains(&complete_pkg.get_name()) + { + Self::insert_funding_data(&mut fundings, &complete_pkg)?; + packages_to_load_names.shift_remove(&complete_pkg.get_name()); } } } @@ -168,10 +166,10 @@ impl Command for FundCommand { continue; } // TODO: check for CompleteAliasPackage as well - if let Some(complete_pkg) = package.as_complete() { - if !complete_pkg.get_funding().is_empty() { - Self::insert_funding_data(&mut fundings, &complete_pkg)?; - } + if let Some(complete_pkg) = package.as_complete() + && !complete_pkg.get_funding().is_empty() + { + Self::insert_funding_data(&mut fundings, &complete_pkg)?; } } diff --git a/crates/shirabe/src/command/global_command.rs b/crates/shirabe/src/command/global_command.rs index 69cf48a..941315b 100644 --- a/crates/shirabe/src/command/global_command.rs +++ b/crates/shirabe/src/command/global_command.rs @@ -35,6 +35,12 @@ pub struct GlobalCommand { base_command_data: BaseCommandData, } +impl Default for GlobalCommand { + fn default() -> Self { + Self::new() + } +} + impl GlobalCommand { pub fn new() -> Self { let mut command = GlobalCommand { @@ -116,7 +122,7 @@ impl GlobalCommand { // TODO(phase-c): getApplication()->resetComposer() needs the shared shirabe Application // handle (deferred with the Application shared-ownership work). - Ok(StringInput::new(&new_input_str)?) + StringInput::new(&new_input_str) } } diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs index 0ac7483..1620205 100644 --- a/crates/shirabe/src/command/home_command.rs +++ b/crates/shirabe/src/command/home_command.rs @@ -35,6 +35,12 @@ pub struct HomeCommand { base_command_data: BaseCommandData, } +impl Default for HomeCommand { + fn default() -> Self { + Self::new() + } +} + impl HomeCommand { pub fn new() -> Self { let mut command = HomeCommand { @@ -57,7 +63,7 @@ impl HomeCommand { .get("source") .cloned() .or_else(|| package.get_source_url().map(|s| s.to_string())); - if url.as_deref().map_or(true, |s| s.is_empty()) || show_homepage { + if url.as_deref().is_none_or(|s| s.is_empty()) || show_homepage { url = package.get_homepage().map(|s| s.to_string()); } @@ -224,13 +230,13 @@ impl Command for HomeCommand { let mut package_exists = false; 'repos: for repo in &repos { - for package in repo.find_packages(&package_name, None)? { + for package in repo.find_packages(package_name, None)? { package_exists = true; - if let Some(complete_pkg) = package.as_complete() { - if self.handle_package(complete_pkg, show_homepage, show_only) { - handled = true; - break 'repos; - } + if let Some(complete_pkg) = package.as_complete() + && self.handle_package(complete_pkg, show_homepage, show_only) + { + handled = true; + break 'repos; } } } diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs index 3806da5..afb4e9d 100644 --- a/crates/shirabe/src/command/init_command.rs +++ b/crates/shirabe/src/command/init_command.rs @@ -93,6 +93,12 @@ impl PackageDiscoveryTrait for InitCommand { } } +impl Default for InitCommand { + fn default() -> Self { + Self::new() + } +} + impl InitCommand { pub fn new() -> Self { let mut command = InitCommand { @@ -357,7 +363,7 @@ impl Command for InitCommand { ); let errors = format!( " - {}", - implode(&format!("{} - ", PHP_EOL), &json_err.get_errors()) + implode(&format!("{} - ", PHP_EOL), json_err.get_errors()) ); io.write_error3( &format!("{}:{}{}", json_err.get_message(), PHP_EOL, errors), @@ -496,7 +502,7 @@ impl Command for InitCommand { None, )?)); io.borrow_mut() - .load_configuration(&mut *config.borrow_mut())?; + .load_configuration(&mut config.borrow_mut())?; let mut repo_manager = RepositoryFactory::manager(io.clone(), &config, None, None, None)?; @@ -970,14 +976,14 @@ impl InitCommand { Some(&mut m), ) { let email = m.get(&CaptureKey::ByName("email".to_string())).cloned(); - if let Some(ref email) = email { - if !self.is_valid_email(email) { - return Err(InvalidArgumentException { - message: format!("Invalid email \"{}\"", email), - code: 0, - } - .into()); + if let Some(ref email) = email + && !self.is_valid_email(email) + { + return Err(InvalidArgumentException { + message: format!("Invalid email \"{}\"", email), + code: 0, } + .into()); } let mut result: IndexMap<String, Option<String>> = IndexMap::new(); @@ -1029,7 +1035,7 @@ impl InitCommand { let namespace: Vec<String> = array_map( |part: &String| { - let part = Preg::replace(r"/[^a-z0-9]/i", " ", &part); + let part = Preg::replace(r"/[^a-z0-9]/i", " ", part); let part = ucwords(&part); str_replace(" ", "", &part) }, @@ -1049,7 +1055,7 @@ impl InitCommand { let mut output = String::new(); if process.execute_args( - &vec!["git".to_string(), "config".to_string(), "-l".to_string()], + &["git".to_string(), "config".to_string(), "-l".to_string()], &mut output, (), ) == 0 @@ -1175,9 +1181,8 @@ impl InitCommand { ); let name = strtolower(&name); let name = Preg::replace(r"{^[_.-]+|[_.-]+$|[^a-z0-9_.-]}u", "", &name); - let name = Preg::replace(r"{([_.-]){2,}}u", "$1", &name); - name + Preg::replace(r"{([_.-]){2,}}u", "$1", &name) } fn get_default_package_name(&mut self) -> String { diff --git a/crates/shirabe/src/command/install_command.rs b/crates/shirabe/src/command/install_command.rs index 3fa8ed2..1605015 100644 --- a/crates/shirabe/src/command/install_command.rs +++ b/crates/shirabe/src/command/install_command.rs @@ -31,6 +31,12 @@ pub struct InstallCommand { base_command_data: BaseCommandData, } +impl Default for InstallCommand { + fn default() -> Self { + Self::new() + } +} + impl InstallCommand { pub fn new() -> Self { let mut command = InstallCommand { @@ -150,7 +156,7 @@ impl Command for InstallCommand { let config = composer.get_config(); let (prefer_source, prefer_dist) = - self.get_preferred_install_options(&*config.borrow(), input.clone(), false)?; + self.get_preferred_install_options(&config.borrow(), input.clone(), false)?; let optimize = input .borrow() @@ -243,7 +249,7 @@ impl Command for InstallCommand { .set_apcu_autoloader(apcu, apcu_prefix.clone()) .set_platform_requirement_filter(self.get_platform_requirement_filter(input.clone())?) .set_audit_config( - self.create_audit_config(&mut *composer.get_config().borrow_mut(), input.clone())?, + self.create_audit_config(&mut composer.get_config().borrow_mut(), input.clone())?, ) .set_error_on_audit( input diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs index 56aa042..1f054d1 100644 --- a/crates/shirabe/src/command/licenses_command.rs +++ b/crates/shirabe/src/command/licenses_command.rs @@ -41,6 +41,12 @@ pub struct LicensesCommand { base_command_data: BaseCommandData, } +impl Default for LicensesCommand { + fn default() -> Self { + Self::new() + } +} + impl LicensesCommand { pub fn new() -> Self { let mut command = LicensesCommand { @@ -161,8 +167,7 @@ impl Command for LicensesCommand { } }; - let packages: Vec<crate::package::PackageInterfaceHandle> = - packages.into_iter().map(|p| p.into()).collect(); + let packages: Vec<crate::package::PackageInterfaceHandle> = packages.into_iter().collect(); let packages = PackageSorter::sort_packages_alphabetically(packages); let io = self.get_io(); diff --git a/crates/shirabe/src/command/outdated_command.rs b/crates/shirabe/src/command/outdated_command.rs index 0627901..22dd120 100644 --- a/crates/shirabe/src/command/outdated_command.rs +++ b/crates/shirabe/src/command/outdated_command.rs @@ -26,6 +26,12 @@ pub struct OutdatedCommand { base_command_data: BaseCommandData, } +impl Default for OutdatedCommand { + fn default() -> Self { + Self::new() + } +} + impl OutdatedCommand { pub fn new() -> Self { let mut command = OutdatedCommand { diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs index 3263444..e2ffa7c 100644 --- a/crates/shirabe/src/command/package_discovery_trait.rs +++ b/crates/shirabe/src/command/package_discovery_trait.rs @@ -136,24 +136,19 @@ pub trait PackageDiscoveryTrait { if is_file(&file) && Filesystem::is_readable(&file) { let contents = file_get_contents(&file).unwrap_or_default(); let composer = json_decode(&contents, true).unwrap_or(PhpMixed::Null); - if is_array(&composer) { - if let Some(arr) = composer.as_array() { - if let Some(ms) = arr.get("minimum-stability") { - if let Some(s) = ms.as_string() { - return VersionParser::normalize_stability(s).unwrap_or_default(); - } - } - } + if is_array(&composer) + && let Some(arr) = composer.as_array() + && let Some(ms) = arr.get("minimum-stability") + && let Some(s) = ms.as_string() + { + return VersionParser::normalize_stability(s).unwrap_or_default(); } } "stable".to_string() } - /// @param array<string> $requires - /// - /// @return array<string> - /// @throws \Exception + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn determine_requirements( &mut self, input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>, @@ -164,7 +159,7 @@ pub trait PackageDiscoveryTrait { use_best_version_constraint: bool, fixed: bool, ) -> Result<Vec<String>> { - if requires.len() > 0 { + if !requires.is_empty() { let requires_norm = self.normalize_requirements(requires.clone()); let mut result: Vec<String> = vec![]; let io = self.get_io(); @@ -268,7 +263,7 @@ pub trait PackageDiscoveryTrait { None, )?; - if matches.len() > 0 { + if !matches.is_empty() { // Remove existing packages from search results. matches.retain(|found_package| { !in_array( @@ -295,7 +290,7 @@ pub trait PackageDiscoveryTrait { if !exact_match { let providers: IndexMap<String, crate::repository::ProviderInfo> = self.get_repos().get_providers(package.clone())?; - if providers.len() > 0 { + if !providers.is_empty() { // PHP: array_unshift($matches, ['name' => $package, 'description' => '']); matches.insert( 0, @@ -356,7 +351,7 @@ pub trait PackageDiscoveryTrait { let validator: Box<dyn Fn(PhpMixed) -> anyhow::Result<PhpMixed>> = Box::new( move |selection_mixed: PhpMixed| -> anyhow::Result<PhpMixed> { let selection = selection_mixed.as_string().unwrap_or("").to_string(); - if "" == selection { + if selection.is_empty() { return Ok(PhpMixed::Bool(false)); } @@ -530,7 +525,7 @@ pub trait PackageDiscoveryTrait { // Check if it is a virtual package provided by others let providers = repo_set.borrow().get_providers(name)?; - if providers.len() > 0 { + if !providers.is_empty() { let mut constraint = "*".to_string(); if input.borrow().is_interactive() { let providers_count = providers.len(); @@ -693,7 +688,7 @@ pub trait PackageDiscoveryTrait { // Check for similar names/typos let similar = self.find_similar(name)?; - if similar.len() > 0 { + if !similar.is_empty() { if in_array( PhpMixed::String(name.to_string()), &PhpMixed::List( @@ -720,25 +715,24 @@ pub trait PackageDiscoveryTrait { "<error>Could not find package {}.</error>\nPick one of these or leave empty to abort:", name, ), - similar.iter().map(|s| s.clone()).collect(), + similar.to_vec(), PhpMixed::Bool(false), PhpMixed::Int(1), "No package named \"%s\" is installed.".to_string(), false, ); - if let Some(idx_str) = result_mixed.as_string() { - if let Ok(idx) = idx_str.parse::<usize>() { - if let Some(selected) = similar.get(idx) { - return self.find_best_version_and_name_for_package( - io.clone(), - input, - selected, - platform_repo, - preferred_stability, - fixed, - ); - } - } + if let Some(idx_str) = result_mixed.as_string() + && let Ok(idx) = idx_str.parse::<usize>() + && let Some(selected) = similar.get(idx) + { + return self.find_best_version_and_name_for_package( + io.clone(), + input, + selected, + platform_repo, + preferred_stability, + fixed, + ); } } diff --git a/crates/shirabe/src/command/prohibits_command.rs b/crates/shirabe/src/command/prohibits_command.rs index 5e66c33..ddbf02a 100644 --- a/crates/shirabe/src/command/prohibits_command.rs +++ b/crates/shirabe/src/command/prohibits_command.rs @@ -27,6 +27,12 @@ pub struct ProhibitsCommand { colors: Vec<String>, } +impl Default for ProhibitsCommand { + fn default() -> Self { + Self::new() + } +} + impl ProhibitsCommand { pub fn new() -> Self { let mut command = ProhibitsCommand { diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs index c7b6cc0..8f48243 100644 --- a/crates/shirabe/src/command/reinstall_command.rs +++ b/crates/shirabe/src/command/reinstall_command.rs @@ -39,6 +39,12 @@ pub struct ReinstallCommand { base_command_data: BaseCommandData, } +impl Default for ReinstallCommand { + fn default() -> Self { + Self::new() + } +} + impl ReinstallCommand { pub fn new() -> Self { let mut command = ReinstallCommand { @@ -171,11 +177,10 @@ impl Command for ReinstallCommand { let present_packages = local_repo.get_packages()?; let result_packages: Vec<crate::package::PackageInterfaceHandle> = - present_packages.iter().map(|p| p.clone().into()).collect(); + present_packages.to_vec(); let present_packages: Vec<crate::package::PackageInterfaceHandle> = present_packages .into_iter() .filter(|package| !package_names_to_reinstall.contains(&package.get_name())) - .map(|p| p.into()) .collect(); let transaction = Transaction::new(present_packages, result_packages); @@ -183,10 +188,10 @@ impl Command for ReinstallCommand { let mut install_order = indexmap::IndexMap::new(); for (index, op) in install_operations.iter().enumerate() { - if let Some(install_op) = op.as_any().downcast_ref::<InstallOperation>() { - if install_op.get_package().as_alias().is_none() { - install_order.insert(install_op.get_package().get_name(), index); - } + if let Some(install_op) = op.as_any().downcast_ref::<InstallOperation>() + && install_op.get_package().as_alias().is_none() + { + install_order.insert(install_op.get_package().get_name(), index); } } @@ -212,7 +217,7 @@ impl Command for ReinstallCommand { let config = composer.get_config(); let (prefer_source, prefer_dist) = - self.get_preferred_install_options(&*config.borrow(), input.clone(), false)?; + self.get_preferred_install_options(&config.borrow(), input.clone(), false)?; let installation_manager = composer.get_installation_manager().clone(); let download_manager = composer.get_download_manager(); diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs index 4e4f5dc..c1ba536 100644 --- a/crates/shirabe/src/command/remove_command.rs +++ b/crates/shirabe/src/command/remove_command.rs @@ -39,6 +39,12 @@ pub struct RemoveCommand { base_command_data: BaseCommandData, } +impl Default for RemoveCommand { + fn default() -> Self { + Self::new() + } +} + impl RemoveCommand { pub fn new() -> Self { let mut command = RemoveCommand { @@ -208,7 +214,7 @@ impl Command for RemoveCommand { .as_list() .map(|l| { l.iter() - .filter_map(|v| v.as_string().map(|s| strtolower(s))) + .filter_map(|v| v.as_string().map(strtolower)) .collect() }) .unwrap_or_default(); @@ -375,22 +381,22 @@ impl Command for RemoveCommand { "<warning>{} could not be found in {} but it is present in {}</warning>", canonical_name, r#type, alt_type )); - if io.is_interactive() { - if io.ask_confirmation( + if io.is_interactive() + && io.ask_confirmation( format!( "Do you want to remove it from {} [<comment>yes</comment>]? ", alt_type ), true, - ) { - if dry_run { - to_remove - .entry(alt_type.to_string()) - .or_default() - .push(canonical_name.clone()); - } else { - json.remove_link(alt_type, &canonical_name); - } + ) + { + if dry_run { + to_remove + .entry(alt_type.to_string()) + .or_default() + .push(canonical_name.clone()); + } else { + json.remove_link(alt_type, &canonical_name); } } } else { @@ -436,22 +442,22 @@ impl Command for RemoveCommand { "<warning>{} could not be found in {} but it is present in {}</warning>", matched_package, r#type, alt_type )); - if io.is_interactive() { - if io.ask_confirmation( + if io.is_interactive() + && io.ask_confirmation( format!( "Do you want to remove it from {} [<comment>yes</comment>]? ", alt_type ), true, - ) { - if dry_run { - to_remove - .entry(alt_type.to_string()) - .or_default() - .push(matched_package.clone()); - } else { - json.remove_link(alt_type, matched_package); - } + ) + { + if dry_run { + to_remove + .entry(alt_type.to_string()) + .or_default() + .push(matched_package.clone()); + } else { + json.remove_link(alt_type, matched_package); } } } @@ -675,7 +681,7 @@ impl Command for RemoveCommand { .set_platform_requirement_filter(self.get_platform_requirement_filter(input.clone())?); install.set_dry_run(dry_run); install.set_audit_config( - self.create_audit_config(&mut *composer.get_config().borrow_mut(), input)?, + self.create_audit_config(&mut composer.get_config().borrow_mut(), input)?, ); install.set_minimal_update(minimal_changes); diff --git a/crates/shirabe/src/command/repository_command.rs b/crates/shirabe/src/command/repository_command.rs index 284b523..6ea26d2 100644 --- a/crates/shirabe/src/command/repository_command.rs +++ b/crates/shirabe/src/command/repository_command.rs @@ -36,6 +36,12 @@ pub struct RepositoryCommand { config_source: Option<JsonConfigSource>, } +impl Default for RepositoryCommand { + fn default() -> Self { + Self::new() + } +} + impl RepositoryCommand { pub fn new() -> Self { let mut command = RepositoryCommand { @@ -94,14 +100,13 @@ impl RepositoryCommand { } if let PhpMixed::Array(ref repo_map) = *repo { - if repo_map.len() == 1 { - if let Some(first_val) = repo_map.values().next() { - if matches!(**first_val, PhpMixed::Bool(false)) { - let first_key = repo_map.keys().next().unwrap(); - io.write(&format!("[{}] <info>disabled</info>", first_key)); - continue; - } - } + if repo_map.len() == 1 + && let Some(first_val) = repo_map.values().next() + && matches!(**first_val, PhpMixed::Bool(false)) + { + let first_key = repo_map.keys().next().unwrap(); + io.write(&format!("[{}] <info>disabled</info>", first_key)); + continue; } let name = repo_map @@ -237,12 +242,11 @@ impl Command for RepositoryCommand { _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>, ) -> anyhow::Result<i64> { let action = strtolower( - &input + input .borrow() .get_argument("action")? .as_string() - .unwrap_or("") - .to_string(), + .unwrap_or(""), ); let name = input .borrow() @@ -406,8 +410,24 @@ impl Command for RepositoryCommand { })); } let name_str = name.as_deref().unwrap(); - if let Some(repo) = repos.get(name_str) { - if let PhpMixed::Array(ref repo_map) = *repo { + if let Some(repo) = repos.get(name_str) + && let PhpMixed::Array(ref repo_map) = *repo + { + let url = repo_map.get("url").and_then(|v| v.as_string()); + if let Some(url) = url { + self.get_io().write(url); + return Ok(0); + } + return Err(anyhow::anyhow!(InvalidArgumentException { + message: format!("The {} repository does not have a URL", name_str), + code: 0, + })); + } + for (_key, val) in &repos { + if let PhpMixed::Array(ref repo_map) = *val + && let Some(n) = repo_map.get("name").and_then(|v| v.as_string()) + && n == name_str + { let url = repo_map.get("url").and_then(|v| v.as_string()); if let Some(url) = url { self.get_io().write(url); @@ -419,26 +439,6 @@ impl Command for RepositoryCommand { })); } } - for (_key, val) in &repos { - if let PhpMixed::Array(ref repo_map) = *val { - if let Some(n) = repo_map.get("name").and_then(|v| v.as_string()) { - if n == name_str { - let url = repo_map.get("url").and_then(|v| v.as_string()); - if let Some(url) = url { - self.get_io().write(url); - return Ok(0); - } - return Err(anyhow::anyhow!(InvalidArgumentException { - message: format!( - "The {} repository does not have a URL", - name_str - ), - code: 0, - })); - } - } - } - } Err(anyhow::anyhow!(InvalidArgumentException { message: format!("There is no {} repository defined", name_str), code: 0, diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs index a82f858..31d345a 100644 --- a/crates/shirabe/src/command/require_command.rs +++ b/crates/shirabe/src/command/require_command.rs @@ -67,6 +67,12 @@ pub struct RequireCommand { dependency_resolution_completed: bool, } +impl Default for RequireCommand { + fn default() -> Self { + Self::new() + } +} + impl RequireCommand { pub fn new() -> Self { let mut command = RequireCommand { @@ -394,7 +400,6 @@ impl Command for RequireCommand { .get_repos() .find_packages(name, None)? .into_iter() - .map(|p| p.into()) .collect(); let pkg: Option<crate::package::PackageInterfaceHandle> = PackageSorter::get_most_current_version(found_packages); @@ -537,9 +542,7 @@ impl Command for RequireCommand { } input.borrow_mut().set_option("dev", PhpMixed::Bool(true))?; - let swap = require_key; - require_key = remove_key; - remove_key = swap; + std::mem::swap(&mut require_key, &mut remove_key); } } } @@ -980,7 +983,7 @@ impl RequireCommand { let mut install = Installer::create(io.clone(), &composer_handle); let (prefer_source, prefer_dist) = self.get_preferred_install_options( - &*composer.get_config().borrow(), + &composer.get_config().borrow(), input.clone(), false, )?; @@ -1034,7 +1037,7 @@ impl RequireCommand { .unwrap_or(false), ) .set_audit_config( - self.create_audit_config(&mut *composer.get_config().borrow_mut(), input.clone())?, + self.create_audit_config(&mut composer.get_config().borrow_mut(), input.clone())?, ) .set_minimal_update(minimal_changes); diff --git a/crates/shirabe/src/command/run_script_command.rs b/crates/shirabe/src/command/run_script_command.rs index 92f9ccf..141b458 100644 --- a/crates/shirabe/src/command/run_script_command.rs +++ b/crates/shirabe/src/command/run_script_command.rs @@ -33,6 +33,12 @@ pub struct RunScriptCommand { script_events: Vec<&'static str>, } +impl Default for RunScriptCommand { + fn default() -> Self { + Self::new() + } +} + impl RunScriptCommand { pub fn new() -> Self { let mut command = RunScriptCommand { @@ -314,9 +320,9 @@ impl Command for RunScriptCommand { Platform::put_env("COMPOSER_DEV_MODE", if dev_mode { "1" } else { "0" }); - Ok(dispatcher + dispatcher .borrow_mut() - .dispatch_script(&script, dev_mode, args, IndexMap::new())?) + .dispatch_script(&script, dev_mode, args, IndexMap::new()) } fn initialize( diff --git a/crates/shirabe/src/command/script_alias_command.rs b/crates/shirabe/src/command/script_alias_command.rs index 02a25b2..1d94f09 100644 --- a/crates/shirabe/src/command/script_alias_command.rs +++ b/crates/shirabe/src/command/script_alias_command.rs @@ -161,9 +161,9 @@ impl Command for ScriptAliasCommand { }) .unwrap_or_default(); - Ok(dispatcher + dispatcher .borrow_mut() - .dispatch_script(&self.script, dev_mode, args_value, flags)?) + .dispatch_script(&self.script, dev_mode, args_value, flags) } fn initialize( diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs index a3254e4..19a215f 100644 --- a/crates/shirabe/src/command/search_command.rs +++ b/crates/shirabe/src/command/search_command.rs @@ -33,6 +33,12 @@ pub struct SearchCommand { base_command_data: BaseCommandData, } +impl Default for SearchCommand { + fn default() -> Self { + Self::new() + } +} + impl SearchCommand { pub fn new() -> Self { let mut command = SearchCommand { @@ -217,7 +223,7 @@ impl Command for SearchCommand { let results = repos.search(query, mode, r#type)?; - if results.len() > 0 && format == "text" { + if !results.is_empty() && format == "text" { let width = self.get_terminal_width(); let mut name_length: i64 = 0; for result in &results { diff --git a/crates/shirabe/src/command/self_update_command.rs b/crates/shirabe/src/command/self_update_command.rs index 510b097..2f319ff 100644 --- a/crates/shirabe/src/command/self_update_command.rs +++ b/crates/shirabe/src/command/self_update_command.rs @@ -27,6 +27,12 @@ pub struct SelfUpdateCommand { base_command_data: BaseCommandData, } +impl Default for SelfUpdateCommand { + fn default() -> Self { + Self::new() + } +} + impl SelfUpdateCommand { pub fn new() -> Self { let mut command = SelfUpdateCommand { diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs index 520e716..f7319ed 100644 --- a/crates/shirabe/src/command/show_command.rs +++ b/crates/shirabe/src/command/show_command.rs @@ -69,6 +69,12 @@ pub struct ShowCommand { repository_set: Option<std::rc::Rc<std::cell::RefCell<RepositorySet>>>, } +impl Default for ShowCommand { + fn default() -> Self { + Self::new() + } +} + impl ShowCommand { pub fn new() -> Self { let mut command = ShowCommand { @@ -283,9 +289,7 @@ impl Command for ShowCommand { .get_repository_manager() .borrow() .get_repositories() - .iter() - .map(|r| r.clone()) - .collect(), + .to_vec(), )); ir.add_repository( composer @@ -512,28 +516,30 @@ impl Command for ShowCommand { // show single package or single version if let Some(ref pkg) = single_package { versions_map.insert(pkg.get_pretty_version(), pkg.get_version()); - } else if let Some(ref pf) = package_filter { - if !pf.contains('*') { - let (matched_package, vers) = self.get_package( - &*installed_repo.borrow(), - &repos, - pf, - input.borrow().get_argument("version")?, - )?; + } else if let Some(ref pf) = package_filter + && !pf.contains('*') + { + let (matched_package, vers) = self.get_package( + &*installed_repo.borrow(), + &repos, + pf, + input.borrow().get_argument("version")?, + )?; - if let Some(ref pkg) = matched_package { - if input.borrow().get_option("direct")?.as_bool() == Some(true) { - if !in_array( - PhpMixed::String(pkg.get_name()), - &PhpMixed::List( - self.get_root_requires() - .into_iter() - .map(|s| Box::new(PhpMixed::String(s))) - .collect(), - ), - true, - ) { - return Err(InvalidArgumentException { + if let Some(ref pkg) = matched_package + && input.borrow().get_option("direct")?.as_bool() == Some(true) + && !in_array( + PhpMixed::String(pkg.get_name()), + &PhpMixed::List( + self.get_root_requires() + .into_iter() + .map(|s| Box::new(PhpMixed::String(s))) + .collect(), + ), + true, + ) + { + return Err(InvalidArgumentException { message: format!( "Package \"{}\" is installed but not a direct dependent of the root package.", pkg.get_name() @@ -541,47 +547,42 @@ impl Command for ShowCommand { code: 0, } .into()); - } - } - } + } - if matched_package.is_none() { - let options = input.borrow().get_options(); - let mut hint = String::new(); - if input.borrow().get_option("locked")?.as_bool() == Some(true) { - hint.push_str(" in lock file"); - } - if options.contains_key("working-dir") { - hint.push_str(&format!( - " in {}/composer.json", - options - .get("working-dir") - .and_then(|v| v.as_string()) - .unwrap_or("") - )); - } - if PlatformRepository::is_platform_package(pf) - && input.borrow().get_option("platform")?.as_bool() != Some(true) - { - hint.push_str(", try using --platform (-p) to show platform packages"); - } - if input.borrow().get_option("all")?.as_bool() != Some(true) - && input.borrow().get_option("available")?.as_bool() != Some(true) - { - hint.push_str( - ", try using --available (-a) to show all available packages", - ); - } + if matched_package.is_none() { + let options = input.borrow().get_options(); + let mut hint = String::new(); + if input.borrow().get_option("locked")?.as_bool() == Some(true) { + hint.push_str(" in lock file"); + } + if options.contains_key("working-dir") { + hint.push_str(&format!( + " in {}/composer.json", + options + .get("working-dir") + .and_then(|v| v.as_string()) + .unwrap_or("") + )); + } + if PlatformRepository::is_platform_package(pf) + && input.borrow().get_option("platform")?.as_bool() != Some(true) + { + hint.push_str(", try using --platform (-p) to show platform packages"); + } + if input.borrow().get_option("all")?.as_bool() != Some(true) + && input.borrow().get_option("available")?.as_bool() != Some(true) + { + hint.push_str(", try using --available (-a) to show all available packages"); + } - return Err(InvalidArgumentException { - message: format!("Package \"{}\" not found{}.", pf, hint), - code: 0, - } - .into()); + return Err(InvalidArgumentException { + message: format!("Package \"{}\" not found{}.", pf, hint), + code: 0, } - single_package = matched_package; - versions_map = vers; + .into()); } + single_package = matched_package; + versions_map = vers; } if let Some(ref package) = single_package { @@ -653,7 +654,7 @@ impl Command for ShowCommand { .as_ref() .unwrap() .as_complete() - .map_or(true, |c| !c.is_abandoned())) + .is_none_or(|c| !c.is_abandoned())) { exit_code = 1; } @@ -669,7 +670,7 @@ impl Command for ShowCommand { }; if let Some(path) = path { let real = realpath(&path).unwrap_or_default(); - let trimmed = real.split(|c| c == '\r' || c == '\n').next().unwrap_or(""); + let trimmed = real.split(['\r', '\n']).next().unwrap_or(""); self.get_io().write(&format!(" {}", trimmed)); } else { self.get_io().write(" null"); @@ -776,7 +777,7 @@ impl Command for ShowCommand { "platform" } else if locked_repo .as_ref() - .map_or(false, |lr| Self::same_repository(&repo, lr)) + .is_some_and(|lr| Self::same_repository(&repo, lr)) { "locked" } else if Self::same_repository(&repo, &installed_repo) @@ -784,9 +785,7 @@ impl Command for ShowCommand { .borrow() .as_any() .downcast_ref::<InstalledRepository>() - .map_or(false, |ir| { - ir.get_repositories().iter().any(|r| r.ptr_eq(&repo)) - }) + .is_some_and(|ir| ir.get_repositories().iter().any(|r| r.ptr_eq(&repo))) { "installed" } else { @@ -800,7 +799,7 @@ impl Command for ShowCommand { for name in names { packages .entry(type_owned.clone()) - .or_insert_with(IndexMap::new) + .or_default() .insert(name.clone(), PackageOrName::Name(name)); } } else { @@ -816,7 +815,7 @@ impl Command for ShowCommand { } }; if need_replace { - let mut p: crate::package::PackageInterfaceHandle = package.clone().into(); + let mut p: crate::package::PackageInterfaceHandle = package.clone(); while let Some(alias) = p.as_alias() { p = alias.get_alias_of().into(); } @@ -840,7 +839,7 @@ impl Command for ShowCommand { if matches_list { packages .entry(type_owned.clone()) - .or_insert_with(IndexMap::new) + .or_default() .insert(p.get_name(), PackageOrName::Pkg(p)); } } @@ -850,7 +849,7 @@ impl Command for ShowCommand { for (name, p) in platform_repo.borrow().get_disabled_packages() { packages .entry(type_owned.clone()) - .or_insert_with(IndexMap::new) + .or_default() .insert(name.clone(), PackageOrName::Pkg(p.clone().into())); } } @@ -869,7 +868,7 @@ impl Command for ShowCommand { .as_list() .map(|l| { l.iter() - .filter_map(|v| v.as_string().map(|s| strtolower(s))) + .filter_map(|v| v.as_string().map(strtolower)) .collect::<Vec<_>>() }) .unwrap_or_default(), @@ -902,24 +901,23 @@ impl Command for ShowCommand { if show_latest && *show_version { for package_or_name in type_packages.values() { - if let PackageOrName::Pkg(package) = package_or_name { - if !Preg::is_match(&ignored_packages_regex, &package.get_pretty_name()) - { - let latest = self.find_latest_package( - package.clone(), - composer.as_ref().unwrap(), - &platform_repo, - show_major_only, - show_minor_only, - show_patch_only, - platform_req_filter.clone(), - )?; - if latest.is_none() { - continue; - } - - latest_packages.insert(package.get_pretty_name(), latest.unwrap()); + if let PackageOrName::Pkg(package) = package_or_name + && !Preg::is_match(&ignored_packages_regex, &package.get_pretty_name()) + { + let latest = self.find_latest_package( + package.clone(), + composer.as_ref().unwrap(), + &platform_repo, + show_major_only, + show_minor_only, + show_patch_only, + platform_req_filter.clone(), + )?; + if latest.is_none() { + continue; } + + latest_packages.insert(package.get_pretty_name(), latest.unwrap()); } } } @@ -967,7 +965,7 @@ impl Command for ShowCommand { ) == package.get_full_pretty_version( true, crate::package::DisplayMode::SourceRefIfDev, - ) && latest.as_complete().map_or(true, |c| !c.is_abandoned()) + ) && latest.as_complete().is_none_or(|c| !c.is_abandoned()) } else { false }; @@ -1065,8 +1063,7 @@ impl Command for ShowCommand { ); } } - if write_latest && latest_package.is_some() { - let latest = latest_package.unwrap(); + if write_latest && let Some(latest) = latest_package { let mut latest_version_str = latest.get_full_pretty_version( true, crate::package::DisplayMode::SourceRefIfDev, @@ -1107,13 +1104,11 @@ impl Command for ShowCommand { ); latest_length = latest_length.max("[none matched]".len()); } - if write_description { - if let Some(c) = package.as_complete() { - package_view_data.insert( - "description".to_string(), - PhpMixed::String(c.get_description().unwrap_or_default()), - ); - } + if write_description && let Some(c) = package.as_complete() { + package_view_data.insert( + "description".to_string(), + PhpMixed::String(c.get_description().unwrap_or_default()), + ); } if write_path { let installation_manager = composer @@ -1126,8 +1121,7 @@ impl Command for ShowCommand { .get_install_path(package.clone()); if let Some(p) = path { let r = realpath(&p).unwrap_or_default(); - let trimmed = - r.split(|c| c == '\r' || c == '\n').next().unwrap_or(""); + let trimmed = r.split(['\r', '\n']).next().unwrap_or(""); package_view_data.insert( "path".to_string(), PhpMixed::String(trimmed.to_string()), @@ -1138,31 +1132,27 @@ impl Command for ShowCommand { } let mut package_is_abandoned: PhpMixed = PhpMixed::Bool(false); - if let Some(latest) = latest_package { - if let Some(c) = latest.as_complete() { - if c.is_abandoned() { - let replacement_package_name = c.get_replacement_package(); - let replacement = if let Some(ref rp) = replacement_package_name - { - format!("Use {} instead", rp) - } else { - "No replacement was suggested".to_string() - }; - let package_warning = format!( - "Package {} is abandoned, you should avoid using it. {}.", - package.get_pretty_name(), - replacement - ); - package_view_data.insert( - "warning".to_string(), - PhpMixed::String(package_warning), - ); - package_is_abandoned = match replacement_package_name { - Some(rp) => PhpMixed::String(rp), - None => PhpMixed::Bool(true), - }; - } - } + if let Some(latest) = latest_package + && let Some(c) = latest.as_complete() + && c.is_abandoned() + { + let replacement_package_name = c.get_replacement_package(); + let replacement = if let Some(ref rp) = replacement_package_name { + format!("Use {} instead", rp) + } else { + "No replacement was suggested".to_string() + }; + let package_warning = format!( + "Package {} is abandoned, you should avoid using it. {}.", + package.get_pretty_name(), + replacement + ); + package_view_data + .insert("warning".to_string(), PhpMixed::String(package_warning)); + package_is_abandoned = match replacement_package_name { + Some(rp) => PhpMixed::String(rp), + None => PhpMixed::Bool(true), + }; } package_view_data.insert("abandoned".to_string(), package_is_abandoned); @@ -1390,6 +1380,7 @@ impl BaseCommand for ShowCommand { impl ShowCommand { // TODO(cli-completion): pub fn suggest_package_based_on_mode(&self) -> Box<dyn Fn(&CompletionInput) -> Vec<String>> + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn print_packages( &mut self, packages: &[IndexMap<String, PhpMixed>], @@ -1445,91 +1436,90 @@ impl ShowCommand { let width_pad = if pad_name { name_length } else { 0 }; io.write_no_newline(&format!("{}{:<width$}", indent, name, width = width_pad)); } - if let Some(version) = package.get("version").and_then(|v| v.as_string()) { - if write_version { - let width_pad = if pad_version { version_length } else { 0 }; - io.write_no_newline(&format!(" {:<width$}", version, width = width_pad)); - } + if let Some(version) = package.get("version").and_then(|v| v.as_string()) + && write_version + { + let width_pad = if pad_version { version_length } else { 0 }; + io.write_no_newline(&format!(" {:<width$}", version, width = width_pad)); } if let (Some(latest_version), Some(update_status)) = ( package.get("latest").and_then(|v| v.as_string()), package.get("latest-status").and_then(|v| v.as_string()), - ) { - if write_latest { - let mut latest_version = latest_version.to_string(); - let style = Self::update_status_to_version_style(update_status); - if !io.is_decorated() { - let marker = update_status - .replace("up-to-date", "=") - .replace("semver-safe-update", "!") - .replace("update-possible", "~"); - latest_version = format!("{} {}", marker, latest_version); - } - let width_pad = if pad_latest { latest_length } else { 0 }; - io.write_no_newline(&format!( - " <{}>{:<width$}</{}>", - style, - latest_version, - style, - width = width_pad - )); - if write_release_date { - if let Some(age) = package.get("release-age").and_then(|v| v.as_string()) { - let width_pad = if pad_release_date { - release_date_length - } else { - 0 - }; - io.write_no_newline(&format!(" {:<width$}", age, width = width_pad)); - } - } + ) && write_latest + { + let mut latest_version = latest_version.to_string(); + let style = Self::update_status_to_version_style(update_status); + if !io.is_decorated() { + let marker = update_status + .replace("up-to-date", "=") + .replace("semver-safe-update", "!") + .replace("update-possible", "~"); + latest_version = format!("{} {}", marker, latest_version); + } + let width_pad = if pad_latest { latest_length } else { 0 }; + io.write_no_newline(&format!( + " <{}>{:<width$}</{}>", + style, + latest_version, + style, + width = width_pad + )); + if write_release_date + && let Some(age) = package.get("release-age").and_then(|v| v.as_string()) + { + let width_pad = if pad_release_date { + release_date_length + } else { + 0 + }; + io.write_no_newline(&format!(" {:<width$}", age, width = width_pad)); } } - if let Some(description) = package.get("description").and_then(|v| v.as_string()) { - if write_description { - let mut description = description - .split(|c| c == '\r' || c == '\n') - .next() - .unwrap_or("") - .to_string(); + if let Some(description) = package.get("description").and_then(|v| v.as_string()) + && write_description + { + let mut description = description + .split(['\r', '\n']) + .next() + .unwrap_or("") + .to_string(); - // Compute remaining width available for the description. - let mut remaining = (width as i64) - - (name_length as i64) - - (version_length as i64) - - (release_date_length as i64) - - 4; - if write_latest { - remaining -= latest_length as i64; - } + // Compute remaining width available for the description. + let mut remaining = (width as i64) + - (name_length as i64) + - (version_length as i64) + - (release_date_length as i64) + - 4; + if write_latest { + remaining -= latest_length as i64; + } - // If nothing fits, clear the description. - if remaining <= 0 { - description = String::new(); - } else if extension_loaded("mbstring") { - // Use mb_strwidth/mb_strimwidth to measure and trim by display width - // (CJK characters count as width 2). mb_strimwidth counts the trim - // marker ('...') in the width parameter, so pass $remaining directly. - if description.chars().count() > remaining as usize { - description = format!( - "{}...", - description - .chars() - .take((remaining as usize).saturating_sub(3)) - .collect::<String>() - ); - } - } else { - // Fallback when mbstring is not available: do a conservative byte-based cut. - // Ensure cut length is non-negative and leave room for the ellipsis. - let cut = (remaining as i64 - 3).max(0) as usize; - if description.len() > cut { - description = format!("{}...", &description[..cut]); - } + // If nothing fits, clear the description. + if remaining <= 0 { + description = String::new(); + } else if extension_loaded("mbstring") { + // Use mb_strwidth/mb_strimwidth to measure and trim by display width + // (CJK characters count as width 2). mb_strimwidth counts the trim + // marker ('...') in the width parameter, so pass $remaining directly. + if description.chars().count() > remaining as usize { + description = format!( + "{}...", + description + .chars() + .take((remaining as usize).saturating_sub(3)) + .collect::<String>() + ); + } + } else { + // Fallback when mbstring is not available: do a conservative byte-based cut. + // Ensure cut length is non-negative and leave room for the ellipsis. + let cut = (remaining - 3).max(0) as usize; + if description.len() > cut { + description = format!("{}...", &description[..cut]); } - - io.write_no_newline(&format!(" {}", description)); } + + io.write_no_newline(&format!(" {}", description)); } if package.contains_key("path") { let path_str = match package.get("path") { @@ -1616,11 +1606,11 @@ impl ShowCommand { let mut literals: Vec<i64> = Vec::new(); for package in matches.iter() { // avoid showing the 9999999-dev alias if the default branch has no branch-alias set - let mut p: crate::package::PackageInterfaceHandle = package.clone().into(); - if let Some(alias) = p.as_alias() { - if p.get_version() == VersionParser::DEFAULT_BRANCH_ALIAS { - p = alias.get_alias_of().into(); - } + let mut p: crate::package::PackageInterfaceHandle = package.clone(); + if let Some(alias) = p.as_alias() + && p.get_version() == VersionParser::DEFAULT_BRANCH_ALIAS + { + p = alias.get_alias_of().into(); } // select an exact match if it is in the installed repo and no specific version was required @@ -1635,12 +1625,13 @@ impl ShowCommand { // select preferred package according to policy rules if matched_package.is_none() && !literals.is_empty() { let preferred = policy.select_preferred_packages(&pool, literals.clone(), None); - matched_package = Some(pool.literal_to_package(preferred[0]).into()); + matched_package = Some(pool.literal_to_package(preferred[0])); } - if let Some(ref mp) = matched_package { - if mp.as_complete().is_none() { - return Err(LogicException { + if let Some(ref mp) = matched_package + && mp.as_complete().is_none() + { + return Err(LogicException { message: format!( "ShowCommand::getPackage can only work with CompletePackageInterface, but got {}", shirabe_php_shim::get_class(&PhpMixed::Null) @@ -1648,7 +1639,6 @@ impl ShowCommand { code: 0, } .into()); - } } let matched_package = matched_package.and_then(|mp| mp.as_complete()); @@ -1708,15 +1698,13 @@ impl ShowCommand { self.get_io() .write(&format!("<info>keywords</info> : {}", keywords.join(", "))); self.print_versions(package.clone(), versions, installed_repo)?; - if is_installed_package { - if let Some(rd) = package.get_release_date() { - let rel = self.get_relative_time(&rd); - self.get_io().write(&format!( - "<info>released</info> : {}, {}", - rd.format(date_format_to_strftime("Y-m-d")), - rel - )); - } + if is_installed_package && let Some(rd) = package.get_release_date() { + let rel = self.get_relative_time(&rd); + self.get_io().write(&format!( + "<info>released</info> : {}, {}", + rd.format(date_format_to_strftime("Y-m-d")), + rel + )); } let latest: PackageInterfaceHandle = if let Some(latest) = latest_package { let style = self.get_version_style(latest.clone(), package.clone().into()); @@ -1764,10 +1752,10 @@ impl ShowCommand { if is_installed_package { let path: Option<String> = self.require_composer(None, None).ok().and_then(|c| { let installation_manager = c.borrow_partial().get_installation_manager(); - let p = installation_manager + + installation_manager .borrow_mut() - .get_install_path(package.clone().into()); - p + .get_install_path(package.clone().into()) }); if let Some(p) = path { self.get_io().write(&format!( @@ -1783,18 +1771,18 @@ impl ShowCommand { package.get_names(true).join(", ") )); - if let Some(c) = latest.as_complete() { - if c.is_abandoned() { - let replacement = match c.get_replacement_package() { - Some(rp) => format!(" The author suggests using the {} package instead.", rp), - None => String::new(), - }; + if let Some(c) = latest.as_complete() + && c.is_abandoned() + { + let replacement = match c.get_replacement_package() { + Some(rp) => format!(" The author suggests using the {} package instead.", rp), + None => String::new(), + }; - self.get_io().write_error(&format!( + self.get_io().write_error(&format!( "<warning>Attention: This package is abandoned and no longer maintained.{}</warning>", replacement )); - } } let support = package.get_support(); @@ -1830,14 +1818,14 @@ impl ShowCommand { .write(&format!("{} => {}", name_disp, path_str)); } } - } else if r#type == "classmap" { - if let PhpMixed::List(l) = autoloads { - let joined: Vec<String> = l - .iter() - .filter_map(|v| v.as_string().map(|s| s.to_string())) - .collect(); - self.get_io().write(&joined.join(", ")); - } + } else if r#type == "classmap" + && let PhpMixed::List(l) = autoloads + { + let joined: Vec<String> = l + .iter() + .filter_map(|v| v.as_string().map(|s| s.to_string())) + .collect(); + self.get_io().write(&joined.join(", ")); } } let include_paths = package.get_include_paths(); @@ -1869,10 +1857,10 @@ impl ShowCommand { .iter() .map(|v| (v.clone(), v.clone())) .collect(); - if let Some(found) = array_search(&installed_version, &key_map) { - if let Some(idx) = versions_keys.iter().position(|v| v == &found) { - versions_keys[idx] = format!("<info>* {}</info>", installed_version); - } + if let Some(found) = array_search(&installed_version, &key_map) + && let Some(idx) = versions_keys.iter().position(|v| v == &found) + { + versions_keys[idx] = format!("<info>* {}</info>", installed_version); } } } @@ -1924,7 +1912,7 @@ impl ShowCommand { // SpdxLicenses::getLicenseByIdentifier returns [0 => fullname, 1 => osiApproved, 2 => url]. let list = license.as_list(); let fullname = list - .and_then(|l| l.get(0)) + .and_then(|l| l.first()) .and_then(|v| v.as_string()) .unwrap_or("") .to_string(); @@ -2075,16 +2063,16 @@ impl ShowCommand { } } - if let Some(c) = latest.as_complete() { - if c.is_abandoned() { - json.insert( - "replacement".to_string(), - match c.get_replacement_package() { - Some(rp) => PhpMixed::String(rp.to_string()), - None => PhpMixed::Null, - }, - ); - } + if let Some(c) = latest.as_complete() + && c.is_abandoned() + { + json.insert( + "replacement".to_string(), + match c.get_replacement_package() { + Some(rp) => PhpMixed::String(rp.to_string()), + None => PhpMixed::Null, + }, + ); } if !package.get_suggests().is_empty() { @@ -2182,7 +2170,7 @@ impl ShowCommand { // Note 'osi' is the license id string, not the OSI-approved flag. let list = l.as_list(); let name = list - .and_then(|x| x.get(0)) + .and_then(|x| x.first()) .and_then(|v| v.as_string()) .unwrap_or("") .to_string(); @@ -2340,10 +2328,7 @@ impl ShowCommand { .to_string(); self.get_io().write_no_newline(&format!(" {}", version)); if let Some(description) = package.get("description").and_then(|v| v.as_string()) { - let trimmed = description - .split(|c| c == '\r' || c == '\n') - .next() - .unwrap_or(""); + let trimmed = description.split(['\r', '\n']).next().unwrap_or(""); self.get_io().write(&format!(" {}", trimmed)); } else { // output newline @@ -2680,6 +2665,7 @@ impl ShowCommand { } /// Given a package, this finds the latest package matching it + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn find_latest_package( &mut self, package: PackageInterfaceHandle, @@ -2829,9 +2815,7 @@ impl ShowCommand { .get_repository_manager() .borrow() .get_repositories() - .iter() - .map(|r| r.clone()) - .collect(), + .to_vec(), )))?; self.repository_set = Some(std::rc::Rc::new(std::cell::RefCell::new(rs))); } diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs index 9115caf..06f19e0 100644 --- a/crates/shirabe/src/command/status_command.rs +++ b/crates/shirabe/src/command/status_command.rs @@ -32,6 +32,12 @@ pub struct StatusCommand { base_command_data: BaseCommandData, } +impl Default for StatusCommand { + fn default() -> Self { + Self::new() + } +} + impl StatusCommand { const EXIT_CODE_ERRORS: i64 = 1; const EXIT_CODE_UNPUSHED_CHANGES: i64 = 2; @@ -115,57 +121,54 @@ impl StatusCommand { } } - if let Some(vcs_downloader) = downloader.as_vcs_capable_downloader_interface() { - if vcs_downloader + if let Some(vcs_downloader) = downloader.as_vcs_capable_downloader_interface() + && vcs_downloader .get_vcs_reference(package.clone(), target_dir.clone()) .is_some() - { - let previous_ref = match package.get_installation_source().as_deref() { - Some("source") => package.get_source_reference().map(|s| s.to_string()), - Some("dist") => package.get_dist_reference().map(|s| s.to_string()), - _ => None, - }; + { + let previous_ref = match package.get_installation_source().as_deref() { + Some("source") => package.get_source_reference().map(|s| s.to_string()), + Some("dist") => package.get_dist_reference().map(|s| s.to_string()), + _ => None, + }; - let current_version = - guesser.guess_version(&dumper.dump(package.clone()), &target_dir)?; + let current_version = + guesser.guess_version(&dumper.dump(package.clone()), &target_dir)?; - if let (Some(prev_ref), Some(cur_version)) = (&previous_ref, ¤t_version) { - if cur_version.commit.as_deref() != Some(prev_ref.as_str()) - && cur_version.pretty_version.as_deref() != Some(prev_ref.as_str()) - { - let mut previous = IndexMap::new(); - previous.insert( - "version".to_string(), - package.get_pretty_version().to_string(), - ); - previous.insert("ref".to_string(), prev_ref.clone()); + if let (Some(prev_ref), Some(cur_version)) = (&previous_ref, ¤t_version) + && cur_version.commit.as_deref() != Some(prev_ref.as_str()) + && cur_version.pretty_version.as_deref() != Some(prev_ref.as_str()) + { + let mut previous = IndexMap::new(); + previous.insert( + "version".to_string(), + package.get_pretty_version().to_string(), + ); + previous.insert("ref".to_string(), prev_ref.clone()); - let mut current = IndexMap::new(); - current.insert( - "version".to_string(), - cur_version.pretty_version.clone().unwrap_or_default(), - ); - current.insert( - "ref".to_string(), - cur_version.commit.clone().unwrap_or_default(), - ); + let mut current = IndexMap::new(); + current.insert( + "version".to_string(), + cur_version.pretty_version.clone().unwrap_or_default(), + ); + current.insert( + "ref".to_string(), + cur_version.commit.clone().unwrap_or_default(), + ); - let mut change = IndexMap::new(); - change.insert("previous".to_string(), previous); - change.insert("current".to_string(), current); + let mut change = IndexMap::new(); + change.insert("previous".to_string(), previous); + change.insert("current".to_string(), current); - vcs_version_changes.insert(target_dir.clone(), change); - } - } + vcs_version_changes.insert(target_dir.clone(), change); } } - if let Some(dvcs_downloader) = downloader.as_dvcs_downloader_interface() { - if let Some(unpushed) = + if let Some(dvcs_downloader) = downloader.as_dvcs_downloader_interface() + && let Some(unpushed) = dvcs_downloader.get_unpushed_changes(package.clone(), target_dir.clone())? - { - unpushed_changes.insert(target_dir, unpushed); - } + { + unpushed_changes.insert(target_dir, unpushed); } } diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs index 344887e..8766196 100644 --- a/crates/shirabe/src/command/suggests_command.rs +++ b/crates/shirabe/src/command/suggests_command.rs @@ -29,6 +29,12 @@ pub struct SuggestsCommand { base_command_data: BaseCommandData, } +impl Default for SuggestsCommand { + fn default() -> Self { + Self::new() + } +} + impl SuggestsCommand { pub fn new() -> Self { let mut command = SuggestsCommand { diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs index 33a13a8..4581ce1 100644 --- a/crates/shirabe/src/command/update_command.rs +++ b/crates/shirabe/src/command/update_command.rs @@ -49,6 +49,12 @@ pub struct UpdateCommand { base_command_data: BaseCommandData, } +impl Default for UpdateCommand { + fn default() -> Self { + Self::new() + } +} + impl UpdateCommand { pub fn new() -> Self { let mut command = UpdateCommand { @@ -152,7 +158,7 @@ impl Command for UpdateCommand { )?; // extract --with shorthands from the allowlist - if packages.len() > 0 { + if !packages.is_empty() { let allowlist_packages_with_requirements: Vec<String> = array_filter(&packages, |pkg: &String| -> bool { Preg::is_match(r"{\S+[ =:]\S+}", pkg) @@ -191,9 +197,10 @@ impl Command for UpdateCommand { let package = strtolower(package); let parsed_constraint = parser.parse_constraints(constraint)?; temporary_constraints.insert(package.clone(), parsed_constraint.clone()); - if let Some(root_req) = root_requirements.get(&package) { - if !Intervals::have_intersections(&parsed_constraint, root_req.get_constraint())? { - io.write_error3( + if let Some(root_req) = root_requirements.get(&package) + && !Intervals::have_intersections(&parsed_constraint, root_req.get_constraint())? + { + io.write_error3( &format!( "<error>The temporary constraint \"{}\" for \"{}\" must be a subset of the constraint in your composer.json ({})</error>", constraint, @@ -203,13 +210,12 @@ impl Command for UpdateCommand { true, io_interface::NORMAL, ); - io.write(&format!( + io.write(&format!( "<info>Run `composer require {}` or `composer require {}:{}` instead to replace the constraint</info>", package, package, constraint, )); - return Ok(crate::command::FAILURE); - } + return Ok(crate::command::FAILURE); } } @@ -346,7 +352,7 @@ impl Command for UpdateCommand { let config = composer.get_config(); let (prefer_source, prefer_dist) = - self.get_preferred_install_options(&*config.borrow(), input.clone(), false)?; + self.get_preferred_install_options(&config.borrow(), input.clone(), false)?; let optimize = input .borrow() @@ -476,7 +482,7 @@ impl Command for UpdateCommand { ) .set_temporary_constraints(temporary_constraints) .set_audit_config( - self.create_audit_config(&mut *composer.get_config().borrow_mut(), input.clone())?, + self.create_audit_config(&mut composer.get_config().borrow_mut(), input.clone())?, ) .set_minimal_update(minimal_changes); @@ -587,7 +593,7 @@ impl UpdateCommand { composer_ref.get_package().get_dev_requires(), ); - let filter: Option<String> = if packages.len() > 0 { + let filter: Option<String> = if !packages.is_empty() { Some(base_package::package_names_to_regexp(&packages, "%s")) } else { None @@ -615,10 +621,10 @@ impl UpdateCommand { }; let mut version_selector = self.create_version_selector(composer)?; for package in &installed_packages { - if let Some(filter) = &filter { - if !Preg::is_match(filter, &package.get_name()) { - continue; - } + if let Some(filter) = &filter + && !Preg::is_match(filter, &package.get_name()) + { + continue; } let current_version = package.get_pretty_version(); let constraint = requires @@ -642,20 +648,20 @@ impl UpdateCommand { PhpMixed::Bool(true), )?; let _ = &platform_req_filter; - if let Some(latest) = latest_version { - if package.get_version() != latest.get_version() || latest.is_dev() { - autocompleter_values.insert( - package.get_name(), - format!( - "<comment>{}</comment> => <comment>{}</comment>", - current_version, - latest.get_pretty_version(), - ), - ); - } + if let Some(latest) = latest_version + && (package.get_version() != latest.get_version() || latest.is_dev()) + { + autocompleter_values.insert( + package.get_name(), + format!( + "<comment>{}</comment> => <comment>{}</comment>", + current_version, + latest.get_pretty_version(), + ), + ); } } - if 0 == installed_packages.len() { + if installed_packages.is_empty() { for (req, _constraint) in &requires { if PlatformRepository::is_platform_package(req) { continue; @@ -664,7 +670,7 @@ impl UpdateCommand { } } - if 0 == autocompleter_values.len() { + if autocompleter_values.is_empty() { return Err(RuntimeException { message: "Could not find any package with new versions available".to_string(), code: 0, diff --git a/crates/shirabe/src/command/validate_command.rs b/crates/shirabe/src/command/validate_command.rs index 5fc8f3d..a32a10c 100644 --- a/crates/shirabe/src/command/validate_command.rs +++ b/crates/shirabe/src/command/validate_command.rs @@ -32,6 +32,12 @@ pub struct ValidateCommand { base_command_data: BaseCommandData, } +impl Default for ValidateCommand { + fn default() -> Self { + Self::new() + } +} + impl ValidateCommand { pub fn new() -> Self { let mut command = ValidateCommand { @@ -325,6 +331,7 @@ impl BaseCommand for ValidateCommand { } impl ValidateCommand { + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn output_result( &self, io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>, @@ -387,16 +394,16 @@ impl ValidateCommand { if !publish_errors.is_empty() && check_publish { *publish_errors = publish_errors.iter().map(|e| format!("- {}", e)).collect(); publish_errors.insert(0, "# Publish errors".to_string()); - errors.extend(publish_errors.drain(..)); + errors.append(publish_errors); } if !lock_errors.is_empty() { if check_lock { lock_errors.insert(0, "# Lock file errors".to_string()); - errors.extend(lock_errors.drain(..)); + errors.append(lock_errors); } else { lock_errors.insert(0, "# Lock file warnings".to_string()); - extra_warnings.extend(lock_errors.drain(..)); + extra_warnings.append(lock_errors); } } diff --git a/crates/shirabe/src/composer.rs b/crates/shirabe/src/composer.rs index 7711d7f..56f1d3b 100644 --- a/crates/shirabe/src/composer.rs +++ b/crates/shirabe/src/composer.rs @@ -15,17 +15,17 @@ use crate::repository::RepositoryManager; use crate::util::r#loop::Loop; // TODO: change this information to Shirabe version. -pub const VERSION: &'static str = "2.9.7"; -pub const BRANCH_ALIAS_VERSION: &'static str = ""; -pub const RELEASE_DATE: &'static str = "2026-04-14 13:31:52"; -pub const SOURCE_VERSION: &'static str = ""; -pub const RUNTIME_API_VERSION: &'static str = "2.2.2"; +pub const VERSION: &str = "2.9.7"; +pub const BRANCH_ALIAS_VERSION: &str = ""; +pub const RELEASE_DATE: &str = "2026-04-14 13:31:52"; +pub const SOURCE_VERSION: &str = ""; +pub const RUNTIME_API_VERSION: &str = "2.2.2"; pub fn get_version() -> String { if VERSION == "@package_version@" { return SOURCE_VERSION.to_string(); } - if BRANCH_ALIAS_VERSION != "" && Preg::is_match("{^[a-f0-9]{40}$}", VERSION) { + if !BRANCH_ALIAS_VERSION.is_empty() && Preg::is_match("{^[a-f0-9]{40}$}", VERSION) { return format!("{}+{}", BRANCH_ALIAS_VERSION, VERSION); } VERSION.to_string() @@ -122,6 +122,12 @@ pub struct Composer { archive_manager: Option<std::rc::Rc<std::cell::RefCell<ArchiveManager>>>, } +impl Default for Composer { + fn default() -> Self { + Self::new() + } +} + impl Composer { pub fn new() -> Self { Self { diff --git a/crates/shirabe/src/config.rs b/crates/shirabe/src/config.rs index 7e63dff..da1b170 100644 --- a/crates/shirabe/src/config.rs +++ b/crates/shirabe/src/config.rs @@ -410,12 +410,11 @@ impl Config { self.config.get(key), Some(PhpMixed::Array(m)) if m.contains_key("*") ); - if has_wildcard { - if let Some(PhpMixed::Array(m)) = self.config.get_mut(key) { - if let Some(wildcard) = m.shift_remove("*") { - m.insert("*".to_string(), wildcard); - } - } + if has_wildcard + && let Some(PhpMixed::Array(m)) = self.config.get_mut(key) + && let Some(wildcard) = m.shift_remove("*") + { + m.insert("*".to_string(), wildcard); } } else { self.config.insert(key.clone(), val.clone()); @@ -481,7 +480,7 @@ impl Config { } // disable a repository with an anonymous {"name": false} repo - if is_array(&repository) + if is_array(repository) && repository.as_array().map(|m| m.len()).unwrap_or(0) == 1 && matches!(current(repository.clone()), PhpMixed::Bool(false)) { @@ -725,10 +724,10 @@ impl Config { // special cases below "cache-files-ttl" => { let v = self.config.get(key).cloned(); - if let Some(v) = v { - if !v.is_null() { - return Ok(PhpMixed::Int(max(0, v.as_int().unwrap_or(0)))); - } + if let Some(v) = v + && !v.is_null() + { + return Ok(PhpMixed::Int(max(0, v.as_int().unwrap_or(0)))); } self.get_with_flags("cache-ttl", 0) @@ -1203,10 +1202,11 @@ impl Config { ) .into()); } - if let Some(ref io) = io { - if let Some(ref hostname) = hostname { - if !self.warned_hosts.contains_key(hostname) { - io.write_error3( + if let Some(ref io) = io + && let Some(ref hostname) = hostname + { + if !self.warned_hosts.contains_key(hostname) { + io.write_error3( &format!( "<warning>Warning: Accessing {} over {} which is an insecure protocol.</warning>", hostname, @@ -1215,51 +1215,49 @@ impl Config { true, io_interface::NORMAL, ); - } - self.warned_hosts.insert(hostname.clone(), true); } + self.warned_hosts.insert(hostname.clone(), true); } } - if let Some(ref io) = io { - if let Some(ref hostname) = hostname { - if !self.ssl_verify_warned_hosts.contains_key(hostname) { - let mut warning: Option<String> = None; - let verify_peer = repo_options - .get("ssl") - .and_then(|v| v.as_array()) - .and_then(|m| m.get("verify_peer")); - if let Some(v) = verify_peer { - if v.as_bool() == Some(false) { - warning = Some("verify_peer".to_string()); - } - } + if let Some(ref io) = io + && let Some(ref hostname) = hostname + && !self.ssl_verify_warned_hosts.contains_key(hostname) + { + let mut warning: Option<String> = None; + let verify_peer = repo_options + .get("ssl") + .and_then(|v| v.as_array()) + .and_then(|m| m.get("verify_peer")); + if let Some(v) = verify_peer + && v.as_bool() == Some(false) + { + warning = Some("verify_peer".to_string()); + } - let verify_peer_name = repo_options - .get("ssl") - .and_then(|v| v.as_array()) - .and_then(|m| m.get("verify_peer_name")); - if let Some(v) = verify_peer_name { - if v.as_bool() == Some(false) { - warning = match warning { - None => Some("verify_peer_name".to_string()), - Some(w) => Some(format!("{} and verify_peer_name", w)), - }; - } - } + let verify_peer_name = repo_options + .get("ssl") + .and_then(|v| v.as_array()) + .and_then(|m| m.get("verify_peer_name")); + if let Some(v) = verify_peer_name + && v.as_bool() == Some(false) + { + warning = match warning { + None => Some("verify_peer_name".to_string()), + Some(w) => Some(format!("{} and verify_peer_name", w)), + }; + } - if let Some(w) = warning { - io.write_error3( - &format!( - "<warning>Warning: Accessing {} with {} disabled.</warning>", - hostname, w - ), - true, - io_interface::NORMAL, - ); - self.ssl_verify_warned_hosts.insert(hostname.clone(), true); - } - } + if let Some(w) = warning { + io.write_error3( + &format!( + "<warning>Warning: Accessing {} with {} disabled.</warning>", + hostname, w + ), + true, + io_interface::NORMAL, + ); + self.ssl_verify_warned_hosts.insert(hostname.clone(), true); } } diff --git a/crates/shirabe/src/config/json_config_source.rs b/crates/shirabe/src/config/json_config_source.rs index 166d2fe..3ae302e 100644 --- a/crates/shirabe/src/config/json_config_source.rs +++ b/crates/shirabe/src/config/json_config_source.rs @@ -93,49 +93,34 @@ impl JsonConfigSource { "scripts-aliases", "support", ] { - if let PhpMixed::Array(map) = &mut config { - if let Some(boxed) = map.get(prop) { - if let PhpMixed::Array(inner) = boxed.as_ref() { - if inner.is_empty() { - // PHP: $config[$prop] = new \stdClass; - map.insert( - prop.to_string(), - Box::new(PhpMixed::Array(IndexMap::new())), - ); - } - } - } + if let PhpMixed::Array(map) = &mut config + && let Some(boxed) = map.get(prop) + && let PhpMixed::Array(inner) = boxed.as_ref() + && inner.is_empty() + { + // PHP: $config[$prop] = new \stdClass; + map.insert(prop.to_string(), Box::new(PhpMixed::Array(IndexMap::new()))); } } for prop in ["psr-0", "psr-4"] { if let PhpMixed::Array(map) = &mut config { - if let Some(autoload) = map.get_mut("autoload") { - if let PhpMixed::Array(autoload_map) = autoload.as_mut() { - if let Some(inner) = autoload_map.get(prop) { - if let PhpMixed::Array(inner_map) = inner.as_ref() { - if inner_map.is_empty() { - autoload_map.insert( - prop.to_string(), - Box::new(PhpMixed::Array(IndexMap::new())), - ); - } - } - } - } + if let Some(autoload) = map.get_mut("autoload") + && let PhpMixed::Array(autoload_map) = autoload.as_mut() + && let Some(inner) = autoload_map.get(prop) + && let PhpMixed::Array(inner_map) = inner.as_ref() + && inner_map.is_empty() + { + autoload_map + .insert(prop.to_string(), Box::new(PhpMixed::Array(IndexMap::new()))); } - if let Some(autoload_dev) = map.get_mut("autoload-dev") { - if let PhpMixed::Array(autoload_dev_map) = autoload_dev.as_mut() { - if let Some(inner) = autoload_dev_map.get(prop) { - if let PhpMixed::Array(inner_map) = inner.as_ref() { - if inner_map.is_empty() { - autoload_dev_map.insert( - prop.to_string(), - Box::new(PhpMixed::Array(IndexMap::new())), - ); - } - } - } - } + if let Some(autoload_dev) = map.get_mut("autoload-dev") + && let PhpMixed::Array(autoload_dev_map) = autoload_dev.as_mut() + && let Some(inner) = autoload_dev_map.get(prop) + && let PhpMixed::Array(inner_map) = inner.as_ref() + && inner_map.is_empty() + { + autoload_dev_map + .insert(prop.to_string(), Box::new(PhpMixed::Array(IndexMap::new()))); } } } @@ -150,21 +135,14 @@ impl JsonConfigSource { "forgejo-token", "preferred-install", ] { - if let PhpMixed::Array(map) = &mut config { - if let Some(cfg) = map.get_mut("config") { - if let PhpMixed::Array(cfg_map) = cfg.as_mut() { - if let Some(inner) = cfg_map.get(prop) { - if let PhpMixed::Array(inner_map) = inner.as_ref() { - if inner_map.is_empty() { - cfg_map.insert( - prop.to_string(), - Box::new(PhpMixed::Array(IndexMap::new())), - ); - } - } - } - } - } + if let PhpMixed::Array(map) = &mut config + && let Some(cfg) = map.get_mut("config") + && let PhpMixed::Array(cfg_map) = cfg.as_mut() + && let Some(inner) = cfg_map.get(prop) + && let PhpMixed::Array(inner_map) = inner.as_ref() + && inner_map.is_empty() + { + cfg_map.insert(prop.to_string(), Box::new(PhpMixed::Array(IndexMap::new()))); } } self.file.borrow().write(config)?; @@ -282,7 +260,7 @@ impl JsonConfigSource { .entry(seg.to_string()) .or_insert_with(|| Box::new(PhpMixed::Array(IndexMap::new()))); if !matches!(entry.as_ref(), PhpMixed::Array(_)) { - *entry = Box::new(PhpMixed::Array(IndexMap::new())); + **entry = PhpMixed::Array(IndexMap::new()); } cursor = match entry.as_mut() { PhpMixed::Array(m) => m, @@ -346,18 +324,17 @@ impl ConfigSourceInterface for JsonConfigSource { { let mut replaced = IndexMap::new(); replaced.insert(name.to_string(), Box::new(PhpMixed::Bool(false))); - *repository = Box::new(PhpMixed::Array(replaced)); + **repository = PhpMixed::Array(replaced); return Ok(()); } - if let PhpMixed::Array(m) = repository.as_ref() { - if m.len() == 1 - && matches!( - m.get(name).map(|b| b.as_ref()), - Some(PhpMixed::Bool(false)) - ) - { - return Ok(()); - } + if let PhpMixed::Array(m) = repository.as_ref() + && m.len() == 1 + && matches!( + m.get(name).map(|b| b.as_ref()), + Some(PhpMixed::Bool(false)) + ) + { + return Ok(()); } } } else { @@ -377,18 +354,19 @@ impl ConfigSourceInterface for JsonConfigSource { } let mut repo_config = config; - if let PhpMixed::Array(rc) = &repo_config { - if !name.is_empty() && !rc.contains_key("name") { - let mut with_name = IndexMap::new(); - with_name.insert( - "name".to_string(), - Box::new(PhpMixed::String(name.to_string())), - ); - for (k, v) in rc.clone() { - with_name.insert(k, v); - } - repo_config = PhpMixed::Array(with_name); + if let PhpMixed::Array(rc) = &repo_config + && !name.is_empty() + && !rc.contains_key("name") + { + let mut with_name = IndexMap::new(); + with_name.insert( + "name".to_string(), + Box::new(PhpMixed::String(name.to_string())), + ); + for (k, v) in rc.clone() { + with_name.insert(k, v); } + repo_config = PhpMixed::Array(with_name); } Self::dedupe_repositories_by_name(root, name); @@ -441,16 +419,15 @@ impl ConfigSourceInterface for JsonConfigSource { index_to_insert = Some(i); break; } - if let PhpMixed::Array(m) = repository.as_ref() { - if m.len() == 1 - && matches!( - m.get(reference_name).map(|b| b.as_ref()), - Some(PhpMixed::Bool(false)) - ) - { - index_to_insert = Some(i); - break; - } + if let PhpMixed::Array(m) = repository.as_ref() + && m.len() == 1 + && matches!( + m.get(reference_name).map(|b| b.as_ref()), + Some(PhpMixed::Bool(false)) + ) + { + index_to_insert = Some(i); + break; } } } @@ -466,18 +443,19 @@ impl ConfigSourceInterface for JsonConfigSource { }; let mut repo_config = config; - if let PhpMixed::Array(rc) = &repo_config { - if !name.is_empty() && !rc.contains_key("name") { - let mut with_name = IndexMap::new(); - with_name.insert( - "name".to_string(), - Box::new(PhpMixed::String(name.to_string())), - ); - for (k, v) in rc.clone() { - with_name.insert(k, v); - } - repo_config = PhpMixed::Array(with_name); + if let PhpMixed::Array(rc) = &repo_config + && !name.is_empty() + && !rc.contains_key("name") + { + let mut with_name = IndexMap::new(); + with_name.insert( + "name".to_string(), + Box::new(PhpMixed::String(name.to_string())), + ); + for (k, v) in rc.clone() { + with_name.insert(k, v); } + repo_config = PhpMixed::Array(with_name); } if let Some(PhpMixed::List(list)) = root.get_mut("repositories").map(|b| b.as_mut()) @@ -529,13 +507,13 @@ impl ConfigSourceInterface for JsonConfigSource { break; } } - if let Some(k) = target { - if let Some(PhpMixed::Array(m)) = map.get_mut(&k).map(|b| b.as_mut()) { - m.insert( - "url".to_string(), - Box::new(PhpMixed::String(url.to_string())), - ); - } + if let Some(k) = target + && let Some(PhpMixed::Array(m)) = map.get_mut(&k).map(|b| b.as_mut()) + { + m.insert( + "url".to_string(), + Box::new(PhpMixed::String(url.to_string())), + ); } } _ => {} @@ -587,7 +565,7 @@ impl ConfigSourceInterface for JsonConfigSource { if auth_config { let parts = explode(".", name); m.add_sub_node( - parts.get(0).map(String::as_str).unwrap_or(""), + parts.first().map(String::as_str).unwrap_or(""), parts.get(1).map(String::as_str).unwrap_or(""), value_cloned, false, @@ -625,7 +603,7 @@ impl ConfigSourceInterface for JsonConfigSource { if auth_config { let parts = explode(".", name); m.remove_sub_node( - parts.get(0).map(String::as_str).unwrap_or(""), + parts.first().map(String::as_str).unwrap_or(""), parts.get(1).map(String::as_str).unwrap_or(""), ) } else { @@ -669,7 +647,7 @@ impl ConfigSourceInterface for JsonConfigSource { .entry(first.to_string()) .or_insert_with(|| Box::new(PhpMixed::Array(IndexMap::new()))); if !matches!(entry.as_ref(), PhpMixed::Array(_)) { - *entry = Box::new(PhpMixed::Array(IndexMap::new())); + **entry = PhpMixed::Array(IndexMap::new()); } let mut cursor = match entry.as_mut() { PhpMixed::Array(m) => m, @@ -680,7 +658,7 @@ impl ConfigSourceInterface for JsonConfigSource { .entry(bit.to_string()) .or_insert_with(|| Box::new(PhpMixed::Array(IndexMap::new()))); if !matches!(e.as_ref(), PhpMixed::Array(_)) { - *e = Box::new(PhpMixed::Array(IndexMap::new())); + **e = PhpMixed::Array(IndexMap::new()); } cursor = match e.as_mut() { PhpMixed::Array(m) => m, diff --git a/crates/shirabe/src/console/application.rs b/crates/shirabe/src/console/application.rs index 4e31577..6622a2d 100644 --- a/crates/shirabe/src/console/application.rs +++ b/crates/shirabe/src/console/application.rs @@ -155,7 +155,7 @@ impl Application { pub fn new(name: String, mut version: String) -> Self { static SHUTDOWN_REGISTERED: std::sync::OnceLock<()> = std::sync::OnceLock::new(); - if version == "" { + if version.is_empty() { version = composer::get_version(); } if function_exists("ini_set") && extension_loaded("xdebug") { @@ -459,22 +459,18 @@ impl Application { && !file_exists(&Factory::get_composer_file().unwrap_or_default()) && use_parent_dir_if_no_json_available.as_bool() != Some(false) && (command_name.as_deref() != Some("config") - || (input + || (!input .borrow() .has_parameter_option(PhpMixed::from(vec!["--file"]), true) - == false - && input + && !input .borrow() - .has_parameter_option(PhpMixed::from(vec!["-f"]), true) - == false)) - && input + .has_parameter_option(PhpMixed::from(vec!["-f"]), true))) + && !input .borrow() .has_parameter_option(PhpMixed::from(vec!["--help"]), true) - == false - && input + && !input .borrow() .has_parameter_option(PhpMixed::from(vec!["-h"]), true) - == false { let mut dir = dirname(&Platform::get_cwd(true).unwrap_or_default()); let home_value = Platform::get_env("HOME") @@ -713,22 +709,21 @@ impl Application { )); } - if is_non_allowed_root { - if command_name.as_deref() != Some("self-update") - && command_name.as_deref() != Some("selfupdate") - && command_name.as_deref() != Some("_complete") - { - io.write_error("<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>"); + if is_non_allowed_root + && command_name.as_deref() != Some("self-update") + && command_name.as_deref() != Some("selfupdate") + && command_name.as_deref() != Some("_complete") + { + io.write_error("<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>"); - if io.is_interactive() { - if !io.ask_confirmation( - "<info>Continue as root/super user</info> [<comment>yes</comment>]? " - .to_string(), - true, - ) { - return Ok(1); - } - } + if io.is_interactive() + && !io.ask_confirmation( + "<info>Continue as root/super user</info> [<comment>yes</comment>]? " + .to_string(), + true, + ) + { + return Ok(1); } } @@ -766,138 +761,135 @@ impl Application { let composer_json: PhpMixed = json_decode(&file_get_contents(&file).unwrap_or_default(), true) .unwrap_or(PhpMixed::Null); - if let Some(arr) = composer_json.as_array() { - if let Some(scripts) = arr.get("scripts").and_then(|v| v.as_array()) { - for (script, dummy) in scripts { - let script_event_const = format!( - "Composer\\Script\\ScriptEvents::{}", - str_replace("-", "_", &strtoupper(script)) - ); - if !defined(&script_event_const) { - if application.borrow_mut().has(script) { - io.write_error(&format!("<warning>A script named {} would override a Composer command and has been skipped</warning>", script)); - } else { - let mut description = format!( - "Runs the {} script as defined in composer.json", - script - ); - - if let Some(desc) = arr - .get("scripts-descriptions") - .and_then(|v| v.as_array()) - .and_then(|a| a.get(script)) - .and_then(|v| v.as_string()) - { - description = desc.to_string(); - } + if let Some(arr) = composer_json.as_array() + && let Some(scripts) = arr.get("scripts").and_then(|v| v.as_array()) + { + for (script, dummy) in scripts { + let script_event_const = format!( + "Composer\\Script\\ScriptEvents::{}", + str_replace("-", "_", &strtoupper(script)) + ); + if !defined(&script_event_const) { + if application.borrow_mut().has(script) { + io.write_error(&format!("<warning>A script named {} would override a Composer command and has been skipped</warning>", script)); + } else { + let mut description = format!( + "Runs the {} script as defined in composer.json", + script + ); - let aliases: Vec<String> = arr - .get("scripts-aliases") - .and_then(|v| v.as_array()) - .and_then(|a| a.get(script)) - .and_then(|v| v.as_list()) - .map(|l| { - l.iter() - .filter_map(|v| { - v.as_string().map(|s| s.to_string()) - }) - .collect() - }) - .unwrap_or_default(); + if let Some(desc) = arr + .get("scripts-descriptions") + .and_then(|v| v.as_array()) + .and_then(|a| a.get(script)) + .and_then(|v| v.as_string()) + { + description = desc.to_string(); + } - let composer_opt = - application.borrow_mut().get_composer(false, None, None)?; - if let Some(composer) = composer_opt { - let composer = crate::command::composer_full(&composer); - let root_package = composer.get_package(); - let generator = composer.get_autoload_generator().clone(); - let generator = generator.borrow(); + let aliases: Vec<String> = arr + .get("scripts-aliases") + .and_then(|v| v.as_array()) + .and_then(|a| a.get(script)) + .and_then(|v| v.as_list()) + .map(|l| { + l.iter() + .filter_map(|v| v.as_string().map(|s| s.to_string())) + .collect() + }) + .unwrap_or_default(); - let installation_manager = - composer.get_installation_manager(); - let package_map = generator.build_package_map( - &mut installation_manager.borrow_mut(), - root_package.clone(), - vec![], - )?; - let map = generator.parse_autoloads( - package_map, - root_package.clone(), - PhpMixed::Bool(false), - ); + let composer_opt = + application.borrow_mut().get_composer(false, None, None)?; + if let Some(composer) = composer_opt { + let composer = crate::command::composer_full(&composer); + let root_package = composer.get_package(); + let generator = composer.get_autoload_generator().clone(); + let generator = generator.borrow(); - let loader = generator.create_loader( - &map, - composer - .get_config() - .borrow() - .get("vendor-dir") - .as_string() - .map(|s| s.to_string()), - ); - loader.register(false); - } + let installation_manager = composer.get_installation_manager(); + let package_map = generator.build_package_map( + &mut installation_manager.borrow_mut(), + root_package.clone(), + vec![], + )?; + let map = generator.parse_autoloads( + package_map, + root_package.clone(), + PhpMixed::Bool(false), + ); - // if the command is not an array of commands, and points to a valid SymfonyCommand subclass, import its details directly - let dummy_str = dummy.as_string().unwrap_or("").to_string(); - let cmd: PhpMixed = if is_string(dummy) - && shirabe_php_shim::class_exists(&dummy_str) - && is_subclass_of( - &PhpMixed::String(dummy_str.clone()), - "Symfony\\Component\\Console\\Command\\Command", - true, - ) { - if is_subclass_of( - &PhpMixed::String(dummy_str.clone()), - "Symfony\\Component\\Console\\SingleCommandApplication", - true, - ) { - io.write_error(&format!("<warning>The script named {} extends SingleCommandApplication which is not compatible with Composer 2.9+, make sure you extend Symfony\\Component\\Console\\Command instead.</warning>", script)); - } - let mut cmd = shirabe_php_shim::instantiate_class( - &dummy_str, - vec![PhpMixed::String(script.clone())], - ); - // TODO(phase-c): the script's command class is built by - // reflection (instantiate_class) and stays PhpMixed; the - // SingleCommandApplication / SymfonyCommand typed registry it - // belongs to is an external-package todo!() stub. - // let _ = SingleCommandApplication::new; + let loader = generator.create_loader( + &map, + composer + .get_config() + .borrow() + .get("vendor-dir") + .as_string() + .map(|s| s.to_string()), + ); + loader.register(false); + } - // makes sure the command is find()'able by the name defined in composer.json, and the name isn't overridden in its configure() - // TODO(phase-c): cmd is the PhpMixed result of reflection - // instantiation; reading/overriding its - // name/description requires the typed SymfonyCommand model that - // the Symfony stub does not yet provide. - let _ = description.clone(); - let _ = &mut cmd; - cmd - } else { - // fallback to usual aliasing behavior - // TODO(phase-c): ScriptAliasCommand is a typed BaseCommand - // but this code path stores commands as PhpMixed; it can - // only be carried as a typed trait object once the Symfony - // command registry is modelled. - let _ = ScriptAliasCommand::new( - script.clone(), - Some(description.clone()), - aliases, - ); - PhpMixed::Null - }; + // if the command is not an array of commands, and points to a valid SymfonyCommand subclass, import its details directly + let dummy_str = dummy.as_string().unwrap_or("").to_string(); + let cmd: PhpMixed = if is_string(dummy) + && shirabe_php_shim::class_exists(&dummy_str) + && is_subclass_of( + &PhpMixed::String(dummy_str.clone()), + "Symfony\\Component\\Console\\Command\\Command", + true, + ) { + if is_subclass_of( + &PhpMixed::String(dummy_str.clone()), + "Symfony\\Component\\Console\\SingleCommandApplication", + true, + ) { + io.write_error(&format!("<warning>The script named {} extends SingleCommandApplication which is not compatible with Composer 2.9+, make sure you extend Symfony\\Component\\Console\\Command instead.</warning>", script)); + } + let mut cmd = shirabe_php_shim::instantiate_class( + &dummy_str, + vec![PhpMixed::String(script.clone())], + ); + // TODO(phase-c): the script's command class is built by + // reflection (instantiate_class) and stays PhpMixed; the + // SingleCommandApplication / SymfonyCommand typed registry it + // belongs to is an external-package todo!() stub. + // let _ = SingleCommandApplication::new; - // Compatibility layer for symfony/console <7.4 - // TODO(phase-c): Application::add() takes Rc<RefCell<dyn - // SymfonyCommand>> - // but `cmd` here is the PhpMixed result of reflection-based - // plugin command instantiation; registering it as a typed - // command instance is blocked on the Symfony command-registry - // model (external-package todo!() stub). - let _ = &cmd; - todo!( - "plugin: register reflection-instantiated command on Application::add" + // makes sure the command is find()'able by the name defined in composer.json, and the name isn't overridden in its configure() + // TODO(phase-c): cmd is the PhpMixed result of reflection + // instantiation; reading/overriding its + // name/description requires the typed SymfonyCommand model that + // the Symfony stub does not yet provide. + let _ = description.clone(); + let _ = &mut cmd; + cmd + } else { + // fallback to usual aliasing behavior + // TODO(phase-c): ScriptAliasCommand is a typed BaseCommand + // but this code path stores commands as PhpMixed; it can + // only be carried as a typed trait object once the Symfony + // command registry is modelled. + let _ = ScriptAliasCommand::new( + script.clone(), + Some(description.clone()), + aliases, ); - } + PhpMixed::Null + }; + + // Compatibility layer for symfony/console <7.4 + // TODO(phase-c): Application::add() takes Rc<RefCell<dyn + // SymfonyCommand>> + // but `cmd` here is the PhpMixed result of reflection-based + // plugin command instantiation; registering it as a typed + // command instance is blocked on the Symfony command-registry + // model (external-package todo!() stub). + let _ = &cmd; + todo!( + "plugin: register reflection-instantiated command on Application::add" + ); } } } @@ -936,14 +928,14 @@ impl Application { } // chdir back to oldWorkingDir if set - if let Some(ref owd) = old_working_dir { - if !owd.is_empty() { - let owd = owd.clone(); - let _ = Silencer::call(|| { - chdir(&owd); - Ok(()) - }); - } + if let Some(ref owd) = old_working_dir + && !owd.is_empty() + { + let owd = owd.clone(); + let _ = Silencer::call(|| { + chdir(&owd); + Ok(()) + }); } if let Some(st) = start_time { @@ -1014,17 +1006,17 @@ impl Application { ) .as_string() .map(|s| s.to_string()); - if let Some(ref wd) = working_dir { - if !is_dir(wd) { - return Err(RuntimeException { - message: format!( - "Invalid working directory specified, {} does not exist.", - wd - ), - code: 0, - } - .into()); + if let Some(ref wd) = working_dir + && !is_dir(wd) + { + return Err(RuntimeException { + message: format!( + "Invalid working directory specified, {} does not exist.", + wd + ), + code: 0, } + .into()); } Ok(working_dir) @@ -1049,8 +1041,7 @@ impl Application { // avoid overlapping borrows of self (get_composer needs &mut self). let disk_hint_msg: Option<String> = (|| -> anyhow::Result<Option<String>> { let composer = self.get_composer(false, Some(true), None)?; - if composer.is_some() && function_exists("disk_free_space") { - let composer = composer.unwrap(); + if let Some(composer) = composer && function_exists("disk_free_space") { let composer = composer.borrow_partial(); let config = composer.get_config(); @@ -1116,7 +1107,7 @@ impl Application { .map(|s| Box::new(PhpMixed::String(s.clone()))) .collect(), ); - if is_array(&avast_detect_pm) && avast_detect.len() != 0 { + if is_array(&avast_detect_pm) && !avast_detect.is_empty() { io.write_error3("<error>The following exception indicates a possible issue with the Avast Firewall</error>", true, io_interface::QUIET); io.write_error3( "<error>Check https://getcomposer.org/local-issuer for details</error>", @@ -1311,7 +1302,7 @@ impl Application { if !composer::BRANCH_ALIAS_VERSION.is_empty() && composer::BRANCH_ALIAS_VERSION != "@package_branch_alias_version@" { - branch_alias_string = format!(" ({})", composer::BRANCH_ALIAS_VERSION.to_string(),); + branch_alias_string = format!(" ({})", composer::BRANCH_ALIAS_VERSION,); } format!( @@ -1492,7 +1483,6 @@ impl Application { // from the exception's `code` field needs the downcast strategy decided. let exit_code = shirabe_php_shim::php_exception_get_code(&e); if shirabe_php_shim::is_numeric_string(&exit_code.to_string()) { - let exit_code = exit_code; if exit_code <= 0 { 1 } else { exit_code } } else { 1 @@ -1743,7 +1733,7 @@ impl Application { let filtered: Vec<shirabe_external_packages::symfony::console::completion::completion_suggestions::StringOrSuggestion> = command_names .into_iter() - .filter(|n| shirabe_php_shim::php_truthy(n)) + .filter(shirabe_php_shim::php_truthy) .map(|n| { shirabe_external_packages::symfony::console::completion::completion_suggestions::StringOrSuggestion::String( shirabe_php_shim::php_to_string(&n), @@ -1926,20 +1916,20 @@ impl Application { return true; } - if let Some(command_loader) = &self.command_loader { - if command_loader.has(name) { - let command = command_loader.get(name); - // $this->add($this->commandLoader->get($name)) - // TODO(review): command_loader.get() returns Box<dyn SymfonyCommand> while add() expects - // Rc<RefCell<dyn SymfonyCommand>>; the loader return type needs reconciliation. - let _ = command; - return self - .add(todo!( - "Rc<RefCell<dyn SymfonyCommand>> from command_loader.get(name)" - )) - .map(|c| c.is_some()) - .unwrap_or(false); - } + if let Some(command_loader) = &self.command_loader + && command_loader.has(name) + { + let command = command_loader.get(name); + // $this->add($this->commandLoader->get($name)) + // TODO(review): command_loader.get() returns Box<dyn SymfonyCommand> while add() expects + // Rc<RefCell<dyn SymfonyCommand>>; the loader return type needs reconciliation. + let _ = command; + return self + .add(todo!( + "Rc<RefCell<dyn SymfonyCommand>> from command_loader.get(name)" + )) + .map(|c| c.is_some()) + .unwrap_or(false); } false @@ -2101,11 +2091,11 @@ impl Application { // if no commands matched or we just matched namespaces if commands.is_empty() - || shirabe_php_shim::preg_grep(&format!("{{^{}$}}i", expr), &commands).len() < 1 + || shirabe_php_shim::preg_grep(&format!("{{^{}$}}i", expr), &commands).is_empty() { if let Some(pos) = shirabe_php_shim::strrpos(name, ":") { // check if a namespace exists and contains commands - self.find_namespace(&name[..pos as usize])?; + self.find_namespace(&name[..pos])?; } let mut message = format!( @@ -2219,7 +2209,7 @@ impl Application { let filtered: Vec<String> = formatted_abbrevs .iter() .filter(|a| shirabe_php_shim::php_truthy(a)) - .map(|a| shirabe_php_shim::php_to_string(a)) + .map(shirabe_php_shim::php_to_string) .collect(); let suggestions = self.get_abbreviation_suggestions(&filtered); diff --git a/crates/shirabe/src/console/github_action_error.rs b/crates/shirabe/src/console/github_action_error.rs index 963f5c1..7475505 100644 --- a/crates/shirabe/src/console/github_action_error.rs +++ b/crates/shirabe/src/console/github_action_error.rs @@ -15,13 +15,13 @@ impl GithubActionError { } pub fn emit(&mut self, message: &str, file: Option<&str>, line: Option<i64>) { - if Platform::get_env("GITHUB_ACTIONS").map_or(false, |v| !v.is_empty()) - && !Platform::get_env("COMPOSER_TESTS_ARE_RUNNING").map_or(false, |v| !v.is_empty()) + if Platform::get_env("GITHUB_ACTIONS").is_some_and(|v| !v.is_empty()) + && Platform::get_env("COMPOSER_TESTS_ARE_RUNNING").is_none_or(|v| v.is_empty()) { let message = self.escape_data(message); - let file_truthy = file.map_or(false, |f| !f.is_empty()); - let line_truthy = line.map_or(false, |l| l != 0); + let file_truthy = file.is_some_and(|f| !f.is_empty()); + let line_truthy = line.is_some_and(|l| l != 0); if file_truthy && line_truthy { let file = self.escape_property(file.unwrap()); @@ -45,8 +45,8 @@ impl GithubActionError { // see https://github.com/actions/toolkit/blob/4f7fb6513a355689f69f0849edeb369a4dc81729/packages/core/src/command.ts#L80-L85 let data = data.replace('%', "%25"); let data = data.replace('\r', "%0D"); - let data = data.replace('\n', "%0A"); - data + + data.replace('\n', "%0A") } fn escape_property(&self, property: &str) -> String { @@ -55,7 +55,7 @@ impl GithubActionError { let property = property.replace('\r', "%0D"); let property = property.replace('\n', "%0A"); let property = property.replace(':', "%3A"); - let property = property.replace(',', "%2C"); - property + + property.replace(',', "%2C") } } diff --git a/crates/shirabe/src/dependency_resolver/default_policy.rs b/crates/shirabe/src/dependency_resolver/default_policy.rs index 541ec44..885ff17 100644 --- a/crates/shirabe/src/dependency_resolver/default_policy.rs +++ b/crates/shirabe/src/dependency_resolver/default_policy.rs @@ -68,14 +68,14 @@ impl DefaultPolicy { return -1; } - if let Some(ref required_package) = required_package { - if let Some(pos) = required_package.find('/') { - let required_vendor = &required_package[..pos]; - let a_is_same_vendor = a.get_name().starts_with(required_vendor); - let b_is_same_vendor = b.get_name().starts_with(required_vendor); - if b_is_same_vendor != a_is_same_vendor { - return if a_is_same_vendor { -1 } else { 1 }; - } + if let Some(ref required_package) = required_package + && let Some(pos) = required_package.find('/') + { + let required_vendor = &required_package[..pos]; + let a_is_same_vendor = a.get_name().starts_with(required_vendor); + let b_is_same_vendor = b.get_name().starts_with(required_vendor); + if b_is_same_vendor != a_is_same_vendor { + return if a_is_same_vendor { -1 } else { 1 }; } } } @@ -140,11 +140,11 @@ impl DefaultPolicy { for &literal in &literals { let package = pool.literal_to_package(literal); - if let Some(alias_pkg) = package.as_alias() { - if alias_pkg.is_root_package_alias() { - has_local_alias = true; - break; - } + if let Some(alias_pkg) = package.as_alias() + && alias_pkg.is_root_package_alias() + { + has_local_alias = true; + break; } } @@ -155,10 +155,10 @@ impl DefaultPolicy { let mut selected = vec![]; for &literal in &literals { let package = pool.literal_to_package(literal); - if let Some(alias_pkg) = package.as_alias() { - if alias_pkg.is_root_package_alias() { - selected.push(literal); - } + if let Some(alias_pkg) = package.as_alias() + && alias_pkg.is_root_package_alias() + { + selected.push(literal); } } selected @@ -235,10 +235,10 @@ impl PolicyInterface for DefaultPolicy { { let cache = self.preferred_package_result_cache_per_pool.borrow(); - if let Some(pool_cache) = cache.get(&pool_id) { - if let Some(cached) = pool_cache.get(&result_cache_key) { - return cached.clone(); - } + if let Some(pool_cache) = cache.get(&pool_id) + && let Some(cached) = pool_cache.get(&result_cache_key) + { + return cached.clone(); } } @@ -250,10 +250,10 @@ impl PolicyInterface for DefaultPolicy { format!("i{}.{}{}", a, b, required_package.as_deref().unwrap_or("")); { let cache = self.sorting_cache_per_pool.borrow(); - if let Some(pool_cache) = cache.get(&pool_id) { - if let Some(&result) = pool_cache.get(&cache_key) { - return result.cmp(&0); - } + if let Some(pool_cache) = cache.get(&pool_id) + && let Some(&result) = pool_cache.get(&cache_key) + { + return result.cmp(&0); } } let result = self.compare_by_priority( @@ -283,10 +283,10 @@ impl PolicyInterface for DefaultPolicy { let cache_key = format!("{}.{}{}", a, b, required_package.as_deref().unwrap_or("")); { let cache = self.sorting_cache_per_pool.borrow(); - if let Some(pool_cache) = cache.get(&pool_id) { - if let Some(&result) = pool_cache.get(&cache_key) { - return result.cmp(&0); - } + if let Some(pool_cache) = cache.get(&pool_id) + && let Some(&result) = pool_cache.get(&cache_key) + { + return result.cmp(&0); } } let result = self.compare_by_priority( diff --git a/crates/shirabe/src/dependency_resolver/lock_transaction.rs b/crates/shirabe/src/dependency_resolver/lock_transaction.rs index 30706f5..3cabdcd 100644 --- a/crates/shirabe/src/dependency_resolver/lock_transaction.rs +++ b/crates/shirabe/src/dependency_resolver/lock_transaction.rs @@ -37,7 +37,7 @@ impl LockTransaction { let all: Vec<PackageInterfaceHandle> = this .result_packages .get("all") - .map(|v| v.iter().cloned().collect()) + .map(|v| v.to_vec()) .unwrap_or_default(); let present: Vec<PackageInterfaceHandle> = this.present_map.values().cloned().collect(); this.inner = Transaction::new(present, all); @@ -59,12 +59,12 @@ impl LockTransaction { result_packages .get_mut("all") .unwrap() - .push(package.clone().into()); + .push(package.clone()); if !self.unlockable_map.contains_key(&package.get_id()) { result_packages .get_mut("non-dev") .unwrap() - .push(package.clone().into()); + .push(package.clone()); } } } diff --git a/crates/shirabe/src/dependency_resolver/pool.rs b/crates/shirabe/src/dependency_resolver/pool.rs index b12d760..7b60002 100644 --- a/crates/shirabe/src/dependency_resolver/pool.rs +++ b/crates/shirabe/src/dependency_resolver/pool.rs @@ -120,12 +120,12 @@ impl Pool { .get(package_name) .unwrap_or(&empty); for (version, _package_with_security_advisories) in versions { - if let Some(c) = constraint { - if c.matches( + if let Some(c) = constraint + && c.matches( &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(), - ) { - return true; - } + ) + { + return true; } } @@ -144,15 +144,15 @@ impl Pool { .get(package_name) .unwrap_or(&empty); for (version, package_with_security_advisories) in versions { - if let Some(c) = constraint { - if c.matches( + if let Some(c) = constraint + && c.matches( &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(), - ) { - return package_with_security_advisories - .iter() - .map(|advisory| advisory.advisory_id().to_string()) - .collect(); - } + ) + { + return package_with_security_advisories + .iter() + .map(|advisory| advisory.advisory_id().to_string()) + .collect(); } } @@ -170,12 +170,12 @@ impl Pool { .get(package_name) .unwrap_or(&empty); for (version, _pretty_version) in versions { - if let Some(c) = constraint { - if c.matches( + if let Some(c) = constraint + && c.matches( &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(), - ) { - return true; - } + ) + { + return true; } } @@ -207,7 +207,7 @@ impl Pool { for provided in package.get_names(true) { self.package_by_name .entry(provided) - .or_insert_with(Vec::new) + .or_default() .push(package.clone()); } @@ -241,16 +241,16 @@ impl Pool { Some(c) => c.to_string(), None => String::new(), }; - if let Some(by_key) = self.provider_cache.get(name) { - if let Some(cached) = by_key.get(&key) { - return cached.clone(); - } + if let Some(by_key) = self.provider_cache.get(name) + && let Some(cached) = by_key.get(&key) + { + return cached.clone(); } let computed = self.compute_what_provides(name, constraint); self.provider_cache .entry(name.to_string()) - .or_insert_with(IndexMap::new) + .or_default() .insert(key, computed.clone()); computed } @@ -352,16 +352,16 @@ impl Pool { return false; } - if let Some(provide) = provides.get(name) { - if constraint.is_none() || constraint.unwrap().matches(provide.get_constraint()) { - return true; - } + if let Some(provide) = provides.get(name) + && (constraint.is_none() || constraint.unwrap().matches(provide.get_constraint())) + { + return true; } - if let Some(replace) = replaces.get(name) { - if constraint.is_none() || constraint.unwrap().matches(replace.get_constraint()) { - return true; - } + if let Some(replace) = replaces.get(name) + && (constraint.is_none() || constraint.unwrap().matches(replace.get_constraint())) + { + return true; } false diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs index 9589276..9b4c561 100644 --- a/crates/shirabe/src/dependency_resolver/pool_builder.rs +++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs @@ -83,6 +83,7 @@ pub struct PoolBuilder { impl PoolBuilder { const LOAD_BATCH_SIZE: i64 = 50; + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn new( acceptable_stabilities: IndexMap<String, i64>, stability_flags: IndexMap<String, i64>, @@ -148,7 +149,7 @@ impl PoolBuilder { None }; - if request.get_update_allow_list().len() > 0 { + if !request.get_update_allow_list().is_empty() { self.update_allow_list = request.get_update_allow_list().clone(); self.warn_about_non_matching_update_allow_list(request)?; @@ -185,7 +186,7 @@ impl PoolBuilder { } } - request.lock_package(locked_package.into()); + request.lock_package(locked_package); } } } @@ -209,9 +210,9 @@ impl PoolBuilder { // TODO in how far can we do the above for conflicts? It's more tricky cause conflicts can be limited to // specific versions while replace is a conflict with all versions of the name - let in_root_or_platform = package.get_repository().map_or(false, |r| { - r.is::<RootPackageRepository>() || r.is::<PlatformRepository>() - }); + let in_root_or_platform = package + .get_repository() + .is_some_and(|r| r.is::<RootPackageRepository>() || r.is::<PlatformRepository>()); if in_root_or_platform || StabilityFilter::is_package_acceptable( &self.acceptable_stabilities, @@ -248,11 +249,11 @@ impl PoolBuilder { self.packages_to_load.shift_remove(&name); } - while self.packages_to_load.len() > 0 { + while !self.packages_to_load.is_empty() { self.load_packages_marked_for_loading(request, &repositories)?; } - if self.temporary_constraints.len() > 0 { + if !self.temporary_constraints.is_empty() { let indices: Vec<i64> = self.packages.keys().cloned().collect(); for i in indices { let package = match self.packages.get(&i) { @@ -298,7 +299,7 @@ impl PoolBuilder { } } - if self.event_dispatcher.is_some() { + if let Some(event_dispatcher) = &self.event_dispatcher { // TODO(plugin): PrePoolCreateEvent::new takes Request and Vec<Box<dyn RepositoryInterface>> // by value but neither can be cloned (PHP class shared semantics). This event is purely // plugin-facing and nothing in the no-plugin path reads it back, so it stays deferred @@ -312,20 +313,13 @@ impl PoolBuilder { self.root_aliases.clone(), self.root_references.clone(), self.packages.values().cloned().collect(), - self.unacceptable_fixed_or_locked_packages - .iter() - .cloned() - .collect(), + self.unacceptable_fixed_or_locked_packages.to_vec(), ); let pre_pool_create_event_name = pre_pool_create_event.get_name().to_string(); - self.event_dispatcher - .as_ref() - .unwrap() - .borrow_mut() - .dispatch( - Some(&pre_pool_create_event_name), - Some(&mut pre_pool_create_event), - )?; + event_dispatcher.borrow_mut().dispatch( + Some(&pre_pool_create_event_name), + Some(&mut pre_pool_create_event), + )?; // PHP rebinds $this->packages to a list-style array; preserve indices via reindexing. // TODO(plugin)/TODO(phase-c): rebind self.packages from the (handle-based) event packages // once EventDispatcher::dispatch returns the mutated event. @@ -334,10 +328,7 @@ impl PoolBuilder { let mut pool = Pool::new( self.packages.values().cloned().collect(), - self.unacceptable_fixed_or_locked_packages - .iter() - .cloned() - .collect(), + self.unacceptable_fixed_or_locked_packages.to_vec(), IndexMap::new(), IndexMap::new(), IndexMap::new(), @@ -390,10 +381,10 @@ impl PoolBuilder { // we make sure that we load at most the intervals covered by the root constraint. let root_requires = request.get_requires(); let mut constraint = constraint; - if let Some(root_constraint) = root_requires.get(name) { - if !Intervals::is_subset_of(&constraint, root_constraint).unwrap_or(false) { - constraint = root_constraint.clone(); - } + if let Some(root_constraint) = root_requires.get(name) + && !Intervals::is_subset_of(&constraint, root_constraint).unwrap_or(false) + { + constraint = root_constraint.clone(); } // Not yet loaded or already marked for a reload, set the constraint to be loaded @@ -499,12 +490,12 @@ impl PoolBuilder { // never need to load anything else from them let is_locked_repo = request .get_locked_repository() - .map_or(false, |h| repository.ptr_eq(&h.into())); + .is_some_and(|h| repository.ptr_eq(&h.into())); if repository.is::<PlatformRepository>() || is_locked_repo { continue; } - if 0 == package_batches.len() { + if package_batches.is_empty() { break; } @@ -620,7 +611,7 @@ impl PoolBuilder { if let Some(alias) = package.as_alias() { self.alias_map .entry(alias.get_alias_of().ptr_id().to_string()) - .or_insert_with(IndexMap::new) + .or_default() .insert(index, alias); } @@ -649,8 +640,9 @@ impl PoolBuilder { .get(&name) .and_then(|m| m.get(&package.get_version())) .cloned(); - if (propagate_update || path_repo_match) && alias_for_version.is_some() { - let alias = alias_for_version.unwrap(); + if (propagate_update || path_repo_match) + && let Some(alias) = alias_for_version + { let base_package: BasePackageHandle = if let Some(ap) = package.as_alias() { ap.get_alias_of().into() } else { @@ -674,7 +666,7 @@ impl PoolBuilder { self.packages.insert(new_index, alias_handle.clone().into()); self.alias_map .entry(alias_handle.get_alias_of().ptr_id().to_string()) - .or_insert_with(IndexMap::new) + .or_default() .insert(new_index, alias_handle); } @@ -692,7 +684,7 @@ impl PoolBuilder { let skipped_root_requires = self.get_skipped_root_requires(request, &require); if request.get_update_allow_transitive_root_dependencies() - || 0 == skipped_root_requires.len() + || skipped_root_requires.is_empty() { self.unlock_package(request, repositories, &require)?; self.mark_package_name_for_loading(request, &require, link_constraint); @@ -727,7 +719,7 @@ impl PoolBuilder { let skipped_root_requires = self.get_skipped_root_requires(request, &replace); if request.get_update_allow_transitive_root_dependencies() - || 0 == skipped_root_requires.len() + || skipped_root_requires.is_empty() { self.unlock_package(request, repositories, &replace)?; // the replaced package only needs to be loaded if something else requires it @@ -875,7 +867,7 @@ impl PoolBuilder { let skipped: Vec<PackageInterfaceHandle> = self .skipped_load .get(name) - .map(|v| v.iter().cloned().collect()) + .map(|v| v.to_vec()) .unwrap_or_default(); for package_or_replacer in &skipped { // if we unfixed a replaced package name, we also need to unfix the replacer itself @@ -1026,7 +1018,7 @@ impl PoolBuilder { fn remove_loaded_package( &mut self, _request: &Request, - repositories: &Vec<RepositoryInterfaceHandle>, + repositories: &[RepositoryInterfaceHandle], package: BasePackageHandle, index: i64, ) { @@ -1040,23 +1032,21 @@ impl PoolBuilder { }) .unwrap_or(-1); - if repo_index >= 0 { - if let Some(repo_map) = self.loaded_per_repo.get_mut(&repo_index) { - if let Some(name_map) = repo_map.get_mut(&package.get_name()) { - name_map.shift_remove(&package.get_version()); - } - } + if repo_index >= 0 + && let Some(repo_map) = self.loaded_per_repo.get_mut(&repo_index) + && let Some(name_map) = repo_map.get_mut(&package.get_name()) + { + name_map.shift_remove(&package.get_version()); } self.packages.shift_remove(&index); let object_hash = package.ptr_id().to_string(); if let Some(aliases) = self.alias_map.shift_remove(&object_hash) { for (alias_index, alias_package) in &aliases { - if repo_index >= 0 { - if let Some(repo_map) = self.loaded_per_repo.get_mut(&repo_index) { - if let Some(name_map) = repo_map.get_mut(&alias_package.get_name()) { - name_map.shift_remove(&alias_package.get_version()); - } - } + if repo_index >= 0 + && let Some(repo_map) = self.loaded_per_repo.get_mut(&repo_index) + && let Some(name_map) = repo_map.get_mut(&alias_package.get_name()) + { + name_map.shift_remove(&alias_package.get_version()); } self.packages.shift_remove(alias_index); } @@ -1110,7 +1100,7 @@ impl PoolBuilder { fn run_security_advisory_filter( &mut self, pool: Pool, - repositories: &Vec<RepositoryInterfaceHandle>, + repositories: &[RepositoryInterfaceHandle], request: &Request, ) -> anyhow::Result<Pool> { if self.security_advisory_pool_filter.is_none() { @@ -1122,7 +1112,7 @@ impl PoolBuilder { let before = microtime(true); let total = pool.get_packages().len() as f64; - let repos_owned: Vec<RepositoryInterfaceHandle> = repositories.iter().cloned().collect(); + let repos_owned: Vec<RepositoryInterfaceHandle> = repositories.to_vec(); let pool = self .security_advisory_pool_filter .as_mut() diff --git a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs index 54ec993..2632dc8 100644 --- a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs +++ b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs @@ -93,7 +93,7 @@ impl PoolOptimizer { for (_, package) in request.get_fixed_or_locked_packages() { irremovable_package_constraint_groups .entry(package.get_name()) - .or_insert_with(Vec::new) + .or_default() .push( SimpleConstraint::new( "==".to_string(), @@ -131,7 +131,7 @@ impl PoolOptimizer { if let Some(alias_pkg) = package.as_alias() { self.aliases_per_package .entry(alias_pkg.get_alias_of().id()) - .or_insert_with(Vec::new) + .or_default() .push(package.clone()); } } @@ -197,7 +197,7 @@ impl PoolOptimizer { } else { removed_versions .entry(package.get_name()) - .or_insert_with(IndexMap::new) + .or_default() .insert( package.get_version().to_string(), package.get_pretty_version().to_string(), @@ -261,7 +261,7 @@ impl PoolOptimizer { )); } - if package.get_replaces().len() > 0 { + if !package.get_replaces().is_empty() { for (_, link) in package.get_replaces() { if CompilingMatcher::r#match( link.get_constraint(), @@ -294,22 +294,22 @@ impl PoolOptimizer { } } - if 0 == group_hash_parts.len() { + if group_hash_parts.is_empty() { continue; } let group_hash = implode("", &group_hash_parts); identical_definitions_per_package .entry(package_name.clone()) - .or_insert_with(IndexMap::new) + .or_default() .entry(group_hash.clone()) - .or_insert_with(IndexMap::new) + .or_default() .entry(dependency_hash.clone()) - .or_insert_with(Vec::new) + .or_default() .push(package.clone()); package_identical_definition_lookup .entry(package.id()) - .or_insert_with(IndexMap::new) + .or_default() .insert( package_name.clone(), IdenticalDefinitionPointers { @@ -382,7 +382,7 @@ impl PoolOptimizer { ]; for (key, links) in hash_relevant_links { - if 0 == links.len() { + if links.is_empty() { continue; } @@ -457,33 +457,32 @@ impl PoolOptimizer { // record all the versions of the package group so we can list them later in Problem output for name in package.get_names(false) { - if let Some(per_name) = package_identical_definition_lookup.get(&package.id()) { - if let Some(package_group_pointers) = per_name.get(&name) { - let package_group = identical_definitions_per_package - .get(&name) - .and_then(|m| m.get(&package_group_pointers.group_hash)) - .and_then(|m| m.get(&package_group_pointers.dependency_hash)); - if let Some(package_group) = package_group { - for pkg in package_group { - let pkg: BasePackageHandle = if let Some(alias_pkg) = pkg.as_alias() { - if alias_pkg.get_pretty_version() - == VersionParser::DEFAULT_BRANCH_ALIAS - { - alias_pkg.get_alias_of().into() - } else { - pkg.clone() - } + if let Some(per_name) = package_identical_definition_lookup.get(&package.id()) + && let Some(package_group_pointers) = per_name.get(&name) + { + let package_group = identical_definitions_per_package + .get(&name) + .and_then(|m| m.get(&package_group_pointers.group_hash)) + .and_then(|m| m.get(&package_group_pointers.dependency_hash)); + if let Some(package_group) = package_group { + for pkg in package_group { + let pkg: BasePackageHandle = if let Some(alias_pkg) = pkg.as_alias() { + if alias_pkg.get_pretty_version() == VersionParser::DEFAULT_BRANCH_ALIAS + { + alias_pkg.get_alias_of().into() } else { pkg.clone() - }; - self.removed_versions_by_package - .entry(package.ptr_id().to_string()) - .or_insert_with(IndexMap::new) - .insert( - pkg.get_version().to_string(), - pkg.get_pretty_version().to_string(), - ); - } + } + } else { + pkg.clone() + }; + self.removed_versions_by_package + .entry(package.ptr_id().to_string()) + .or_default() + .insert( + pkg.get_version().to_string(), + pkg.get_pretty_version().to_string(), + ); } } } @@ -504,34 +503,33 @@ impl PoolOptimizer { // record all the versions of the package group so we can list them later in Problem output for name in alias_names { - if let Some(per_name) = package_identical_definition_lookup.get(&alias_id) { - if let Some(package_group_pointers) = per_name.get(&name) { - let package_group = identical_definitions_per_package - .get(&name) - .and_then(|m| m.get(&package_group_pointers.group_hash)) - .and_then(|m| m.get(&package_group_pointers.dependency_hash)); - if let Some(package_group) = package_group { - for pkg in package_group { - let pkg: BasePackageHandle = if let Some(alias_pkg) = pkg.as_alias() + if let Some(per_name) = package_identical_definition_lookup.get(&alias_id) + && let Some(package_group_pointers) = per_name.get(&name) + { + let package_group = identical_definitions_per_package + .get(&name) + .and_then(|m| m.get(&package_group_pointers.group_hash)) + .and_then(|m| m.get(&package_group_pointers.dependency_hash)); + if let Some(package_group) = package_group { + for pkg in package_group { + let pkg: BasePackageHandle = if let Some(alias_pkg) = pkg.as_alias() { + if alias_pkg.get_pretty_version() + == VersionParser::DEFAULT_BRANCH_ALIAS { - if alias_pkg.get_pretty_version() - == VersionParser::DEFAULT_BRANCH_ALIAS - { - alias_pkg.get_alias_of().into() - } else { - pkg.clone() - } + alias_pkg.get_alias_of().into() } else { pkg.clone() - }; - self.removed_versions_by_package - .entry(format!("alias-{}", alias_id)) - .or_insert_with(IndexMap::new) - .insert( - pkg.get_version().to_string(), - pkg.get_pretty_version().to_string(), - ); - } + } + } else { + pkg.clone() + }; + self.removed_versions_by_package + .entry(format!("alias-{}", alias_id)) + .or_default() + .insert( + pkg.get_version().to_string(), + pkg.get_pretty_version().to_string(), + ); } } } @@ -543,7 +541,7 @@ impl PoolOptimizer { /// This will reduce packages with significant numbers of historical versions to a smaller number /// and reduce the resulting rule set that is generated fn optimize_impossible_packages_away(&mut self, request: &Request, pool: &Pool) { - if request.get_locked_packages().len() == 0 { + if request.get_locked_packages().is_empty() { return; } @@ -569,7 +567,7 @@ impl PoolOptimizer { package_index .entry(package.get_name()) - .or_insert_with(IndexMap::new) + .or_default() .insert(package.id(), package.clone()); } @@ -607,18 +605,16 @@ impl PoolOptimizer { .get(require) .and_then(|m| m.get(&id)) .map(|p| p.get_version().to_string()); - if let Some(version_str) = version_str { - if false - == CompilingMatcher::r#match( - link_constraint, - SimpleConstraint::OP_EQ, - version_str, - ) - { - self.mark_package_for_removal(id); - if let Some(map) = package_index.get_mut(require) { - map.shift_remove(&id); - } + if let Some(version_str) = version_str + && !CompilingMatcher::r#match( + link_constraint, + SimpleConstraint::OP_EQ, + version_str, + ) + { + self.mark_package_for_removal(id); + if let Some(map) = package_index.get_mut(require) { + map.shift_remove(&id); } } } @@ -639,7 +635,7 @@ impl PoolOptimizer { for expanded in self.expand_disjunctive_multi_constraints(constraint) { self.require_constraints_per_package .entry(package.to_string()) - .or_insert_with(IndexMap::new) + .or_default() .insert(expanded.to_string(), expanded); } } @@ -657,7 +653,7 @@ impl PoolOptimizer { for expanded in self.expand_disjunctive_multi_constraints(constraint) { self.conflict_constraints_per_package .entry(package.to_string()) - .or_insert_with(IndexMap::new) + .or_default() .insert(expanded.to_string(), expanded); } } @@ -669,12 +665,12 @@ impl PoolOptimizer { ) -> Vec<AnyConstraint> { let constraint = Intervals::compact_constraint(&constraint).unwrap_or(constraint); - if let Some(multi) = constraint.as_multi_constraint() { - if multi.is_disjunctive_mc() { - // No need to call ourselves recursively here because Intervals::compactConstraint() ensures that there - // are no nested disjunctive MultiConstraint instances possible - return multi.get_constraints().iter().map(|c| c.clone()).collect(); - } + if let Some(multi) = constraint.as_multi_constraint() + && multi.is_disjunctive_mc() + { + // No need to call ourselves recursively here because Intervals::compactConstraint() ensures that there + // are no nested disjunctive MultiConstraint instances possible + return multi.get_constraints().to_vec(); } // Regular constraints and conjunctive MultiConstraints diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs index 93d82be..0075b5e 100644 --- a/crates/shirabe/src/dependency_resolver/problem.rs +++ b/crates/shirabe/src/dependency_resolver/problem.rs @@ -41,6 +41,12 @@ pub struct Problem { pub(crate) section: i64, } +impl Default for Problem { + fn default() -> Self { + Self::new() + } +} + impl Problem { pub fn new() -> Self { Self { @@ -101,7 +107,7 @@ impl Problem { }; let packages = pool.compute_what_provides(&package_name, constraint); - if packages.len() == 0 { + if packages.is_empty() { let missing = Self::get_missing_package_reason( repository_set, request, @@ -193,7 +199,7 @@ impl Problem { } } - /// @internal + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn format_deduplicated_rules( rules: &Vec<std::rc::Rc<std::cell::RefCell<Rule>>>, indent: &str, @@ -208,8 +214,7 @@ impl Problem { let mut templates: IndexMap<String, IndexMap<String, IndexMap<String, String>>> = IndexMap::new(); let parser = VersionParser::new(); - let deduplicatable_rule_types = - vec![rule::RULE_PACKAGE_REQUIRES, rule::RULE_PACKAGE_CONFLICT]; + let deduplicatable_rule_types = [rule::RULE_PACKAGE_REQUIRES, rule::RULE_PACKAGE_CONFLICT]; for rule in rules { let rule_ref = rule.borrow(); let mut message = rule_ref.get_pretty_string( @@ -248,9 +253,9 @@ impl Problem { let version_key = parser.normalize(&m2, Some("")).unwrap_or_default(); templates .entry(template.clone()) - .or_insert_with(IndexMap::new) + .or_default() .entry(pkg_key.clone()) - .or_insert_with(IndexMap::new) + .or_default() .insert(version_key, m2.clone()); let source_package = rule_ref.get_source_package(pool).unwrap(); for (version, pretty_version) in @@ -263,7 +268,7 @@ impl Problem { .unwrap() .insert(version, pretty_version); } - } else if message != "" { + } else if !message.is_empty() { messages.push(message); } } @@ -367,10 +372,7 @@ impl Problem { if !self.reason_seen.contains_key(&id) { self.reason_seen.insert(id, true); - self.reasons - .entry(self.section) - .or_insert_with(Vec::new) - .push(reason); + self.reasons.entry(self.section).or_default().push(reason); } } @@ -403,7 +405,8 @@ impl Problem { ); if defined("HHVM_VERSION") - || (package_name == "hhvm" && pool.what_provides(package_name, None).len() > 0) + || (package_name == "hhvm" + && !pool.what_provides(package_name, None).is_empty()) { return Ok(( msg, @@ -562,64 +565,61 @@ impl Problem { } } - if let Some(c) = constraint { - if c.is_constraint() - && c.get_operator() == SimpleConstraint::STR_OP_EQ - && Preg::is_match3(r"{^dev-.*#.*}", &c.get_pretty_string(), None) - { - let new_constraint = - Preg::replace(r"{ +as +([^,\s|]+)$}", "", &c.get_pretty_string()); - let packages = repository_set.find_packages( - package_name, - Some( - MultiConstraint::new( - vec![ - AnyConstraint::Simple(SimpleConstraint::new( - SimpleConstraint::STR_OP_EQ.to_string(), - new_constraint.clone(), - None, - )), - AnyConstraint::Simple(SimpleConstraint::new( - SimpleConstraint::STR_OP_EQ.to_string(), - str_replace("#", "+", &new_constraint), - None, - )), - ], - false, - None, - ) - .into(), + if let Some(c) = constraint + && c.is_constraint() + && c.get_operator() == SimpleConstraint::STR_OP_EQ + && Preg::is_match3(r"{^dev-.*#.*}", &c.get_pretty_string(), None) + { + let new_constraint = Preg::replace(r"{ +as +([^,\s|]+)$}", "", &c.get_pretty_string()); + let packages = repository_set.find_packages( + package_name, + Some( + MultiConstraint::new( + vec![ + AnyConstraint::Simple(SimpleConstraint::new( + SimpleConstraint::STR_OP_EQ.to_string(), + new_constraint.clone(), + None, + )), + AnyConstraint::Simple(SimpleConstraint::new( + SimpleConstraint::STR_OP_EQ.to_string(), + str_replace("#", "+", &new_constraint), + None, + )), + ], + false, + None, + ) + .into(), + ), + 0, + )?; + if !packages.is_empty() { + return Ok(( + format!( + "- Root composer.json requires {}{}, ", + package_name, + Self::constraint_to_text(constraint) ), - 0, - )?; - if packages.len() > 0 { - return Ok(( - format!( - "- Root composer.json requires {}{}, ", - package_name, - Self::constraint_to_text(constraint) - ), - format!( - "found {}. The # character in branch names is replaced by a + character. Make sure to require it as \"{}\".", - Self::get_package_list( - &packages, - is_verbose, - Some(pool), - constraint, - false - ), - str_replace("#", "+", &c.get_pretty_string()) + format!( + "found {}. The # character in branch names is replaced by a + character. Make sure to require it as \"{}\".", + Self::get_package_list( + &packages, + is_verbose, + Some(pool), + constraint, + false ), - )); - } + str_replace("#", "+", &c.get_pretty_string()) + ), + )); } } // first check if the actual requested package is found in normal conditions // if so it must mean it is rejected by another constraint than the one given here - let packages = - repository_set.find_packages(package_name, constraint.map(|c| c.clone()), 0)?; - if packages.len() > 0 { + let packages = repository_set.find_packages(package_name, constraint.cloned(), 0)?; + if !packages.is_empty() { let root_reqs = repository_set.get_root_requires(); if root_reqs.contains_key(package_name) { let filtered: Vec<&BasePackageHandle> = packages @@ -635,7 +635,7 @@ impl Problem { ) }) .collect(); - if filtered.len() == 0 { + if filtered.is_empty() { return Ok(( format!( "- Root composer.json requires {}{}, ", @@ -679,7 +679,7 @@ impl Problem { ) }) .collect(); - if filtered.len() == 0 { + if filtered.is_empty() { return Ok(( format!( "- Root composer.json requires {}{}, ", @@ -727,7 +727,7 @@ impl Problem { ) }) .collect(); - if filtered.len() == 0 { + if filtered.is_empty() { return Ok(( format!( "- Root composer.json requires {}{}, ", @@ -753,11 +753,11 @@ impl Problem { .iter() .filter(|p| { !p.get_repository() - .map_or(false, |r| r.is::<LockArrayRepository>()) + .is_some_and(|r| r.is::<LockArrayRepository>()) }) .collect(); - if non_locked_packages.len() == 0 { + if non_locked_packages.is_empty() { return Ok(( format!( "- Root composer.json requires {}{}, ", @@ -863,17 +863,17 @@ impl Problem { // check if the package is found when bypassing stability checks let packages = repository_set.find_packages( package_name, - constraint.map(|c| c.clone()), + constraint.cloned(), RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES, )?; - if packages.len() > 0 { + if !packages.is_empty() { // we must first verify if a valid package would be found in a lower priority repository let all_repos_packages = repository_set.find_packages( package_name, - constraint.map(|c| c.clone()), + constraint.cloned(), RepositorySet::ALLOW_SHADOWED_REPOSITORIES, )?; - if all_repos_packages.len() > 0 { + if !all_repos_packages.is_empty() { return Ok(Self::compute_check_for_lower_prio_repo( pool, is_verbose, @@ -909,14 +909,14 @@ impl Problem { None, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES, )?; - if packages.len() > 0 { + if !packages.is_empty() { // we must first verify if a valid package would be found in a lower priority repository let all_repos_packages = repository_set.find_packages( package_name, - constraint.map(|c| c.clone()), + constraint.cloned(), RepositorySet::ALLOW_SHADOWED_REPOSITORIES, )?; - if all_repos_packages.len() > 0 { + if !all_repos_packages.is_empty() { return Ok(Self::compute_check_for_lower_prio_repo( pool, is_verbose, @@ -929,23 +929,24 @@ impl Problem { } let mut suffix = String::new(); - if let Some(c) = constraint { - if c.is_constraint() && c.get_version() == "dev-master" { - for candidate in &packages { - if in_array( - PhpMixed::String(candidate.get_version().to_string()), - &PhpMixed::List(vec![ - Box::new(PhpMixed::String("dev-default".to_string())), - Box::new(PhpMixed::String("dev-main".to_string())), - ]), - true, - ) { - suffix = format!( - " Perhaps dev-master was renamed to {}?", - candidate.get_pretty_version() - ); - break; - } + if let Some(c) = constraint + && c.is_constraint() + && c.get_version() == "dev-master" + { + for candidate in &packages { + if in_array( + PhpMixed::String(candidate.get_version().to_string()), + &PhpMixed::List(vec![ + Box::new(PhpMixed::String("dev-default".to_string())), + Box::new(PhpMixed::String("dev-main".to_string())), + ]), + true, + ) { + suffix = format!( + " Perhaps dev-master was renamed to {}?", + candidate.get_pretty_version() + ); + break; } } } @@ -953,11 +954,11 @@ impl Problem { // check if the root package is a name match and hint the dependencies on root troubleshooting article let all_repos_packages = &packages; let top_package = all_repos_packages.first(); - if let Some(tp) = top_package { - if tp.as_root().is_some() { - suffix = " See https://getcomposer.org/dep-on-root for details and assistance." - .to_string(); - } + if let Some(tp) = top_package + && tp.as_root().is_some() + { + suffix = " See https://getcomposer.org/dep-on-root for details and assistance." + .to_string(); } return Ok(( @@ -1045,18 +1046,18 @@ impl Problem { package.get_version().to_string(), format!("{}{}", package.get_pretty_version(), alias_suffix), ); - if pool.is_some() && constraint.is_some() { - for (version, pretty_version) in pool - .unwrap() - .get_removed_versions(&pkg_name, constraint.unwrap()) - { + if let Some(pool) = pool + && let Some(constraint) = constraint + { + for (version, pretty_version) in pool.get_removed_versions(&pkg_name, constraint) { entry.versions.insert(version, pretty_version); } } - if pool.is_some() && use_removed_version_group { - for (version, pretty_version) in pool - .unwrap() - .get_removed_versions_by_package(&package.ptr_id().to_string()) + if let Some(pool) = pool + && use_removed_version_group + { + for (version, pretty_version) in + pool.get_removed_versions_by_package(&package.ptr_id().to_string()) { entry.versions.insert(version, pretty_version); } @@ -1120,12 +1121,12 @@ impl Problem { ) -> Option<String> { let available = pool.what_provides(package_name, None); - if available.len() > 0 { + if !available.is_empty() { let mut selected: Option<&BasePackageHandle> = None; for pkg in &available { if pkg .get_repository() - .map_or(false, |r| r.is::<PlatformRepository>()) + .is_some_and(|r| r.is::<PlatformRepository>()) { selected = Some(pkg); break; @@ -1188,14 +1189,11 @@ impl Problem { if stripos(version, "dev-") == Some(0) { by_major .entry("dev".to_string()) - .or_insert_with(Vec::new) + .or_default() .push(pretty.clone()); } else { let key = Preg::replace(r"{^(\d+)\..*}", "$1", version); - by_major - .entry(key) - .or_insert_with(Vec::new) - .push(pretty.clone()); + by_major.entry(key).or_default().push(pretty.clone()); } } for (major_version, versions_for_major) in by_major { @@ -1255,7 +1253,7 @@ impl Problem { } let next_repo = next_repo.expect("next_repo must be set"); - if higher_repo_packages.len() > 0 { + if !higher_repo_packages.is_empty() { let top_package = higher_repo_packages.first().unwrap(); if top_package.as_root().is_some() { return ( @@ -1366,45 +1364,38 @@ impl Problem { /// Turns a constraint into text usable in a sentence describing a request pub(crate) fn constraint_to_text(constraint: Option<&AnyConstraint>) -> String { - if let Some(c) = constraint { - if c.is_constraint() - && c.get_operator() == SimpleConstraint::STR_OP_EQ - && !str_starts_with(&c.get_version(), "dev-") - { - if !Preg::is_match3(r"{^\d+(?:\.\d+)*$}", &c.get_pretty_string(), None) { - return format!(" {} (exact version match)", c.get_pretty_string()); - } - - let mut versions = vec![c.get_pretty_string()]; - let mut i = 3 - substr_count(&versions[0], "."); - while i > 0 { - let last = versions.last().unwrap().clone(); - versions.push(format!("{}.0", last)); - i -= 1; - } + if let Some(c) = constraint + && c.is_constraint() + && c.get_operator() == SimpleConstraint::STR_OP_EQ + && !str_starts_with(c.get_version(), "dev-") + { + if !Preg::is_match3(r"{^\d+(?:\.\d+)*$}", &c.get_pretty_string(), None) { + return format!(" {} (exact version match)", c.get_pretty_string()); + } + let mut versions = vec![c.get_pretty_string()]; + let mut i = 3 - substr_count(&versions[0], "."); + while i > 0 { let last = versions.last().unwrap().clone(); - let detail = if versions.len() > 1 { - format!( - "{} or {}", - implode( - ", ", - &versions[..versions.len() - 1] - .iter() - .cloned() - .collect::<Vec<_>>() - ), - last - ) - } else { - versions[0].clone() - }; - return format!( - " {} (exact version match: {})", - c.get_pretty_string(), - detail - ); + versions.push(format!("{}.0", last)); + i -= 1; } + + let last = versions.last().unwrap().clone(); + let detail = if versions.len() > 1 { + format!( + "{} or {}", + implode(", ", &versions[..versions.len() - 1]), + last + ) + } else { + versions[0].clone() + }; + return format!( + " {} (exact version match: {})", + c.get_pretty_string(), + detail + ); } match constraint { @@ -1419,7 +1410,7 @@ impl Problem { max_providers: i64, ) -> anyhow::Result<Option<String>> { let providers = repository_set.get_providers(package_name)?; - if providers.len() > 0 { + if !providers.is_empty() { let provider_count = providers.len() as i64; let slice: Vec<crate::repository::ProviderInfo> = if provider_count > max_providers + 1 { diff --git a/crates/shirabe/src/dependency_resolver/rule.rs b/crates/shirabe/src/dependency_resolver/rule.rs index e62bb7b..30fa079 100644 --- a/crates/shirabe/src/dependency_resolver/rule.rs +++ b/crates/shirabe/src/dependency_resolver/rule.rs @@ -208,77 +208,76 @@ impl Rule { request: &Request, pool: &Pool, ) -> bool { - if self.get_reason() == RULE_PACKAGE_REQUIRES { - if let ReasonData::Link(link) = self.get_reason_data() { - if PlatformRepository::is_platform_package(link.get_target()) { - return false; - } - // TODO(phase-c): request.get_locked_repository() exists, but its get_packages() - // returns Result while is_caused_by_lock returns bool; resolving needs the bool - // chain (also via Problem/SolverProblemsException, itself phase-c) to carry Result. - let locked_repo: Option<()> = todo!("request.get_locked_repository()"); - if let Some(_locked_repo) = locked_repo { - let packages: Vec<BasePackageHandle> = todo!("locked_repo.get_packages()"); - for package in packages { - let p = package.clone(); - if p.get_name() == link.get_target() { - if pool.is_unacceptable_fixed_or_locked_package(p.clone()) { - return true; - } - if !link.get_constraint().matches( - &SimpleConstraint::new( - "=".to_string(), - p.get_version().to_string(), - None, - ) - .into(), - ) { - return true; - } - // required package was locked but has been unlocked and still matches - if !request.is_locked_package(p) { - return true; - } - break; + if self.get_reason() == RULE_PACKAGE_REQUIRES + && let ReasonData::Link(link) = self.get_reason_data() + { + if PlatformRepository::is_platform_package(link.get_target()) { + return false; + } + // TODO(phase-c): request.get_locked_repository() exists, but its get_packages() + // returns Result while is_caused_by_lock returns bool; resolving needs the bool + // chain (also via Problem/SolverProblemsException, itself phase-c) to carry Result. + let locked_repo: Option<()> = todo!("request.get_locked_repository()"); + if let Some(_locked_repo) = locked_repo { + let packages: Vec<BasePackageHandle> = todo!("locked_repo.get_packages()"); + for package in packages { + let p = package.clone(); + if p.get_name() == link.get_target() { + if pool.is_unacceptable_fixed_or_locked_package(p.clone()) { + return true; + } + if !link.get_constraint().matches( + &SimpleConstraint::new( + "=".to_string(), + p.get_version().to_string(), + None, + ) + .into(), + ) { + return true; } + // required package was locked but has been unlocked and still matches + if !request.is_locked_package(p) { + return true; + } + break; } } } } - if self.get_reason() == RULE_ROOT_REQUIRE { - if let ReasonData::RootRequire { + if self.get_reason() == RULE_ROOT_REQUIRE + && let ReasonData::RootRequire { package_name, constraint, } = self.get_reason_data() - { - if PlatformRepository::is_platform_package(package_name) { - return false; - } - // TODO(phase-c): request.get_locked_repository() exists, but its get_packages() - // returns Result while is_caused_by_lock returns bool; resolving needs the bool - // chain (also via Problem/SolverProblemsException, itself phase-c) to carry Result. - let locked_repo: Option<()> = todo!("request.get_locked_repository()"); - if let Some(_locked_repo) = locked_repo { - let packages: Vec<BasePackageHandle> = todo!("locked_repo.get_packages()"); - for package in packages { - let p = package.clone(); - if p.get_name() == *package_name { - if pool.is_unacceptable_fixed_or_locked_package(p.clone()) { - return true; - } - if !constraint.matches( - &SimpleConstraint::new( - "=".to_string(), - p.get_version().to_string(), - None, - ) - .into(), - ) { - return true; - } - break; + { + if PlatformRepository::is_platform_package(package_name) { + return false; + } + // TODO(phase-c): request.get_locked_repository() exists, but its get_packages() + // returns Result while is_caused_by_lock returns bool; resolving needs the bool + // chain (also via Problem/SolverProblemsException, itself phase-c) to carry Result. + let locked_repo: Option<()> = todo!("request.get_locked_repository()"); + if let Some(_locked_repo) = locked_repo { + let packages: Vec<BasePackageHandle> = todo!("locked_repo.get_packages()"); + for package in packages { + let p = package.clone(); + if p.get_name() == *package_name { + if pool.is_unacceptable_fixed_or_locked_package(p.clone()) { + return true; } + if !constraint.matches( + &SimpleConstraint::new( + "=".to_string(), + p.get_version().to_string(), + None, + ) + .into(), + ) { + return true; + } + break; } } } @@ -300,10 +299,10 @@ impl Rule { let reason_data = self.get_reason_data(); // swap literals if they are not in the right order with package2 being the conflicter - if let ReasonData::Link(link) = reason_data { - if link.get_source() == package1.get_name() { - std::mem::swap(&mut package1, &mut package2); - } + if let ReasonData::Link(link) = reason_data + && link.get_source() == package1.get_name() + { + std::mem::swap(&mut package1, &mut package2); } Ok(package2) @@ -350,7 +349,7 @@ impl Rule { }; let packages = pool.what_provides(package_name, Some(constraint)); - if 0 == packages.len() { + if packages.is_empty() { return Ok(format!( "No package found to satisfy root composer.json require {} {}", package_name, @@ -361,7 +360,7 @@ impl Rule { let packages_non_alias: Vec<BasePackageHandle> = packages .iter() .filter(|p| p.as_alias().is_none()) - .map(|p| p.clone()) + .cloned() .collect(); if packages_non_alias.len() == 1 { let package = &packages_non_alias[0]; @@ -380,7 +379,7 @@ impl Rule { constraint.get_pretty_string(), self.format_packages_unique_from_packages( pool, - packages.iter().map(|p| p.clone()).collect(), + packages.to_vec(), is_verbose, Some(constraint), false @@ -473,7 +472,7 @@ impl Rule { } r if r == RULE_PACKAGE_REQUIRES => { - assert!(literals.len() > 0); + assert!(!literals.is_empty()); let source_literal = array_shift(&mut literals).unwrap(); let source_package = self.deduplicate_default_branch_alias(pool.literal_to_package(source_literal)); @@ -489,7 +488,7 @@ impl Rule { } let text = link.get_pretty_string(source_package.clone()); - if requires.len() > 0 { + if !requires.is_empty() { format!( "{} -> satisfiable by {}.", text, @@ -562,7 +561,7 @@ impl Rule { } } - if installed_packages.len() > 0 && removable_packages.len() > 0 { + if !installed_packages.is_empty() && !removable_packages.is_empty() { return Ok(format!( "{} cannot be installed as that would require removing {}. {}", self.format_packages_unique_from_packages( @@ -605,7 +604,7 @@ impl Rule { let learned_string = " (conflict analysis result)"; let rule_text = if literals.len() == 1 { - pool.literal_to_pretty_string(literals[0], &installed_map) + pool.literal_to_pretty_string(literals[0], installed_map) } else { let mut groups: IndexMap<String, Vec<BasePackageHandle>> = IndexMap::new(); for literal in &literals { @@ -622,7 +621,7 @@ impl Rule { groups .entry(group.to_string()) - .or_insert_with(Vec::new) + .or_default() .push(self.deduplicate_default_branch_alias(package.clone())); } let mut rule_texts: Vec<String> = vec![]; @@ -633,7 +632,7 @@ impl Rule { if packages.len() > 1 { " one of" } else { "" }, self.format_packages_unique_from_packages( pool, - packages.iter().map(|p| p.clone()).collect(), + packages.to_vec(), is_verbose, None, false, @@ -685,7 +684,7 @@ impl Rule { if i != 0 { rule_text.push('|'); } - rule_text.push_str(&pool.literal_to_pretty_string(*literal, &installed_map)); + rule_text.push_str(&pool.literal_to_pretty_string(*literal, installed_map)); } format!("({})", rule_text) @@ -734,10 +733,10 @@ impl Rule { } fn deduplicate_default_branch_alias(&self, package: BasePackageHandle) -> BasePackageHandle { - if let Some(alias_pkg) = package.as_alias() { - if alias_pkg.get_pretty_version() == VersionParser::DEFAULT_BRANCH_ALIAS { - return alias_pkg.get_alias_of().into(); - } + if let Some(alias_pkg) = package.as_alias() + && alias_pkg.get_pretty_version() == VersionParser::DEFAULT_BRANCH_ALIAS + { + return alias_pkg.get_alias_of().into(); } package diff --git a/crates/shirabe/src/dependency_resolver/rule_set.rs b/crates/shirabe/src/dependency_resolver/rule_set.rs index 195f498..2d1cb78 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set.rs @@ -21,6 +21,12 @@ pub struct RuleSet { pub(crate) rules_by_hash: IndexMap<String, Vec<Rc<RefCell<Rule>>>>, } +impl Default for RuleSet { + fn default() -> Self { + Self::new() + } +} + impl RuleSet { pub const TYPE_PACKAGE: i64 = 0; pub const TYPE_REQUEST: i64 = 1; @@ -74,19 +80,13 @@ impl RuleSet { // The same rule instance is referenced from `rules`, `rule_by_id`, and // `rules_by_hash` (PHP shares one object across all three). - self.rules - .entry(r#type) - .or_insert_with(Vec::new) - .push(rule.clone()); + self.rules.entry(r#type).or_default().push(rule.clone()); self.rule_by_id.insert(self.next_rule_id, rule.clone()); rule.borrow_mut().set_type(r#type); self.next_rule_id += 1; - self.rules_by_hash - .entry(hash) - .or_insert_with(Vec::new) - .push(rule); + self.rules_by_hash.entry(hash).or_default().push(rule); Ok(()) } diff --git a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs index f2e7b75..d9452a3 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs @@ -208,7 +208,6 @@ impl RuleSetGenerator { .borrow_mut() .what_provides(link.get_target(), Some(&constraint)) .into_iter() - .map(|p| p.into()) .collect(); let rule = self.create_require_rule( @@ -257,7 +256,6 @@ impl RuleSetGenerator { .borrow_mut() .what_provides(link.get_target(), Some(&constraint)) .into_iter() - .map(|p| p.into()) .collect(); for conflict in &conflicts { @@ -282,7 +280,7 @@ impl RuleSetGenerator { let names_packages: Vec<(String, Vec<PackageInterfaceHandle>)> = self .added_packages_by_names .iter() - .map(|(k, v)| (k.clone(), v.iter().cloned().collect())) + .map(|(k, v)| (k.clone(), v.to_vec())) .collect(); for (name, packages) in names_packages { @@ -324,13 +322,13 @@ impl RuleSetGenerator { })); } - self.add_rules_for_package(package.clone().into(), platform_requirement_filter); + self.add_rules_for_package(package.clone(), platform_requirement_filter); let rule = self.create_install_one_of_rule( - &[package.clone().into()], + &[package.clone()], rule::RULE_FIXED, rule::ReasonData::Fixed { - package: package.clone().into(), + package: package.clone(), }, ); self.add_rule(RuleSet::TYPE_REQUEST, Some(Rule::Generic(rule))); @@ -355,7 +353,6 @@ impl RuleSetGenerator { .borrow_mut() .what_provides(package_name, Some(&constraint)) .into_iter() - .map(|p| p.into()) .collect(); if !packages.is_empty() { for package in &packages { @@ -382,29 +379,21 @@ impl RuleSetGenerator { &mut self, platform_requirement_filter: &dyn PlatformRequirementFilterInterface, ) { - let packages: Vec<PackageInterfaceHandle> = self - .pool - .borrow() - .get_packages() - .iter() - .map(|p| p.clone().into()) - .collect(); + let packages: Vec<PackageInterfaceHandle> = self.pool.borrow().get_packages().to_vec(); for package in &packages { // ensure that rules for root alias packages and aliases of packages which were loaded are also loaded // even if the alias itself isn't required, otherwise a package could be installed without its alias which // leads to unexpected behavior let is_not_added = !self.added_map.contains_key(&package.get_id()); let as_alias = package.as_alias(); - if is_not_added { - if let Some(alias_pkg) = as_alias { - if alias_pkg.is_root_package_alias() - || self - .added_map - .contains_key(&alias_pkg.get_alias_of().get_id()) - { - self.add_rules_for_package(package.clone(), platform_requirement_filter); - } - } + if is_not_added + && let Some(alias_pkg) = as_alias + && (alias_pkg.is_root_package_alias() + || self + .added_map + .contains_key(&alias_pkg.get_alias_of().get_id())) + { + self.add_rules_for_package(package.clone(), platform_requirement_filter); } } } @@ -427,7 +416,7 @@ impl RuleSetGenerator { self.added_map = IndexMap::new(); self.added_packages_by_names = IndexMap::new(); - let rules = std::mem::replace(&mut self.rules, RuleSet::new()); + let rules = std::mem::take(&mut self.rules); Ok(rules) } diff --git a/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs b/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs index c1b8657..91cfff2 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs @@ -59,7 +59,7 @@ impl RuleSetIterator { self.current_type = self.types[self.current_type_offset as usize]; - if self.rules[&self.current_type].len() != 0 { + if !self.rules[&self.current_type].is_empty() { break; } } @@ -81,7 +81,7 @@ impl RuleSetIterator { self.current_type = self.types[self.current_type_offset as usize]; - if self.rules[&self.current_type].len() != 0 { + if !self.rules[&self.current_type].is_empty() { break; } } diff --git a/crates/shirabe/src/dependency_resolver/rule_watch_chain.rs b/crates/shirabe/src/dependency_resolver/rule_watch_chain.rs index aa2d7f7..a29ff30 100644 --- a/crates/shirabe/src/dependency_resolver/rule_watch_chain.rs +++ b/crates/shirabe/src/dependency_resolver/rule_watch_chain.rs @@ -9,6 +9,12 @@ pub struct RuleWatchChain { current_offset: usize, } +impl Default for RuleWatchChain { + fn default() -> Self { + Self::new() + } +} + impl RuleWatchChain { pub fn new() -> Self { Self { diff --git a/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs b/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs index f5f66df..370d553 100644 --- a/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs +++ b/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs @@ -15,6 +15,12 @@ pub struct RuleWatchGraph { pub(crate) watch_chains: IndexMap<i64, RuleWatchChain>, } +impl Default for RuleWatchGraph { + fn default() -> Self { + Self::new() + } +} + impl RuleWatchGraph { pub fn new() -> Self { Self { diff --git a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs index 80769bb..933e1d0 100644 --- a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs +++ b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs @@ -92,14 +92,13 @@ impl SecurityAdvisoryPoolFilter { IndexMap::new(); for package in pool.get_packages() { if self.audit_config.block_abandoned - && self + && !self .auditor .filter_abandoned_packages( - &[package.clone()], + std::slice::from_ref(package), &self.audit_config.ignore_abandoned_for_blocking, )? - .len() - != 0 + .is_empty() { for package_name in package.get_names(false) { abandoned_removed_versions @@ -114,7 +113,7 @@ impl SecurityAdvisoryPoolFilter { } let matching_advisories = self.get_matching_advisories(package.clone(), &advisory_map); - if matching_advisories.len() > 0 { + if !matching_advisories.is_empty() { for package_name in package.get_names(false) { security_removed_versions .entry(package_name) diff --git a/crates/shirabe/src/dependency_resolver/solver.rs b/crates/shirabe/src/dependency_resolver/solver.rs index 1278970..d6654a9 100644 --- a/crates/shirabe/src/dependency_resolver/solver.rs +++ b/crates/shirabe/src/dependency_resolver/solver.rs @@ -271,7 +271,7 @@ impl Solver { crate::io::VERBOSE, ); - if self.problems.len() > 0 { + if !self.problems.is_empty() { // TODO(phase-c): SolverProblemsException stores `Rc<RefCell<Rule>>` which is not // `Send + Sync`, so it cannot satisfy `anyhow::Error`'s bounds. Returning a // placeholder error preserves control flow until the solver error path is reworked to @@ -285,18 +285,10 @@ impl Solver { // LockTransaction stores PackageInterfaceHandle maps; widen the request's BasePackageHandle // maps into them. - let present_map = request - .get_present_map(false)? - .into_iter() - .map(|(k, v)| (k, v.into())) - .collect(); - let unlockable_map = request - .get_fixed_packages_map() - .into_iter() - .map(|(k, v)| (k, v.into())) - .collect(); + let present_map = request.get_present_map(false)?.into_iter().collect(); + let unlockable_map = request.get_fixed_packages_map().into_iter().collect(); Ok(LockTransaction::new( - &*self.pool.borrow(), + &self.pool.borrow(), present_map, unlockable_map, &self.decisions, @@ -430,7 +422,7 @@ impl Solver { ) -> anyhow::Result<i64> { // choose best package to install from decisionQueue let mut literals = self.policy.select_preferred_packages( - &*self.pool.borrow(), + &self.pool.borrow(), decision_queue, rule.borrow().get_required_package(), ); @@ -439,7 +431,7 @@ impl Solver { .expect("select_preferred_packages returned an empty literal list"); // if there are multiple candidates, then branch - if literals.len() > 0 { + if !literals.is_empty() { self.branches.push((literals, level)); } @@ -519,8 +511,8 @@ impl Solver { return Err(anyhow::anyhow!(SolverBugException::new(format!( "Reached invalid decision id {} while looking through {} for a literal present in the analyzed rule {}.", decision_id, - rule.borrow().to_string(), - analyzed_rule.borrow().to_string() + rule.borrow(), + analyzed_rule.borrow() )))); } @@ -600,7 +592,7 @@ impl Solver { None => { return Err(anyhow::anyhow!(SolverBugException::new(format!( "Did not find a learnable literal in analyzed rule {}.", - analyzed_rule.borrow().to_string() + analyzed_rule.borrow() )))); } }; @@ -731,7 +723,7 @@ impl Solver { } } - if none_satisfied && decision_queue.len() > 0 { + if none_satisfied && !decision_queue.is_empty() { // if any of the options in the decision queue are fixed, only use those let mut pruned_queue: Vec<i64> = Vec::new(); for literal in &decision_queue { @@ -739,12 +731,12 @@ impl Solver { pruned_queue.push(*literal); } } - if pruned_queue.len() > 0 { + if !pruned_queue.is_empty() { decision_queue = pruned_queue; } } - if none_satisfied && decision_queue.len() > 0 { + if none_satisfied && !decision_queue.is_empty() { let o_level = level; level = self.select_and_install(level, decision_queue, rule)?; @@ -875,7 +867,7 @@ impl Solver { } // minimization step - if self.branches.len() > 0 { + if !self.branches.is_empty() { let mut last_literal: Option<i64> = None; let mut last_level: Option<i64> = None; let mut last_branch_index = 0_usize; diff --git a/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs b/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs index 513d4d9..d5f5560 100644 --- a/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs +++ b/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs @@ -128,7 +128,7 @@ impl SolverProblemsException { fn create_extension_hint(&self, missing_extensions: &[String]) -> String { let mut paths = IniHelper::get_all(); - if paths.first().map_or(false, |s| s.is_empty()) { + if paths.first().is_some_and(|s| s.is_empty()) { if paths.len() == 1 { return String::new(); } @@ -162,10 +162,10 @@ impl SolverProblemsException { for reason_set in reason_sets.values() { for rule in reason_set { let required = rule.borrow().get_required_package(); - if let Some(req) = required { - if req.starts_with("ext-") { - missing_extensions.insert(req.to_string(), 1); - } + if let Some(req) = required + && req.starts_with("ext-") + { + missing_extensions.insert(req.to_string(), 1); } } } diff --git a/crates/shirabe/src/dependency_resolver/transaction.rs b/crates/shirabe/src/dependency_resolver/transaction.rs index d20659c..9e0a709 100644 --- a/crates/shirabe/src/dependency_resolver/transaction.rs +++ b/crates/shirabe/src/dependency_resolver/transaction.rs @@ -92,7 +92,7 @@ impl Transaction { for name in package.get_names(true) { self.result_packages_by_name .entry(name) - .or_insert_with(Vec::new) + .or_default() .push(package.clone()); } self.result_package_map @@ -266,7 +266,7 @@ impl Transaction { return vec![]; }; - packages.iter().cloned().collect() + packages.to_vec() } /// Workaround: if your packages depend on plugins, we must be sure @@ -315,8 +315,8 @@ impl Transaction { // is this a downloads modifying plugin or a dependency of one? if is_downloads_modifying_plugin - || array_intersect(&package.get_names(true), &dl_modifying_plugin_requires).len() - > 0 + || !array_intersect(&package.get_names(true), &dl_modifying_plugin_requires) + .is_empty() { // get the package's requires, but filter out any platform requirements let requires: Vec<String> = array_filter( @@ -344,7 +344,8 @@ impl Transaction { || package.get_type() == "composer-installer"; // is this a plugin or a dependency of a plugin? - if is_plugin || array_intersect(&package.get_names(true), &plugin_requires).len() > 0 { + if is_plugin || !array_intersect(&package.get_names(true), &plugin_requires).is_empty() + { // get the package's requires, but filter out any platform requirements let requires: Vec<String> = array_filter( &array_keys(&package.get_requires()), diff --git a/crates/shirabe/src/downloader/file_downloader.rs b/crates/shirabe/src/downloader/file_downloader.rs index e5112cc..3c4f7e2 100644 --- a/crates/shirabe/src/downloader/file_downloader.rs +++ b/crates/shirabe/src/downloader/file_downloader.rs @@ -201,7 +201,7 @@ impl DownloaderInterface for FileDownloader { cache_key, }); } - debug_assert!(urls.len() > 0); + debug_assert!(!urls.is_empty()); let file_name = self.get_file_name(package.clone(), path); self.filesystem.borrow_mut().ensure_directory_exists(path)?; @@ -253,13 +253,13 @@ impl DownloaderInterface for FileDownloader { // mark the file as having been written in cache even though it is only read from cache, so that if // the cache is corrupt the archive will be deleted and the next attempt will re-download it // see https://github.com/composer/composer/issues/10028 - if let Some(cache) = self.cache.as_ref() { - if !cache.borrow().is_read_only() { - self.last_cache_writes - .lock() - .unwrap() - .insert(package.get_name().to_string(), cache_key.clone()); - } + if let Some(cache) = self.cache.as_ref() + && !cache.borrow().is_read_only() + { + self.last_cache_writes + .lock() + .unwrap() + .insert(package.get_name().to_string(), cache_key.clone()); } } else { if output { @@ -304,14 +304,14 @@ impl DownloaderInterface for FileDownloader { ); } - if let Some(cache) = self.cache.as_ref() { - if !cache.borrow().is_read_only() { - self.last_cache_writes - .lock() - .unwrap() - .insert(package.get_name().to_string(), cache_key.clone()); - cache.borrow_mut().copy_from(&cache_key, &file_name); - } + if let Some(cache) = self.cache.as_ref() + && !cache.borrow().is_read_only() + { + self.last_cache_writes + .lock() + .unwrap() + .insert(package.get_name().to_string(), cache_key.clone()); + cache.borrow_mut().copy_from(&cache_key, &file_name); } response.collect(); @@ -366,7 +366,7 @@ impl DownloaderInterface for FileDownloader { if !urls.is_empty() { urls.remove(0); } - if urls.len() > 0 { + if !urls.is_empty() { let code = e .downcast_ref::<TransportException>() .map_or(0, |te| te.get_code()); @@ -414,19 +414,18 @@ impl DownloaderInterface for FileDownloader { .into()); } - if let Some(checksum) = checksum.as_deref() { - if !checksum.is_empty() - && hash_file("sha1", &file_name).as_deref() != Some(checksum) - { - return Err(UnexpectedValueException { - message: format!( - "The checksum verification of the file failed (downloaded from {})", - url.base - ), - code: 0, - } - .into()); + if let Some(checksum) = checksum.as_deref() + && !checksum.is_empty() + && hash_file("sha1", &file_name).as_deref() != Some(checksum) + { + return Err(UnexpectedValueException { + message: format!( + "The checksum verification of the file failed (downloaded from {})", + url.base + ), + code: 0, } + .into()); } // TODO(plugin): dispatch PostFileDownloadEvent. @@ -526,7 +525,7 @@ impl DownloaderInterface for FileDownloader { // clean up the target directory, unless it contains the vendor dir, as the vendor dir contains // the file to be installed. This is the case when installing with create-project in the current directory // but in that case we ensure the directory is empty already in ProjectInstaller so no need to empty it here. - if false == { + if !{ let normalized_vendor = self.filesystem.borrow_mut().normalize_path(&vendor_dir); let normalized_path = self .filesystem @@ -620,7 +619,7 @@ impl ChangeReportInterface for FileDownloader { ); self.io .borrow_mut() - .load_configuration(&mut *self.config.borrow_mut())?; + .load_configuration(&mut self.config.borrow_mut())?; let target_dir = Filesystem::trim_trailing_slash(path); // PHP attaches an onRejected handler to capture the error and drives the promise via @@ -721,7 +720,7 @@ impl FileDownloader { pub(crate) fn add_cleanup_path(&mut self, package: PackageInterfaceHandle, path: &str) { self.additional_cleanup_paths .entry(package.get_name()) - .or_insert_with(Vec::new) + .or_default() .push(path.to_string()); } @@ -786,7 +785,7 @@ impl FileDownloader { let mut url = url.to_string(); if package.get_dist_reference().is_some() { url = UrlUtil::update_dist_reference( - &*self.config.borrow(), + &self.config.borrow(), url, &package.get_dist_reference().unwrap(), ); diff --git a/crates/shirabe/src/downloader/fossil_downloader.rs b/crates/shirabe/src/downloader/fossil_downloader.rs index 2c4e7de..ab98168 100644 --- a/crates/shirabe/src/downloader/fossil_downloader.rs +++ b/crates/shirabe/src/downloader/fossil_downloader.rs @@ -276,7 +276,11 @@ impl ChangeReportInterface for FossilDownloader { let output = output.trim().to_string(); - Ok(if output.len() > 0 { Some(output) } else { None }) + Ok(if !output.is_empty() { + Some(output) + } else { + None + }) } } diff --git a/crates/shirabe/src/downloader/git_downloader.rs b/crates/shirabe/src/downloader/git_downloader.rs index c38e491..0a6e242 100644 --- a/crates/shirabe/src/downloader/git_downloader.rs +++ b/crates/shirabe/src/downloader/git_downloader.rs @@ -208,7 +208,7 @@ impl GitDownloader { if unpushed_changes.is_some() && i == 0 { let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &vec!["git".to_string(), "fetch".to_string(), "--all".to_string()], + &["git".to_string(), "fetch".to_string(), "--all".to_string()], &mut output, Some(path.clone()), ); @@ -278,7 +278,7 @@ impl GitDownloader { // If the non-existent branch is actually the name of a file, the file // is checked out. - let mut branch = Preg::replace(r"{(?:^dev-|(?:\.x)?-dev$)}i", "", &pretty_version); + let mut branch = Preg::replace(r"{(?:^dev-|(?:\.x)?-dev$)}i", "", pretty_version); // Closure equivalent: $execute = function(array $command) use (&$output, $path) { ... }; // Inlined below at each call site. @@ -287,7 +287,7 @@ impl GitDownloader { { let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &vec!["git".to_string(), "branch".to_string(), "-r".to_string()], + &["git".to_string(), "branch".to_string(), "-r".to_string()], &mut output, Some(path.to_string()), ) == 0 @@ -483,7 +483,7 @@ impl GitDownloader { pub(crate) fn update_origin_url(&mut self, path: &str, url: &str) { let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &vec![ + &[ "git".to_string(), "remote".to_string(), "set-url".to_string(), @@ -503,7 +503,7 @@ impl GitDownloader { if Preg::is_match3( &format!( "{{^(?:https?|git)://{}/([^/]+)/([^/]+?)(?:\\.git)?$}}", - GitUtil::get_github_domains_regex(&*self.inner.config.borrow()) + GitUtil::get_github_domains_regex(&self.inner.config.borrow()) ), url, Some(&mut match_), @@ -549,7 +549,7 @@ impl GitDownloader { let path = self.normalize_path(path); let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &vec!["git".to_string(), "clean".to_string(), "-df".to_string()], + &["git".to_string(), "clean".to_string(), "-df".to_string()], &mut output, Some(path.clone()), ) != 0 @@ -562,7 +562,7 @@ impl GitDownloader { } let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &vec!["git".to_string(), "reset".to_string(), "--hard".to_string()], + &["git".to_string(), "reset".to_string(), "--hard".to_string()], &mut output, Some(path.clone()), ) != 0 @@ -585,7 +585,7 @@ impl GitDownloader { let path = self.normalize_path(path); let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &vec![ + &[ "git".to_string(), "stash".to_string(), "--include-untracked".to_string(), @@ -611,7 +611,7 @@ impl GitDownloader { let path = self.normalize_path(path); let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &vec!["git".to_string(), "diff".to_string(), "HEAD".to_string()], + &["git".to_string(), "diff".to_string(), "HEAD".to_string()], &mut output, Some(path.clone()), ) != 0 @@ -829,7 +829,7 @@ impl VcsDownloader for GitDownloader { { self.cached_packages .entry(package.get_id()) - .or_insert_with(IndexMap::new) + .or_default() .insert(r#ref.as_deref().unwrap_or("").to_string(), true); } } else if git_version.is_none() { @@ -880,12 +880,11 @@ impl VcsDownloader for GitDownloader { cache_path.clone(), ]; let transport_options = package.get_transport_options(); - if let Some(git_opts) = transport_options.get("git").and_then(|v| v.as_array()) { - if let Some(single) = git_opts.get("single_use_clone").and_then(|v| v.as_bool()) { - if single { - clone_flags = vec![]; - } - } + if let Some(git_opts) = transport_options.get("git").and_then(|v| v.as_array()) + && let Some(single) = git_opts.get("single_use_clone").and_then(|v| v.as_bool()) + && single + { + clone_flags = vec![]; } commands = vec![ @@ -1057,7 +1056,7 @@ impl VcsDownloader for GitDownloader { let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &vec![ + &[ "git".to_string(), "rev-parse".to_string(), "--quiet".to_string(), @@ -1118,7 +1117,7 @@ impl VcsDownloader for GitDownloader { let mut update_origin_url = false; let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &vec!["git".to_string(), "remote".to_string(), "-v".to_string()], + &["git".to_string(), "remote".to_string(), "-v".to_string()], &mut output, Some(path.clone()), ) == 0 @@ -1166,25 +1165,24 @@ impl VcsDownloader for GitDownloader { let path = self.normalize_path(path); let unpushed = self.get_unpushed_changes(package.clone(), &path)?; - if let Some(unpushed) = unpushed.as_deref() { - if self.inner.io.is_interactive() + if let Some(unpushed) = unpushed.as_deref() + && (self.inner.io.is_interactive() || self .inner .config .borrow_mut() .get("discard-changes") .as_bool() - != Some(true) - { - return Err(RuntimeException { - message: format!( - "Source directory {} has unpushed changes on the current branch: \n{}", - path, unpushed - ), - code: 0, - } - .into()); + != Some(true)) + { + return Err(RuntimeException { + message: format!( + "Source directory {} has unpushed changes on the current branch: \n{}", + path, unpushed + ), + code: 0, } + .into()); } let changes = match self.get_local_changes(package.clone(), &path)? { @@ -1337,7 +1335,7 @@ impl VcsDownloader for GitDownloader { ); let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &vec!["git".to_string(), "stash".to_string(), "pop".to_string()], + &["git".to_string(), "stash".to_string(), "pop".to_string()], &mut output, Some(path.clone()), ) != 0 diff --git a/crates/shirabe/src/downloader/hg_downloader.rs b/crates/shirabe/src/downloader/hg_downloader.rs index a9a5bf8..59a4473 100644 --- a/crates/shirabe/src/downloader/hg_downloader.rs +++ b/crates/shirabe/src/downloader/hg_downloader.rs @@ -85,7 +85,7 @@ impl VcsDownloader for HgDownloader { ) -> Result<Option<PhpMixed>> { let hg_utils = HgUtils::new( self.inner.io.clone(), - &*self.inner.config.borrow(), + &self.inner.config.borrow(), &self.inner.process, ); @@ -140,7 +140,7 @@ impl VcsDownloader for HgDownloader { ) -> Result<Option<PhpMixed>> { let hg_utils = HgUtils::new( self.inner.io.clone(), - &*self.inner.config.borrow(), + &self.inner.config.borrow(), &self.inner.process, ); diff --git a/crates/shirabe/src/downloader/path_downloader.rs b/crates/shirabe/src/downloader/path_downloader.rs index 6d0e098..35c3709 100644 --- a/crates/shirabe/src/downloader/path_downloader.rs +++ b/crates/shirabe/src/downloader/path_downloader.rs @@ -135,7 +135,7 @@ impl PathDownloader { let mut allowed_strategies = vec![Self::STRATEGY_SYMLINK, Self::STRATEGY_MIRROR]; let mirror_path_repos = Platform::get_env("COMPOSER_MIRROR_PATH_REPOS"); - if mirror_path_repos.map_or(false, |v| !v.is_empty()) { + if mirror_path_repos.is_some_and(|v| !v.is_empty()) { current_strategy = Self::STRATEGY_MIRROR; } diff --git a/crates/shirabe/src/downloader/perforce_downloader.rs b/crates/shirabe/src/downloader/perforce_downloader.rs index 2d91c60..687b7ef 100644 --- a/crates/shirabe/src/downloader/perforce_downloader.rs +++ b/crates/shirabe/src/downloader/perforce_downloader.rs @@ -56,11 +56,10 @@ impl PerforceDownloader { let repository = package.get_repository(); let repo_config: Option<IndexMap<String, PhpMixed>> = if let Some(repo) = repository { let repo_ref = repo.borrow(); - if let Some(vcs_repo) = repo_ref.as_any().downcast_ref::<VcsRepository>() { - Some(self.get_repo_config(vcs_repo)) - } else { - None - } + repo_ref + .as_any() + .downcast_ref::<VcsRepository>() + .map(|vcs_repo| self.get_repo_config(vcs_repo)) } else { None }; diff --git a/crates/shirabe/src/downloader/svn_downloader.rs b/crates/shirabe/src/downloader/svn_downloader.rs index 03fd292..6aed27a 100644 --- a/crates/shirabe/src/downloader/svn_downloader.rs +++ b/crates/shirabe/src/downloader/svn_downloader.rs @@ -67,7 +67,7 @@ impl SvnDownloader { pub(crate) async fn discard_changes(&self, path: &str) -> anyhow::Result<Option<PhpMixed>> { let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &["svn", "revert", "-R", "."].map(|s| s.to_string()).to_vec(), + ["svn", "revert", "-R", "."].map(|s| s.to_string()).as_ref(), &mut output, Some(path.to_string()), ) != 0 @@ -169,13 +169,12 @@ impl VcsDownloader for SvnDownloader { let repo_ref = repo.borrow(); if let Some(vcs_repo) = repo_ref.as_any().downcast_ref::<VcsRepository>() { let repo_config = vcs_repo.get_repo_config(); - if repo_config.contains_key("svn-cache-credentials") { - if let Some(val) = repo_config + if repo_config.contains_key("svn-cache-credentials") + && let Some(val) = repo_config .get("svn-cache-credentials") .and_then(|v| v.as_bool()) - { - self.cache_credentials = val; - } + { + self.cache_credentials = val; } } } @@ -412,8 +411,8 @@ impl VcsDownloader for SvnDownloader { }; // strip paths from references and only keep the actual revision - let from_revision = Preg::replace(r"{.*@(\d+)$}", "$1", &from_reference); - let to_revision = Preg::replace(r"{.*@(\d+)$}", "$1", &to_reference); + let from_revision = Preg::replace(r"{.*@(\d+)$}", "$1", from_reference); + let to_revision = Preg::replace(r"{.*@(\d+)$}", "$1", to_reference); let command = vec![ "svn".to_string(), @@ -463,9 +462,9 @@ impl ChangeReportInterface for SvnDownloader { let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &["svn", "status", "--ignore-externals"] + ["svn", "status", "--ignore-externals"] .map(|s| s.to_string()) - .to_vec(), + .as_ref(), &mut output, Some(path.to_string()), ); diff --git a/crates/shirabe/src/downloader/vcs_downloader.rs b/crates/shirabe/src/downloader/vcs_downloader.rs index 18a50da..993d18a 100644 --- a/crates/shirabe/src/downloader/vcs_downloader.rs +++ b/crates/shirabe/src/downloader/vcs_downloader.rs @@ -165,14 +165,14 @@ pub trait VcsDownloader: true, io_interface::NORMAL, ); - } else if urls.len() > 0 { + } else if !urls.is_empty() { self.io().write_error3( " Failed, trying the next URL", true, io_interface::NORMAL, ); } - if urls.len() == 0 { + if urls.is_empty() { return Err(e); } } @@ -269,14 +269,14 @@ pub trait VcsDownloader: true, io_interface::NORMAL, ); - } else if urls.len() > 0 { + } else if !urls.is_empty() { self.io().write_error3( " Failed, trying the next URL", true, io_interface::NORMAL, ); } - if urls.len() == 0 { + if urls.is_empty() { return Err(e); } } @@ -338,7 +338,7 @@ pub trait VcsDownloader: true, io_interface::NORMAL, ); - } else if urls.len() > 0 { + } else if !urls.is_empty() { self.io().write_error3( " Failed, trying the next URL", true, @@ -358,12 +358,12 @@ pub trait VcsDownloader: let mut message = "Pulling in changes:"; let mut logs = self.get_commit_logs(&initial_ref, &target_ref, path)?; - if trim(&logs, None) == "" { + if trim(&logs, None).is_empty() { message = "Rolling back changes:"; logs = self.get_commit_logs(&target_ref, &initial_ref, path)?; } - if trim(&logs, None) != "" { + if !trim(&logs, None).is_empty() { let prefixed: Vec<String> = array_map( |line: &String| format!(" {}", line), &explode("\n", &logs), @@ -379,10 +379,10 @@ pub trait VcsDownloader: } } - if urls.is_empty() { - if let Some(e) = exception { - return Err(e); - } + if urls.is_empty() + && let Some(e) = exception + { + return Err(e); } Ok(None) diff --git a/crates/shirabe/src/downloader/xz_downloader.rs b/crates/shirabe/src/downloader/xz_downloader.rs index 1c03f1d..f7611fd 100644 --- a/crates/shirabe/src/downloader/xz_downloader.rs +++ b/crates/shirabe/src/downloader/xz_downloader.rs @@ -69,7 +69,7 @@ impl ArchiveDownloader for XzDownloader { file: &str, path: &str, ) -> Result<Option<PhpMixed>> { - let command = vec!["tar", "-xJf", file, "-C", path]; + let command = ["tar", "-xJf", file, "-C", path]; let mut ignored_output = PhpMixed::Null; if self.inner.process.borrow_mut().execute( diff --git a/crates/shirabe/src/downloader/zip_downloader.rs b/crates/shirabe/src/downloader/zip_downloader.rs index 2eb7b94..04e71b4 100644 --- a/crates/shirabe/src/downloader/zip_downloader.rs +++ b/crates/shirabe/src/downloader/zip_downloader.rs @@ -75,7 +75,7 @@ impl ZipDownloader { .lock() .unwrap() .as_ref() - .map_or(true, |v| v.is_empty()); + .is_none_or(|v| v.is_empty()); if unzip_commands_empty { return self.extract_with_zip_archive(package, file, path).await; } @@ -283,13 +283,10 @@ impl ZipDownloader { file: &str, path: &str, ) -> Result<Option<PhpMixed>> { - let mut zip_archive = self - .zip_archive_object - .take() - .unwrap_or_else(ZipArchive::new); + let mut zip_archive = self.zip_archive_object.take().unwrap_or_default(); let result: Result<Option<PhpMixed>> = (|| { - let retval = if !file_exists(file) || filesize(file).map_or(true, |s| s == 0) { + let retval = if !file_exists(file) || filesize(file).is_none_or(|s| s == 0) { Err(-1i64) } else { zip_archive.open(file, 0) @@ -323,16 +320,17 @@ impl ZipDownloader { } i += 1; } - if let Some(archive_sz) = archive_size { - if total_size > archive_sz * 100 && total_size > 50 * 1024 * 1024 { - return Err(RuntimeException { + if let Some(archive_sz) = archive_size + && total_size > archive_sz * 100 + && total_size > 50 * 1024 * 1024 + { + return Err(RuntimeException { message: format!( "Invalid zip file for \"{}\" with compression ratio >99% (possible zip bomb)", package.get_name(), ), code: 0, }.into()); - } } } @@ -343,20 +341,20 @@ impl ZipDownloader { return Ok(None); } - return Err(RuntimeException { + Err(RuntimeException { message: format!( "There was an error extracting the ZIP file for \"{}\", it is either corrupted or using an invalid format.", package.get_name(), ), code: 0, - }.into()); + }.into()) } else { let code = retval.unwrap_err(); - return Err(UnexpectedValueException { + Err(UnexpectedValueException { message: self.get_error_message(code, file).trim_end().to_string(), code, } - .into()); + .into()) } })(); @@ -461,20 +459,19 @@ impl crate::downloader::DownloaderInterface for ZipDownloader { *unzip_commands = Some(vec![]); let finder = ExecutableFinder::new(); let commands = unzip_commands.as_mut().unwrap(); - if Platform::is_windows() { - if let Some(cmd) = + if Platform::is_windows() + && let Some(cmd) = finder.find("7z", None, &[r"C:\Program Files\7-Zip".to_string()]) - { - commands.push(vec![ - "7z".to_string(), - cmd, - "x".to_string(), - "-bb0".to_string(), - "-y".to_string(), - "%file%".to_string(), - "-o%path%".to_string(), - ]); - } + { + commands.push(vec![ + "7z".to_string(), + cmd, + "x".to_string(), + "-bb0".to_string(), + "-y".to_string(), + "%file%".to_string(), + "-o%path%".to_string(), + ]); } if let Some(cmd) = finder.find("unzip", None, &[]) { commands.push(vec![ @@ -542,7 +539,7 @@ impl crate::downloader::DownloaderInterface for ZipDownloader { .lock() .unwrap() .as_ref() - .map_or(true, |v| v.is_empty()); + .is_none_or(|v| v.is_empty()); if !has_zip_archive && unzip_commands_empty { let ini_message = IniHelper::get_message(); diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs index 3c23967..fb3a17c 100644 --- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs +++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs @@ -84,12 +84,11 @@ impl EventDispatcher { )))) }); let event_stack: Vec<String> = Vec::new(); - let skip_scripts_env = - Platform::get_env("COMPOSER_SKIP_SCRIPTS").unwrap_or_else(|| "".to_string()); + let skip_scripts_env = Platform::get_env("COMPOSER_SKIP_SCRIPTS").unwrap_or_default(); let skip_scripts: Vec<String> = skip_scripts_env .split(',') .map(|v| trim(v, Some(" \t\n\r\0\u{0B}"))) - .filter(|val| val != "") + .filter(|val| !val.is_empty()) .collect(); Self { composer, @@ -252,15 +251,14 @@ impl EventDispatcher { } for cb in spl_autoload_functions() { // once we get to the first known autoloader, we can leave any appended autoloader without problems - if let Some(entry) = known_identifiers.get(&Self::get_callback_identifier(&cb)) { - if entry + if let Some(entry) = known_identifiers.get(&Self::get_callback_identifier(&cb)) + && entry .get("key") .and_then(|v| v.as_int()) .map(|k| k == 0) .unwrap_or(false) - { - break; - } + { + break; } // other newly appeared prepended autoloaders should be appended instead to ensure Composer loads its classes first @@ -289,12 +287,12 @@ impl EventDispatcher { let mut additional_args = event.get_arguments().clone(); let mut callable = callable; - if let Callable::String(ref s) = callable { - if str_contains(s, "@no_additional_args") { - let replaced = Preg::replace("{ ?@no_additional_args}", "", s); - callable = Callable::String(replaced); - additional_args = Vec::new(); - } + if let Callable::String(ref s) = callable + && str_contains(s, "@no_additional_args") + { + let replaced = Preg::replace("{ ?@no_additional_args}", "", s); + callable = Callable::String(replaced); + additional_args = Vec::new(); } let formatted_event_name_with_args = format!( "{}{}", @@ -514,12 +512,9 @@ impl EventDispatcher { Err(e) => { self.io.write_error3( &format!( - "<error>{}</error>", - format!( - "Script {} handling the {} event terminated with an exception", - PhpMixed::String(callable_str.clone()), - PhpMixed::String(event.get_name().to_string()), - ) + "<error>Script {} handling the {} event terminated with an exception</error>", + PhpMixed::String(callable_str.clone()), + PhpMixed::String(event.get_name().to_string()), ), true, crate::io::QUIET, @@ -608,7 +603,7 @@ impl EventDispatcher { format!( "{}{}", callable_str, - if args == "" { + if args.is_empty() { "".to_string() } else { format!(" {}", args) @@ -810,7 +805,7 @@ impl EventDispatcher { } }; let php_args = finder.find_arguments(); - let php_args = if php_args.len() > 0 { + let php_args = if !php_args.is_empty() { format!(" {}", implode(" ", &php_args)) } else { "".to_string() @@ -894,9 +889,9 @@ impl EventDispatcher { pub fn add_listener(&mut self, event_name: &str, listener: Callable, priority: i64) { self.listeners .entry(event_name.to_string()) - .or_insert_with(IndexMap::new) + .or_default() .entry(priority) - .or_insert_with(Vec::new) + .or_default() .push(listener); } @@ -949,7 +944,7 @@ impl EventDispatcher { { self.listeners .entry(name.clone()) - .or_insert_with(IndexMap::new) + .or_default() .insert(0, Vec::new()); } if let Some(priorities) = self.listeners.get_mut(&name) { @@ -957,10 +952,10 @@ impl EventDispatcher { } let mut listeners = self.listeners.clone(); - if let Some(priorities) = listeners.get_mut(&name) { - if let Some(zero_list) = priorities.get_mut(&0) { - zero_list.extend(script_listeners); - } + if let Some(priorities) = listeners.get_mut(&name) + && let Some(zero_list) = priorities.get_mut(&0) + { + zero_list.extend(script_listeners); } let mut result: Vec<Callable> = Vec::new(); @@ -976,7 +971,7 @@ impl EventDispatcher { pub fn has_event_listeners(&mut self, event: &dyn EventInterface) -> bool { let listeners = self.get_listeners(event); - listeners.len() > 0 + !listeners.is_empty() } /// Finds all listeners defined as scripts in the package @@ -1096,28 +1091,28 @@ impl EventDispatcher { if is_object(cb) { return format!("obj:{}", spl_object_hash(cb)); } - if is_array(cb) { - if let PhpMixed::Array(map) = cb { - let entries: Vec<&Box<PhpMixed>> = map.values().collect(); - if entries.len() >= 2 { - let first = entries[0].as_ref(); - let second = entries[1].as_ref(); - let prefix = if is_string(first) { - if let PhpMixed::String(s) = first { - s.clone() - } else { - "?".to_string() - } - } else { - format!("{}#{}", get_class(first), spl_object_hash(first)) - }; - let suffix = if let PhpMixed::String(s) = second { + if is_array(cb) + && let PhpMixed::Array(map) = cb + { + let entries: Vec<&Box<PhpMixed>> = map.values().collect(); + if entries.len() >= 2 { + let first = entries[0].as_ref(); + let second = entries[1].as_ref(); + let prefix = if is_string(first) { + if let PhpMixed::String(s) = first { s.clone() } else { "?".to_string() - }; - return format!("array:{}::{}", prefix, suffix); - } + } + } else { + format!("{}#{}", get_class(first), spl_object_hash(first)) + }; + let suffix = if let PhpMixed::String(s) = second { + s.clone() + } else { + "?".to_string() + }; + return format!("array:{}::{}", prefix, suffix); } } diff --git a/crates/shirabe/src/event_dispatcher/mod.rs b/crates/shirabe/src/event_dispatcher/mod.rs index 5278691..a50fa4d 100644 --- a/crates/shirabe/src/event_dispatcher/mod.rs +++ b/crates/shirabe/src/event_dispatcher/mod.rs @@ -1,4 +1,5 @@ pub mod event; +#[allow(clippy::module_inception, reason = "to port PHP's structure as it is")] pub mod event_dispatcher; pub mod event_subscriber_interface; pub mod script_execution_exception; diff --git a/crates/shirabe/src/factory.rs b/crates/shirabe/src/factory.rs index 78aa7ea..73407bc 100644 --- a/crates/shirabe/src/factory.rs +++ b/crates/shirabe/src/factory.rs @@ -98,10 +98,10 @@ pub struct Factory; impl Factory { fn get_home_dir() -> anyhow::Result<String> { let home = Platform::get_env("COMPOSER_HOME"); - if let Some(h) = home { - if !h.is_empty() { - return Ok(h); - } + if let Some(h) = home + && !h.is_empty() + { + return Ok(h); } if Platform::is_windows() { @@ -369,7 +369,7 @@ impl Factory { let env = Platform::get_env("COMPOSER"); if let Some(env_str) = env { let env_trimmed = trim(&env_str, Some(" \t\n\r\0\u{0B}")); - if env_trimmed != "" { + if !env_trimmed.is_empty() { if is_dir(&env_trimmed) { return Err(anyhow::anyhow!(RuntimeException { message: format!( @@ -448,10 +448,11 @@ impl Factory { // if a custom composer.json path is given, we change the default cwd to be that file's directory let mut local_config = local_config; let mut cwd = cwd.map(|s| s.to_string()); - if let Some(LocalConfigInput::Path(ref s)) = local_config { - if is_file(s) && cwd.is_none() { - cwd = Some(dirname(s)); - } + if let Some(LocalConfigInput::Path(ref s)) = local_config + && is_file(s) + && cwd.is_none() + { + cwd = Some(dirname(s)); } let cwd = match cwd { @@ -489,21 +490,21 @@ impl Factory { })); } - if !Platform::is_input_completion_process() { - if let Err(e) = file.validate_schema(JsonFile::LAX_SCHEMA, None) { - if let Some(jve) = e.downcast_ref::<JsonValidationException>() { - let errors = format!( - " - {}", - implode(&format!("{} - ", PHP_EOL), jve.get_errors()) - ); - let message = format!("{}:{}{}", jve.get_message(), PHP_EOL, errors); - return Err(anyhow::anyhow!(JsonValidationException::new( - message, - jve.get_errors().clone(), - ))); - } - return Err(e); + if !Platform::is_input_completion_process() + && let Err(e) = file.validate_schema(JsonFile::LAX_SCHEMA, None) + { + if let Some(jve) = e.downcast_ref::<JsonValidationException>() { + let errors = format!( + " - {}", + implode(&format!("{} - ", PHP_EOL), jve.get_errors()) + ); + let message = format!("{}:{}{}", jve.get_message(), PHP_EOL, errors); + return Err(anyhow::anyhow!(JsonValidationException::new( + message, + jve.get_errors().clone(), + ))); } + return Err(e); } local_config_data = file @@ -604,7 +605,7 @@ impl Factory { if full_load { // load auth configs into the IO instance io.borrow_mut() - .load_configuration(&mut *config.borrow_mut())?; + .load_configuration(&mut config.borrow_mut())?; // load existing Composer\InstalledVersions instance if available and scripts/plugins are allowed, as they might need it // we only load if the InstalledVersions class wasn't defined yet so that this is only loaded once @@ -734,7 +735,7 @@ impl Factory { )); // initialize archive manager - let am = self.create_archive_manager(&*config.borrow(), &dm, &r#loop)?; + let am = self.create_archive_manager(&config.borrow(), &dm, &r#loop)?; composer_full .set_archive_manager(std::rc::Rc::new(std::cell::RefCell::new(am))); } @@ -826,7 +827,7 @@ impl Factory { let global_composer = if !is_global { self.create_global_composer( io.clone(), - &*config.borrow(), + &config.borrow(), disable_plugins, disable_scripts, false, @@ -1004,7 +1005,7 @@ impl Factory { Some("source") => { dm.set_prefer_source(true); } - Some("auto") | _ => { + _ => { // noop } } @@ -1404,24 +1405,24 @@ impl Factory { let http_downloader = match http_downloader_result { Ok(h) => h, Err(e) => { - if let Some(te) = e.downcast_ref::<TransportException>() { - if strpos(&te.get_message(), "cafile").is_some() { - io.write3( + if let Some(te) = e.downcast_ref::<TransportException>() + && strpos(te.get_message(), "cafile").is_some() + { + io.write3( "<error>Unable to locate a valid CA certificate file. You must set a valid 'cafile' option.</error>", true, crate::io::NORMAL, ); - io.write3( + io.write3( "<error>A valid CA certificate file is required for SSL/TLS protection.</error>", true, crate::io::NORMAL, ); - io.write3( + io.write3( "<error>You can disable this error, at your own risk, by setting the 'disable-tls' option to true.</error>", true, crate::io::NORMAL, ); - } } return Err(e); } diff --git a/crates/shirabe/src/filter/platform_requirement_filter/ignore_list_platform_requirement_filter.rs b/crates/shirabe/src/filter/platform_requirement_filter/ignore_list_platform_requirement_filter.rs index efa8634..4255af7 100644 --- a/crates/shirabe/src/filter/platform_requirement_filter/ignore_list_platform_requirement_filter.rs +++ b/crates/shirabe/src/filter/platform_requirement_filter/ignore_list_platform_requirement_filter.rs @@ -58,23 +58,23 @@ impl IgnoreListPlatformRequirementFilter { let intervals = Intervals::get(&constraint)?; let last = intervals.numeric.last(); - if let Some(last) = last { - if last.get_end().to_string() != Interval::until_positive_infinity().to_string() { - let constraint = MultiConstraint::new( - vec![ - constraint, - AnyConstraint::Simple(SimpleConstraint::new( - ">=".to_string(), - last.get_end().get_version().to_string(), - None, - )), - ], - false, - None, - ) - .into(); - return Ok(constraint); - } + if let Some(last) = last + && last.get_end().to_string() != Interval::until_positive_infinity().to_string() + { + let constraint = MultiConstraint::new( + vec![ + constraint, + AnyConstraint::Simple(SimpleConstraint::new( + ">=".to_string(), + last.get_end().get_version().to_string(), + None, + )), + ], + false, + None, + ) + .into(); + return Ok(constraint); } Ok(constraint) diff --git a/crates/shirabe/src/installed_versions.rs b/crates/shirabe/src/installed_versions.rs index fb6e8bf..fb1f73f 100644 --- a/crates/shirabe/src/installed_versions.rs +++ b/crates/shirabe/src/installed_versions.rs @@ -111,12 +111,11 @@ impl InstalledVersions { .cloned() .unwrap_or_default(); for (name, package) in versions { - if let Some(pkg) = package.as_array() { - if let Some(pkg_type) = pkg.get("type").and_then(|v| v.as_string()) { - if pkg_type == r#type { - packages_by_type.push(name); - } - } + if let Some(pkg) = package.as_array() + && let Some(pkg_type) = pkg.get("type").and_then(|v| v.as_string()) + && pkg_type == r#type + { + packages_by_type.push(name); } } } diff --git a/crates/shirabe/src/installer.rs b/crates/shirabe/src/installer.rs index 86c9714..3e64dd9 100644 --- a/crates/shirabe/src/installer.rs +++ b/crates/shirabe/src/installer.rs @@ -163,6 +163,7 @@ impl Installer { // technically exceptions are thrown with various status codes >400, but the process exit code is normalized to 100 pub const ERROR_TRANSPORT_EXCEPTION: i64 = 100; + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn new( io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>, config: std::rc::Rc<std::cell::RefCell<Config>>, @@ -416,12 +417,12 @@ impl Installer { let local_repo_handle = self.repository_manager.borrow().get_local_repository(); let mut local_repo_ref = local_repo_handle.borrow_mut(); self.autoload_generator.borrow_mut().dump( - &*self.config.borrow(), + &self.config.borrow(), local_repo_ref .as_installed_repository_interface_mut() .unwrap(), self.package.clone(), - &mut *self.installation_manager.borrow_mut(), + &mut self.installation_manager.borrow_mut(), "composer", self.optimize_autoloader, None, @@ -455,10 +456,11 @@ impl Installer { let repository_manager = self.repository_manager.clone(); let repository_manager = repository_manager.borrow(); for package in repository_manager.get_local_repository().get_packages()? { - if let Some(cp) = package.as_complete() { - if package.as_alias().is_none() && !cp.get_funding().is_empty() { - funding_count += 1; - } + if let Some(cp) = package.as_complete() + && package.as_alias().is_none() + && !cp.get_funding().is_empty() + { + funding_count += 1; } } if funding_count > 0 { @@ -510,7 +512,7 @@ impl Installer { "installed", ) }; - if packages.len() > 0 { + if !packages.is_empty() { let auditor = Auditor; let mut repo_set = RepositorySet::new( "stable", @@ -930,7 +932,7 @@ impl Installer { &mut self, lock_transaction: &mut LockTransaction, platform_repo: &PlatformRepositoryHandle, - aliases: &Vec<IndexMap<String, String>>, + aliases: &[IndexMap<String, String>], policy: std::rc::Rc<dyn PolicyInterface>, locked_repository: Option<&crate::repository::LockArrayRepositoryHandle>, ) -> anyhow::Result<i64> { @@ -1029,7 +1031,7 @@ impl Installer { let mut repository_set = self.create_repository_set( false, &platform_repo, - &vec![], + &[], Some(&mut *locked_repo_borrow), )?; drop(locked_repo_borrow); @@ -1117,7 +1119,7 @@ impl Installer { solver = None; // installing the locked packages on this platform resulted in lock modifying operations, there wasn't a conflict, but the lock file as-is seems to not work on this system - if 0 != lock_transaction.get_operations().len() { + if !lock_transaction.get_operations().is_empty() { self.io.write_error3( "<error>Your lock file cannot be installed on this system without changes. Please run composer update.</error>", true, @@ -1229,7 +1231,7 @@ impl Installer { drop(local_repo_ref); // see https://github.com/composer/composer/issues/2764 - if local_repo_transaction.get_operations().len() > 0 { + if !local_repo_transaction.get_operations().is_empty() { let vendor_dir = self .config .borrow_mut() @@ -1291,7 +1293,7 @@ impl Installer { &mut self, for_update: bool, platform_repo: &PlatformRepositoryHandle, - root_aliases: &Vec<IndexMap<String, String>>, + root_aliases: &[IndexMap<String, String>], locked_repository: Option<&mut dyn RepositoryInterface>, ) -> anyhow::Result<RepositorySet> { let minimum_stability: String; @@ -1377,7 +1379,7 @@ impl Installer { ); let root_aliases_input: Vec<crate::repository::RootAliasInput> = root_aliases - .into_iter() + .iter() .map(|alias| crate::repository::RootAliasInput { package: alias.get("package").cloned().unwrap_or_default(), version: alias.get("version").cloned().unwrap_or_default(), @@ -1498,7 +1500,7 @@ impl Installer { // skip platform packages that are provided by the root package let pkg_repo_is_platform = package .get_repository() - .map_or(false, |r| r.is::<PlatformRepository>()); + .is_some_and(|r| r.is::<PlatformRepository>()); let name = package.get_name(); if !pkg_repo_is_platform || !provided.contains_key(&name) @@ -1658,7 +1660,7 @@ impl Installer { fn get_audit_config(&mut self) -> anyhow::Result<&AuditConfig> { if self.audit_config.is_none() { self.audit_config = Some(AuditConfig::from_config( - &mut *self.config.borrow_mut(), + &mut self.config.borrow_mut(), self.audit, &self.audit_format, )?); @@ -1871,7 +1873,7 @@ impl Installer { /// restrict the update operation to a few packages, all other packages /// that are already installed will be kept at their current version pub fn set_update_allow_list(&mut self, packages: Vec<String>) -> &mut Self { - if packages.len() == 0 { + if packages.is_empty() { self.update_allow_list = None; } else { let lowered: Vec<String> = array_map(|s: &String| strtolower(s), &packages); diff --git a/crates/shirabe/src/installer/binary_installer.rs b/crates/shirabe/src/installer/binary_installer.rs index bc7d694..b9c56f6 100644 --- a/crates/shirabe/src/installer/binary_installer.rs +++ b/crates/shirabe/src/installer/binary_installer.rs @@ -310,7 +310,7 @@ impl BinaryInstaller { .find_shortest_path_code(link, bin, false, true, false); let mut stream_proxy_code = String::new(); let mut stream_hint = String::new(); - let mut globals_code = format!("$GLOBALS['_composer_bin_dir'] = __DIR__;\n",); + let mut globals_code = "$GLOBALS['_composer_bin_dir'] = __DIR__;\n".to_string(); let mut phpunit_hack1 = String::new(); let mut phpunit_hack2 = String::new(); // Don't expose autoload path when vendor dir was not set in custom installers @@ -329,30 +329,29 @@ impl BinaryInstaller { )); } // Add workaround for PHPUnit process isolation - if let Some(vendor_dir) = &self.vendor_dir { - if self.filesystem.borrow().normalize_path(bin) + if let Some(vendor_dir) = &self.vendor_dir + && self.filesystem.borrow().normalize_path(bin) == self .filesystem .borrow() .normalize_path(&format!("{}/phpunit/phpunit/phpunit", vendor_dir)) - { - // workaround issue on PHPUnit 6.5+ running on PHP 8+ - globals_code.push_str(&format!( + { + // workaround issue on PHPUnit 6.5+ running on PHP 8+ + globals_code.push_str(&format!( "$GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'] = $GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST'] = array(realpath({}));\n", bin_path_exported, )); - // workaround issue on all PHPUnit versions running on PHP <8 - phpunit_hack1 = "'phpvfscomposer://'.".to_string(); - phpunit_hack2 = " + // workaround issue on all PHPUnit versions running on PHP <8 + phpunit_hack1 = "'phpvfscomposer://'.".to_string(); + phpunit_hack2 = " $data = str_replace('__DIR__', var_export(dirname($this->realpath), true), $data); $data = str_replace('__FILE__', var_export($this->realpath, true), $data);" - .to_string(); - } + .to_string(); } - if trim(m.get(0).map(|s| s.as_str()).unwrap_or(""), None) != "<?php" { - stream_hint = format!( + if trim(m.first().map(|s| s.as_str()).unwrap_or(""), None) != "<?php" { + stream_hint = " using a stream wrapper to prevent the shebang from being output on PHP<8\n *" - ); + .to_string(); stream_proxy_code = format!( "if (PHP_VERSION_ID < 80000) {{\n if (!class_exists('Composer\\BinProxyWrapper')) {{\n /**\n * @internal\n */\n final class BinProxyWrapper\n {{\n private $handle;\n private $position;\n private $realpath;\n\n public function stream_open($path, $mode, $options, &$opened_path)\n {{\n // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution\n $opened_path = substr($path, 17);\n $this->realpath = realpath($opened_path) ?: $opened_path;\n $opened_path = {phpunit_hack1}$this->realpath;\n $this->handle = fopen($this->realpath, $mode);\n $this->position = 0;\n\n return (bool) $this->handle;\n }}\n\n public function stream_read($count)\n {{\n $data = fread($this->handle, $count);\n\n if ($this->position === 0) {{\n $data = preg_replace('{{^#!.*\\r?\\n}}', '', $data);\n }}{phpunit_hack2}\n\n $this->position += strlen($data);\n\n return $data;\n }}\n\n public function stream_cast($castAs)\n {{\n return $this->handle;\n }}\n\n public function stream_close()\n {{\n fclose($this->handle);\n }}\n\n public function stream_lock($operation)\n {{\n return $operation ? flock($this->handle, $operation) : true;\n }}\n\n public function stream_seek($offset, $whence)\n {{\n if (0 === fseek($this->handle, $offset, $whence)) {{\n $this->position = ftell($this->handle);\n return true;\n }}\n\n return false;\n }}\n\n public function stream_tell()\n {{\n return $this->position;\n }}\n\n public function stream_eof()\n {{\n return feof($this->handle);\n }}\n\n public function stream_stat()\n {{\n return array();\n }}\n\n public function stream_set_option($option, $arg1, $arg2)\n {{\n return true;\n }}\n\n public function url_stat($path, $flags)\n {{\n $path = substr($path, 17);\n if (file_exists($path)) {{\n return stat($path);\n }}\n\n return false;\n }}\n }}\n }}\n\n if (\n (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))\n || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper'))\n ) {{\n return include(\"phpvfscomposer://\" . {bin_path_exported});\n }}\n}}\n", phpunit_hack1 = phpunit_hack1, diff --git a/crates/shirabe/src/installer/installation_manager.rs b/crates/shirabe/src/installer/installation_manager.rs index 90801ec..6f8b65c 100644 --- a/crates/shirabe/src/installer/installation_manager.rs +++ b/crates/shirabe/src/installer/installation_manager.rs @@ -222,23 +222,23 @@ impl InstallationManager { .as_install_operation() .map(|install| install.get_package()) }; - if let Some(package) = package { - if package.get_type() == "composer-plugin" { - let extra = package.get_extra(); - if extra - .get("plugin-modifies-downloads") - .and_then(|v| v.as_bool()) - == Some(true) - { - if (batch.len() as i64) > 0 { - batches.push(std::mem::take(&mut batch)); - } - let mut single = IndexMap::new(); - single.insert(index, operation); - batches.push(single); - - continue; + if let Some(package) = package + && package.get_type() == "composer-plugin" + { + let extra = package.get_extra(); + if extra + .get("plugin-modifies-downloads") + .and_then(|v| v.as_bool()) + == Some(true) + { + if (batch.len() as i64) > 0 { + batches.push(std::mem::take(&mut batch)); } + let mut single = IndexMap::new(); + single.insert(index, operation); + batches.push(single); + + continue; } } batch.insert(index, operation); @@ -290,9 +290,7 @@ impl InstallationManager { Ok(()) } - /// @param OperationInterface[] $operations List of operations to execute in this batch - /// @param OperationInterface[] $allOperations Complete list of operations to be executed in the install job, used for event listeners - /// @phpstan-param array<callable(): ?PromiseInterface<void|null>> $cleanupPromises + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] async fn download_and_execute_batch( &mut self, repo: &mut dyn InstalledRepositoryInterface, @@ -563,9 +561,8 @@ impl InstallationManager { /// @phpstan-return PromiseInterface<void|null>|null pub async fn download(&mut self, package: PackageInterfaceHandle) -> Option<PhpMixed> { let installer = self.get_installer(&package.get_type()).ok()?; - let promise = installer.cleanup("install", package, None).await.ok()?; - promise + installer.cleanup("install", package, None).await.ok()? } /// Executes install operation. @@ -599,7 +596,7 @@ impl InstallationManager { let initial_type = initial.get_type(); let target_type = target.get_type(); - let promise = if initial_type == target_type { + if initial_type == target_type { let installer = self.get_installer(&initial_type).ok()?; let promise = installer.update(repo, initial, target.clone()).await.ok()?; self.mark_for_notification(target.clone()); @@ -614,9 +611,7 @@ impl InstallationManager { .ok()?; let installer = self.get_installer(&target_type).ok()?; installer.install(repo, target).await.ok()? - }; - - promise + } } /// Uninstalls package. @@ -803,7 +798,7 @@ impl InstallationManager { if let Some(notification_url) = package.get_notification_url() { self.notifiable_packages .entry(notification_url) - .or_insert_with(Vec::new) + .or_default() .push(package.clone()); } } diff --git a/crates/shirabe/src/installer/library_installer.rs b/crates/shirabe/src/installer/library_installer.rs index 9fb3e43..d2f222e 100644 --- a/crates/shirabe/src/installer/library_installer.rs +++ b/crates/shirabe/src/installer/library_installer.rs @@ -109,18 +109,18 @@ impl LibraryInstaller { let install_path = self.get_install_path(package.clone()).unwrap(); let target_dir = package.get_target_dir(); - if let Some(target_dir) = target_dir { - if !target_dir.is_empty() { - let replaced = Preg::replace( - &format!( - "{{/*{}/?$}}", - preg_quote(&target_dir, None).replace('/', "/+") - ), - "", - &install_path, - ); - return replaced; - } + if let Some(target_dir) = target_dir + && !target_dir.is_empty() + { + let replaced = Preg::replace( + &format!( + "{{/*{}/?$}}", + preg_quote(&target_dir, None).replace('/', "/+") + ), + "", + &install_path, + ); + return replaced; } install_path @@ -368,7 +368,7 @@ impl InstallerInterface for LibraryInstaller { self.binary_installer.remove_binaries(package.clone()); repo.remove_package(package.clone()); - if strpos(&package.get_name(), "/").map_or(false, |pos| pos != 0) { + if strpos(&package.get_name(), "/").is_some_and(|pos| pos != 0) { let package_vendor_dir = dirname(&download_path); if is_dir(&package_vendor_dir) && self.filesystem.borrow().is_dir_empty(&package_vendor_dir) diff --git a/crates/shirabe/src/installer/suggested_packages_reporter.rs b/crates/shirabe/src/installer/suggested_packages_reporter.rs index 2a2ed9f..979b4bb 100644 --- a/crates/shirabe/src/installer/suggested_packages_reporter.rs +++ b/crates/shirabe/src/installer/suggested_packages_reporter.rs @@ -64,11 +64,11 @@ impl SuggestedPackagesReporter { for suggestion in &suggested_packages { suggesters .entry(suggestion["source"].clone()) - .or_insert_with(IndexMap::new) + .or_default() .insert(suggestion["target"].clone(), suggestion["reason"].clone()); suggested .entry(suggestion["target"].clone()) - .or_insert_with(IndexMap::new) + .or_default() .insert(suggestion["source"].clone(), suggestion["reason"].clone()); } suggesters.sort_keys(); @@ -132,8 +132,7 @@ impl SuggestedPackagesReporter { } if let Some(only_dependents_of) = only_dependents_of { - let all_suggested_packages = - self.get_filtered_suggestions(installed_repo.as_deref_mut(), None)?; + let all_suggested_packages = self.get_filtered_suggestions(installed_repo, None)?; let diff = all_suggested_packages.len() as i64 - suggested_packages.len() as i64; if diff != 0 { self.io.write(&format!("<info>{} additional suggestions</info> by transitive dependencies can be shown with <info>--all</info>", diff)); diff --git a/crates/shirabe/src/io/buffer_io.rs b/crates/shirabe/src/io/buffer_io.rs index 91fdac1..2b07c6b 100644 --- a/crates/shirabe/src/io/buffer_io.rs +++ b/crates/shirabe/src/io/buffer_io.rs @@ -39,7 +39,7 @@ impl BufferIO { .into()); } - let _decorated = formatter.as_ref().map_or(false, |f| f.is_decorated()); + let _decorated = formatter.as_ref().is_some_and(|f| f.is_decorated()); // TODO(phase-c): wire StreamOutput as the output. StreamOutput::new requires a // PhpResource, but `fopen` here yields a PhpMixed; PhpMixed has no resource variant, // so the stream cannot be passed through yet (same PhpResource/PhpMixed gap noted in @@ -81,7 +81,7 @@ impl BufferIO { let output = stream_get_contents(stream).unwrap_or_default(); - let output = Preg::replace_callback( + Preg::replace_callback( r"{(?<=^|\n|\x08)(.+?)(\x08+)}", |matches: &indexmap::IndexMap< shirabe_external_packages::composer::pcre::CaptureKey, @@ -105,9 +105,7 @@ impl BufferIO { format!("{}\n", g1.trim_end()) }, &output, - ); - - output + ) } pub fn set_user_inputs(&mut self, inputs: Vec<String>) -> Result<()> { diff --git a/crates/shirabe/src/io/console_io.rs b/crates/shirabe/src/io/console_io.rs index ecb12b1..fc46832 100644 --- a/crates/shirabe/src/io/console_io.rs +++ b/crates/shirabe/src/io/console_io.rs @@ -638,7 +638,7 @@ impl IOInterfaceImmutable for ConsoleIO { _ => vec![], }; let is_assoc = - !choice_keys.is_empty() && choice_keys.iter().any(|k| !k.parse::<i64>().is_ok()); + !choice_keys.is_empty() && choice_keys.iter().any(|k| k.parse::<i64>().is_err()); if is_assoc { return result; } diff --git a/crates/shirabe/src/io/null_io.rs b/crates/shirabe/src/io/null_io.rs index ee533c1..b0e2139 100644 --- a/crates/shirabe/src/io/null_io.rs +++ b/crates/shirabe/src/io/null_io.rs @@ -11,6 +11,12 @@ pub struct NullIO { authentications: indexmap::IndexMap<String, indexmap::IndexMap<String, Option<String>>>, } +impl Default for NullIO { + fn default() -> Self { + Self::new() + } +} + impl NullIO { pub fn new() -> Self { Self { diff --git a/crates/shirabe/src/json/json_file.rs b/crates/shirabe/src/json/json_file.rs index f04a7a4..22b104b 100644 --- a/crates/shirabe/src/json/json_file.rs +++ b/crates/shirabe/src/json/json_file.rs @@ -154,20 +154,20 @@ impl JsonFile { } .into()); } - if let Some(io) = &self.io { - if io.is_debug() { - let mut realpath_info = String::new(); - if let Some(realpath) = realpath(&self.path) { - if realpath != self.path { - realpath_info = format!(" ({})", realpath); - } - } - io.write_error3( - &format!("Reading {}{}", self.path, realpath_info), - true, - io_interface::NORMAL, - ); + if let Some(io) = &self.io + && io.is_debug() + { + let mut realpath_info = String::new(); + if let Some(realpath) = realpath(&self.path) + && realpath != self.path + { + realpath_info = format!(" ({})", realpath); } + io.write_error3( + &format!("Reading {}{}", self.path, realpath_info), + true, + io_interface::NORMAL, + ); } Ok(file_get_contents(&self.path)) } @@ -502,21 +502,22 @@ impl JsonFile { let mut data = json_decode(json, true)?; if matches!(data, PhpMixed::Null) && JSON_ERROR_NONE != json_last_error() { // attempt resolving simple conflicts in lock files so that one can run `composer update --lock` and get a valid lock file - if let Some(file) = file { - if str_ends_with(file, ".lock") && str_contains(json, "\"content-hash\"") { - let mut count: usize = 0; - let replaced = Preg::replace5( - r#"{\r?\n<<<<<<< [^\r\n]+\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n(?:\|{7} [^\r\n]+\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n)?=======\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n>>>>>>> [^\r\n]+(\r?\n)}"#, - " \"content-hash\": \"VCS merge conflict detected. Please run `composer update --lock`.\",$1", - json, - -1, - &mut count, - ); - if count == 1 { - data = json_decode(&replaced, true)?; - if !matches!(data, PhpMixed::Null) { - return Ok(data); - } + if let Some(file) = file + && str_ends_with(file, ".lock") + && str_contains(json, "\"content-hash\"") + { + let mut count: usize = 0; + let replaced = Preg::replace5( + r#"{\r?\n<<<<<<< [^\r\n]+\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n(?:\|{7} [^\r\n]+\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n)?=======\r?\n\s+"content-hash": *"[0-9a-f]+", *\r?\n>>>>>>> [^\r\n]+(\r?\n)}"#, + " \"content-hash\": \"VCS merge conflict detected. Please run `composer update --lock`.\",$1", + json, + -1, + &mut count, + ); + if count == 1 { + data = json_decode(&replaced, true)?; + if !matches!(data, PhpMixed::Null) { + return Ok(data); } } } diff --git a/crates/shirabe/src/json/json_manipulator.rs b/crates/shirabe/src/json/json_manipulator.rs index 3bc5725..a753c93 100644 --- a/crates/shirabe/src/json/json_manipulator.rs +++ b/crates/shirabe/src/json/json_manipulator.rs @@ -33,7 +33,7 @@ impl JsonManipulator { pub fn new(contents: String) -> anyhow::Result<Self> { let mut contents = trim(&contents, Some(" \t\n\r\0\u{0B}")); - if contents == "" { + if contents.is_empty() { contents = "{}".to_string(); } if !Preg::is_match3("#^\\{(.*)\\}$#s", &contents, None) { @@ -215,7 +215,7 @@ impl JsonManipulator { config: PhpMixed, append: bool, ) -> anyhow::Result<bool> { - if "" != name && !self.do_remove_repository(name)? { + if !name.is_empty() && !self.do_remove_repository(name)? { return Ok(false); } @@ -225,7 +225,7 @@ impl JsonManipulator { let final_config = if is_array(&config) && !is_numeric(&PhpMixed::String(name.to_string())) - && "" != name + && !name.is_empty() { // PHP: ['name' => $name] + $config — preserve $config keys let mut merged: IndexMap<String, Box<PhpMixed>> = IndexMap::new(); @@ -365,9 +365,9 @@ impl JsonManipulator { ); let mut matches: IndexMap<String, String> = IndexMap::new(); - let list_match = list_regex.as_ref().map_or(false, |r| { - Preg::is_match_named(r, &self.contents, &mut matches) - }); + let list_match = list_regex + .as_ref() + .is_some_and(|r| Preg::is_match_named(r, &self.contents, &mut matches)); if list_match || Preg::is_match_named(&object_regex, &self.contents, &mut matches) { // invalid match due to un-regexable content, abort let raw_repo = matches.get("repository").cloned().unwrap_or_default(); @@ -418,7 +418,7 @@ impl JsonManipulator { reference_name: &str, offset: i64, ) -> anyhow::Result<bool> { - if "" != name && !self.do_remove_repository(name)? { + if !name.is_empty() && !self.do_remove_repository(name)? { return Ok(false); } @@ -447,16 +447,15 @@ impl JsonManipulator { // PHP: $repositoryIndex === $referenceName — comparing list index to a string is rare; skip in Rust port // PHP: [$referenceName => false] === $repository - if let Some(arr) = repository.as_array() { - if arr.len() == 1 - && arr - .get(reference_name) - .map(|v| v.as_bool() == Some(false)) - .unwrap_or(false) - { - index_to_insert = Some(i as i64); - break; - } + if let Some(arr) = repository.as_array() + && arr.len() == 1 + && arr + .get(reference_name) + .map(|v| v.as_bool() == Some(false)) + .unwrap_or(false) + { + index_to_insert = Some(i as i64); + break; } } @@ -467,7 +466,7 @@ impl JsonManipulator { let final_config = if is_array(&config) && !is_numeric(&PhpMixed::String(name.to_string())) - && "" != name + && !name.is_empty() { let mut merged: IndexMap<String, Box<PhpMixed>> = IndexMap::new(); merged.insert( @@ -968,61 +967,59 @@ impl JsonManipulator { "#^\\{\\s*?(?P<content>\\S+.*?)?(?P<trailingspace>\\s*)\\}$#s", &children_clean, &mut empty_match, - ) { - if empty_match.get("content").is_none() { - let newline = self.newline.clone(); - let indent = self.indent.clone(); + ) && empty_match.get("content").is_none() + { + let newline = self.newline.clone(); + let indent = self.indent.clone(); - self.contents = Preg::replace_callback( - &node_regex, - move |matches: &IndexMap<CaptureKey, String>| -> String { - format!( - "{}{{{}{}}}{}", - matches - .get(&CaptureKey::ByName("start".to_string())) - .cloned() - .unwrap_or_default(), - newline, - indent, - matches - .get(&CaptureKey::ByName("end".to_string())) - .cloned() - .unwrap_or_default() - ) - }, - &self.contents, - ); + self.contents = Preg::replace_callback( + &node_regex, + move |matches: &IndexMap<CaptureKey, String>| -> String { + format!( + "{}{{{}{}}}{}", + matches + .get(&CaptureKey::ByName("start".to_string())) + .cloned() + .unwrap_or_default(), + newline, + indent, + matches + .get(&CaptureKey::ByName("end".to_string())) + .cloned() + .unwrap_or_default() + ) + }, + &self.contents, + ); - // we have a subname, so we restore the rest of $name - if let Some(sub) = sub_name { - let mut cur_val = json_decode(&children, true)?; - if let Some(arr) = cur_val.as_array_mut() { - if let Some(inner) = arr.get_mut(&name_owned).and_then(|v| v.as_array_mut()) - { - inner.shift_remove(&sub); - } - let now_empty = arr - .get(&name_owned) - .and_then(|v| v.as_array()) - .map(|a| a.is_empty()) - .unwrap_or(false); - if now_empty { - arr.insert( - name_owned.clone(), - Box::new(PhpMixed::Object(ArrayObject::new(None))), - ); - } + // we have a subname, so we restore the rest of $name + if let Some(sub) = sub_name { + let mut cur_val = json_decode(&children, true)?; + if let Some(arr) = cur_val.as_array_mut() { + if let Some(inner) = arr.get_mut(&name_owned).and_then(|v| v.as_array_mut()) { + inner.shift_remove(&sub); + } + let now_empty = arr + .get(&name_owned) + .and_then(|v| v.as_array()) + .map(|a| a.is_empty()) + .unwrap_or(false); + if now_empty { + arr.insert( + name_owned.clone(), + Box::new(PhpMixed::Object(ArrayObject::new(None))), + ); } - let val = cur_val - .as_array() - .and_then(|a| a.get(&name_owned)) - .map(|v| (**v).clone()) - .unwrap_or(PhpMixed::Null); - self.add_sub_node(main_node, &name_owned, val, true)?; } - - return Ok(true); + let val = cur_val + .as_array() + .and_then(|a| a.get(&name_owned)) + .map(|v| (**v).clone()) + .unwrap_or(PhpMixed::Null); + self.add_sub_node(main_node, &name_owned, val, true)?; } + + return Ok(true); } let name_capture = name_owned.clone(); @@ -1088,10 +1085,10 @@ impl JsonManipulator { let decoded = JsonFile::parse_json(Some(&self.contents), Some("composer.json"))?; // no main node yet - if decoded.as_array().and_then(|a| a.get(main_node)).is_none() { - if !self.add_main_key(main_node, PhpMixed::List(vec![]))? { - return Ok(false); - } + if decoded.as_array().and_then(|a| a.get(main_node)).is_none() + && !self.add_main_key(main_node, PhpMixed::List(vec![]))? + { + return Ok(false); } // main node content not match-able @@ -1229,10 +1226,10 @@ impl JsonManipulator { let decoded = JsonFile::parse_json(Some(&self.contents), Some("composer.json"))?; // no main node yet - if decoded.as_array().and_then(|a| a.get(main_node)).is_none() { - if !self.add_main_key(main_node, PhpMixed::List(vec![]))? { - return Ok(false); - } + if decoded.as_array().and_then(|a| a.get(main_node)).is_none() + && !self.add_main_key(main_node, PhpMixed::List(vec![]))? + { + return Ok(false); } let main_node_count = decoded diff --git a/crates/shirabe/src/package/archiver/archivable_files_filter.rs b/crates/shirabe/src/package/archiver/archivable_files_filter.rs index f820e08..ee39ba3 100644 --- a/crates/shirabe/src/package/archiver/archivable_files_filter.rs +++ b/crates/shirabe/src/package/archiver/archivable_files_filter.rs @@ -1,7 +1,7 @@ //! ref: composer/src/Composer/Package/Archiver/ArchivableFilesFilter.php use shirabe_php_shim::PharData; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; pub struct ArchivableFilesFilter { inner: Box<dyn Iterator<Item = PathBuf>>, @@ -16,7 +16,7 @@ impl ArchivableFilesFilter { } } - fn accept(&mut self, file: &PathBuf) -> bool { + fn accept(&mut self, file: &Path) -> bool { if file.is_dir() { self.dirs.push(file.to_string_lossy().into_owned()); return false; diff --git a/crates/shirabe/src/package/archiver/archive_manager.rs b/crates/shirabe/src/package/archiver/archive_manager.rs index cb15b76..2c9eb35 100644 --- a/crates/shirabe/src/package/archiver/archive_manager.rs +++ b/crates/shirabe/src/package/archiver/archive_manager.rs @@ -198,20 +198,20 @@ impl ArchiveManager { let mut json_file = JsonFile::new(composer_json_path, None, None)?; let json_data = json_file.read()?; if let Some(archive) = json_data.get("archive") { - if let Some(name) = archive.get("name").and_then(|v| v.as_string()) { - if !name.is_empty() { - package.set_archive_name(name.to_string()); - } + if let Some(name) = archive.get("name").and_then(|v| v.as_string()) + && !name.is_empty() + { + package.set_archive_name(name.to_string()); } - if let Some(exclude) = archive.get("exclude") { - if let Some(excludes) = exclude.as_array() { - let excludes: Vec<String> = excludes - .values() - .filter_map(|v| v.as_string().map(|s| s.to_string())) - .collect(); - if !excludes.is_empty() { - package.set_archive_excludes(excludes); - } + if let Some(exclude) = archive.get("exclude") + && let Some(excludes) = exclude.as_array() + { + let excludes: Vec<String> = excludes + .values() + .filter_map(|v| v.as_string().map(|s| s.to_string())) + .collect(); + if !excludes.is_empty() { + package.set_archive_excludes(excludes); } } } diff --git a/crates/shirabe/src/package/archiver/phar_archiver.rs b/crates/shirabe/src/package/archiver/phar_archiver.rs index d2854eb..c25b90b 100644 --- a/crates/shirabe/src/package/archiver/phar_archiver.rs +++ b/crates/shirabe/src/package/archiver/phar_archiver.rs @@ -29,6 +29,12 @@ fn compress_formats() -> IndexMap<&'static str, i64> { #[derive(Debug)] pub struct PharArchiver; +impl Default for PharArchiver { + fn default() -> Self { + Self::new() + } +} + impl PharArchiver { pub fn new() -> Self { Self diff --git a/crates/shirabe/src/package/archiver/zip_archiver.rs b/crates/shirabe/src/package/archiver/zip_archiver.rs index 7d9f126..41201b5 100644 --- a/crates/shirabe/src/package/archiver/zip_archiver.rs +++ b/crates/shirabe/src/package/archiver/zip_archiver.rs @@ -13,6 +13,12 @@ use std::path::PathBuf; #[derive(Debug)] pub struct ZipArchiver; +impl Default for ZipArchiver { + fn default() -> Self { + Self::new() + } +} + impl ZipArchiver { pub fn new() -> Self { Self diff --git a/crates/shirabe/src/package/base_package.rs b/crates/shirabe/src/package/base_package.rs index 54abc13..d7b6978 100644 --- a/crates/shirabe/src/package/base_package.rs +++ b/crates/shirabe/src/package/base_package.rs @@ -90,7 +90,7 @@ pub trait BasePackage: PackageInterface + std::fmt::Display { fn is_platform(&self) -> bool { self.repository_opt() - .map_or(false, |r| r.is::<PlatformRepository>()) + .is_some_and(|r| r.is::<PlatformRepository>()) } fn get_full_pretty_version(&self, truncate: bool, display_mode: DisplayMode) -> String { diff --git a/crates/shirabe/src/package/comparer/comparer.rs b/crates/shirabe/src/package/comparer/comparer.rs index 73c94f4..d23e669 100644 --- a/crates/shirabe/src/package/comparer/comparer.rs +++ b/crates/shirabe/src/package/comparer/comparer.rs @@ -12,6 +12,12 @@ pub struct Comparer { changed: IndexMap<String, Vec<String>>, } +impl Default for Comparer { + fn default() -> Self { + Self::new() + } +} + impl Comparer { pub fn new() -> Self { Self { @@ -96,7 +102,7 @@ impl Comparer { } for (dir, value) in &destination { for (file, _hash) in value { - if !source.get(dir).map_or(false, |d| d.contains_key(file)) { + if !source.get(dir).is_some_and(|d| d.contains_key(file)) { self.changed .entry("added".to_string()) .or_default() diff --git a/crates/shirabe/src/package/comparer/mod.rs b/crates/shirabe/src/package/comparer/mod.rs index d6ce6cb..878d7e0 100644 --- a/crates/shirabe/src/package/comparer/mod.rs +++ b/crates/shirabe/src/package/comparer/mod.rs @@ -1,3 +1,4 @@ +#[allow(clippy::module_inception, reason = "to port PHP's structure as it is")] pub mod comparer; pub use comparer::*; diff --git a/crates/shirabe/src/package/dumper/array_dumper.rs b/crates/shirabe/src/package/dumper/array_dumper.rs index 27fc415..7bf62f2 100644 --- a/crates/shirabe/src/package/dumper/array_dumper.rs +++ b/crates/shirabe/src/package/dumper/array_dumper.rs @@ -21,6 +21,12 @@ fn mirror_to_php(mirror: Mirror) -> PhpMixed { #[derive(Debug)] pub struct ArrayDumper; +impl Default for ArrayDumper { + fn default() -> Self { + Self::new() + } +} + impl ArrayDumper { pub fn new() -> Self { Self @@ -66,19 +72,19 @@ impl ArrayDumper { Box::new(PhpMixed::String(reference.to_string())), ); } - if let Some(mirrors) = package.get_source_mirrors() { - if !mirrors.is_empty() { - source.insert( - "mirrors".to_string(), - Box::new(PhpMixed::Array( - mirrors - .into_iter() - .enumerate() - .map(|(i, m)| (i.to_string(), Box::new(mirror_to_php(m)))) - .collect(), - )), - ); - } + if let Some(mirrors) = package.get_source_mirrors() + && !mirrors.is_empty() + { + source.insert( + "mirrors".to_string(), + Box::new(PhpMixed::Array( + mirrors + .into_iter() + .enumerate() + .map(|(i, m)| (i.to_string(), Box::new(mirror_to_php(m)))) + .collect(), + )), + ); } data.insert("source".to_string(), PhpMixed::Array(source)); } @@ -105,19 +111,19 @@ impl ArrayDumper { Box::new(PhpMixed::String(shasum.to_string())), ); } - if let Some(mirrors) = package.get_dist_mirrors() { - if !mirrors.is_empty() { - dist.insert( - "mirrors".to_string(), - Box::new(PhpMixed::Array( - mirrors - .into_iter() - .enumerate() - .map(|(i, m)| (i.to_string(), Box::new(mirror_to_php(m)))) - .collect(), - )), - ); - } + if let Some(mirrors) = package.get_dist_mirrors() + && !mirrors.is_empty() + { + dist.insert( + "mirrors".to_string(), + Box::new(PhpMixed::Array( + mirrors + .into_iter() + .enumerate() + .map(|(i, m)| (i.to_string(), Box::new(mirror_to_php(m)))) + .collect(), + )), + ); } data.insert("dist".to_string(), PhpMixed::Array(dist)); } diff --git a/crates/shirabe/src/package/link.rs b/crates/shirabe/src/package/link.rs index 0157989..027fa00 100644 --- a/crates/shirabe/src/package/link.rs +++ b/crates/shirabe/src/package/link.rs @@ -92,10 +92,7 @@ impl std::fmt::Display for Link { write!( f, "{} {} {} ({})", - self.source, - self.description, - self.target, - self.constraint.to_string(), + self.source, self.description, self.target, self.constraint, ) } } diff --git a/crates/shirabe/src/package/loader/array_loader.rs b/crates/shirabe/src/package/loader/array_loader.rs index 222b5df..889624d 100644 --- a/crates/shirabe/src/package/loader/array_loader.rs +++ b/crates/shirabe/src/package/loader/array_loader.rs @@ -35,10 +35,7 @@ pub struct ArrayLoader { impl ArrayLoader { pub fn new(parser: Option<VersionParser>, load_options: bool) -> Self { - let parser = match parser { - Some(p) => p, - None => VersionParser::new(), - }; + let parser = parser.unwrap_or_default(); Self { version_parser: parser, load_options, @@ -340,11 +337,11 @@ impl ArrayLoader { .set_target_dir(target_dir.as_string().map(|s| s.to_string())); } - if let Some(extra) = config.get("extra") { - if matches!(extra, PhpMixed::Array(_)) { - let extra_map = php_to_map(extra); - package.package_mut().set_extra(extra_map); - } + if let Some(extra) = config.get("extra") + && matches!(extra, PhpMixed::Array(_)) + { + let extra_map = php_to_map(extra); + package.package_mut().set_extra(extra_map); } if let Some(bin) = config.get("bin").cloned() { @@ -355,13 +352,13 @@ impl ArrayLoader { if let PhpMixed::List(ref mut list) = bin_list { for item in list.iter_mut() { if let Some(s) = item.as_string() { - *item = Box::new(PhpMixed::String(ltrim(s, Some("/")))); + **item = PhpMixed::String(ltrim(s, Some("/"))); } } } else if let PhpMixed::Array(ref mut map) = bin_list { for (_k, v) in map.iter_mut() { if let Some(s) = v.as_string() { - *v = Box::new(PhpMixed::String(ltrim(s, Some("/")))); + **v = PhpMixed::String(ltrim(s, Some("/"))); } } } @@ -376,10 +373,10 @@ impl ArrayLoader { .set_installation_source(installation_source.as_string().map(|s| s.to_string())); } - if let Some(default_branch) = config.get("default-branch") { - if default_branch.as_bool() == Some(true) { - package.package_mut().set_is_default_branch(true); - } + if let Some(default_branch) = config.get("default-branch") + && default_branch.as_bool() == Some(true) + { + package.package_mut().set_is_default_branch(true); } if let Some(source) = config.get("source").cloned() { @@ -473,25 +470,23 @@ impl ArrayLoader { } } - if let Some(suggest) = config.get("suggest").cloned() { - if let PhpMixed::Array(mut suggest_map) = suggest { - for (target, reason) in suggest_map.iter_mut() { - if let Some(r) = reason.as_string() { - if trim(r, None) == "self.version" { - *reason = Box::new(PhpMixed::String( - package.get_pretty_version().to_string(), - )); - let _ = target; - } - } + if let Some(suggest) = config.get("suggest").cloned() + && let PhpMixed::Array(mut suggest_map) = suggest + { + for (target, reason) in suggest_map.iter_mut() { + if let Some(r) = reason.as_string() + && trim(r, None) == "self.version" + { + **reason = PhpMixed::String(package.get_pretty_version().to_string()); + let _ = target; } - let suggests: IndexMap<String, String> = suggest_map - .iter() - .map(|(k, v)| (k.clone(), strval(v))) - .collect(); - config.insert("suggest".to_string(), PhpMixed::Array(suggest_map)); - package.package_mut().set_suggests(suggests); } + let suggests: IndexMap<String, String> = suggest_map + .iter() + .map(|(k, v)| (k.clone(), strval(v))) + .collect(); + config.insert("suggest".to_string(), PhpMixed::Array(suggest_map)); + package.package_mut().set_suggests(suggests); } if let Some(autoload) = config.get("autoload") { @@ -514,201 +509,198 @@ impl ArrayLoader { package.package_mut().set_php_ext(Some(php_ext_map)); } - if let Some(time_value) = config.get("time") { - if !shirabe_php_shim::empty(time_value) { - let time_str = time_value.as_string().unwrap_or(""); - let time = if Preg::is_match(r"/^\d++$/D", time_str) { - format!("@{}", time_str) - } else { - time_str.to_string() - }; + if let Some(time_value) = config.get("time") + && !shirabe_php_shim::empty(time_value) + { + let time_str = time_value.as_string().unwrap_or(""); + let time = if Preg::is_match(r"/^\d++$/D", time_str) { + format!("@{}", time_str) + } else { + time_str.to_string() + }; - if let Ok(date) = shirabe_php_shim::date_create::<Utc>(&time) { - package.package_mut().set_release_date(Some(date)); - } + if let Ok(date) = shirabe_php_shim::date_create::<Utc>(&time) { + package.package_mut().set_release_date(Some(date)); } } - if let Some(notification_url) = config.get("notification-url") { - if !shirabe_php_shim::empty(notification_url) { - package - .package_mut() - .set_notification_url(strval(notification_url)); - } + if let Some(notification_url) = config.get("notification-url") + && !shirabe_php_shim::empty(notification_url) + { + package + .package_mut() + .set_notification_url(strval(notification_url)); } - if let Some(archive) = config.get("archive").cloned() { - if let PhpMixed::Array(archive_map) = archive { - if let Some(name) = archive_map.get("name") { - if !shirabe_php_shim::empty(name) { - package.complete_mut().set_archive_name(strval(name)); - } - } - if let Some(exclude) = archive_map.get("exclude") { - if !shirabe_php_shim::empty(exclude) { - package - .complete_mut() - .set_archive_excludes(php_to_string_vec(exclude)); - } - } + if let Some(archive) = config.get("archive").cloned() + && let PhpMixed::Array(archive_map) = archive + { + if let Some(name) = archive_map.get("name") + && !shirabe_php_shim::empty(name) + { + package.complete_mut().set_archive_name(strval(name)); + } + if let Some(exclude) = archive_map.get("exclude") + && !shirabe_php_shim::empty(exclude) + { + package + .complete_mut() + .set_archive_excludes(php_to_string_vec(exclude)); } } - if let Some(scripts) = config.get("scripts").cloned() { - if let PhpMixed::Array(mut scripts_map) = scripts { - for (event, listeners) in scripts_map.iter_mut() { - let listeners_array = match listeners.as_ref() { - PhpMixed::Array(_) | PhpMixed::List(_) => listeners.clone(), - other => Box::new(PhpMixed::List(vec![Box::new(other.clone())])), - }; - *listeners = listeners_array; - let _ = event; - } - for reserved in ["composer", "php", "putenv"].iter() { - if scripts_map.contains_key(*reserved) { - trigger_error( - &format!( - "The `{}` script name is reserved for internal use, please avoid defining it", - reserved - ), - E_USER_DEPRECATED, - ); - } + if let Some(scripts) = config.get("scripts").cloned() + && let PhpMixed::Array(mut scripts_map) = scripts + { + for (event, listeners) in scripts_map.iter_mut() { + let listeners_array = match listeners.as_ref() { + PhpMixed::Array(_) | PhpMixed::List(_) => listeners.clone(), + other => Box::new(PhpMixed::List(vec![Box::new(other.clone())])), + }; + *listeners = listeners_array; + let _ = event; + } + for reserved in ["composer", "php", "putenv"].iter() { + if scripts_map.contains_key(*reserved) { + trigger_error( + &format!( + "The `{}` script name is reserved for internal use, please avoid defining it", + reserved + ), + E_USER_DEPRECATED, + ); } - let scripts: IndexMap<String, Vec<String>> = scripts_map - .iter() - .map(|(k, v)| (k.clone(), php_to_string_vec(v))) - .collect(); - config.insert("scripts".to_string(), PhpMixed::Array(scripts_map)); - package.complete_mut().set_scripts(scripts); } + let scripts: IndexMap<String, Vec<String>> = scripts_map + .iter() + .map(|(k, v)| (k.clone(), php_to_string_vec(v))) + .collect(); + config.insert("scripts".to_string(), PhpMixed::Array(scripts_map)); + package.complete_mut().set_scripts(scripts); } - if let Some(description) = config.get("description") { - if !shirabe_php_shim::empty(description) && is_string(description) { - package - .complete_mut() - .set_description(description.as_string().unwrap_or("").to_string()); - } + if let Some(description) = config.get("description") + && !shirabe_php_shim::empty(description) + && is_string(description) + { + package + .complete_mut() + .set_description(description.as_string().unwrap_or("").to_string()); } - if let Some(homepage) = config.get("homepage") { - if !shirabe_php_shim::empty(homepage) && is_string(homepage) { - package - .complete_mut() - .set_homepage(homepage.as_string().unwrap_or("").to_string()); - } + if let Some(homepage) = config.get("homepage") + && !shirabe_php_shim::empty(homepage) + && is_string(homepage) + { + package + .complete_mut() + .set_homepage(homepage.as_string().unwrap_or("").to_string()); } - if let Some(keywords) = config.get("keywords") { - if !shirabe_php_shim::empty(keywords) { - if matches!(keywords, PhpMixed::Array(_) | PhpMixed::List(_)) { - let keywords_vec: Vec<String> = match keywords { - PhpMixed::List(list) => list.iter().map(|v| strval(v)).collect(), - PhpMixed::Array(map) => map.values().map(|v| strval(v)).collect(), - _ => vec![], - }; - package.complete_mut().set_keywords(keywords_vec); - } - } + if let Some(keywords) = config.get("keywords") + && !shirabe_php_shim::empty(keywords) + && matches!(keywords, PhpMixed::Array(_) | PhpMixed::List(_)) + { + let keywords_vec: Vec<String> = match keywords { + PhpMixed::List(list) => list.iter().map(|v| strval(v)).collect(), + PhpMixed::Array(map) => map.values().map(|v| strval(v)).collect(), + _ => vec![], + }; + package.complete_mut().set_keywords(keywords_vec); } - if let Some(license) = config.get("license") { - if !shirabe_php_shim::empty(license) { - let license_vec: Vec<String> = match license { - PhpMixed::Array(map) => map - .values() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect(), - PhpMixed::List(list) => list - .iter() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect(), - other => vec![other.as_string().unwrap_or("").to_string()], - }; - package.complete_mut().set_license(license_vec); - } + if let Some(license) = config.get("license") + && !shirabe_php_shim::empty(license) + { + let license_vec: Vec<String> = match license { + PhpMixed::Array(map) => map + .values() + .map(|v| v.as_string().unwrap_or("").to_string()) + .collect(), + PhpMixed::List(list) => list + .iter() + .map(|v| v.as_string().unwrap_or("").to_string()) + .collect(), + other => vec![other.as_string().unwrap_or("").to_string()], + }; + package.complete_mut().set_license(license_vec); } - if let Some(authors) = config.get("authors") { - if !shirabe_php_shim::empty(authors) { - if let PhpMixed::List(list) = authors { - let authors_vec: Vec<IndexMap<String, String>> = list - .iter() - .filter_map(|v| match v.as_ref() { - PhpMixed::Array(m) => Some( - m.iter() - .map(|(k, v)| { - (k.clone(), v.as_string().unwrap_or("").to_string()) - }) - .collect(), - ), - _ => None, - }) - .collect(); - package.complete_mut().set_authors(authors_vec); - } - } + if let Some(authors) = config.get("authors") + && !shirabe_php_shim::empty(authors) + && let PhpMixed::List(list) = authors + { + let authors_vec: Vec<IndexMap<String, String>> = list + .iter() + .filter_map(|v| match v.as_ref() { + PhpMixed::Array(m) => Some( + m.iter() + .map(|(k, v)| (k.clone(), v.as_string().unwrap_or("").to_string())) + .collect(), + ), + _ => None, + }) + .collect(); + package.complete_mut().set_authors(authors_vec); } - if let Some(support) = config.get("support") { - if let PhpMixed::Array(map) = support { - let support_map: IndexMap<String, String> = map - .iter() - .map(|(k, v)| (k.clone(), v.as_string().unwrap_or("").to_string())) - .collect(); - package.complete_mut().set_support(support_map); - } + if let Some(support) = config.get("support") + && let PhpMixed::Array(map) = support + { + let support_map: IndexMap<String, String> = map + .iter() + .map(|(k, v)| (k.clone(), v.as_string().unwrap_or("").to_string())) + .collect(); + package.complete_mut().set_support(support_map); } - if let Some(funding) = config.get("funding") { - if !shirabe_php_shim::empty(funding) { - if let PhpMixed::List(list) = funding { - let funding_vec: Vec<IndexMap<String, PhpMixed>> = list - .iter() - .filter_map(|v| match v.as_ref() { - PhpMixed::Array(m) => { - Some(m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect()) - } - _ => None, - }) - .collect(); - package.complete_mut().set_funding(funding_vec); - } - } + if let Some(funding) = config.get("funding") + && !shirabe_php_shim::empty(funding) + && let PhpMixed::List(list) = funding + { + let funding_vec: Vec<IndexMap<String, PhpMixed>> = list + .iter() + .filter_map(|v| match v.as_ref() { + PhpMixed::Array(m) => { + Some(m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect()) + } + _ => None, + }) + .collect(); + package.complete_mut().set_funding(funding_vec); } if let Some(abandoned) = config.get("abandoned") { package.complete_mut().set_abandoned(abandoned.clone()); } - if self.load_options { - if let Some(transport_options) = config.get("transport-options") { - let options = php_to_map(transport_options); - package.package_mut().set_transport_options(options); - } + if self.load_options + && let Some(transport_options) = config.get("transport-options") + { + let options = php_to_map(transport_options); + package.package_mut().set_transport_options(options); } let alias_normalized = self.get_branch_alias(config)?; - if let Some(alias_normalized) = alias_normalized { - if !alias_normalized.is_empty() { - let pretty_alias = Preg::replace(r"{(\.9{7})+}", ".x", &alias_normalized); + if let Some(alias_normalized) = alias_normalized + && !alias_normalized.is_empty() + { + let pretty_alias = Preg::replace(r"{(\.9{7})+}", ".x", &alias_normalized); - return Ok(match package { - CompleteOrRootPackage::Root(root) => RootAliasPackageHandle::new( - RootPackageHandle::from_root_package(root), - alias_normalized, - pretty_alias, - ) - .into(), - CompleteOrRootPackage::Complete(complete) => CompleteAliasPackageHandle::new( - CompletePackageHandle::from_complete_package(complete), - alias_normalized, - pretty_alias, - ) - .into(), - }); - } + return Ok(match package { + CompleteOrRootPackage::Root(root) => RootAliasPackageHandle::new( + RootPackageHandle::from_root_package(root), + alias_normalized, + pretty_alias, + ) + .into(), + CompleteOrRootPackage::Complete(complete) => CompleteAliasPackageHandle::new( + CompletePackageHandle::from_complete_package(complete), + alias_normalized, + pretty_alias, + ) + .into(), + }); } Ok(package.into_handle()) @@ -773,11 +765,11 @@ impl ArrayLoader { let entry = (target.clone(), link); link_cache .entry(name.clone()) - .or_insert_with(IndexMap::new) + .or_default() .entry(r#type.to_string()) - .or_insert_with(IndexMap::new) + .or_default() .entry(target.clone()) - .or_insert_with(IndexMap::new) + .or_default() .insert(constraint_str.clone(), entry.clone()); entry }; @@ -940,10 +932,10 @@ impl ArrayLoader { let target_prefix = self .version_parser .parse_numeric_alias_prefix(&target_branch); - if let (Some(sp), Some(tp)) = (source_prefix.as_ref(), target_prefix.as_ref()) { - if stripos(tp, sp) != Some(0) { - continue; - } + if let (Some(sp), Some(tp)) = (source_prefix.as_ref(), target_prefix.as_ref()) + && stripos(tp, sp) != Some(0) + { + continue; } return Ok(Some(validated_target_branch)); diff --git a/crates/shirabe/src/package/loader/root_package_loader.rs b/crates/shirabe/src/package/loader/root_package_loader.rs index 92f2be0..2d3bd0a 100644 --- a/crates/shirabe/src/package/loader/root_package_loader.rs +++ b/crates/shirabe/src/package/loader/root_package_loader.rs @@ -221,17 +221,17 @@ impl RootPackageLoader { } for link_type in SUPPORTED_LINK_TYPES.keys() { - if let Some(section) = config.get(*link_type) { - if let Some(section_map) = section.as_array() { - for (link_name, _constraint) in section_map { - if let Some(err) = - ValidatingArrayLoader::has_package_naming_error(link_name, true) - { - return Err(anyhow::anyhow!(RuntimeException { - message: format!("{}.{}", link_type, err), - code: 0, - })); - } + if let Some(section) = config.get(*link_type) + && let Some(section_map) = section.as_array() + { + for (link_name, _constraint) in section_map { + if let Some(err) = + ValidatingArrayLoader::has_package_naming_error(link_name, true) + { + return Err(anyhow::anyhow!(RuntimeException { + message: format!("{}.{}", link_type, err), + code: 0, + })); } } } @@ -392,14 +392,14 @@ impl RootPackageLoader { for (req_name, req_version) in requires { let req_version = Preg::replace(r"^([^,\s@]+) as .+$", "$1", req_version); let mut m: IndexMap<CaptureKey, String> = IndexMap::new(); - if Preg::is_match3(r"^[^,\s@]+?#([a-f0-9]+)$", &req_version, Some(&mut m)) { - if VersionParser::parse_stability(&req_version) == "dev" { - let name = strtolower(req_name); - references.insert( - name, - m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(), - ); - } + if Preg::is_match3(r"^[^,\s@]+?#([a-f0-9]+)$", &req_version, Some(&mut m)) + && VersionParser::parse_stability(&req_version) == "dev" + { + let name = strtolower(req_name); + references.insert( + name, + m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(), + ); } } references diff --git a/crates/shirabe/src/package/loader/validating_array_loader.rs b/crates/shirabe/src/package/loader/validating_array_loader.rs index dd2642e..490c0a9 100644 --- a/crates/shirabe/src/package/loader/validating_array_loader.rs +++ b/crates/shirabe/src/package/loader/validating_array_loader.rs @@ -43,9 +43,9 @@ impl ValidatingArrayLoader { parser: Option<VersionParser>, flags: i64, ) -> Self { - let version_parser = parser.unwrap_or_else(|| VersionParser::new()); + let version_parser = parser.unwrap_or_default(); - if strict_name != true { + if !strict_name { trigger_error( "$strictName must be set to true in ValidatingArrayLoader's constructor as of 2.2, and it will be removed in 3.0", E_USER_DEPRECATED, @@ -72,21 +72,21 @@ impl ValidatingArrayLoader { self.config = config.clone(); self.validate_string("name", true); - if let Some(name_val) = config.get("name").and_then(|v| v.as_string()) { - if let Some(err) = Self::has_package_naming_error(name_val, false) { - self.errors.push(format!("name : {}", err)); - } + if let Some(name_val) = config.get("name").and_then(|v| v.as_string()) + && let Some(err) = Self::has_package_naming_error(name_val, false) + { + self.errors.push(format!("name : {}", err)); } if self.config.contains_key("version") { let version_val = self.config["version"].clone(); - if !is_scalar(&*version_val) { + if !is_scalar(&version_val) { self.validate_string("version", false); } else { - if !is_string(&*version_val) { + if !is_string(&version_val) { self.config.insert( "version".to_string(), - Box::new(PhpMixed::String(php_to_string(&*version_val))), + Box::new(PhpMixed::String(php_to_string(&version_val))), ); } let version_str = self @@ -111,36 +111,35 @@ impl ValidatingArrayLoader { .get("config") .and_then(|v| v.as_array()) .cloned() + && let Some(platform_val) = config_section.get("platform") { - if let Some(platform_val) = config_section.get("platform") { - let platform_array: IndexMap<String, Box<PhpMixed>> = match platform_val.as_ref() { - PhpMixed::Array(m) => m.clone(), - other => { - let mut m = IndexMap::new(); - m.insert("0".to_string(), Box::new(other.clone())); - m - } - }; - for (key, platform) in &platform_array { - if let PhpMixed::Bool(false) = platform.as_ref() { - continue; - } - if !is_string(platform) { - self.errors.push(format!( - "config.platform.{} : invalid value ({} {}): expected string or false", - key, - get_debug_type(platform), - var_export(platform, true) - )); - continue; - } - let platform_str = platform.as_string().unwrap_or("").to_string(); - if let Err(e) = self.version_parser.normalize(&platform_str, None) { - self.errors.push(format!( - "config.platform.{} : invalid value ({}): {}", - key, platform_str, e - )); - } + let platform_array: IndexMap<String, Box<PhpMixed>> = match platform_val.as_ref() { + PhpMixed::Array(m) => m.clone(), + other => { + let mut m = IndexMap::new(); + m.insert("0".to_string(), Box::new(other.clone())); + m + } + }; + for (key, platform) in &platform_array { + if let PhpMixed::Bool(false) = platform.as_ref() { + continue; + } + if !is_string(platform) { + self.errors.push(format!( + "config.platform.{} : invalid value ({} {}): expected string or false", + key, + get_debug_type(platform), + var_export(platform, true) + )); + continue; + } + let platform_str = platform.as_string().unwrap_or("").to_string(); + if let Err(e) = self.version_parser.normalize(&platform_str, None) { + self.errors.push(format!( + "config.platform.{} : invalid value ({}): {}", + key, platform_str, e + )); } } } @@ -150,7 +149,7 @@ impl ValidatingArrayLoader { self.validate_array("extra", false); if self.config.contains_key("bin") { - if is_string(&*self.config["bin"]) { + if is_string(&self.config["bin"]) { self.validate_string("bin", false); } else { self.validate_flat_array("bin", None, false); @@ -181,7 +180,7 @@ impl ValidatingArrayLoader { if self.config.contains_key("license") { let license_val = self.config["license"].clone(); // validate main data types - if is_array(&*license_val) || is_string(&*license_val) { + if is_array(&license_val) || is_string(&license_val) { let mut licenses: IndexMap<String, Box<PhpMixed>> = match license_val.as_ref() { PhpMixed::Array(m) => m.clone(), other => { @@ -194,7 +193,7 @@ impl ValidatingArrayLoader { let license_keys: Vec<String> = licenses.keys().cloned().collect(); for index in &license_keys { let license = licenses[index].clone(); - if !is_string(&*license) { + if !is_string(&license) { self.warnings.push(format!( "License {} should be a string.", PhpMixed::String(json_encode(&*license).unwrap_or_default()), @@ -264,11 +263,11 @@ impl ValidatingArrayLoader { .unwrap_or_default(); for key in &author_keys { let author = self.config["authors"].as_array().unwrap()[key].clone(); - if !is_array(&*author) { + if !is_array(&author) { self.errors.push(format!( "authors.{} : should be an array, {} given", key, - get_debug_type(&*author) + get_debug_type(&author) )); if let Some(PhpMixed::Array(m)) = self.config.get_mut("authors").map(|v| v.as_mut()) @@ -279,21 +278,19 @@ impl ValidatingArrayLoader { } for author_data in ["homepage", "email", "name", "role"] { let val_opt = author.as_array().and_then(|m| m.get(author_data)).cloned(); - if let Some(val) = val_opt { - if !is_string(&*val) { - self.errors.push(format!( - "authors.{}.{} : invalid value, must be a string", - key, author_data - )); - if let Some(PhpMixed::Array(authors)) = - self.config.get_mut("authors").map(|v| v.as_mut()) - { - if let Some(author_entry) = authors.get_mut(key) { - if let PhpMixed::Array(am) = author_entry.as_mut() { - am.shift_remove(author_data); - } - } - } + if let Some(val) = val_opt + && !is_string(&val) + { + self.errors.push(format!( + "authors.{}.{} : invalid value, must be a string", + key, author_data + )); + if let Some(PhpMixed::Array(authors)) = + self.config.get_mut("authors").map(|v| v.as_mut()) + && let Some(author_entry) = authors.get_mut(key) + && let PhpMixed::Array(am) = author_entry.as_mut() + { + am.shift_remove(author_data); } } } @@ -302,21 +299,19 @@ impl ValidatingArrayLoader { .and_then(|m| m.get("homepage")) .and_then(|v| v.as_string()) .map(|s| s.to_string()); - if let Some(homepage_str) = homepage { - if !self.filter_url(&homepage_str, &["http", "https"]) { - self.warnings.push(format!( - "authors.{}.homepage : invalid value ({}), must be an http/https URL", - key, homepage_str - )); - if let Some(PhpMixed::Array(authors)) = - self.config.get_mut("authors").map(|v| v.as_mut()) - { - if let Some(author_entry) = authors.get_mut(key) { - if let PhpMixed::Array(am) = author_entry.as_mut() { - am.shift_remove("homepage"); - } - } - } + if let Some(homepage_str) = homepage + && !self.filter_url(&homepage_str, &["http", "https"]) + { + self.warnings.push(format!( + "authors.{}.homepage : invalid value ({}), must be an http/https URL", + key, homepage_str + )); + if let Some(PhpMixed::Array(authors)) = + self.config.get_mut("authors").map(|v| v.as_mut()) + && let Some(author_entry) = authors.get_mut(key) + && let PhpMixed::Array(am) = author_entry.as_mut() + { + am.shift_remove("homepage"); } } let email = author @@ -324,21 +319,19 @@ impl ValidatingArrayLoader { .and_then(|m| m.get("email")) .and_then(|v| v.as_string()) .map(|s| s.to_string()); - if let Some(email_str) = email { - if !filter_var(&email_str, FILTER_VALIDATE_EMAIL) { - self.warnings.push(format!( - "authors.{}.email : invalid value ({}), must be a valid email address", - key, email_str - )); - if let Some(PhpMixed::Array(authors)) = - self.config.get_mut("authors").map(|v| v.as_mut()) - { - if let Some(author_entry) = authors.get_mut(key) { - if let PhpMixed::Array(am) = author_entry.as_mut() { - am.shift_remove("email"); - } - } - } + if let Some(email_str) = email + && !filter_var(&email_str, FILTER_VALIDATE_EMAIL) + { + self.warnings.push(format!( + "authors.{}.email : invalid value ({}), must be a valid email address", + key, email_str + )); + if let Some(PhpMixed::Array(authors)) = + self.config.get_mut("authors").map(|v| v.as_mut()) + && let Some(author_entry) = authors.get_mut(key) + && let PhpMixed::Array(am) = author_entry.as_mut() + { + am.shift_remove("email"); } } let current_author_len = self @@ -349,12 +342,11 @@ impl ValidatingArrayLoader { .and_then(|v| v.as_array()) .map(|m| m.len()) .unwrap_or(0); - if current_author_len == 0 { - if let Some(PhpMixed::Array(authors)) = + if current_author_len == 0 + && let Some(PhpMixed::Array(authors)) = self.config.get_mut("authors").map(|v| v.as_mut()) - { - authors.shift_remove(key); - } + { + authors.shift_remove(key); } } let authors_len = self @@ -381,15 +373,15 @@ impl ValidatingArrayLoader { .and_then(|v| v.as_array()) .and_then(|m| m.get(key)) .cloned(); - if let Some(val) = val_opt { - if !is_string(&*val) { - self.errors - .push(format!("support.{} : invalid value, must be a string", key)); - if let Some(PhpMixed::Array(support)) = - self.config.get_mut("support").map(|v| v.as_mut()) - { - support.shift_remove(key); - } + if let Some(val) = val_opt + && !is_string(&val) + { + self.errors + .push(format!("support.{} : invalid value, must be a string", key)); + if let Some(PhpMixed::Array(support)) = + self.config.get_mut("support").map(|v| v.as_mut()) + { + support.shift_remove(key); } } } @@ -401,17 +393,17 @@ impl ValidatingArrayLoader { .and_then(|m| m.get("email")) .and_then(|v| v.as_string()) .map(|s| s.to_string()); - if let Some(email_str) = support_email { - if !filter_var(&email_str, FILTER_VALIDATE_EMAIL) { - self.warnings.push(format!( - "support.email : invalid value ({}), must be a valid email address", - email_str - )); - if let Some(PhpMixed::Array(support)) = - self.config.get_mut("support").map(|v| v.as_mut()) - { - support.shift_remove("email"); - } + if let Some(email_str) = support_email + && !filter_var(&email_str, FILTER_VALIDATE_EMAIL) + { + self.warnings.push(format!( + "support.email : invalid value ({}), must be a valid email address", + email_str + )); + if let Some(PhpMixed::Array(support)) = + self.config.get_mut("support").map(|v| v.as_mut()) + { + support.shift_remove("email"); } } @@ -422,17 +414,17 @@ impl ValidatingArrayLoader { .and_then(|m| m.get("irc")) .and_then(|v| v.as_string()) .map(|s| s.to_string()); - if let Some(irc_str) = support_irc { - if !self.filter_url(&irc_str, &["irc", "ircs"]) { - self.warnings.push(format!( + if let Some(irc_str) = support_irc + && !self.filter_url(&irc_str, &["irc", "ircs"]) + { + self.warnings.push(format!( "support.irc : invalid value ({}), must be a irc://<server>/<channel> or ircs:// URL", irc_str )); - if let Some(PhpMixed::Array(support)) = - self.config.get_mut("support").map(|v| v.as_mut()) - { - support.shift_remove("irc"); - } + if let Some(PhpMixed::Array(support)) = + self.config.get_mut("support").map(|v| v.as_mut()) + { + support.shift_remove("irc"); } } @@ -446,17 +438,17 @@ impl ValidatingArrayLoader { .and_then(|m| m.get(key)) .and_then(|v| v.as_string()) .map(|s| s.to_string()); - if let Some(url_str) = url_opt { - if !self.filter_url(&url_str, &["http", "https"]) { - self.warnings.push(format!( - "support.{} : invalid value ({}), must be an http/https URL", - key, url_str - )); - if let Some(PhpMixed::Array(support)) = - self.config.get_mut("support").map(|v| v.as_mut()) - { - support.shift_remove(key); - } + if let Some(url_str) = url_opt + && !self.filter_url(&url_str, &["http", "https"]) + { + self.warnings.push(format!( + "support.{} : invalid value ({}), must be an http/https URL", + key, url_str + )); + if let Some(PhpMixed::Array(support)) = + self.config.get_mut("support").map(|v| v.as_mut()) + { + support.shift_remove(key); } } } @@ -476,11 +468,11 @@ impl ValidatingArrayLoader { .unwrap_or_default(); for key in &funding_keys { let funding_option = self.config["funding"].as_array().unwrap()[key].clone(); - if !is_array(&*funding_option) { + if !is_array(&funding_option) { self.errors.push(format!( "funding.{} : should be an array, {} given", key, - get_debug_type(&*funding_option) + get_debug_type(&funding_option) )); if let Some(PhpMixed::Array(funding)) = self.config.get_mut("funding").map(|v| v.as_mut()) @@ -494,21 +486,19 @@ impl ValidatingArrayLoader { .as_array() .and_then(|m| m.get(funding_data)) .cloned(); - if let Some(val) = val_opt { - if !is_string(&*val) { - self.errors.push(format!( - "funding.{}.{} : invalid value, must be a string", - key, funding_data - )); - if let Some(PhpMixed::Array(funding)) = - self.config.get_mut("funding").map(|v| v.as_mut()) - { - if let Some(entry) = funding.get_mut(key) { - if let PhpMixed::Array(em) = entry.as_mut() { - em.shift_remove(funding_data); - } - } - } + if let Some(val) = val_opt + && !is_string(&val) + { + self.errors.push(format!( + "funding.{}.{} : invalid value, must be a string", + key, funding_data + )); + if let Some(PhpMixed::Array(funding)) = + self.config.get_mut("funding").map(|v| v.as_mut()) + && let Some(entry) = funding.get_mut(key) + && let PhpMixed::Array(em) = entry.as_mut() + { + em.shift_remove(funding_data); } } } @@ -517,21 +507,19 @@ impl ValidatingArrayLoader { .and_then(|m| m.get("url")) .and_then(|v| v.as_string()) .map(|s| s.to_string()); - if let Some(url_str) = url { - if !self.filter_url(&url_str, &["http", "https"]) { - self.warnings.push(format!( - "funding.{}.url : invalid value ({}), must be an http/https URL", - key, url_str - )); - if let Some(PhpMixed::Array(funding)) = - self.config.get_mut("funding").map(|v| v.as_mut()) - { - if let Some(entry) = funding.get_mut(key) { - if let PhpMixed::Array(em) = entry.as_mut() { - em.shift_remove("url"); - } - } - } + if let Some(url_str) = url + && !self.filter_url(&url_str, &["http", "https"]) + { + self.warnings.push(format!( + "funding.{}.url : invalid value ({}), must be an http/https URL", + key, url_str + )); + if let Some(PhpMixed::Array(funding)) = + self.config.get_mut("funding").map(|v| v.as_mut()) + && let Some(entry) = funding.get_mut(key) + && let PhpMixed::Array(em) = entry.as_mut() + { + em.shift_remove("url"); } } let entry_empty = self @@ -542,12 +530,11 @@ impl ValidatingArrayLoader { .and_then(|v| v.as_array()) .map(|m| m.is_empty()) .unwrap_or(true); - if entry_empty { - if let Some(PhpMixed::Array(funding)) = + if entry_empty + && let Some(PhpMixed::Array(funding)) = self.config.get_mut("funding").map(|v| v.as_mut()) - { - funding.shift_remove(key); - } + { + funding.shift_remove(key); } } if Self::is_empty_array(self.config.get("funding")) { @@ -576,62 +563,63 @@ impl ValidatingArrayLoader { _ => IndexMap::new(), }; - if let Some(v) = php_ext.get("extension-name").cloned() { - if !is_string(&*v) { - self.errors.push(format!( - "php-ext.extension-name : should be a string, {} given", - get_debug_type(&*v) - )); - php_ext.shift_remove("extension-name"); - } + if let Some(v) = php_ext.get("extension-name").cloned() + && !is_string(&v) + { + self.errors.push(format!( + "php-ext.extension-name : should be a string, {} given", + get_debug_type(&v) + )); + php_ext.shift_remove("extension-name"); } - if let Some(v) = php_ext.get("priority").cloned() { - if !is_int(&*v) { - self.errors.push(format!( - "php-ext.priority : should be an integer, {} given", - get_debug_type(&*v) - )); - php_ext.shift_remove("priority"); - } + if let Some(v) = php_ext.get("priority").cloned() + && !is_int(&v) + { + self.errors.push(format!( + "php-ext.priority : should be an integer, {} given", + get_debug_type(&v) + )); + php_ext.shift_remove("priority"); } - if let Some(v) = php_ext.get("support-zts").cloned() { - if !is_bool(&*v) { - self.errors.push(format!( - "php-ext.support-zts : should be a boolean, {} given", - get_debug_type(&*v) - )); - php_ext.shift_remove("support-zts"); - } + if let Some(v) = php_ext.get("support-zts").cloned() + && !is_bool(&v) + { + self.errors.push(format!( + "php-ext.support-zts : should be a boolean, {} given", + get_debug_type(&v) + )); + php_ext.shift_remove("support-zts"); } - if let Some(v) = php_ext.get("support-nts").cloned() { - if !is_bool(&*v) { - self.errors.push(format!( - "php-ext.support-nts : should be a boolean, {} given", - get_debug_type(&*v) - )); - php_ext.shift_remove("support-nts"); - } + if let Some(v) = php_ext.get("support-nts").cloned() + && !is_bool(&v) + { + self.errors.push(format!( + "php-ext.support-nts : should be a boolean, {} given", + get_debug_type(&v) + )); + php_ext.shift_remove("support-nts"); } - if let Some(v) = php_ext.get("build-path").cloned() { - if !is_string(&*v) && !matches!(v.as_ref(), PhpMixed::Null) { - self.errors.push(format!( - "php-ext.build-path : should be a string or null, {} given", - get_debug_type(&*v) - )); - php_ext.shift_remove("build-path"); - } + if let Some(v) = php_ext.get("build-path").cloned() + && !is_string(&v) + && !matches!(v.as_ref(), PhpMixed::Null) + { + self.errors.push(format!( + "php-ext.build-path : should be a string or null, {} given", + get_debug_type(&v) + )); + php_ext.shift_remove("build-path"); } if php_ext.contains_key("download-url-method") { let v = php_ext["download-url-method"].clone(); - if !is_array(&*v) && !is_string(&*v) { + if !is_array(&v) && !is_string(&v) { self.errors.push(format!( "php-ext.download-url-method : should be an array or a string, {} given", - get_debug_type(&*v) + get_debug_type(&v) )); php_ext.shift_remove("download-url-method"); } else { @@ -641,7 +629,7 @@ impl ValidatingArrayLoader { "pre-packaged-binary", ]; let defined_download_url_methods: IndexMap<String, Box<PhpMixed>> = - if is_array(&*v) { + if is_array(&v) { v.as_array().unwrap().clone() } else { let mut m = IndexMap::new(); @@ -657,11 +645,11 @@ impl ValidatingArrayLoader { php_ext.shift_remove("download-url-method"); } else { for (key, download_url_method) in &defined_download_url_methods { - if !is_string(&**download_url_method) { + if !is_string(download_url_method) { self.errors.push(format!( "php-ext.download-url-method.{} : should be a string, {} given", key, - get_debug_type(&**download_url_method) + get_debug_type(download_url_method) )); php_ext.shift_remove("download-url-method"); } else if !valid_download_url_methods @@ -695,11 +683,11 @@ impl ValidatingArrayLoader { for field_name in ["os-families", "os-families-exclude"] { if let Some(field_val) = php_ext.get(field_name).cloned() { - if !is_array(&*field_val) { + if !is_array(&field_val) { self.errors.push(format!( "php-ext.{} : should be an array, {} given", field_name, - get_debug_type(&*field_val) + get_debug_type(&field_val) )); php_ext.shift_remove(field_name); } else if field_val.as_array().unwrap().is_empty() { @@ -713,12 +701,12 @@ impl ValidatingArrayLoader { field_val.as_array().unwrap().keys().cloned().collect(); for key in &field_keys { let os_family = field_val.as_array().unwrap()[key].clone(); - if !is_string(&*os_family) { + if !is_string(&os_family) { self.errors.push(format!( "php-ext.{}.{} : should be a string, {} given", field_name, key, - get_debug_type(&*os_family) + get_debug_type(&os_family) )); if let Some(PhpMixed::Array(arr)) = php_ext.get_mut(field_name).map(|v| v.as_mut()) @@ -757,10 +745,10 @@ impl ValidatingArrayLoader { if php_ext.contains_key("configure-options") { let configure_options = php_ext["configure-options"].clone(); - if !is_array(&*configure_options) { + if !is_array(&configure_options) { self.errors.push(format!( "php-ext.configure-options : should be an array, {} given", - get_debug_type(&*configure_options) + get_debug_type(&configure_options) )); php_ext.shift_remove("configure-options"); } else { @@ -772,11 +760,11 @@ impl ValidatingArrayLoader { .collect(); for key in &configure_keys { let option = configure_options.as_array().unwrap()[key].clone(); - if !is_array(&*option) { + if !is_array(&option) { self.errors.push(format!( "php-ext.configure-options.{} : should be an array, {} given", key, - get_debug_type(&*option) + get_debug_type(&option) )); if let Some(PhpMixed::Array(arr)) = php_ext.get_mut("configure-options").map(|v| v.as_mut()) @@ -801,11 +789,11 @@ impl ValidatingArrayLoader { } let name_val = option_map["name"].clone(); - if !is_string(&*name_val) { + if !is_string(&name_val) { self.errors.push(format!( "php-ext.configure-options.{}.name : should be a string, {} given", key, - get_debug_type(&*name_val) + get_debug_type(&name_val) )); if let Some(PhpMixed::Array(arr)) = php_ext.get_mut("configure-options").map(|v| v.as_mut()) @@ -815,41 +803,37 @@ impl ValidatingArrayLoader { continue; } - if let Some(needs_value) = option_map.get("needs-value").cloned() { - if !is_bool(&*needs_value) { - self.errors.push(format!( + if let Some(needs_value) = option_map.get("needs-value").cloned() + && !is_bool(&needs_value) + { + self.errors.push(format!( "php-ext.configure-options.{}.needs-value : should be a boolean, {} given", key, - get_debug_type(&*needs_value) + get_debug_type(&needs_value) )); - if let Some(PhpMixed::Array(co)) = - php_ext.get_mut("configure-options").map(|v| v.as_mut()) - { - if let Some(entry) = co.get_mut(key) { - if let PhpMixed::Array(em) = entry.as_mut() { - em.shift_remove("needs-value"); - } - } - } + if let Some(PhpMixed::Array(co)) = + php_ext.get_mut("configure-options").map(|v| v.as_mut()) + && let Some(entry) = co.get_mut(key) + && let PhpMixed::Array(em) = entry.as_mut() + { + em.shift_remove("needs-value"); } } - if let Some(description) = option_map.get("description").cloned() { - if !is_string(&*description) { - self.errors.push(format!( + if let Some(description) = option_map.get("description").cloned() + && !is_string(&description) + { + self.errors.push(format!( "php-ext.configure-options.{}.description : should be a string, {} given", key, - get_debug_type(&*description) + get_debug_type(&description) )); - if let Some(PhpMixed::Array(co)) = - php_ext.get_mut("configure-options").map(|v| v.as_mut()) - { - if let Some(entry) = co.get_mut(key) { - if let PhpMixed::Array(em) = entry.as_mut() { - em.shift_remove("description"); - } - } - } + if let Some(PhpMixed::Array(co)) = + php_ext.get_mut("configure-options").map(|v| v.as_mut()) + && let Some(entry) = co.get_mut(key) + && let PhpMixed::Array(em) = entry.as_mut() + { + em.shift_remove("description"); } } } @@ -885,19 +869,19 @@ impl ValidatingArrayLoader { .unwrap_or_default(); for (package, constraint) in &link_section { let package = package.to_string(); - if let Some(name_val) = self.config.get("name").and_then(|v| v.as_string()) { - if strcasecmp(&package, name_val) == 0 { - self.errors.push(format!( - "{}.{} : a package cannot set a {} on itself", - link_type, package, link_type - )); - if let Some(PhpMixed::Array(arr)) = - self.config.get_mut(link_type).map(|v| v.as_mut()) - { - arr.shift_remove(&package); - } - continue; + if let Some(name_val) = self.config.get("name").and_then(|v| v.as_string()) + && strcasecmp(&package, name_val) == 0 + { + self.errors.push(format!( + "{}.{} : a package cannot set a {} on itself", + link_type, package, link_type + )); + if let Some(PhpMixed::Array(arr)) = + self.config.get_mut(link_type).map(|v| v.as_mut()) + { + arr.shift_remove(&package); } + continue; } if let Some(err) = Self::has_package_naming_error(&package, true) { self.warnings.push(format!("{}.{}", link_type, err)); @@ -907,7 +891,7 @@ impl ValidatingArrayLoader { link_type, package )); } - if !is_string(&**constraint) { + if !is_string(constraint) { self.errors.push(format!( "{}.{} : invalid value, must be a string containing a version constraint", link_type, package @@ -950,7 +934,7 @@ impl ValidatingArrayLoader { && link_type == "require" && link_constraint .as_constraint() - .map_or(false, |c| ["==", "="].contains(&c.get_operator())) + .is_some_and(|c| ["==", "="].contains(&c.get_operator())) && AnyConstraint::from(SimpleConstraint::new( ">=".to_string(), "1.0.0.0-dev".to_string(), @@ -1017,7 +1001,7 @@ impl ValidatingArrayLoader { .cloned() .unwrap_or_default(); for (package, description) in &suggest_map { - if !is_string(&**description) { + if !is_string(description) { self.errors.push(format!( "suggest.{} : invalid value, must be a string describing why the package is suggested", package @@ -1076,16 +1060,16 @@ impl ValidatingArrayLoader { arr.shift_remove(r#type); } } - if r#type == "psr-4" { - if let Some(type_map) = type_config.as_array() { - for (namespace, _dirs) in type_map { - let ns_str = namespace.as_str(); - if ns_str != "" && substr(ns_str, -1, None) != "\\" { - self.errors.push(format!( + if r#type == "psr-4" + && let Some(type_map) = type_config.as_array() + { + for (namespace, _dirs) in type_map { + let ns_str = namespace.as_str(); + if !ns_str.is_empty() && substr(ns_str, -1, None) != "\\" { + self.errors.push(format!( "autoload.psr-4 : invalid value ({}), namespaces must end with a namespace separator, should be {}\\\\", ns_str, ns_str )); - } } } } @@ -1132,35 +1116,36 @@ impl ValidatingArrayLoader { self.errors .push(format!("{}.reference : must be present", src_type)); } - if let Some(type_val) = section.get("type") { - if !is_string(&**type_val) { - self.errors.push(format!( - "{}.type : should be a string, {} given", - src_type, - get_debug_type(&**type_val) - )); - } + if let Some(type_val) = section.get("type") + && !is_string(type_val) + { + self.errors.push(format!( + "{}.type : should be a string, {} given", + src_type, + get_debug_type(type_val) + )); } - if let Some(url_val) = section.get("url") { - if !is_string(&**url_val) { - self.errors.push(format!( - "{}.url : should be a string, {} given", - src_type, - get_debug_type(&**url_val) - )); - } + if let Some(url_val) = section.get("url") + && !is_string(url_val) + { + self.errors.push(format!( + "{}.url : should be a string, {} given", + src_type, + get_debug_type(url_val) + )); } - if let Some(ref_val) = section.get("reference") { - if !is_string(&**ref_val) && !is_int(&**ref_val) { - self.errors.push(format!( - "{}.reference : should be a string or int, {} given", - src_type, - get_debug_type(&**ref_val) - )); - } + if let Some(ref_val) = section.get("reference") + && !is_string(ref_val) + && !is_int(ref_val) + { + self.errors.push(format!( + "{}.reference : should be a string or int, {} given", + src_type, + get_debug_type(ref_val) + )); } if let Some(ref_val) = section.get("reference") { - let ref_str = php_to_string(&**ref_val); + let ref_str = php_to_string(ref_val); if Preg::is_match("{^\\s*-}", &ref_str) { self.errors.push(format!( "{}.reference : must not start with a \"-\", \"{}\" given", @@ -1169,7 +1154,7 @@ impl ValidatingArrayLoader { } } if let Some(url_val) = section.get("url") { - let url_str = php_to_string(&**url_val); + let url_str = php_to_string(url_val); if Preg::is_match("{^\\s*-}", &url_str) { self.errors.push(format!( "{}.url : must not start with a \"-\", \"{}\" given", @@ -1195,28 +1180,26 @@ impl ValidatingArrayLoader { .unwrap_or(false); if has_branch_alias { let branch_alias_val = self.config["extra"].as_array().unwrap()["branch-alias"].clone(); - if !is_array(&*branch_alias_val) { + if !is_array(&branch_alias_val) { self.errors.push( "extra.branch-alias : must be an array of versions => aliases".to_string(), ); } else { let branch_alias_map = branch_alias_val.as_array().cloned().unwrap_or_default(); for (source_branch, target_branch) in &branch_alias_map { - if !is_string(&**target_branch) { + if !is_string(target_branch) { self.warnings.push(format!( "extra.branch-alias.{} : the target branch ({}) must be a string, \"{}\" received.", source_branch, json_encode(&**target_branch).unwrap_or_default(), - get_debug_type(&**target_branch) + get_debug_type(target_branch) )); if let Some(PhpMixed::Array(extra)) = self.config.get_mut("extra").map(|v| v.as_mut()) + && let Some(ba) = extra.get_mut("branch-alias") + && let PhpMixed::Array(bam) = ba.as_mut() { - if let Some(ba) = extra.get_mut("branch-alias") { - if let PhpMixed::Array(bam) = ba.as_mut() { - bam.shift_remove(source_branch); - } - } + bam.shift_remove(source_branch); } continue; } @@ -1231,12 +1214,10 @@ impl ValidatingArrayLoader { )); if let Some(PhpMixed::Array(extra)) = self.config.get_mut("extra").map(|v| v.as_mut()) + && let Some(ba) = extra.get_mut("branch-alias") + && let PhpMixed::Array(bam) = ba.as_mut() { - if let Some(ba) = extra.get_mut("branch-alias") { - if let PhpMixed::Array(bam) = ba.as_mut() { - bam.shift_remove(source_branch); - } - } + bam.shift_remove(source_branch); } continue; } @@ -1255,12 +1236,10 @@ impl ValidatingArrayLoader { )); if let Some(PhpMixed::Array(extra)) = self.config.get_mut("extra").map(|v| v.as_mut()) + && let Some(ba) = extra.get_mut("branch-alias") + && let PhpMixed::Array(bam) = ba.as_mut() { - if let Some(ba) = extra.get_mut("branch-alias") { - if let PhpMixed::Array(bam) = ba.as_mut() { - bam.shift_remove(source_branch); - } - } + bam.shift_remove(source_branch); } continue; } @@ -1272,21 +1251,19 @@ impl ValidatingArrayLoader { let target_prefix = self .version_parser .parse_numeric_alias_prefix(&target_branch_str); - if let (Some(sp), Some(tp)) = (source_prefix, target_prefix) { - if !tp.to_lowercase().starts_with(&sp.to_lowercase()) { - self.warnings.push(format!( + if let (Some(sp), Some(tp)) = (source_prefix, target_prefix) + && !tp.to_lowercase().starts_with(&sp.to_lowercase()) + { + self.warnings.push(format!( "extra.branch-alias.{} : the target branch ({}) is not a valid numeric alias for this version", source_branch, target_branch_str )); - if let Some(PhpMixed::Array(extra)) = - self.config.get_mut("extra").map(|v| v.as_mut()) - { - if let Some(ba) = extra.get_mut("branch-alias") { - if let PhpMixed::Array(bam) = ba.as_mut() { - bam.shift_remove(source_branch); - } - } - } + if let Some(PhpMixed::Array(extra)) = + self.config.get_mut("extra").map(|v| v.as_mut()) + && let Some(ba) = extra.get_mut("branch-alias") + && let PhpMixed::Array(bam) = ba.as_mut() + { + bam.shift_remove(source_branch); } } } @@ -1410,11 +1387,11 @@ impl ValidatingArrayLoader { } fn validate_string(&mut self, property: &str, mandatory: bool) -> bool { - if self.config.contains_key(property) && !is_string(&*self.config[property]) { + if self.config.contains_key(property) && !is_string(&self.config[property]) { self.errors.push(format!( "{} : should be a string, {} given", property, - get_debug_type(&*self.config[property]) + get_debug_type(&self.config[property]) )); self.config.shift_remove(property); @@ -1425,7 +1402,8 @@ impl ValidatingArrayLoader { || trim( self.config[property].as_string().unwrap_or(""), Some(" \t\n\r\0\u{0B}"), - ) == ""; + ) + .is_empty(); if is_empty { if mandatory { self.errors.push(format!("{} : must be present", property)); @@ -1439,11 +1417,11 @@ impl ValidatingArrayLoader { } fn validate_array(&mut self, property: &str, mandatory: bool) -> bool { - if self.config.contains_key(property) && !is_array(&*self.config[property]) { + if self.config.contains_key(property) && !is_array(&self.config[property]) { self.errors.push(format!( "{} : should be an array, {} given", property, - get_debug_type(&*self.config[property]) + get_debug_type(&self.config[property]) )); self.config.shift_remove(property); @@ -1486,12 +1464,12 @@ impl ValidatingArrayLoader { .map(|m| m.iter().map(|(k, v)| (k.clone(), v.clone())).collect()) .unwrap_or_default(); for (key, value) in entries { - if !is_string(&*value) && !is_numeric(&*value) { + if !is_string(&value) && !is_numeric(&value) { self.errors.push(format!( "{}.{} : must be a string or int, {} given", property, key, - get_debug_type(&*value) + get_debug_type(&value) )); if let Some(PhpMixed::Array(arr)) = self.config.get_mut(property).map(|v| v.as_mut()) @@ -1504,7 +1482,7 @@ impl ValidatingArrayLoader { } if let Some(regex_str) = regex { - let value_str = php_to_string(&*value); + let value_str = php_to_string(&value); if !Preg::is_match(&format!("{{^{}$}}u", regex_str), &value_str) { self.warnings.push(format!( "{}.{} : invalid value ({}), must match {}", @@ -1543,7 +1521,7 @@ impl ValidatingArrayLoader { } fn filter_url(&self, value: &str, schemes: &[&str]) -> bool { - if value == "" { + if value.is_empty() { return true; } diff --git a/crates/shirabe/src/package/locker.rs b/crates/shirabe/src/package/locker.rs index 1a16c27..369433e 100644 --- a/crates/shirabe/src/package/locker.rs +++ b/crates/shirabe/src/package/locker.rs @@ -240,33 +240,33 @@ impl Locker { } } - if let Some(aliases) = lock_data.get("aliases") { - if let PhpMixed::List(alias_list) = aliases { - for alias in alias_list { - if let PhpMixed::Array(m) = alias.as_ref() { - let alias_pkg_name = m - .get("package") - .and_then(|v| v.as_string()) - .unwrap_or("") - .to_string(); - if let Some(base_pkg) = package_by_name.get(&alias_pkg_name) { - let alias_of = base_pkg.as_complete_package().expect( + if let Some(aliases) = lock_data.get("aliases") + && let PhpMixed::List(alias_list) = aliases + { + for alias in alias_list { + if let PhpMixed::Array(m) = alias.as_ref() { + let alias_pkg_name = m + .get("package") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(); + if let Some(base_pkg) = package_by_name.get(&alias_pkg_name) { + let alias_of = base_pkg.as_complete_package().expect( "CompleteAliasPackage requires aliasOf to be a real CompletePackage", ); - let alias_pkg = CompleteAliasPackageHandle::new( - alias_of, - m.get("alias_normalized") - .and_then(|v| v.as_string()) - .unwrap_or("") - .to_string(), - m.get("alias") - .and_then(|v| v.as_string()) - .unwrap_or("") - .to_string(), - ); - alias_pkg.set_root_package_alias(true); - packages.add_package(alias_pkg.into())?; - } + let alias_pkg = CompleteAliasPackageHandle::new( + alias_of, + m.get("alias_normalized") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(), + m.get("alias") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(), + ); + alias_pkg.set_root_package_alias(true); + packages.add_package(alias_pkg.into())?; } } } @@ -465,6 +465,7 @@ impl Locker { } /// Locks provided data into lockfile. + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn set_lock_data( &mut self, packages: Vec<PackageInterfaceHandle>, @@ -585,7 +586,7 @@ impl Locker { .collect(), ), ); - if platform_overrides.len() > 0 { + if !platform_overrides.is_empty() { lock.insert( "platform-overrides".to_string(), PhpMixed::Array( @@ -663,7 +664,7 @@ impl Locker { where F: FnOnce(IndexMap<String, PhpMixed>) -> IndexMap<String, PhpMixed>, { - let contents = file_get_contents(&composer_json.get_path()); + let contents = file_get_contents(composer_json.get_path()); let contents = match contents { Some(s) => s, None => { @@ -678,7 +679,7 @@ impl Locker { } }; - let lock_mtime = filemtime(&self.lock_file.get_path()); + let lock_mtime = filemtime(self.lock_file.get_path()); let lock_data_php = self.lock_file.read()?; let mut lock_data: IndexMap<String, PhpMixed> = match lock_data_php { PhpMixed::Array(m) => m.into_iter().map(|(k, v)| (k, *v)).collect(), @@ -700,10 +701,10 @@ impl Locker { ))?; *self.lock_data_cache.borrow_mut() = None; self.virtual_file_written = false; - if let Some(mtime) = lock_mtime { - if is_int(&PhpMixed::Int(mtime)) { - let _ = touch2(&self.lock_file.get_path(), mtime); - } + if let Some(mtime) = lock_mtime + && is_int(&PhpMixed::Int(mtime)) + { + let _ = touch2(self.lock_file.get_path(), mtime); } Ok(()) } @@ -930,7 +931,7 @@ impl Locker { method: "getRequires".to_string(), description: "Required".to_string(), }]; - if include_dev == true { + if include_dev { sets.push(SetEntry { repo: self.get_locked_repository(true)?, method: "getDevRequires".to_string(), @@ -949,7 +950,7 @@ impl Locker { _ => unreachable!(), }; for link in links.values() { - if PlatformRepository::is_platform_package(&link.get_target()) { + if PlatformRepository::is_platform_package(link.get_target()) { continue; } if link.get_pretty_constraint() == "self.version" { @@ -957,7 +958,7 @@ impl Locker { } if installed_repo .find_packages_with_replacers_and_providers( - &link.get_target(), + link.get_target(), Some(FindPackageConstraint::Constraint( link.get_constraint().clone(), )), @@ -965,7 +966,7 @@ impl Locker { .is_empty() { let results = installed_repo - .find_packages_with_replacers_and_providers(&link.get_target(), None)?; + .find_packages_with_replacers_and_providers(link.get_target(), None)?; if !results.is_empty() { // PHP `reset($results)` returns the first shared package; clone the handle. diff --git a/crates/shirabe/src/package/mod.rs b/crates/shirabe/src/package/mod.rs index 903056f..912ac17 100644 --- a/crates/shirabe/src/package/mod.rs +++ b/crates/shirabe/src/package/mod.rs @@ -10,6 +10,7 @@ pub mod handle; pub mod link; pub mod loader; pub mod locker; +#[allow(clippy::module_inception, reason = "to port PHP's structure as it is")] pub mod package; pub mod package_interface; pub mod root_alias_package; diff --git a/crates/shirabe/src/package/package.rs b/crates/shirabe/src/package/package.rs index 8ef93be..a579baa 100644 --- a/crates/shirabe/src/package/package.rs +++ b/crates/shirabe/src/package/package.rs @@ -719,14 +719,14 @@ impl PackageInterface for Package { self.php_ext.clone() } fn set_repository(&mut self, repository: RepositoryInterfaceHandle) -> anyhow::Result<()> { - if let Some(existing) = self.repository.as_ref().and_then(|w| w.upgrade()) { - if !Rc::ptr_eq(&existing, repository.as_rc()) { - return Err(LogicException { - message: "A package can only be added to one repository".to_string(), - code: 0, - } - .into()); + if let Some(existing) = self.repository.as_ref().and_then(|w| w.upgrade()) + && !Rc::ptr_eq(&existing, repository.as_rc()) + { + return Err(LogicException { + message: "A package can only be added to one repository".to_string(), + code: 0, } + .into()); } self.repository = Some(repository.downgrade()); Ok(()) diff --git a/crates/shirabe/src/package/version/stability_filter.rs b/crates/shirabe/src/package/version/stability_filter.rs index da2f1a6..0bcfe4a 100644 --- a/crates/shirabe/src/package/version/stability_filter.rs +++ b/crates/shirabe/src/package/version/stability_filter.rs @@ -15,10 +15,10 @@ impl StabilityFilter { for name in names { // allow if package matches the package-specific stability flag if let Some(&flag) = stability_flags.get(name) { - if let Some(&stability_value) = STABILITIES.get(stability) { - if stability_value <= flag { - return true; - } + if let Some(&stability_value) = STABILITIES.get(stability) + && stability_value <= flag + { + return true; } } else if acceptable_stabilities.contains_key(stability) { // allow if package matches the global stability requirement and has no exception diff --git a/crates/shirabe/src/package/version/version_guesser.rs b/crates/shirabe/src/package/version/version_guesser.rs index 4eb3864..5d41434 100644 --- a/crates/shirabe/src/package/version/version_guesser.rs +++ b/crates/shirabe/src/package/version/version_guesser.rs @@ -90,10 +90,10 @@ impl VersionGuesser { } let version_data = self.guess_hg_version(package_config, path)?; - if let Some(vd) = version_data { - if vd.version.is_some() { - return Ok(Some(self.postprocess(vd))); - } + if let Some(vd) = version_data + && vd.version.is_some() + { + return Ok(Some(self.postprocess(vd))); } let version_data = self.guess_fossil_version(path)?; @@ -102,10 +102,10 @@ impl VersionGuesser { } let version_data = self.guess_svn_version(package_config, path)?; - if let Some(vd) = version_data { - if vd.version.is_some() { - return Ok(Some(self.postprocess(vd))); - } + if let Some(vd) = version_data + && vd.version.is_some() + { + return Ok(Some(self.postprocess(vd))); } Ok(None) @@ -173,7 +173,7 @@ impl VersionGuesser { package_config: &IndexMap<String, PhpMixed>, path: &str, ) -> Result<VersionData> { - GitUtil::clean_env(&mut self.process); + GitUtil::clean_env(&self.process); let mut commit: Option<String> = None; let mut version: Option<String> = None; let mut pretty_version: Option<String> = None; @@ -263,7 +263,7 @@ impl VersionGuesser { } } GitUtil::check_for_repo_ownership_error( - &self.process.borrow().get_error_output(), + self.process.borrow().get_error_output(), path, self.io.clone(), ); diff --git a/crates/shirabe/src/package/version/version_parser.rs b/crates/shirabe/src/package/version/version_parser.rs index e600c37..87fa6c8 100644 --- a/crates/shirabe/src/package/version/version_parser.rs +++ b/crates/shirabe/src/package/version/version_parser.rs @@ -18,6 +18,12 @@ pub struct VersionParser { inner: SemverVersionParser, } +impl Default for VersionParser { + fn default() -> Self { + Self::new() + } +} + impl VersionParser { pub const DEFAULT_BRANCH_ALIAS: &'static str = "9999999-dev"; @@ -45,7 +51,7 @@ impl VersionParser { let count = pairs.len(); let mut i = 0_usize; while i < count { - let mut pair = Preg::replace(r"{^([^=: ]+)[=: ](.*)$}", "$1 $2", &pairs[i].trim()); + let mut pair = Preg::replace(r"{^([^=: ]+)[=: ](.*)$}", "$1 $2", pairs[i].trim()); if !pair.contains(' ') && i + 1 < count && !pairs[i + 1].contains('/') diff --git a/crates/shirabe/src/package/version/version_selector.rs b/crates/shirabe/src/package/version/version_selector.rs index 872ca93..0d69132 100644 --- a/crates/shirabe/src/package/version/version_selector.rs +++ b/crates/shirabe/src/package/version/version_selector.rs @@ -59,6 +59,7 @@ impl VersionSelector { }) } + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn find_best_candidate( &mut self, package_name: &str, @@ -92,7 +93,7 @@ impl VersionSelector { }; let mut candidates = self.repository_set.borrow().find_packages( &strtolower(package_name), - constraint.as_ref().map(|c| c.clone()), + constraint.clone(), repo_set_flags, )?; @@ -158,16 +159,16 @@ impl VersionSelector { .as_any() .downcast_ref::<IgnoreListPlatformRequirementFilter>( ); - if let Some(list_filter) = list_filter_opt { - if list_filter.is_upper_bound_ignored(name) { - let filtered_constraint = list_filter.filter_constraint( - name, - link.get_constraint().clone(), - false, - )?; - if filtered_constraint.matches(provided_constraint) { - continue 'reqs; - } + if let Some(list_filter) = list_filter_opt + && list_filter.is_upper_bound_ignored(name) + { + let filtered_constraint = list_filter.filter_constraint( + name, + link.get_constraint().clone(), + false, + )?; + if filtered_constraint.matches(provided_constraint) { + continue 'reqs; } } } @@ -220,13 +221,13 @@ impl VersionSelector { continue; } - found_package = Some(pkg.clone().into()); + found_package = Some(pkg.clone()); break; } package = found_package; } else { package = if !candidates.is_empty() { - Some(candidates.remove(0).into()) + Some(candidates.remove(0)) } else { None }; @@ -279,14 +280,13 @@ impl VersionSelector { let loader = ArrayLoader::new(Some(self.get_parser().clone()), false); let dumper = ArrayDumper::new(); let extra = loader.get_branch_alias(&dumper.dump(package.clone()))?; - if let Some(extra) = extra { - if extra != VersionParser::DEFAULT_BRANCH_ALIAS { - let new_extra = - Preg::replace(r"{^(\d+\.\d+\.\d+)(\.9999999)-dev$}", "$1.0", &extra); - if new_extra != extra { - let new_extra = new_extra.replace(".9999999", ".0"); - return self.transform_version(&new_extra, &new_extra, "dev"); - } + if let Some(extra) = extra + && extra != VersionParser::DEFAULT_BRANCH_ALIAS + { + let new_extra = Preg::replace(r"{^(\d+\.\d+\.\d+)(\.9999999)-dev$}", "$1.0", &extra); + if new_extra != extra { + let new_extra = new_extra.replace(".9999999", ".0"); + return self.transform_version(&new_extra, &new_extra, "dev"); } } diff --git a/crates/shirabe/src/plugin/capability/mod.rs b/crates/shirabe/src/plugin/capability/mod.rs index d9874b4..5b7dcea 100644 --- a/crates/shirabe/src/plugin/capability/mod.rs +++ b/crates/shirabe/src/plugin/capability/mod.rs @@ -1,3 +1,4 @@ +#[allow(clippy::module_inception, reason = "to port PHP's structure as it is")] pub mod capability; pub mod command_provider; diff --git a/crates/shirabe/src/plugin/plugin_interface.rs b/crates/shirabe/src/plugin/plugin_interface.rs index c0212de..d335bf0 100644 --- a/crates/shirabe/src/plugin/plugin_interface.rs +++ b/crates/shirabe/src/plugin/plugin_interface.rs @@ -6,7 +6,7 @@ use crate::plugin::Capable; use std::cell::RefCell; use std::rc::Rc; -pub const PLUGIN_API_VERSION: &'static str = "2.9.0"; +pub const PLUGIN_API_VERSION: &str = "2.9.0"; pub trait PluginInterface: std::fmt::Debug { fn activate(&mut self, composer: &ComposerHandle, io: Rc<RefCell<dyn IOInterface>>); diff --git a/crates/shirabe/src/plugin/plugin_manager.rs b/crates/shirabe/src/plugin/plugin_manager.rs index 25953ab..e8377f3 100644 --- a/crates/shirabe/src/plugin/plugin_manager.rs +++ b/crates/shirabe/src/plugin/plugin_manager.rs @@ -460,7 +460,7 @@ impl PluginManager { // — add_subscriber here is generic over `S: EventSubscriberInterface` and cannot // accept a `&dyn EventSubscriberInterface`. Skipped until subscriber dispatch is // implemented dynamically. - let _ = (&*plugin).is_event_subscriber_interface(); + let _ = (*plugin).is_event_subscriber_interface(); self.plugins.push(plugin); Ok(()) } @@ -520,10 +520,7 @@ impl PluginManager { } } - let sorted_packages = PackageSorter::sort_packages( - packages.iter().map(|p| p.clone().into()).collect(), - weights, - ); + let sorted_packages = PackageSorter::sort_packages(packages.to_vec(), weights); let required_packages: Vec<crate::package::BasePackageHandle> = if !is_global_repo { // PHP: $requiredPackages = RepositoryUtils::filterRequiredPackages($packages, $rootPackage, true); let bucket: Vec<crate::package::BasePackageHandle> = vec![]; @@ -582,10 +579,7 @@ impl PluginManager { // TODO(plugin): deactivate plugins from a repository let packages = repo.get_packages()?; // PHP: $sortedPackages = array_reverse(PackageSorter::sortPackages($packages)); - let mut sorted_packages = PackageSorter::sort_packages( - packages.iter().map(|p| p.clone().into()).collect(), - IndexMap::new(), - ); + let mut sorted_packages = PackageSorter::sort_packages(packages.to_vec(), IndexMap::new()); sorted_packages.reverse(); for package in &sorted_packages { @@ -615,11 +609,11 @@ impl PluginManager { .find_packages_with_replacers_and_providers(require_link.get_target(), None)? { if !collected.contains_key(&required_package.get_name()) { - collected.insert(required_package.get_name(), required_package.clone().into()); + collected.insert(required_package.get_name(), required_package.clone()); collected = self.collect_dependencies( installed_repo, collected, - required_package.clone().into(), + required_package.clone(), )?; } } @@ -794,12 +788,12 @@ impl PluginManager { } pub fn are_plugins_disabled(&self, r#type: &str) -> bool { - match (&self.disable_plugins, r#type) { - (DisablePlugins::All, _) => true, - (DisablePlugins::Local, "local") => true, - (DisablePlugins::Global, "global") => true, - _ => false, - } + matches!( + (&self.disable_plugins, r#type), + (DisablePlugins::All, _) + | (DisablePlugins::Local, "local") + | (DisablePlugins::Global, "global") + ) } pub fn disable_plugins(&mut self) { diff --git a/crates/shirabe/src/repository/array_repository.rs b/crates/shirabe/src/repository/array_repository.rs index cfc804f..7f99c1c 100644 --- a/crates/shirabe/src/repository/array_repository.rs +++ b/crates/shirabe/src/repository/array_repository.rs @@ -46,13 +46,7 @@ impl ArrayRepository { "initialize failed to initialize the packages array" ); - self.packages - .borrow() - .as_ref() - .unwrap() - .iter() - .map(|p| p.clone()) - .collect() + self.packages.borrow().as_ref().unwrap().to_vec() } /// @param array<PackageInterface> $packages @@ -295,8 +289,8 @@ impl RepositoryInterface for ArrayRepository { }; for package in self.get_packages_internal() { - if name == package.get_name() { - if constraint.is_none() + if name == package.get_name() + && (constraint.is_none() || constraint.as_ref().unwrap().matches( &SimpleConstraint::new( "==".to_string(), @@ -304,10 +298,9 @@ impl RepositoryInterface for ArrayRepository { None, ) .into(), - ) - { - packages.push(package); - } + )) + { + packages.push(package); } } @@ -340,10 +333,10 @@ impl RepositoryInterface for ArrayRepository { if matches.contains_key(&name) { continue; } - if let Some(t) = &r#type { - if package.get_type() != *t { - continue; - } + if let Some(t) = &r#type + && package.get_type() != *t + { + continue; } let complete = package.as_complete(); diff --git a/crates/shirabe/src/repository/composer_repository.rs b/crates/shirabe/src/repository/composer_repository.rs index 4cc106f..618d375 100644 --- a/crates/shirabe/src/repository/composer_repository.rs +++ b/crates/shirabe/src/repository/composer_repository.rs @@ -190,13 +190,12 @@ impl ComposerRepository { .into()); } - if url_after.starts_with("https?") { + if let Some(rest) = url_after.strip_prefix("https?") { let scheme = if extension_loaded("openssl") { "https" } else { "http" }; - let rest = &url_after[6..]; repo_config.insert( "url".to_string(), PhpMixed::String(format!("{}{}", scheme, rest)), @@ -213,7 +212,7 @@ impl ComposerRepository { let scheme_present = url_bits_arr .and_then(|a| a.get("scheme")) .and_then(|v| v.as_string()) - .map_or(false, |s| !s.is_empty()); + .is_some_and(|s| !s.is_empty()); if url_bits_arr.is_none() || !scheme_present { return Err(UnexpectedValueException { message: format!("Invalid url given for Composer repository: {}", current_url), @@ -226,10 +225,10 @@ impl ComposerRepository { repo_config.insert("options".to_string(), PhpMixed::Array(IndexMap::new())); } let mut allow_ssl_downgrade = false; - if let Some(v) = repo_config.get("allow_ssl_downgrade") { - if v.as_bool() == Some(true) { - allow_ssl_downgrade = true; - } + if let Some(v) = repo_config.get("allow_ssl_downgrade") + && v.as_bool() == Some(true) + { + allow_ssl_downgrade = true; } let options = repo_config @@ -372,19 +371,17 @@ impl ComposerRepository { let has_providers = self.has_providers()?; if self.lazy_providers_url.is_some() { - if let Some(ref available_packages) = self.available_packages.clone() { - if self.available_package_patterns.is_none() { - let mut package_map: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); - for name in available_packages.values() { - package_map - .insert(name.clone(), Some(MatchAllConstraint::new(None).into())); - } + if let Some(ref available_packages) = self.available_packages.clone() + && self.available_package_patterns.is_none() + { + let mut package_map: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); + for name in available_packages.values() { + package_map.insert(name.clone(), Some(MatchAllConstraint::new(None).into())); + } - let result = - self.load_async_packages(package_map, None, None, IndexMap::new())?; + let result = self.load_async_packages(package_map, None, None, IndexMap::new())?; - return Ok(result.packages.into_values().collect()); - } + return Ok(result.packages.into_values().collect()); } if self.has_partial_packages()? { @@ -418,7 +415,7 @@ impl ComposerRepository { }.into()); } - Ok(self.inner.get_packages()?) + self.inner.get_packages() } /// @param packageFilter Package pattern filter which can include "*" as a wildcard @@ -482,21 +479,19 @@ impl ComposerRepository { fn get_vendor_names(&mut self) -> anyhow::Result<Vec<String>> { let cache_key = "vendor-list.txt"; let cache_age = self.cache.get_age(cache_key); - if let Some(age) = cache_age { - if age < 600 { - if let Some(cached_data) = self.cache.read(cache_key) { - let cached_data: Vec<String> = - cached_data.split('\n').map(|s| s.to_string()).collect(); - return Ok(cached_data); - } - } + if let Some(age) = cache_age + && age < 600 + && let Some(cached_data) = self.cache.read(cache_key) + { + let cached_data: Vec<String> = cached_data.split('\n').map(|s| s.to_string()).collect(); + return Ok(cached_data); } let names = self.get_package_names(None)?; let mut uniques: IndexMap<String, bool> = IndexMap::new(); for name in &names { - let vendor = name.splitn(2, '/').next().unwrap_or("").to_string(); + let vendor = name.split('/').next().unwrap_or("").to_string(); uniques.insert(vendor, true); } @@ -519,39 +514,37 @@ impl ComposerRepository { } let mut url = self.list_url.clone().unwrap(); - if let Some(filter) = package_filter { - if !filter.is_empty() { - url.push_str(&format!("?filter={}", urlencode(filter))); - let result = self - .http_downloader - .borrow_mut() - .get(&url, self.options.clone())? - .decode_json()?; - let package_names: Vec<String> = result - .as_array() - .and_then(|a| a.get("packageNames")) - .and_then(|v| v.as_list()) - .map(|l| { - l.iter() - .filter_map(|v| v.as_string().map(|s| s.to_string())) - .collect() - }) - .unwrap_or_default(); + if let Some(filter) = package_filter + && !filter.is_empty() + { + url.push_str(&format!("?filter={}", urlencode(filter))); + let result = self + .http_downloader + .borrow_mut() + .get(&url, self.options.clone())? + .decode_json()?; + let package_names: Vec<String> = result + .as_array() + .and_then(|a| a.get("packageNames")) + .and_then(|v| v.as_list()) + .map(|l| { + l.iter() + .filter_map(|v| v.as_string().map(|s| s.to_string())) + .collect() + }) + .unwrap_or_default(); - return Ok(package_names); - } + return Ok(package_names); } let cache_key = "package-list.txt"; let cache_age = self.cache.get_age(cache_key); - if let Some(age) = cache_age { - if age < 600 { - if let Some(cached_data) = self.cache.read(cache_key) { - let cached_data: Vec<String> = - cached_data.split('\n').map(|s| s.to_string()).collect(); - return Ok(cached_data); - } - } + if let Some(age) = cache_age + && age < 600 + && let Some(cached_data) = self.cache.read(cache_key) + { + let cached_data: Vec<String> = cached_data.split('\n').map(|s| s.to_string()).collect(); + return Ok(cached_data); } let result = self @@ -610,7 +603,7 @@ impl ComposerRepository { && !self .partial_packages_by_name .as_ref() - .map_or(false, |m| m.contains_key(&name)) + .is_some_and(|m| m.contains_key(&name)) { continue; } @@ -621,9 +614,7 @@ impl ComposerRepository { Some(&stability_flags), already_loaded.clone(), )?; - let constraint = package_name_map - .get(&name) - .and_then(|c| c.as_ref().map(|c| c.clone())); + let constraint = package_name_map.get(&name).and_then(|c| c.clone()); for (_uid, candidate) in candidates.iter() { if candidate.get_name() != name { return Err(LogicException { @@ -715,61 +706,61 @@ impl ComposerRepository { ) -> anyhow::Result<Vec<IndexMap<String, PhpMixed>>> { self.load_root_server_file(Some(600))?; - if let Some(search_url) = self.search_url.clone() { - if mode == SEARCH_FULLTEXT { - let url = search_url - .replace("%query%", &urlencode(&query)) - .replace("%type%", r#type.as_deref().unwrap_or("")); + if let Some(search_url) = self.search_url.clone() + && mode == SEARCH_FULLTEXT + { + let url = search_url + .replace("%query%", &urlencode(&query)) + .replace("%type%", r#type.as_deref().unwrap_or("")); - let search = self - .http_downloader - .borrow_mut() - .get(&url, self.options.clone())? - .decode_json()?; + let search = self + .http_downloader + .borrow_mut() + .get(&url, self.options.clone())? + .decode_json()?; - let results_arr = search - .as_array() - .and_then(|a| a.get("results")) - .and_then(|v| v.as_list()) - .cloned() - .unwrap_or_default(); - if results_arr.is_empty() { - return Ok(vec![]); - } + let results_arr = search + .as_array() + .and_then(|a| a.get("results")) + .and_then(|v| v.as_list()) + .cloned() + .unwrap_or_default(); + if results_arr.is_empty() { + return Ok(vec![]); + } - let mut results: Vec<IndexMap<String, PhpMixed>> = Vec::new(); - for result in results_arr.iter() { - let arr = match result.as_array() { - Some(a) => a, - None => continue, + let mut results: Vec<IndexMap<String, PhpMixed>> = Vec::new(); + for result in results_arr.iter() { + let arr = match result.as_array() { + Some(a) => a, + None => continue, + }; + // do not show virtual packages in results as they are not directly useful from a composer perspective + if let Some(v) = arr.get("virtual") { + // PHP's `empty()` is false when the value is truthy + let is_empty = match &**v { + PhpMixed::Null => true, + PhpMixed::Bool(false) => true, + PhpMixed::Int(0) => true, + PhpMixed::Float(f) if *f == 0.0 => true, + PhpMixed::String(s) if s.is_empty() || s == "0" => true, + PhpMixed::List(l) if l.is_empty() => true, + PhpMixed::Array(a) if a.is_empty() => true, + _ => false, }; - // do not show virtual packages in results as they are not directly useful from a composer perspective - if let Some(v) = arr.get("virtual") { - // PHP's `empty()` is false when the value is truthy - let is_empty = match &**v { - PhpMixed::Null => true, - PhpMixed::Bool(false) => true, - PhpMixed::Int(0) => true, - PhpMixed::Float(f) if *f == 0.0 => true, - PhpMixed::String(s) if s.is_empty() || s == "0" => true, - PhpMixed::List(l) if l.is_empty() => true, - PhpMixed::Array(a) if a.is_empty() => true, - _ => false, - }; - if !is_empty { - continue; - } + if !is_empty { + continue; } - - results.push( - arr.iter() - .map(|(k, v)| (k.clone(), (**v).clone())) - .collect(), - ); } - return Ok(results); + results.push( + arr.iter() + .map(|(k, v)| (k.clone(), (**v).clone())) + .collect(), + ); } + + return Ok(results); } if mode == SEARCH_VENDOR { @@ -888,7 +879,7 @@ impl ComposerRepository { Ok(self .security_advisory_config .as_ref() - .map_or(false, |c| c.metadata || c.api_url.is_some())) + .is_some_and(|c| c.metadata || c.api_url.is_some())) } /// @inheritDoc @@ -965,7 +956,7 @@ impl ComposerRepository { if self .security_advisory_config .as_ref() - .map_or(false, |c| c.metadata) + .is_some_and(|c| c.metadata) && (allow_partial_advisories || api_url.is_none()) { let names: Vec<String> = package_constraint_map.keys().cloned().collect(); @@ -1019,96 +1010,95 @@ impl ComposerRepository { } } - if let Some(api_url) = api_url { - if !package_constraint_map.is_empty() { - let mut options = self.options.clone(); - let http_entry = options - .entry("http".to_string()) - .or_insert(PhpMixed::Array(IndexMap::new())); - if let PhpMixed::Array(http_map) = http_entry { - http_map.insert( - "method".to_string(), - Box::new(PhpMixed::String("POST".to_string())), - ); - if let Some(header_box) = http_map.get("header") { - // cast to array - let arr = match &**header_box { - PhpMixed::List(l) => l.clone(), - other => vec![Box::new(other.clone())], - }; - http_map.insert("header".to_string(), Box::new(PhpMixed::List(arr))); - } - let mut headers = match http_map.get("header") { - Some(b) => match &**b { - PhpMixed::List(l) => l.clone(), - _ => vec![], - }, - None => vec![], + if let Some(api_url) = api_url + && !package_constraint_map.is_empty() + { + let mut options = self.options.clone(); + let http_entry = options + .entry("http".to_string()) + .or_insert(PhpMixed::Array(IndexMap::new())); + if let PhpMixed::Array(http_map) = http_entry { + http_map.insert( + "method".to_string(), + Box::new(PhpMixed::String("POST".to_string())), + ); + if let Some(header_box) = http_map.get("header") { + // cast to array + let arr = match &**header_box { + PhpMixed::List(l) => l.clone(), + other => vec![Box::new(other.clone())], }; - headers.push(Box::new(PhpMixed::String( - "Content-type: application/x-www-form-urlencoded".to_string(), - ))); - http_map.insert("header".to_string(), Box::new(PhpMixed::List(headers))); - http_map.insert("timeout".to_string(), Box::new(PhpMixed::Int(10))); - let packages_list: Vec<(String, String)> = package_constraint_map - .keys() - .map(|k| ("packages".to_string(), k.clone())) - .collect(); - let body = http_build_query( - &packages_list - .iter() - .map(|(k, v)| (k.as_str(), v.as_str())) - .collect::<Vec<_>>(), - "&", - "=", - ); - http_map.insert("content".to_string(), Box::new(PhpMixed::String(body))); + http_map.insert("header".to_string(), Box::new(PhpMixed::List(arr))); } + let mut headers = match http_map.get("header") { + Some(b) => match &**b { + PhpMixed::List(l) => l.clone(), + _ => vec![], + }, + None => vec![], + }; + headers.push(Box::new(PhpMixed::String( + "Content-type: application/x-www-form-urlencoded".to_string(), + ))); + http_map.insert("header".to_string(), Box::new(PhpMixed::List(headers))); + http_map.insert("timeout".to_string(), Box::new(PhpMixed::Int(10))); + let packages_list: Vec<(String, String)> = package_constraint_map + .keys() + .map(|k| ("packages".to_string(), k.clone())) + .collect(); + let body = http_build_query( + &packages_list + .iter() + .map(|(k, v)| (k.as_str(), v.as_str())) + .collect::<Vec<_>>(), + "&", + "=", + ); + http_map.insert("content".to_string(), Box::new(PhpMixed::String(body))); + } - let response = self.http_downloader.borrow_mut().get(&api_url, options)?; - let mut warned = false; - let decoded = response.decode_json()?; - let advisories_response = decoded - .as_array() - .and_then(|a| a.get("advisories")) - .and_then(|v| v.as_array()) - .cloned() - .unwrap_or_default(); - for (name, list_box) in advisories_response.iter() { - if !package_constraint_map.contains_key(name) { - if !warned { - self.io.write_error(&format!( + let response = self.http_downloader.borrow_mut().get(&api_url, options)?; + let mut warned = false; + let decoded = response.decode_json()?; + let advisories_response = decoded + .as_array() + .and_then(|a| a.get("advisories")) + .and_then(|v| v.as_array()) + .cloned() + .unwrap_or_default(); + for (name, list_box) in advisories_response.iter() { + if !package_constraint_map.contains_key(name) { + if !warned { + self.io.write_error(&format!( "<warning>{} returned names which were not requested in response to the security-advisories API. {} was not requested but is present in the response. Requested names were: {}</warning>", self.get_repo_name(), name, package_constraint_map.keys().cloned().collect::<Vec<_>>().join(", "), )); - warned = true; - } - continue; + warned = true; } - let list = match list_box.as_list() { - Some(l) => l.clone(), - None => continue, - }; - if !list.is_empty() { - let mut entries: Vec<AnySecurityAdvisory> = Vec::new(); - for data_mixed in list.iter() { - if let Some(data) = data_mixed.as_array() { - let data_map: IndexMap<String, PhpMixed> = data - .iter() - .map(|(k, v)| (k.clone(), (**v).clone())) - .collect(); - if let Some(adv) = create(&data_map, name, &package_constraint_map)? - { - entries.push(adv); - } + continue; + } + let list = match list_box.as_list() { + Some(l) => l.clone(), + None => continue, + }; + if !list.is_empty() { + let mut entries: Vec<AnySecurityAdvisory> = Vec::new(); + for data_mixed in list.iter() { + if let Some(data) = data_mixed.as_array() { + let data_map: IndexMap<String, PhpMixed> = data + .iter() + .map(|(k, v)| (k.clone(), (**v).clone())) + .collect(); + if let Some(adv) = create(&data_map, name, &package_constraint_map)? { + entries.push(adv); } } - advisories.insert(name.clone(), entries); } - names_found.insert(name.clone(), true); + advisories.insert(name.clone(), entries); } + names_found.insert(name.clone(), true); } } @@ -1137,10 +1127,10 @@ impl ComposerRepository { ) { Ok(resp) => resp.decode_json()?, Err(e) => { - if let Some(te) = e.downcast_ref::<TransportException>() { - if te.get_status_code() == Some(404) { - return Ok(result); - } + if let Some(te) = e.downcast_ref::<TransportException>() + && te.get_status_code() == Some(404) + { + return Ok(result); } return Err(e); } @@ -1152,14 +1142,14 @@ impl ComposerRepository { .and_then(|v| v.as_list()) { for provider_mixed in providers.iter() { - if let Some(provider) = provider_mixed.as_array() { - if let Some(name) = provider.get("name").and_then(|v| v.as_string()) { - let entry: IndexMap<String, PhpMixed> = provider - .iter() - .map(|(k, v)| (k.clone(), (**v).clone())) - .collect(); - result.insert(name.to_string(), entry); - } + if let Some(provider) = provider_mixed.as_array() + && let Some(name) = provider.get("name").and_then(|v| v.as_string()) + { + let entry: IndexMap<String, PhpMixed> = provider + .iter() + .map(|(k, v)| (k.clone(), (**v).clone())) + .collect(); + result.insert(name.to_string(), entry); } } } @@ -1187,7 +1177,7 @@ impl ComposerRepository { || !candidate .get("provide") .and_then(|v| v.as_array()) - .map_or(false, |a| a.contains_key(package_name)) + .is_some_and(|a| a.contains_key(package_name)) { continue; } @@ -1291,7 +1281,7 @@ impl ComposerRepository { || !self .partial_packages_by_name .as_ref() - .map_or(false, |m| m.contains_key(name)) + .is_some_and(|m| m.contains_key(name)) { // skip platform packages, root package and composer-plugin-api if PlatformRepository::is_platform_package(name) || name == "__root__" { @@ -1314,7 +1304,7 @@ impl ComposerRepository { && !self .provider_listing .as_ref() - .map_or(false, |m| m.contains_key(name)) + .is_some_and(|m| m.contains_key(name)) { hash_opt = None; url = self @@ -1329,7 +1319,7 @@ impl ComposerRepository { if !self .provider_listing .as_ref() - .map_or(false, |m| m.contains_key(name)) + .is_some_and(|m| m.contains_key(name)) { return Ok(IndexMap::new()); } @@ -1365,13 +1355,33 @@ impl ComposerRepository { )); } } - } else if use_last_modified_check { - if let Some(contents_raw) = self.cache.read(&cache_key) { - let contents = json_decode(&contents_raw, true)?; - let contents_arr = contents.as_array().cloned(); - // we already loaded some packages from this file, so assume it is fresh and avoid fetching it again - if already_loaded.contains_key(name) { - if let Some(arr) = &contents_arr { + } else if use_last_modified_check + && let Some(contents_raw) = self.cache.read(&cache_key) + { + let contents = json_decode(&contents_raw, true)?; + let contents_arr = contents.as_array().cloned(); + // we already loaded some packages from this file, so assume it is fresh and avoid fetching it again + if already_loaded.contains_key(name) { + if let Some(arr) = &contents_arr { + let map: IndexMap<String, PhpMixed> = arr + .iter() + .map(|(k, v)| (k.clone(), (**v).clone())) + .collect(); + packages_opt = Some(map); + packages_source = Some(format!( + "cached file ({} originating from {})", + cache_key, + Url::sanitize(url.clone()) + )); + } + } else if let Some(arr) = &contents_arr + && let Some(last_modified) = + arr.get("last-modified").and_then(|v| v.as_string()) + { + let response = + self.fetch_file_if_last_modified(&url, &cache_key, last_modified)?; + match response { + FetchFileIfLastModifiedResult::NotModified => { let map: IndexMap<String, PhpMixed> = arr .iter() .map(|(k, v)| (k.clone(), (**v).clone())) @@ -1383,33 +1393,10 @@ impl ComposerRepository { Url::sanitize(url.clone()) )); } - } else if let Some(arr) = &contents_arr { - if let Some(last_modified) = - arr.get("last-modified").and_then(|v| v.as_string()) - { - let response = - self.fetch_file_if_last_modified(&url, &cache_key, last_modified)?; - match response { - FetchFileIfLastModifiedResult::NotModified => { - let map: IndexMap<String, PhpMixed> = arr - .iter() - .map(|(k, v)| (k.clone(), (**v).clone())) - .collect(); - packages_opt = Some(map); - packages_source = Some(format!( - "cached file ({} originating from {})", - cache_key, - Url::sanitize(url.clone()) - )); - } - FetchFileIfLastModifiedResult::Data(data) => { - packages_opt = Some(data); - packages_source = Some(format!( - "downloaded file ({})", - Url::sanitize(url.clone()) - )); - } - } + FetchFileIfLastModifiedResult::Data(data) => { + packages_opt = Some(data); + packages_source = + Some(format!("downloaded file ({})", Url::sanitize(url.clone()))); } } } @@ -1545,7 +1532,7 @@ impl ComposerRepository { && self .partial_packages_by_name .as_ref() - .map_or(false, |m| m.contains_key(&normalized_name)) + .is_some_and(|m| m.contains_key(&normalized_name)) { continue; } @@ -1572,7 +1559,7 @@ impl ComposerRepository { } else if version .get("version_normalized") .and_then(|v| v.as_string()) - .map_or(false, |s| s == VersionParser::DEFAULT_BRANCH_ALIAS) + == Some(VersionParser::DEFAULT_BRANCH_ALIAS) { // handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it let v = version @@ -1595,7 +1582,7 @@ impl ComposerRepository { // avoid loading packages which have already been loaded if already_loaded .get(name) - .map_or(false, |m| m.contains_key(&version_normalized)) + .is_some_and(|m| m.contains_key(&version_normalized)) { continue; } @@ -1661,7 +1648,7 @@ impl ComposerRepository { /// Adds a new package to the repository pub fn add_package(&mut self, package: BasePackageHandle) { self.configure_package_transport_options(package.clone()); - self.inner.add_package(package.into()); + self.inner.add_package(package); } /// Forwards the outermost handle's weak to the inner `ArrayRepository` so that packages added @@ -1705,9 +1692,7 @@ impl ComposerRepository { // load ~dev versions of the packages as well if needed let names_snapshot: Vec<String> = package_names.keys().cloned().collect(); for name in names_snapshot { - let constraint = package_names - .get(&name) - .and_then(|c| c.as_ref().map(|c| c.clone())); + let constraint = package_names.get(&name).and_then(|c| c.clone()); if acceptable_stabilities.is_none() || stability_flags.is_none() || StabilityFilter::is_package_acceptable( @@ -1720,8 +1705,8 @@ impl ComposerRepository { package_names.insert(format!("{}~dev", name), constraint); } // if only dev stability is requested, we skip loading the non dev file - if acceptable_stabilities.map_or(false, |m| m.contains_key("dev") && m.len() == 1) - && stability_flags.map_or(false, |m| m.is_empty()) + if acceptable_stabilities.is_some_and(|m| m.contains_key("dev") && m.len() == 1) + && stability_flags.is_some_and(|m| m.is_empty()) { package_names.shift_remove(&name); } @@ -1801,10 +1786,8 @@ impl ComposerRepository { _ => continue, }; - let minified = response_arr - .get("minified") - .and_then(|v| v.as_string()) - .map_or(false, |s| s == "composer/2.0"); + let minified = + response_arr.get("minified").and_then(|v| v.as_string()) == Some("composer/2.0"); if minified { versions = MetadataMinifier::expand(versions); } @@ -1828,7 +1811,7 @@ impl ComposerRepository { } else if version .get("version_normalized") .and_then(|v| v.as_string()) - .map_or(false, |s| s == VersionParser::DEFAULT_BRANCH_ALIAS) + == Some(VersionParser::DEFAULT_BRANCH_ALIAS) { // handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it let v = version @@ -1851,7 +1834,7 @@ impl ComposerRepository { // avoid loading packages which have already been loaded if already_loaded .get(&real_name) - .map_or(false, |m| m.contains_key(&version_normalized)) + .is_some_and(|m| m.contains_key(&version_normalized)) { continue; } @@ -1966,8 +1949,8 @@ impl ComposerRepository { let has_pkg = response_arr .and_then(|a| a.get("packages")) .and_then(|v| v.as_array()) - .map_or(false, |a| a.contains_key(&package_name)); - let has_advisories = response_arr.map_or(false, |a| a.contains_key("security-advisories")); + .is_some_and(|a| a.contains_key(&package_name)); + let has_advisories = response_arr.is_some_and(|a| a.contains_key("security-advisories")); if !has_pkg && !has_advisories { return Ok(PhpMixed::List(vec![ Box::new(PhpMixed::Null), @@ -2050,10 +2033,10 @@ impl ComposerRepository { continue; } - if let Some(c) = constraint { - if !CompilingMatcher::r#match(c, SimpleConstraint::OP_EQ, version.clone()) { - continue; - } + if let Some(c) = constraint + && !CompilingMatcher::r#match(c, SimpleConstraint::OP_EQ, version.clone()) + { + continue; } return Ok(true); @@ -2069,7 +2052,7 @@ impl ComposerRepository { .as_array() .and_then(|a| a.get("path")) .and_then(|v| v.as_string()) - .map_or(false, |p| p.contains(".json")); + .is_some_and(|p| p.contains(".json")); if has_json { return self.url.clone(); } @@ -2177,7 +2160,7 @@ impl ComposerRepository { self.source_mirrors .get_or_insert_with(IndexMap::new) .entry("git".to_string()) - .or_insert_with(Vec::new) + .or_default() .push(SourceMirror { url: git_url, preferred, @@ -2196,7 +2179,7 @@ impl ComposerRepository { self.source_mirrors .get_or_insert_with(IndexMap::new) .entry("hg".to_string()) - .or_insert_with(Vec::new) + .or_default() .push(SourceMirror { url: hg_url, preferred, @@ -2268,19 +2251,18 @@ impl ComposerRepository { .get("available-packages") .and_then(|v| v.as_list()) .cloned() + && !available.is_empty() { - if !available.is_empty() { - let avail_packages: Vec<String> = available - .iter() - .filter_map(|v| v.as_string().map(|s| strtolower(s))) - .collect(); - let mut combined: IndexMap<String, String> = IndexMap::new(); - for k in avail_packages.iter() { - combined.insert(k.clone(), k.clone()); - } - self.available_packages = Some(combined); - self.has_available_package_list = true; + let avail_packages: Vec<String> = available + .iter() + .filter_map(|v| v.as_string().map(strtolower)) + .collect(); + let mut combined: IndexMap<String, String> = IndexMap::new(); + for k in avail_packages.iter() { + combined.insert(k.clone(), k.clone()); } + self.available_packages = Some(combined); + self.has_available_package_list = true; } // Provides a list of package name patterns (using * wildcards to match any substring, e.g. "vendor/*") that are available in this repo @@ -2290,16 +2272,15 @@ impl ComposerRepository { .get("available-package-patterns") .and_then(|v| v.as_list()) .cloned() + && !patterns.is_empty() { - if !patterns.is_empty() { - let mapped: Vec<String> = patterns - .iter() - .filter_map(|v| v.as_string()) - .map(|p| base_package::package_name_to_regexp(p)) - .collect(); - self.available_package_patterns = Some(mapped); - self.has_available_package_list = true; - } + let mapped: Vec<String> = patterns + .iter() + .filter_map(|v| v.as_string()) + .map(base_package::package_name_to_regexp) + .collect(); + self.available_package_patterns = Some(mapped); + self.has_available_package_list = true; } // Remove legacy keys as most repos need to be compatible with Composer v1 @@ -2459,53 +2440,50 @@ impl ComposerRepository { } let listing = self.provider_listing.as_mut().unwrap(); for (k, v) in providers.iter() { - if let Some(arr) = v.as_array() { - if let Some(sha256) = arr.get("sha256").and_then(|v| v.as_string()) { - listing.insert( - k.clone(), - ProviderListingEntry { - sha256: sha256.to_string(), - }, - ); - } + if let Some(arr) = v.as_array() + && let Some(sha256) = arr.get("sha256").and_then(|v| v.as_string()) + { + listing.insert( + k.clone(), + ProviderListingEntry { + sha256: sha256.to_string(), + }, + ); } } } - if self.providers_url.is_some() { - if let Some(includes) = data + if self.providers_url.is_some() + && let Some(includes) = data .get("provider-includes") .and_then(|v| v.as_array()) .cloned() - { - for (include, metadata_mixed) in includes.iter() { - let metadata = match metadata_mixed.as_array() { - Some(a) => a, - None => continue, + { + for (include, metadata_mixed) in includes.iter() { + let metadata = match metadata_mixed.as_array() { + Some(a) => a, + None => continue, + }; + let sha256 = metadata + .get("sha256") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(); + let url = format!("{}/{}", self.base_url, include.replace("%hash%", &sha256)); + let cache_key = include.replace("%hash%", "").replace("$", ""); + let included_data: IndexMap<String, PhpMixed> = + if self.cache.sha256(&cache_key).as_deref() == Some(sha256.as_str()) { + let raw = self.cache.read(&cache_key).unwrap_or_default(); + let decoded = json_decode(&raw, true)?; + decoded + .as_array() + .map(|a| a.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect()) + .unwrap_or_default() + } else { + self.fetch_file(&url, Some(&cache_key), Some(&sha256), false)? }; - let sha256 = metadata - .get("sha256") - .and_then(|v| v.as_string()) - .unwrap_or("") - .to_string(); - let url = format!("{}/{}", self.base_url, include.replace("%hash%", &sha256)); - let cache_key = include.replace("%hash%", "").replace("$", ""); - let included_data: IndexMap<String, PhpMixed> = - if self.cache.sha256(&cache_key).as_deref() == Some(sha256.as_str()) { - let raw = self.cache.read(&cache_key).unwrap_or_default(); - let decoded = json_decode(&raw, true)?; - decoded - .as_array() - .map(|a| { - a.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect() - }) - .unwrap_or_default() - } else { - self.fetch_file(&url, Some(&cache_key), Some(&sha256), false)? - }; - self.load_provider_listings(&included_data)?; - } + self.load_provider_listings(&included_data)?; } } Ok(()) @@ -2633,19 +2611,18 @@ impl ComposerRepository { let mut results: Vec<BasePackageHandle> = Vec::new(); for package in package_instances.into_iter() { - if let Some(src_type) = package.get_source_type() { - if let Some(mirrors) = + if let Some(src_type) = package.get_source_type() + && let Some(mirrors) = self.source_mirrors.as_ref().and_then(|m| m.get(&src_type)) - { - let converted: Vec<crate::package::Mirror> = mirrors - .iter() - .map(|m| crate::package::Mirror { - url: m.url.clone(), - preferred: m.preferred, - }) - .collect(); - package.set_source_mirrors(Some(converted)); - } + { + let converted: Vec<crate::package::Mirror> = mirrors + .iter() + .map(|m| crate::package::Mirror { + url: m.url.clone(), + preferred: m.preferred, + }) + .collect(); + package.set_source_mirrors(Some(converted)); } if let Some(dist_mirrors) = self.dist_mirrors.as_ref() { let converted: Vec<crate::package::Mirror> = dist_mirrors @@ -2658,7 +2635,7 @@ impl ComposerRepository { package.set_dist_mirrors(Some(converted)); } self.configure_package_transport_options(package.clone()); - results.push(package.into()); + results.push(package); } Ok(results) })(); @@ -2673,7 +2650,7 @@ impl ComposerRepository { .map(|s| format!(" from {}", s)) .unwrap_or_default(), "Exception", - e.to_string() + e ), code: 0, } @@ -2689,11 +2666,7 @@ impl ComposerRepository { return Ok(vec![]); } let loader = ArrayLoader::new(Some(VersionParser::new()), true); - Ok(loader - .load_packages(packages)? - .into_iter() - .map(|p| p.into()) - .collect()) + Ok(loader.load_packages(packages)?.into_iter().collect()) } fn fetch_file( @@ -2721,10 +2694,11 @@ impl ComposerRepository { }; // url-encode $ signs in URLs as bad proxies choke on them - if let Some(pos) = filename.find('$') { - if pos > 0 && Preg::is_match(r"{^https?://}i", &filename) { - filename = format!("{}%24{}", &filename[..pos], &filename[pos + 1..]); - } + if let Some(pos) = filename.find('$') + && pos > 0 + && Preg::is_match(r"{^https?://}i", &filename) + { + filename = format!("{}%24{}", &filename[..pos], &filename[pos + 1..]); } let mut retries: i64 = 3; @@ -2776,29 +2750,29 @@ impl ComposerRepository { .borrow_mut() .get(&filename, options.clone())?; let mut json = response.get_body().unwrap_or("").to_string(); - if let Some(sha256_val) = sha256 { - if sha256_val != hash("sha256", &json) { - // undo downgrade before trying again if http seems to be hijacked or modifying content somehow - if self.allow_ssl_downgrade { - self.url = self.url.replace("http://", "https://"); - self.base_url = self.base_url.replace("http://", "https://"); - filename = filename.replace("http://", "https://"); - } + if let Some(sha256_val) = sha256 + && sha256_val != hash("sha256", &json) + { + // undo downgrade before trying again if http seems to be hijacked or modifying content somehow + if self.allow_ssl_downgrade { + self.url = self.url.replace("http://", "https://"); + self.base_url = self.base_url.replace("http://", "https://"); + filename = filename.replace("http://", "https://"); + } - if retries > 0 { - std::thread::sleep(std::time::Duration::from_micros(100000)); - return Err(RetryMarker.into()); - } + if retries > 0 { + std::thread::sleep(std::time::Duration::from_micros(100000)); + return Err(RetryMarker.into()); + } - // TODO use scarier wording once we know for sure it doesn't do false positives anymore - return Err(RepositorySecurityException(shirabe_php_shim::Exception { + // TODO use scarier wording once we know for sure it doesn't do false positives anymore + return Err(RepositorySecurityException(shirabe_php_shim::Exception { message: format!( "The contents of {} do not match its signature. This could indicate a man-in-the-middle attack or e.g. antivirus software corrupting files. Try running composer again and report this if you think it is a mistake.", filename ), code: 0, }).into()); - } } if let Some(dispatcher) = self.event_dispatcher.as_ref() { @@ -2832,28 +2806,26 @@ impl ComposerRepository { .unwrap_or_default(); HttpDownloader::output_warnings(self.io.clone(), &self.url, &data_local); - if let Some(ck) = cache_key_owned.as_ref() { - if !ck.is_empty() && !self.cache.is_read_only() { - if store_last_modified_time { - if let Some(last_modified_date) = response.get_header("last-modified") { - data_local.insert( - "last-modified".to_string(), - PhpMixed::String(last_modified_date), - ); - let as_mixed = PhpMixed::Array( - data_local - .iter() - .map(|(k, v)| (k.clone(), Box::new(v.clone()))) - .collect(), - ); - json = JsonFile::encode_with_options( - &as_mixed, - JsonEncodeOptions::none(), - ); - } - } - self.cache.write(ck, &json); + if let Some(ck) = cache_key_owned.as_ref() + && !ck.is_empty() + && !self.cache.is_read_only() + { + if store_last_modified_time + && let Some(last_modified_date) = response.get_header("last-modified") + { + data_local.insert( + "last-modified".to_string(), + PhpMixed::String(last_modified_date), + ); + let as_mixed = PhpMixed::Array( + data_local + .iter() + .map(|(k, v)| (k.clone(), Box::new(v.clone()))) + .collect(), + ); + json = JsonFile::encode_with_options(&as_mixed, JsonEncodeOptions::none()); } + self.cache.write(ck, &json); } response.collect(); @@ -2871,41 +2843,38 @@ impl ComposerRepository { if e.downcast_ref::<LogicException>().is_some() { return Err(e); } - if let Some(te) = e.downcast_ref::<TransportException>() { - if te.get_status_code() == Some(404) { - return Err(e); - } + if let Some(te) = e.downcast_ref::<TransportException>() + && te.get_status_code() == Some(404) + { + return Err(e); } if e.downcast_ref::<RepositorySecurityException>().is_some() { return Err(e); } - if let Some(ck) = cache_key_owned.as_ref() { - if !ck.is_empty() { - if let Some(contents) = self.cache.read(ck) { - if !self.degraded_mode { - self.io.write_error(&format!( + if let Some(ck) = cache_key_owned.as_ref() + && !ck.is_empty() + && let Some(contents) = self.cache.read(ck) + { + if !self.degraded_mode { + self.io.write_error(&format!( "<warning>{} could not be fully loaded ({}), package information was loaded from the local cache and may be out of date</warning>", self.url, - e.to_string() + e )); - } - self.degraded_mode = true; - let parsed = JsonFile::parse_json( - Some(&contents), - Some(&format!("{}{}", self.cache.get_root(), ck)), - )?; - let map: IndexMap<String, PhpMixed> = parsed - .as_array() - .map(|a| { - a.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect() - }) - .unwrap_or_default(); - data = Some(map); - - break; - } } + self.degraded_mode = true; + let parsed = JsonFile::parse_json( + Some(&contents), + Some(&format!("{}{}", self.cache.get_root(), ck)), + )?; + let map: IndexMap<String, PhpMixed> = parsed + .as_array() + .map(|a| a.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect()) + .unwrap_or_default(); + data = Some(map); + + break; } return Err(e); @@ -3060,17 +3029,17 @@ impl ComposerRepository { if e.downcast_ref::<LogicException>().is_some() { return Err(e); } - if let Some(te) = e.downcast_ref::<TransportException>() { - if te.get_status_code() == Some(404) { - return Err(e); - } + if let Some(te) = e.downcast_ref::<TransportException>() + && te.get_status_code() == Some(404) + { + return Err(e); } if !self.degraded_mode { self.io.write_error(&format!( "<warning>{} could not be fully loaded ({}), package information was loaded from the local cache and may be out of date</warning>", self.url, - e.to_string() + e )); } self.degraded_mode = true; @@ -3252,13 +3221,13 @@ impl ComposerRepository { cache_key: &str, last_modified_time: Option<&str>, ) -> anyhow::Result<PhpMixed> { - if let Some(te) = e.downcast_ref::<TransportException>() { - if te.get_status_code() == Some(404) { - self.packages_not_found_cache - .insert(filename.to_string(), true); + if let Some(te) = e.downcast_ref::<TransportException>() + && te.get_status_code() == Some(404) + { + self.packages_not_found_cache + .insert(filename.to_string(), true); - return Ok(PhpMixed::Bool(false)); - } + return Ok(PhpMixed::Bool(false)); } if !self.degraded_mode { @@ -3277,12 +3246,11 @@ impl ComposerRepository { } // special error code returned when network is being artificially disabled - if let Some(te) = e.downcast_ref::<TransportException>() { - if te.get_status_code() == Some(499) { - let resp = - Response::new(self.url.clone(), Some(404), Vec::new(), Some(String::new())); - return self.async_fetch_file_accept(resp, filename, cache_key); - } + if let Some(te) = e.downcast_ref::<TransportException>() + && te.get_status_code() == Some(499) + { + let resp = Response::new(self.url.clone(), Some(404), Vec::new(), Some(String::new())); + return self.async_fetch_file_accept(resp, filename, cache_key); } Err(e) @@ -3328,7 +3296,7 @@ impl ComposerRepository { .as_mut() .unwrap() .entry(version_package_name.clone()) - .or_insert_with(Vec::new) + .or_default() .push(version_map); if !self.displayed_warning_about_non_matching_package_index && version_package_name != strtolower(package) @@ -3359,10 +3327,10 @@ impl ComposerRepository { }.into()); } - if let Some(ref available) = self.available_packages { - if available.contains_key(name) { - return Ok(true); - } + if let Some(ref available) = self.available_packages + && available.contains_key(name) + { + return Ok(true); } if let Some(ref patterns) = self.available_package_patterns { @@ -3432,7 +3400,7 @@ impl RepositoryInterface for ComposerRepository { && self .partial_packages_by_name .as_ref() - .map_or(false, |m| m.contains_key(&name)) + .is_some_and(|m| m.contains_key(&name)) { let packages = self.what_provides(&name, None, None, IndexMap::new())?; let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); @@ -3506,7 +3474,7 @@ impl RepositoryInterface for ComposerRepository { && self .partial_packages_by_name .as_ref() - .map_or(false, |m| m.contains_key(&name)) + .is_some_and(|m| m.contains_key(&name)) { let packages = self.what_provides(&name, None, None, IndexMap::new())?; let packages_vec: Vec<BasePackageHandle> = packages.into_values().collect(); diff --git a/crates/shirabe/src/repository/composite_repository.rs b/crates/shirabe/src/repository/composite_repository.rs index dafedfc..27e6bf2 100644 --- a/crates/shirabe/src/repository/composite_repository.rs +++ b/crates/shirabe/src/repository/composite_repository.rs @@ -137,7 +137,7 @@ impl RepositoryInterface for CompositeRepository { for repository in &self.repositories { let name_map_cloned: IndexMap<String, Option<AnyConstraint>> = package_name_map .iter() - .map(|(k, v)| (k.clone(), v.as_ref().map(|c| c.clone()))) + .map(|(k, v)| (k.clone(), v.clone())) .collect(); let result = repository.load_packages( name_map_cloned, diff --git a/crates/shirabe/src/repository/filesystem_repository.rs b/crates/shirabe/src/repository/filesystem_repository.rs index 38d5836..79136c9 100644 --- a/crates/shirabe/src/repository/filesystem_repository.rs +++ b/crates/shirabe/src/repository/filesystem_repository.rs @@ -253,28 +253,28 @@ impl FilesystemRepository { let mut pkg_array = dumper.dump(package.clone()); let path = installation_manager.get_install_path(package.clone()); let mut install_path: Option<String> = None; - if let Some(path_str) = &path { - if !path_str.is_empty() { - let normalized_path = self.filesystem.borrow_mut().normalize_path(&if self - .filesystem - .borrow() - .is_absolute_path(path_str) - { - path_str.clone() - } else { - format!( - "{}/{}", - Platform::get_cwd(false).unwrap_or_default(), - path_str - ) - }); - install_path = Some(self.filesystem.borrow_mut().find_shortest_path( - &repo_dir, - &normalized_path, - true, - false, - )); - } + if let Some(path_str) = &path + && !path_str.is_empty() + { + let normalized_path = self.filesystem.borrow_mut().normalize_path(&if self + .filesystem + .borrow() + .is_absolute_path(path_str) + { + path_str.clone() + } else { + format!( + "{}/{}", + Platform::get_cwd(false).unwrap_or_default(), + path_str + ) + }); + install_path = Some(self.filesystem.borrow_mut().find_shortest_path( + &repo_dir, + &normalized_path, + true, + false, + )); } install_paths.insert(package.get_name().to_string(), install_path.clone()); @@ -306,10 +306,9 @@ impl FilesystemRepository { .collect(), ), true, - ) { - if let Some(PhpMixed::List(list)) = data.get_mut("dev-package-names") { - list.push(Box::new(PhpMixed::String(package.get_name().to_string()))); - } + ) && let Some(PhpMixed::List(list)) = data.get_mut("dev-package-names") + { + list.push(Box::new(PhpMixed::String(package.get_name().to_string()))); } } @@ -497,12 +496,8 @@ impl FilesystemRepository { .map(|s| Box::new(PhpMixed::String(s.clone()))) .collect(), )); - let mut packages: Vec<PackageInterfaceHandle> = self - .inner - .get_packages()? - .into_iter() - .map(|p| p.into()) - .collect(); + let mut packages: Vec<PackageInterfaceHandle> = + self.inner.get_packages()?.into_iter().collect(); let mut current_root: RootPackageInterfaceHandle = match &self.root_package { None => { return Err(LogicException { @@ -617,10 +612,10 @@ impl FilesystemRepository { "aliases", pretty.clone(), ); - if package.as_root().is_some() { - if let Some(PhpMixed::Array(root_map)) = versions.get_mut("root") { - push_to_list(root_map, "aliases", pretty); - } + if package.as_root().is_some() + && let Some(PhpMixed::Array(root_map)) = versions.get_mut("root") + { + push_to_list(root_map, "aliases", pretty); } } @@ -633,16 +628,16 @@ impl FilesystemRepository { for (_name, version) in versions_map.iter_mut() { if let PhpMixed::Array(version_map) = version.as_mut() { for key in ["aliases", "replaced", "provided"] { - if let Some(boxed) = version_map.get_mut(key) { - if let PhpMixed::List(list) = boxed.as_mut() { - // PHP: sort($versions['versions'][$name][$key], SORT_NATURAL); - usort(list, |a: &Box<PhpMixed>, b: &Box<PhpMixed>| -> i64 { - shirabe_php_shim::strnatcmp( - a.as_string().unwrap_or(""), - b.as_string().unwrap_or(""), - ) - }); - } + if let Some(boxed) = version_map.get_mut(key) + && let PhpMixed::List(list) = boxed.as_mut() + { + // PHP: sort($versions['versions'][$name][$key], SORT_NATURAL); + usort(list, |a: &Box<PhpMixed>, b: &Box<PhpMixed>| -> i64 { + shirabe_php_shim::strnatcmp( + a.as_string().unwrap_or(""), + b.as_string().unwrap_or(""), + ) + }); } } } @@ -665,9 +660,9 @@ impl FilesystemRepository { let mut reference: Option<String> = None; if let Some(install_src) = package.get_installation_source() { reference = if install_src == "source" { - package.get_source_reference().map(String::from) + package.get_source_reference() } else { - package.get_dist_reference().map(String::from) + package.get_dist_reference() }; } if reference.is_none() { diff --git a/crates/shirabe/src/repository/handle.rs b/crates/shirabe/src/repository/handle.rs index 6721bb2..2e83ef8 100644 --- a/crates/shirabe/src/repository/handle.rs +++ b/crates/shirabe/src/repository/handle.rs @@ -152,7 +152,7 @@ impl RepositoryInterfaceHandle { self.0 .borrow() .as_installed_repository_interface() - .map_or(false, |r| r.is_fresh()) + .is_some_and(|r| r.is_fresh()) } pub fn get_dev_mode(&self) -> Option<bool> { diff --git a/crates/shirabe/src/repository/installed_repository.rs b/crates/shirabe/src/repository/installed_repository.rs index f6b9643..55ec50f 100644 --- a/crates/shirabe/src/repository/installed_repository.rs +++ b/crates/shirabe/src/repository/installed_repository.rs @@ -140,37 +140,32 @@ impl InstalledRepository { let needles_snapshot = needles.clone(); for link in package.get_replaces().values() { for needle in &needles_snapshot { - if link.get_source() == needle.as_str() { - if constraint.is_none() - || link.get_constraint().matches(constraint.as_ref().unwrap()) - { - if packages_in_tree.contains(&link.get_target().to_string()) { - results.push(DependentsEntry( - package.clone(), - link.clone(), - None, - )); - continue; - } - packages_in_tree.push(link.get_target().to_string()); - let dependents = if recurse { - self.get_dependents( - NeedleInput::Single(link.get_target().to_string()), - None, - false, - true, - Some(packages_in_tree.clone()), - )? - } else { - vec![] - }; - results.push(DependentsEntry( - package.clone(), - link.clone(), - Some(dependents), - )); - needles.push(link.get_target().to_string()); + if link.get_source() == needle.as_str() + && (constraint.is_none() + || link.get_constraint().matches(constraint.as_ref().unwrap())) + { + if packages_in_tree.contains(&link.get_target().to_string()) { + results.push(DependentsEntry(package.clone(), link.clone(), None)); + continue; } + packages_in_tree.push(link.get_target().to_string()); + let dependents = if recurse { + self.get_dependents( + NeedleInput::Single(link.get_target().to_string()), + None, + false, + true, + Some(packages_in_tree.clone()), + )? + } else { + vec![] + }; + results.push(DependentsEntry( + package.clone(), + link.clone(), + Some(dependents), + )); + needles.push(link.get_target().to_string()); } } } @@ -187,7 +182,7 @@ impl InstalledRepository { if link.get_target() == needle.as_str() { let matches_constraint = constraint .as_ref() - .map_or(true, |c| link.get_constraint().matches(c) == !invert); + .is_none_or(|c| link.get_constraint().matches(c) != invert); if constraint.is_none() || matches_constraint { if packages_in_tree.contains(&link.get_source().to_string()) { results.push(DependentsEntry(package.clone(), link.clone(), None)); diff --git a/crates/shirabe/src/repository/path_repository.rs b/crates/shirabe/src/repository/path_repository.rs index cfd42e5..160c917 100644 --- a/crates/shirabe/src/repository/path_repository.rs +++ b/crates/shirabe/src/repository/path_repository.rs @@ -209,43 +209,40 @@ impl PathRepository { .get("name") .and_then(|v| v.as_string()) .map(|s| s.to_string()) - { - if let Some(version) = self + && let Some(version) = self .options .get("versions") .and_then(|v| v.as_array()) .and_then(|a| a.get(&name)) .and_then(|v| v.as_string()) .map(|s| s.to_string()) - { - package.insert("version".to_string(), PhpMixed::String(version)); - } + { + package.insert("version".to_string(), PhpMixed::String(version)); } // carry over the root package version if this path repo is in the same git repository as root package - if !package.contains_key("version") { - if let Some(root_version) = Platform::get_env("COMPOSER_ROOT_VERSION") { - if !root_version.is_empty() { - let mut ref1 = PhpMixed::Null; - let mut ref2 = PhpMixed::Null; - let cmd = PhpMixed::from(vec!["git", "rev-parse", "HEAD"]); - let code1 = self - .process - .borrow_mut() - .execute(cmd.clone(), Some(&mut ref1), Some(path.as_str())) - .unwrap_or(1); - let code2 = self - .process - .borrow_mut() - .execute(cmd, Some(&mut ref2), ()) - .unwrap_or(1); - if code1 == 0 && code2 == 0 && ref1.as_string() == ref2.as_string() { - package.insert( - "version".to_string(), - PhpMixed::String(self.version_guesser.get_root_version_from_env()?), - ); - } - } + if !package.contains_key("version") + && let Some(root_version) = Platform::get_env("COMPOSER_ROOT_VERSION") + && !root_version.is_empty() + { + let mut ref1 = PhpMixed::Null; + let mut ref2 = PhpMixed::Null; + let cmd = PhpMixed::from(vec!["git", "rev-parse", "HEAD"]); + let code1 = self + .process + .borrow_mut() + .execute(cmd.clone(), Some(&mut ref1), Some(path.as_str())) + .unwrap_or(1); + let code2 = self + .process + .borrow_mut() + .execute(cmd, Some(&mut ref2), ()) + .unwrap_or(1); + if code1 == 0 && code2 == 0 && ref1.as_string() == ref2.as_string() { + package.insert( + "version".to_string(), + PhpMixed::String(self.version_guesser.get_root_version_from_env()?), + ); } } diff --git a/crates/shirabe/src/repository/platform_repository.rs b/crates/shirabe/src/repository/platform_repository.rs index 3136065..f345eaa 100644 --- a/crates/shirabe/src/repository/platform_repository.rs +++ b/crates/shirabe/src/repository/platform_repository.rs @@ -70,7 +70,7 @@ impl PlatformRepository { runtime: Option<Runtime>, hhvm_detector: Option<HhvmDetector>, ) -> anyhow::Result<Self> { - let runtime = runtime.unwrap_or_else(|| Runtime); + let runtime = runtime.unwrap_or(Runtime); let hhvm_detector = hhvm_detector.unwrap_or_else(|| HhvmDetector::new(None, None)); let mut overrides_map: IndexMap<String, PlatformOverride> = IndexMap::new(); for (name, version) in overrides { @@ -329,12 +329,10 @@ impl PlatformRepository { .collect(), ), true, - ) { - if let Some(xdebug_pretty_version) = XdebugHandler::get_skipped_version() { - if !xdebug_pretty_version.is_empty() { - self.add_extension("xdebug", &xdebug_pretty_version)?; - } - } + ) && let Some(xdebug_pretty_version) = XdebugHandler::get_skipped_version() + && !xdebug_pretty_version.is_empty() + { + self.add_extension("xdebug", &xdebug_pretty_version)?; } // Another quick loop, just for possible libraries @@ -1551,11 +1549,11 @@ impl PlatformRepository { } else { format!("actual: {}", package.get_pretty_version()) }; - if let Some(overrider) = overrider { - if let Some(overrider) = overrider.as_complete() { - let description = overrider.get_description().unwrap_or_default(); - overrider.set_description(format!("{}, {}", description, actual_text)); - } + if let Some(overrider) = overrider + && let Some(overrider) = overrider.as_complete() + { + let description = overrider.get_description().unwrap_or_default(); + overrider.set_description(format!("{}, {}", description, actual_text)); } return Ok(()); diff --git a/crates/shirabe/src/repository/repository_factory.rs b/crates/shirabe/src/repository/repository_factory.rs index 71b1471..d78fc48 100644 --- a/crates/shirabe/src/repository/repository_factory.rs +++ b/crates/shirabe/src/repository/repository_factory.rs @@ -48,11 +48,9 @@ impl RepositoryFactory { Some(io.clone()), )?; let data = json.read()?; - let has_packages = data.get("packages").map_or(false, |v| !v.is_null()); - let has_includes = data.get("includes").map_or(false, |v| !v.is_null()); - let has_provider_includes = data - .get("provider-includes") - .map_or(false, |v| !v.is_null()); + let has_packages = data.get("packages").is_some_and(|v| !v.is_null()); + let has_includes = data.get("includes").is_some_and(|v| !v.is_null()); + let has_provider_includes = data.get("provider-includes").is_some_and(|v| !v.is_null()); if has_packages || has_includes || has_provider_includes { let real_path = std::fs::canonicalize(repository) .ok() @@ -153,7 +151,7 @@ impl RepositoryFactory { }; if let Some(io) = &io { io.borrow_mut() - .load_configuration(&mut *config.borrow_mut())?; + .load_configuration(&mut config.borrow_mut())?; } let mut owned_rm; @@ -241,7 +239,7 @@ impl RepositoryFactory { )?)); let mut manager = Self::manager(io.clone(), &config, None, None, None)?; io.borrow_mut() - .load_configuration(&mut *config.borrow_mut())?; + .load_configuration(&mut config.borrow_mut())?; Self::default_repos(Some(io), Some(config), Some(&mut manager)) } diff --git a/crates/shirabe/src/repository/repository_manager.rs b/crates/shirabe/src/repository/repository_manager.rs index 9027af6..c838657 100644 --- a/crates/shirabe/src/repository/repository_manager.rs +++ b/crates/shirabe/src/repository/repository_manager.rs @@ -61,7 +61,7 @@ impl RepositoryManager { name, crate::repository::FindPackageConstraint::Constraint(constraint.clone()), )? { - return Ok(Some(package.into())); + return Ok(Some(package)); } } Ok(None) diff --git a/crates/shirabe/src/repository/repository_set.rs b/crates/shirabe/src/repository/repository_set.rs index bf7b525..40e7f22 100644 --- a/crates/shirabe/src/repository/repository_set.rs +++ b/crates/shirabe/src/repository/repository_set.rs @@ -222,7 +222,7 @@ impl RepositorySet { } else { 'outer: for repository in &self.repositories { let mut name_map: IndexMap<String, Option<AnyConstraint>> = IndexMap::new(); - name_map.insert(name.to_string(), constraint.as_ref().map(|c| c.clone())); + name_map.insert(name.to_string(), constraint.clone()); let acceptable = if ignore_stability { // PHP: BasePackage::STABILITIES crate::package::STABILITIES @@ -314,10 +314,10 @@ impl RepositorySet { let mut map: IndexMap<String, AnyConstraint> = IndexMap::new(); for package in packages { // ignore root alias versions as they are not actual package versions and should not matter when it comes to vulnerabilities - if let Some(alias) = package.as_alias() { - if alias.is_root_package_alias() { - continue; - } + if let Some(alias) = package.as_alias() + && alias.is_root_package_alias() + { + continue; } let name = package.get_name().to_string(); if map.contains_key(&name) { @@ -452,9 +452,7 @@ impl RepositorySet { } /// Create a pool for dependency resolution from the packages in this repository set. - /// - /// @param list<string> $ignoredTypes Packages of those types are ignored - /// @param list<string>|null $allowedTypes Only packages of those types are allowed if set to non-null + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn create_pool( &mut self, request: &mut Request, @@ -546,32 +544,32 @@ impl RepositorySet { let version = package.get_version(); packages.push(package.clone()); - if let Some(versions) = self.root_aliases.get(&name) { - if let Some(alias) = versions.get(&version) { - while let Some(alias_pkg) = package.as_alias() { - package = alias_pkg.get_alias_of().into(); - } - let alias_package: BasePackageHandle = - if let Some(complete) = package.as_complete_package() { - CompleteAliasPackageHandle::new( - complete, - alias.alias_normalized.clone(), - alias.alias.clone(), - ) - .into() - } else { - AliasPackageHandle::new( - package.as_package().unwrap(), - alias.alias_normalized.clone(), - alias.alias.clone(), - ) - .into() - }; - if let Some(alias_handle) = alias_package.as_alias() { - alias_handle.set_root_package_alias(true); - } - packages.push(alias_package); + if let Some(versions) = self.root_aliases.get(&name) + && let Some(alias) = versions.get(&version) + { + while let Some(alias_pkg) = package.as_alias() { + package = alias_pkg.get_alias_of().into(); } + let alias_package: BasePackageHandle = + if let Some(complete) = package.as_complete_package() { + CompleteAliasPackageHandle::new( + complete, + alias.alias_normalized.clone(), + alias.alias.clone(), + ) + .into() + } else { + AliasPackageHandle::new( + package.as_package().unwrap(), + alias.alias_normalized.clone(), + alias.alias.clone(), + ) + .into() + }; + if let Some(alias_handle) = alias_package.as_alias() { + alias_handle.set_root_package_alias(true); + } + packages.push(alias_package); } } } @@ -643,16 +641,13 @@ impl RepositorySet { IndexMap::new(); for alias in aliases { - normalized_aliases - .entry(alias.package) - .or_insert_with(IndexMap::new) - .insert( - alias.version, - RootAliasEntry { - alias: alias.alias, - alias_normalized: alias.alias_normalized, - }, - ); + normalized_aliases.entry(alias.package).or_default().insert( + alias.version, + RootAliasEntry { + alias: alias.alias, + alias_normalized: alias.alias_normalized, + }, + ); } normalized_aliases diff --git a/crates/shirabe/src/repository/vcs/forgejo_driver.rs b/crates/shirabe/src/repository/vcs/forgejo_driver.rs index df52820..3706e02 100644 --- a/crates/shirabe/src/repository/vcs/forgejo_driver.rs +++ b/crates/shirabe/src/repository/vcs/forgejo_driver.rs @@ -76,7 +76,7 @@ impl ForgejoDriver { None, false, )); - self.inner.cache.as_mut().map(|c| { + if let Some(c) = self.inner.cache.as_mut() { c.set_read_only( self.inner .config @@ -85,7 +85,7 @@ impl ForgejoDriver { .as_bool() .unwrap_or(false), ) - }); + } self.fetch_repository_data()?; @@ -114,11 +114,8 @@ impl ForgejoDriver { let needs_git_blob = if let PhpMixed::Array(ref arr) = resource { let content_empty = arr .get("content") - .map_or(true, |v| v.as_string().map_or(true, |s| s.is_empty())); - let encoding_none = arr - .get("encoding") - .and_then(|v| v.as_string()) - .map_or(false, |s| s == "none"); + .is_none_or(|v| v.as_string().is_none_or(|s| s.is_empty())); + let encoding_none = arr.get("encoding").and_then(|v| v.as_string()) == Some("none"); let has_git_url = arr.contains_key("git_url"); content_empty && encoding_none && has_git_url } else { @@ -143,10 +140,7 @@ impl ForgejoDriver { let content_b64 = if let PhpMixed::Array(ref arr) = resource { let has_content = arr.contains_key("content"); - let encoding_ok = arr - .get("encoding") - .and_then(|v| v.as_string()) - .map_or(false, |s| s == "base64"); + let encoding_ok = arr.get("encoding").and_then(|v| v.as_string()) == Some("base64"); if has_content && encoding_ok { arr.get("content") .and_then(|v| v.as_string()) @@ -357,25 +351,25 @@ impl ForgejoDriver { file_content, || self.get_change_date(identifier), )?; - if self.inner.should_cache(identifier) { - if let Some(ref composer_map) = c { - let encoded = JsonFile::encode_with_options( - &PhpMixed::Array( - composer_map - .iter() - .map(|(k, v)| (k.clone(), Box::new(v.clone()))) - .collect(), - ), - JsonEncodeOptions { - pretty_print: false, - ..Default::default() - }, - ); - self.inner - .cache - .as_mut() - .map(|c| c.write(identifier, &encoded)); - } + if self.inner.should_cache(identifier) + && let Some(ref composer_map) = c + { + let encoded = JsonFile::encode_with_options( + &PhpMixed::Array( + composer_map + .iter() + .map(|(k, v)| (k.clone(), Box::new(v.clone()))) + .collect(), + ), + JsonEncodeOptions { + pretty_print: false, + ..Default::default() + }, + ); + self.inner + .cache + .as_mut() + .map(|c| c.write(identifier, &encoded)); } c } @@ -392,7 +386,7 @@ impl ForgejoDriver { // specials for forgejo let support_not_array = composer_map .get("support") - .map_or(false, |v| v.as_array().is_none()); + .is_some_and(|v| v.as_array().is_none()); if support_not_array { composer_map.insert("support".to_string(), PhpMixed::Array(IndexMap::new())); } @@ -400,7 +394,7 @@ impl ForgejoDriver { let has_source = composer_map .get("support") .and_then(|v| v.as_array()) - .map_or(false, |arr| arr.contains_key("source")); + .is_some_and(|arr| arr.contains_key("source")); if !has_source { let html_url = self @@ -437,14 +431,9 @@ impl ForgejoDriver { let has_issues = composer_map .get("support") .and_then(|v| v.as_array()) - .map_or(false, |arr| arr.contains_key("issues")); + .is_some_and(|arr| arr.contains_key("issues")); - if !has_issues - && self - .repository_data - .as_ref() - .map_or(false, |r| r.has_issues) - { + if !has_issues && self.repository_data.as_ref().is_some_and(|r| r.has_issues) { let issues_url = format!( "{}/issues", self.repository_data @@ -459,10 +448,7 @@ impl ForgejoDriver { } if !composer_map.contains_key("abandoned") - && self - .repository_data - .as_ref() - .map_or(false, |r| r.is_archived) + && self.repository_data.as_ref().is_some_and(|r| r.is_archived) { composer_map.insert("abandoned".to_string(), PhpMixed::Bool(true)); } @@ -520,9 +506,8 @@ impl ForgejoDriver { let forgejo_domains = config.borrow().get("forgejo-domains"); let in_domains = if let Some(list) = forgejo_domains.as_list() { list.iter().any(|d| { - d.as_string().map_or(false, |s| { - s.to_lowercase() == forgejo_url.origin_url.to_lowercase() - }) + d.as_string() + .is_some_and(|s| s.to_lowercase() == forgejo_url.origin_url.to_lowercase()) }) } else { false @@ -605,10 +590,10 @@ impl ForgejoDriver { let links = explode(",", &header); for link in links { let mut m: IndexMap<CaptureKey, String> = IndexMap::new(); - if Preg::match3(r#"{<(.+?)>; *rel="next"}"#, &link, Some(&mut m)) { - if let Some(url) = m.get(&CaptureKey::ByIndex(1)) { - return Some(url.clone()); - } + if Preg::match3(r#"{<(.+?)>; *rel="next"}"#, &link, Some(&mut m)) + && let Some(url) = m.get(&CaptureKey::ByIndex(1)) + { + return Some(url.clone()); } } diff --git a/crates/shirabe/src/repository/vcs/fossil_driver.rs b/crates/shirabe/src/repository/vcs/fossil_driver.rs index c205379..1da7a2a 100644 --- a/crates/shirabe/src/repository/vcs/fossil_driver.rs +++ b/crates/shirabe/src/repository/vcs/fossil_driver.rs @@ -101,7 +101,7 @@ impl FossilDriver { pub(crate) fn check_fossil(&self) -> anyhow::Result<()> { let mut ignored_output = String::new(); if self.inner.process.borrow_mut().execute_args( - &["fossil", "version"].map(|s| s.to_string()).to_vec(), + ["fossil", "version"].map(|s| s.to_string()).as_ref(), &mut ignored_output, (), ) != 0 @@ -141,13 +141,13 @@ impl FossilDriver { if is_file(&repo_file) && is_dir(&self.checkout_dir) && self.inner.process.borrow_mut().execute_args( - &["fossil", "info"].map(|s| s.to_string()).to_vec(), + ["fossil", "info"].map(|s| s.to_string()).as_ref(), &mut String::new(), Some(self.checkout_dir.clone()), ) == 0 { if self.inner.process.borrow_mut().execute_args( - &["fossil", "pull"].map(|s| s.to_string()).to_vec(), + ["fossil", "pull"].map(|s| s.to_string()).as_ref(), &mut String::new(), Some(self.checkout_dir.clone()), ) != 0 @@ -166,9 +166,9 @@ impl FossilDriver { let mut output = String::new(); if self.inner.process.borrow_mut().execute_args( - &["fossil", "clone", "--", &self.inner.url, &repo_file] + ["fossil", "clone", "--", &self.inner.url, &repo_file] .map(|s| s.to_string()) - .to_vec(), + .as_ref(), &mut output, (), ) != 0 @@ -185,9 +185,9 @@ impl FossilDriver { } if self.inner.process.borrow_mut().execute_args( - &["fossil", "open", "--nested", "--", &repo_file] + ["fossil", "open", "--nested", "--", &repo_file] .map(|s| s.to_string()) - .to_vec(), + .as_ref(), &mut output, Some(self.checkout_dir.clone()), ) != 0 @@ -244,9 +244,9 @@ impl FossilDriver { let mut content = String::new(); self.inner.process.borrow_mut().execute_args( - &["fossil", "cat", "-r", identifier, "--", file] + ["fossil", "cat", "-r", identifier, "--", file] .map(|s| s.to_string()) - .to_vec(), + .as_ref(), &mut content, Some(self.checkout_dir.clone()), ); @@ -264,9 +264,9 @@ impl FossilDriver { ) -> anyhow::Result<Option<DateTime<FixedOffset>>> { let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &["fossil", "finfo", "-b", "-n", "1", "composer.json"] + ["fossil", "finfo", "-b", "-n", "1", "composer.json"] .map(|s| s.to_string()) - .to_vec(), + .as_ref(), &mut output, Some(self.checkout_dir.clone()), ); @@ -282,7 +282,7 @@ impl FossilDriver { let mut tags: IndexMap<String, String> = IndexMap::new(); let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &["fossil", "tag", "list"].map(|s| s.to_string()).to_vec(), + ["fossil", "tag", "list"].map(|s| s.to_string()).as_ref(), &mut output, Some(self.checkout_dir.clone()), ); @@ -299,12 +299,12 @@ impl FossilDriver { let mut branches: IndexMap<String, String> = IndexMap::new(); let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &["fossil", "branch", "list"].map(|s| s.to_string()).to_vec(), + ["fossil", "branch", "list"].map(|s| s.to_string()).as_ref(), &mut output, Some(self.checkout_dir.clone()), ); for branch in self.inner.process.borrow().split_lines(&output) { - let branch = Preg::replace(r"/^\*/", "", &branch.trim()); + let branch = Preg::replace(r"/^\*/", "", branch.trim()); let branch = branch.trim().to_string(); branches.insert(branch.clone(), branch); } @@ -340,7 +340,7 @@ impl FossilDriver { let mut process = ProcessExecutor::new(Some(io)); let mut output = String::new(); if process.execute_args( - &["fossil", "info"].map(|s| s.to_string()).to_vec(), + ["fossil", "info"].map(|s| s.to_string()).as_ref(), &mut output, Some(url), ) == 0 diff --git a/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs b/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs index b0985e5..44c0d08 100644 --- a/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs +++ b/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs @@ -789,16 +789,16 @@ impl GitBitbucketDriver { _ => return, }; for clone_link in list { - if let PhpMixed::Array(m) = clone_link.as_ref() { - if m.get("name").and_then(|v| v.as_string()) == Some("https") { - // Format: https://(user@)bitbucket.org/{user}/{repo} - // Strip username from URL (only present in clone URL's for private repositories) - self.clone_https_url = Preg::replace( - r"/https:\/\/([^@]+@)?/", - "https://", - m.get("href").and_then(|v| v.as_string()).unwrap_or(""), - ); - } + if let PhpMixed::Array(m) = clone_link.as_ref() + && m.get("name").and_then(|v| v.as_string()) == Some("https") + { + // Format: https://(user@)bitbucket.org/{user}/{repo} + // Strip username from URL (only present in clone URL's for private repositories) + self.clone_https_url = Preg::replace( + r"/https:\/\/([^@]+@)?/", + "https://", + m.get("href").and_then(|v| v.as_string()).unwrap_or(""), + ); } } } diff --git a/crates/shirabe/src/repository/vcs/git_driver.rs b/crates/shirabe/src/repository/vcs/git_driver.rs index 3c950bb..e639649 100644 --- a/crates/shirabe/src/repository/vcs/git_driver.rs +++ b/crates/shirabe/src/repository/vcs/git_driver.rs @@ -167,7 +167,7 @@ impl GitDriver { None, false, )); - self.inner.cache.as_mut().map(|c| { + if let Some(c) = self.inner.cache.as_mut() { c.set_read_only( self.inner .config @@ -176,7 +176,7 @@ impl GitDriver { .as_bool() .unwrap_or(false), ) - }); + } Ok(()) } @@ -215,11 +215,11 @@ impl GitDriver { for branch in &branches { if !branch.is_empty() { let mut caps: IndexMap<CaptureKey, String> = IndexMap::new(); - if Preg::match3(r"{^\* +(\S+)}", branch, Some(&mut caps)) { - if let Some(name) = caps.get(&CaptureKey::ByIndex(1)) { - self.root_identifier = Some(name.clone()); - break; - } + if Preg::match3(r"{^\* +(\S+)}", branch, Some(&mut caps)) + && let Some(name) = caps.get(&CaptureKey::ByIndex(1)) + { + self.root_identifier = Some(name.clone()); + break; } } } @@ -338,16 +338,14 @@ impl GitDriver { r"{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}", &tag, Some(&mut caps), + ) && let (Some(hash), Some(name)) = ( + caps.get(&CaptureKey::ByIndex(1)), + caps.get(&CaptureKey::ByIndex(2)), ) { - if let (Some(hash), Some(name)) = ( - caps.get(&CaptureKey::ByIndex(1)), - caps.get(&CaptureKey::ByIndex(2)), - ) { - self.tags - .as_mut() - .unwrap() - .insert(name.clone(), hash.clone()); - } + self.tags + .as_mut() + .unwrap() + .insert(name.clone(), hash.clone()); } } } @@ -379,15 +377,12 @@ impl GitDriver { r"{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}", &branch, Some(&mut caps), - ) { - if let (Some(name), Some(hash)) = ( - caps.get(&CaptureKey::ByIndex(1)), - caps.get(&CaptureKey::ByIndex(2)), - ) { - if !name.starts_with('-') { - branches.insert(name.clone(), hash.clone()); - } - } + ) && let (Some(name), Some(hash)) = ( + caps.get(&CaptureKey::ByIndex(1)), + caps.get(&CaptureKey::ByIndex(2)), + ) && !name.starts_with('-') + { + branches.insert(name.clone(), hash.clone()); } } } @@ -430,7 +425,7 @@ impl GitDriver { return Ok(true); } GitUtil::check_for_repo_ownership_error( - &process.borrow().get_error_output(), + process.borrow().get_error_output(), &url, Some(io.clone()), )?; diff --git a/crates/shirabe/src/repository/vcs/github_driver.rs b/crates/shirabe/src/repository/vcs/github_driver.rs index 696851e..8c8c81a 100644 --- a/crates/shirabe/src/repository/vcs/github_driver.rs +++ b/crates/shirabe/src/repository/vcs/github_driver.rs @@ -130,7 +130,7 @@ impl GitHubDriver { None, false, )); - self.inner.cache.as_mut().map(|c| { + if let Some(c) = self.inner.cache.as_mut() { c.set_read_only( self.inner .config @@ -139,7 +139,7 @@ impl GitHubDriver { .as_bool() .unwrap_or(false), ) - }); + } if self .inner @@ -290,27 +290,27 @@ impl GitHubDriver { || self.get_change_date(identifier), )?; - if self.inner.should_cache(identifier) { - if let Some(ref composer_map) = composer { - let php_value: PhpMixed = PhpMixed::Array( - composer_map - .iter() - .map(|(k, v)| (k.clone(), Box::new(v.clone()))) - .collect(), - ); - self.inner.cache.as_mut().map(|c| { - c.write( - identifier, - &JsonFile::encode_with_options( - &php_value, - JsonEncodeOptions { - pretty_print: false, - ..Default::default() - }, - ), - ) - }); - } + if self.inner.should_cache(identifier) + && let Some(ref composer_map) = composer + { + let php_value: PhpMixed = PhpMixed::Array( + composer_map + .iter() + .map(|(k, v)| (k.clone(), Box::new(v.clone()))) + .collect(), + ); + self.inner.cache.as_mut().map(|c| { + c.write( + identifier, + &JsonFile::encode_with_options( + &php_value, + JsonEncodeOptions { + pretty_print: false, + ..Default::default() + }, + ), + ) + }); } composer @@ -379,21 +379,22 @@ impl GitHubDriver { .and_then(|v| v.as_array()) .map(|m| m.contains_key("issues")) .unwrap_or(false); - if issues_missing && self.has_issues { - if let Some(support) = composer.get_mut("support").and_then(|v| match v { + if issues_missing + && self.has_issues + && let Some(support) = composer.get_mut("support").and_then(|v| match v { PhpMixed::Array(m) => Some(m), _ => None, - }) { - support.insert( - "issues".to_string(), - Box::new(PhpMixed::String(format!( - "https://{}/{}/{}/issues", - PhpMixed::String(self.inner.origin_url.clone()), - PhpMixed::String(self.owner.clone()), - PhpMixed::String(self.repository.clone()), - ))), - ); - } + }) + { + support.insert( + "issues".to_string(), + Box::new(PhpMixed::String(format!( + "https://{}/{}/{}/issues", + PhpMixed::String(self.inner.origin_url.clone()), + PhpMixed::String(self.owner.clone()), + PhpMixed::String(self.repository.clone()), + ))), + ); } if !composer.contains_key("abandoned") && self.is_archived { composer.insert("abandoned".to_string(), PhpMixed::Bool(true)); @@ -1066,7 +1067,9 @@ impl GitHubDriver { let scopes_failed = array_diff(&scopes_needed, &scopes_issued); // non-authenticated requests get no scopesNeeded, so ask for credentials // authenticated requests which failed some scopes should ask for new credentials too - if headers.is_empty() || scopes_needed.is_empty() || scopes_failed.len() > 0 + if headers.is_empty() + || scopes_needed.is_empty() + || !scopes_failed.is_empty() { git_hub_util.authorize_oauth_interactively( &self.inner.origin_url, diff --git a/crates/shirabe/src/repository/vcs/gitlab_driver.rs b/crates/shirabe/src/repository/vcs/gitlab_driver.rs index fc09108..a5e6b73 100644 --- a/crates/shirabe/src/repository/vcs/gitlab_driver.rs +++ b/crates/shirabe/src/repository/vcs/gitlab_driver.rs @@ -222,7 +222,7 @@ impl GitLabDriver { None, false, )); - self.inner.cache.as_mut().map(|c| { + if let Some(c) = self.inner.cache.as_mut() { c.set_read_only( self.inner .config @@ -231,7 +231,7 @@ impl GitLabDriver { .as_bool() .unwrap_or(false), ) - }); + } self.fetch_project()?; @@ -283,27 +283,27 @@ impl GitLabDriver { || self.get_change_date(identifier), )?; - if self.inner.should_cache(identifier) { - if let Some(ref composer_map) = composer { - self.inner.cache.as_mut().map(|c| { - c.write( - identifier, - &JsonFile::encode_with_options( - &PhpMixed::Array( - composer_map - .clone() - .into_iter() - .map(|(k, v)| (k, Box::new(v))) - .collect(), - ), - JsonEncodeOptions { - pretty_print: false, - ..Default::default() - }, + if self.inner.should_cache(identifier) + && let Some(ref composer_map) = composer + { + self.inner.cache.as_mut().map(|c| { + c.write( + identifier, + &JsonFile::encode_with_options( + &PhpMixed::Array( + composer_map + .clone() + .into_iter() + .map(|(k, v)| (k, Box::new(v))) + .collect(), ), - ) - }); - } + JsonEncodeOptions { + pretty_print: false, + ..Default::default() + }, + ), + ) + }); } composer @@ -615,7 +615,7 @@ impl GitLabDriver { ]), true, ) { - format!("%{}", format!("{:02X}", ord(&character))) + format!("%{:02X}", ord(&character)) } else { character }; @@ -828,14 +828,12 @@ impl GitLabDriver { json_map.get("permissions").and_then(|v| v.as_array()) { for (_, permission) in permissions { - if let Some(perm_map) = permission.as_array() { - if let Some(level) = + if let Some(perm_map) = permission.as_array() + && let Some(level) = perm_map.get("access_level").and_then(|v| v.as_int()) - { - if level >= 20 { - more_than_guest_access = true; - } - } + && level >= 20 + { + more_than_guest_access = true; } } } @@ -874,7 +872,7 @@ impl GitLabDriver { } if !empty( - &*json_map + &json_map .get("id") .cloned() .unwrap_or(Box::new(PhpMixed::Null)), diff --git a/crates/shirabe/src/repository/vcs/hg_driver.rs b/crates/shirabe/src/repository/vcs/hg_driver.rs index 63a400c..4a6188e 100644 --- a/crates/shirabe/src/repository/vcs/hg_driver.rs +++ b/crates/shirabe/src/repository/vcs/hg_driver.rs @@ -85,19 +85,19 @@ impl HgDriver { let hg_utils = HgUtils::new( self.inner.io.clone(), - &*self.inner.config.borrow(), + &self.inner.config.borrow(), &self.inner.process, ); if is_dir(&self.repo_dir) && self.inner.process.borrow_mut().execute_args( - &["hg", "summary"].map(|s| s.to_string()).to_vec(), + ["hg", "summary"].map(|s| s.to_string()).as_ref(), &mut String::new(), Some(self.repo_dir.clone()), ) == 0 { if self.inner.process.borrow_mut().execute_args( - &["hg", "pull"].map(|s| s.to_string()).to_vec(), + ["hg", "pull"].map(|s| s.to_string()).as_ref(), &mut String::new(), Some(self.repo_dir.clone()), ) != 0 @@ -134,9 +134,9 @@ impl HgDriver { if self.root_identifier.is_none() { let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &["hg", "tip", "--template", "{node}"] + ["hg", "tip", "--template", "{node}"] .map(|s| s.to_string()) - .to_vec(), + .as_ref(), &mut output, Some(self.repo_dir.clone()), ); @@ -214,7 +214,7 @@ impl HgDriver { let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &[ + [ "hg", "log", "--template", @@ -223,7 +223,7 @@ impl HgDriver { identifier, ] .map(|s| s.to_string()) - .to_vec(), + .as_ref(), &mut output, Some(self.repo_dir.clone()), ); @@ -237,7 +237,7 @@ impl HgDriver { let mut tags: IndexMap<String, String> = IndexMap::new(); let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &["hg", "tags"].map(|s| s.to_string()).to_vec(), + ["hg", "tags"].map(|s| s.to_string()).as_ref(), &mut output, Some(self.repo_dir.clone()), ); @@ -267,7 +267,7 @@ impl HgDriver { let mut output = String::new(); self.inner.process.borrow_mut().execute_args( - &["hg", "branches"].map(|s| s.to_string()).to_vec(), + ["hg", "branches"].map(|s| s.to_string()).as_ref(), &mut output, Some(self.repo_dir.clone()), ); @@ -288,7 +288,7 @@ impl HgDriver { output.clear(); self.inner.process.borrow_mut().execute_args( - &["hg", "bookmarks"].map(|s| s.to_string()).to_vec(), + ["hg", "bookmarks"].map(|s| s.to_string()).as_ref(), &mut output, Some(self.repo_dir.clone()), ); @@ -337,7 +337,7 @@ impl HgDriver { let mut process = crate::util::ProcessExecutor::new(Some(io.clone())); let mut output = String::new(); if process.execute_args( - &["hg", "summary"].map(|s| s.to_string()).to_vec(), + ["hg", "summary"].map(|s| s.to_string()).as_ref(), &mut output, Some(url), ) == 0 @@ -353,9 +353,9 @@ impl HgDriver { let mut process = crate::util::ProcessExecutor::new(Some(io)); let mut ignored = String::new(); let exit = process.execute_args( - &["hg", "identify", "--", url] + ["hg", "identify", "--", url] .map(|s| s.to_string()) - .to_vec(), + .as_ref(), &mut ignored, (), ); diff --git a/crates/shirabe/src/repository/vcs/perforce_driver.rs b/crates/shirabe/src/repository/vcs/perforce_driver.rs index 10cf913..3077cff 100644 --- a/crates/shirabe/src/repository/vcs/perforce_driver.rs +++ b/crates/shirabe/src/repository/vcs/perforce_driver.rs @@ -50,10 +50,9 @@ impl PerforceDriver { .repo_config .get("branch") .and_then(|v| v.as_string()) + && !branch.is_empty() { - if !branch.is_empty() { - self.branch = branch.to_string(); - } + self.branch = branch.to_string(); } let repo_config = self.inner.repo_config.clone(); @@ -171,7 +170,7 @@ impl PerforceDriver { .as_mut() .unwrap() .get_composer_information(&path) - .map_or(false, |info| info.map_or(false, |i| !i.is_empty())) + .is_ok_and(|info| info.is_some_and(|i| !i.is_empty())) } pub fn get_contents(&self, _url: &str) -> anyhow::Result<Response> { diff --git a/crates/shirabe/src/repository/vcs/svn_driver.rs b/crates/shirabe/src/repository/vcs/svn_driver.rs index b48ce99..6346a84 100644 --- a/crates/shirabe/src/repository/vcs/svn_driver.rs +++ b/crates/shirabe/src/repository/vcs/svn_driver.rs @@ -168,33 +168,32 @@ impl SvnDriver { identifier: &str, ) -> Result<Option<IndexMap<String, PhpMixed>>> { if !self.inner.info_cache.contains_key(identifier) { - if self.should_cache(identifier) { - if let Some(mut res) = self + if self.should_cache(identifier) + && let Some(mut res) = self .inner .cache .as_mut() .and_then(|c| c.read(&format!("{}.json", identifier))) - { - // old cache files had '' stored instead of null due to af3783b5f40bae32a23e353eaf0a00c9b8ce82e2, so we make sure here that we always return null or array - // and fix outdated invalid cache files - if res == "\"\"" { - res = "null".to_string(); - self.inner - .cache - .as_mut() - .unwrap() - .write(&format!("{}.json", identifier), &res)?; - } - - let parsed = JsonFile::parse_json(Some(res.as_str()), None)?; - let composer: Option<IndexMap<String, PhpMixed>> = parsed - .as_array() - .map(|m| m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect()); + { + // old cache files had '' stored instead of null due to af3783b5f40bae32a23e353eaf0a00c9b8ce82e2, so we make sure here that we always return null or array + // and fix outdated invalid cache files + if res == "\"\"" { + res = "null".to_string(); self.inner - .info_cache - .insert(identifier.to_string(), composer.clone()); - return Ok(composer); + .cache + .as_mut() + .unwrap() + .write(&format!("{}.json", identifier), &res)?; } + + let parsed = JsonFile::parse_json(Some(res.as_str()), None)?; + let composer: Option<IndexMap<String, PhpMixed>> = parsed + .as_array() + .map(|m| m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect()); + self.inner + .info_cache + .insert(identifier.to_string(), composer.clone()); + return Ok(composer); } let base_result = @@ -290,7 +289,7 @@ impl SvnDriver { return Err(e); } }; - if trim(&output, None) == "" { + if trim(&output, None).is_empty() { return Ok(None); } @@ -506,14 +505,14 @@ impl SvnDriver { } // Subversion client 1.7 and older - if stripos(&process.get_error_output(), "authorization failed:").is_some() { + if stripos(process.get_error_output(), "authorization failed:").is_some() { // This is likely a remote Subversion repository that requires // authentication. We will handle actual authentication later. return Ok(true); } // Subversion client 1.8 and newer - if stripos(&process.get_error_output(), "Authentication failed").is_some() { + if stripos(process.get_error_output(), "Authentication failed").is_some() { // This is likely a remote Subversion or newer repository that requires // authentication. We will handle actual authentication later. return Ok(true); diff --git a/crates/shirabe/src/repository/vcs/vcs_driver.rs b/crates/shirabe/src/repository/vcs/vcs_driver.rs index d1bb3cc..ac7496d 100644 --- a/crates/shirabe/src/repository/vcs/vcs_driver.rs +++ b/crates/shirabe/src/repository/vcs/vcs_driver.rs @@ -119,17 +119,16 @@ impl VcsDriverBase { let mut composer: IndexMap<String, PhpMixed> = array.into_iter().map(|(k, v)| (k, *v)).collect(); - if !composer.contains_key("time") + if (!composer.contains_key("time") || composer .get("time") - .map_or(true, |v| v.as_string().map_or(true, |s| s.is_empty())) + .is_none_or(|v| v.as_string().is_none_or(|s| s.is_empty()))) + && let Some(d) = change_date()? { - if let Some(d) = change_date()? { - composer.insert( - "time".to_string(), - PhpMixed::String(d.format(DATE_RFC3339).to_string()), - ); - } + composer.insert( + "time".to_string(), + PhpMixed::String(d.format(DATE_RFC3339).to_string()), + ); } Ok(Some(composer)) @@ -150,16 +149,16 @@ impl VcsDriverBase { self.info_cache.get(identifier).and_then(|v| v.clone()), )); } - if self.should_cache(identifier) { - if let Some(res) = self.cache.as_mut().and_then(|c| c.read(identifier)) { - let parsed = JsonFile::parse_json(Some(&res), None)?; - let composer: Option<IndexMap<String, PhpMixed>> = parsed - .as_array() - .map(|m| m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect()); - self.info_cache - .insert(identifier.to_string(), composer.clone()); - return Ok(Some(composer)); - } + if self.should_cache(identifier) + && let Some(res) = self.cache.as_mut().and_then(|c| c.read(identifier)) + { + let parsed = JsonFile::parse_json(Some(&res), None)?; + let composer: Option<IndexMap<String, PhpMixed>> = parsed + .as_array() + .map(|m| m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect()); + self.info_cache + .insert(identifier.to_string(), composer.clone()); + return Ok(Some(composer)); } Ok(None) } @@ -215,38 +214,38 @@ pub trait VcsDriver: VcsDriverInterface { identifier: &str, ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> { if !self.info_cache().contains_key(identifier) { - if self.should_cache(identifier) { - if let Some(res) = self.cache_mut().and_then(|c| c.read(identifier)) { - let parsed = JsonFile::parse_json(Some(&res), None)?; - let parsed_map: Option<IndexMap<String, PhpMixed>> = match parsed { - PhpMixed::Array(a) => Some(a.into_iter().map(|(k, v)| (k, *v)).collect()), - _ => None, - }; - self.info_cache_mut() - .insert(identifier.to_string(), parsed_map); - return Ok(self.info_cache().get(identifier).and_then(|v| v.clone())); - } + if self.should_cache(identifier) + && let Some(res) = self.cache_mut().and_then(|c| c.read(identifier)) + { + let parsed = JsonFile::parse_json(Some(&res), None)?; + let parsed_map: Option<IndexMap<String, PhpMixed>> = match parsed { + PhpMixed::Array(a) => Some(a.into_iter().map(|(k, v)| (k, *v)).collect()), + _ => None, + }; + self.info_cache_mut() + .insert(identifier.to_string(), parsed_map); + return Ok(self.info_cache().get(identifier).and_then(|v| v.clone())); } let composer = self.get_base_composer_information(identifier)?; - if self.should_cache(identifier) { - if let Some(ref composer_map) = composer { - let composer_mixed = PhpMixed::Array( - composer_map - .iter() - .map(|(k, v)| (k.clone(), Box::new(v.clone()))) - .collect(), - ); - let encoded = JsonFile::encode_with_options( - &composer_mixed, - JsonEncodeOptions { - pretty_print: false, - ..Default::default() - }, - ); - self.cache_mut().map(|c| c.write(identifier, &encoded)); - } + if self.should_cache(identifier) + && let Some(ref composer_map) = composer + { + let composer_mixed = PhpMixed::Array( + composer_map + .iter() + .map(|(k, v)| (k.clone(), Box::new(v.clone()))) + .collect(), + ); + let encoded = JsonFile::encode_with_options( + &composer_mixed, + JsonEncodeOptions { + pretty_print: false, + ..Default::default() + }, + ); + self.cache_mut().map(|c| c.write(identifier, &encoded)); } self.info_cache_mut() @@ -278,27 +277,26 @@ pub trait VcsDriver: VcsDriverInterface { _ => return Ok(None), }; - if !composer.contains_key("time") + if (!composer.contains_key("time") || composer .get("time") - .map_or(true, |v| v.as_string().map_or(true, |s| s.is_empty())) + .is_none_or(|v| v.as_string().is_none_or(|s| s.is_empty()))) + && let Some(change_date) = self.get_change_date(identifier)? { - if let Some(change_date) = self.get_change_date(identifier)? { - composer.insert( - "time".to_string(), - PhpMixed::String(change_date.format(DATE_RFC3339).to_string()), - ); - } + composer.insert( + "time".to_string(), + PhpMixed::String(change_date.format(DATE_RFC3339).to_string()), + ); } Ok(Some(composer)) } fn has_composer_file(&mut self, identifier: &str) -> bool { - match VcsDriver::get_composer_information(self, identifier) { - Ok(Some(_)) => true, - _ => false, - } + matches!( + VcsDriver::get_composer_information(self, identifier), + Ok(Some(_)) + ) } fn get_scheme(&self) -> &str { diff --git a/crates/shirabe/src/repository/vcs_repository.rs b/crates/shirabe/src/repository/vcs_repository.rs index ebab76f..de51a34 100644 --- a/crates/shirabe/src/repository/vcs_repository.rs +++ b/crates/shirabe/src/repository/vcs_repository.rs @@ -84,8 +84,7 @@ impl ConfigurableRepositoryInterface for VcsRepository { } impl VcsRepository { - /// @param array{url: string, type?: string}&array<string, mixed> $repoConfig - /// @param array<string, class-string<VcsDriverInterface>>|null $drivers + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn new( mut repo_config: IndexMap<String, PhpMixed>, io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>, @@ -315,10 +314,10 @@ impl VcsRepository { } Ok(None) => {} Err(e) => { - if let Some(te) = e.downcast_ref::<TransportException>() { - if self.should_rethrow_transport_exception(te) { - return Err(e); - } + if let Some(te) = e.downcast_ref::<TransportException>() + && self.should_rethrow_transport_exception(te) + { + return Err(e); } if is_very_verbose { self.io.write_error(&format!( @@ -331,10 +330,10 @@ impl VcsRepository { } } Err(e) => { - if let Some(te) = e.downcast_ref::<TransportException>() { - if self.should_rethrow_transport_exception(te) { - return Err(e); - } + if let Some(te) = e.downcast_ref::<TransportException>() + && self.should_rethrow_transport_exception(te) + { + return Err(e); } if is_very_verbose { self.io.write_error(&format!( @@ -528,7 +527,7 @@ impl VcsRepository { if let Some(te) = e.downcast_ref::<TransportException>() { self.version_transport_exceptions .entry("tags".to_string()) - .or_insert_with(IndexMap::new) + .or_default() .insert(tag.clone(), te.clone()); if te.get_code() == 404 { self.empty_references.push(identifier.clone()); @@ -701,15 +700,15 @@ impl VcsRepository { .loader .as_ref() .and_then(|l| l.as_any().downcast_ref::<ValidatingArrayLoader>()); - if let Some(validating) = loader_as_validating { - if !validating.get_warnings().is_empty() { - return Err(InvalidPackageException::new( - validating.get_errors().to_vec(), - validating.get_warnings().to_vec(), - package_data, - ) - .into()); - } + if let Some(validating) = loader_as_validating + && !validating.get_warnings().is_empty() + { + return Err(InvalidPackageException::new( + validating.get_errors().to_vec(), + validating.get_warnings().to_vec(), + package_data, + ) + .into()); } self.inner.add_package(package)?; Ok(()) @@ -718,7 +717,7 @@ impl VcsRepository { if let Some(te) = e.downcast_ref::<TransportException>() { self.version_transport_exceptions .entry("branches".to_string()) - .or_insert_with(IndexMap::new) + .or_default() .insert(branch.clone(), te.clone()); if te.get_code() == 404 { self.empty_references.push(identifier.clone()); @@ -830,10 +829,12 @@ impl VcsRepository { PhpMixed::Array(m) => m.get("reference").cloned(), _ => None, }); - if dist_is_array && dist_lacks_reference && source_reference.is_some() { - if let Some(PhpMixed::Array(dist_map)) = data.get_mut("dist") { - dist_map.insert("reference".to_string(), source_reference.unwrap()); - } + if dist_is_array + && dist_lacks_reference + && source_reference.is_some() + && let Some(PhpMixed::Array(dist_map)) = data.get_mut("dist") + { + dist_map.insert("reference".to_string(), source_reference.unwrap()); } Ok(data) diff --git a/crates/shirabe/src/self_update/versions.rs b/crates/shirabe/src/self_update/versions.rs index d854050..7c360e6 100644 --- a/crates/shirabe/src/self_update/versions.rs +++ b/crates/shirabe/src/self_update/versions.rs @@ -107,13 +107,13 @@ impl Versions { }; std::fs::write(&channel_file, format!("{}{}", stored_channel, PHP_EOL))?; - if let Some(io) = io { - if previously_stored.as_deref() != Some(&stored_channel) { - io.write_error(&format!( + if let Some(io) = io + && previously_stored.as_deref() != Some(&stored_channel) + { + io.write_error(&format!( "Storing \"<info>{}</info>\" as default update channel for the next self-update run.", stored_channel )); - } } Ok(Ok(())) @@ -129,19 +129,18 @@ impl Versions { None => self.get_channel()?, }; - if let PhpMixed::Array(ref map) = versions { - if let Some(channel_versions) = map.get(&effective_channel) { - if let PhpMixed::List(ref list) = **channel_versions { - for version in list { - if let PhpMixed::Array(ref v) = **version { - let min_php = v.get("min-php").and_then(|p| p.as_int()).unwrap_or(0); - if min_php <= PHP_VERSION_ID { - return Ok(Ok(v - .iter() - .map(|(k, val)| (k.clone(), *val.clone())) - .collect())); - } - } + if let PhpMixed::Array(ref map) = versions + && let Some(channel_versions) = map.get(&effective_channel) + && let PhpMixed::List(ref list) = **channel_versions + { + for version in list { + if let PhpMixed::Array(ref v) = **version { + let min_php = v.get("min-php").and_then(|p| p.as_int()).unwrap_or(0); + if min_php <= PHP_VERSION_ID { + return Ok(Ok(v + .iter() + .map(|(k, val)| (k.clone(), *val.clone())) + .collect())); } } } diff --git a/crates/shirabe/src/util/auth_helper.rs b/crates/shirabe/src/util/auth_helper.rs index d520270..5952429 100644 --- a/crates/shirabe/src/util/auth_helper.rs +++ b/crates/shirabe/src/util/auth_helper.rs @@ -114,13 +114,7 @@ impl AuthHelper { Ok(()) } - /// @param int $statusCode HTTP status code that triggered this call - /// @param string|null $reason a message/description explaining why this was called - /// @param string[] $headers - /// @param int $retryCount the amount of retries already done on this URL - /// @return array containing retry (bool) and storeAuth (string|bool) keys, if retry is true the request should be - /// retried, if storeAuth is true then on a successful retry the authentication should be persisted to auth.json - /// @phpstan-return array{retry: bool, storeAuth: 'prompt'|bool} + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn prompt_auth_if_needed( &mut self, url: &str, @@ -194,28 +188,23 @@ impl AuthHelper { } message = format!( - "{}\n", - format!( - "GitHub API limit ({} calls/hr) is exhausted, could not fetch {}. {} You can also wait until {} for the rate limit to reset.", - rate_limit.get("limit").cloned().unwrap_or(PhpMixed::Null), - url, - message, - rate_limit.get("reset").cloned().unwrap_or(PhpMixed::Null), - ), + "GitHub API limit ({} calls/hr) is exhausted, could not fetch {}. {} You can also wait until {} for the rate limit to reset.\n", + rate_limit.get("limit").cloned().unwrap_or(PhpMixed::Null), + url, + message, + rate_limit.get("reset").cloned().unwrap_or(PhpMixed::Null), ); } else { // Try to extract a more specific error message from GitHub's API response let mut git_hub_api_message: Option<String> = None; if let Some(body) = response_body { let decoded = json_decode(body, true)?; - if is_array(&decoded) { - if let Some(arr) = decoded.as_array() { - if let Some(msg) = arr.get("message") { - if is_string(msg) { - git_hub_api_message = msg.as_string().map(|s| s.to_string()); - } - } - } + if is_array(&decoded) + && let Some(arr) = decoded.as_array() + && let Some(msg) = arr.get("message") + && is_string(msg) + { + git_hub_api_message = msg.as_string().map(|s| s.to_string()); } } @@ -297,16 +286,16 @@ impl AuthHelper { .into()); } - if let Some(prev_auth) = auth { - if self.io.has_authentication(origin) { - let current_auth = self.io.get_authentication(origin); - if prev_auth == current_auth { - return Err(TransportException::new( - format!("Invalid credentials for '{}', aborting.", url), - status_code, - ) - .into()); - } + if let Some(prev_auth) = auth + && self.io.has_authentication(origin) + { + let current_auth = self.io.get_authentication(origin); + if prev_auth == current_auth { + return Err(TransportException::new( + format!("Invalid credentials for '{}', aborting.", url), + status_code, + ) + .into()); } } } else if origin == "bitbucket.org" || origin == "api.bitbucket.org" { @@ -473,10 +462,8 @@ impl AuthHelper { } else { false }; - if !http_has_header { - if let Some(PhpMixed::Array(http)) = options.get_mut("http") { - http.insert("header".to_string(), Box::new(PhpMixed::List(vec![]))); - } + if !http_has_header && let Some(PhpMixed::Array(http)) = options.get_mut("http") { + http.insert("header".to_string(), Box::new(PhpMixed::List(vec![]))); } } diff --git a/crates/shirabe/src/util/bitbucket.rs b/crates/shirabe/src/util/bitbucket.rs index 67ae575..0584308 100644 --- a/crates/shirabe/src/util/bitbucket.rs +++ b/crates/shirabe/src/util/bitbucket.rs @@ -382,7 +382,7 @@ impl Bitbucket { .remove_config_setting(&format!("bitbucket-oauth.{}", origin_url))?; let token = self.token.as_ref().ok_or_else(|| LogicException { - message: format!("Expected a token configured with expires_in present, got null",), + message: "Expected a token configured with expires_in present, got null".to_string(), code: 0, })?; let expires_in = token diff --git a/crates/shirabe/src/util/config_validator.rs b/crates/shirabe/src/util/config_validator.rs index 90195e7..a3f6ef7 100644 --- a/crates/shirabe/src/util/config_validator.rs +++ b/crates/shirabe/src/util/config_validator.rs @@ -97,7 +97,7 @@ impl ConfigValidator { // validate actual data if manifest .get("license") - .map_or(true, |v| matches!(v, PhpMixed::Null)) + .is_none_or(|v| matches!(v, PhpMixed::Null)) || !manifest.contains_key("license") { warnings.push("No license specified, it is recommended to do so. For closed-source software you may use \"proprietary\" as license.".to_string()); @@ -160,26 +160,28 @@ impl ConfigValidator { warnings.push("The version field is present, it is recommended to leave it out if the package is published on Packagist.".to_string()); } - if let Some(PhpMixed::String(name)) = manifest.get("name") { - if !name.is_empty() && Preg::is_match(r"{[A-Z]}", name) { - let suggest_name = Preg::replace( - r"{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}", - r"\1\3-\2\4", - name, - ); - let suggest_name = suggest_name.to_lowercase(); + if let Some(PhpMixed::String(name)) = manifest.get("name") + && !name.is_empty() + && Preg::is_match(r"{[A-Z]}", name) + { + let suggest_name = Preg::replace( + r"{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}", + r"\1\3-\2\4", + name, + ); + let suggest_name = suggest_name.to_lowercase(); - publish_errors.push(format!( + publish_errors.push(format!( "Name \"{}\" does not match the best practice (e.g. lower-cased/with-dashes). We suggest using \"{}\" instead. As such you will not be able to submit it to Packagist.", name, suggest_name )); - } } - if let Some(PhpMixed::String(t)) = manifest.get("type") { - if !t.is_empty() && t == "composer-installer" { - warnings.push("The package type 'composer-installer' is deprecated. Please distribute your custom installers as plugins from now on. See https://getcomposer.org/doc/articles/plugins.md for plugin documentation.".to_string()); - } + if let Some(PhpMixed::String(t)) = manifest.get("type") + && !t.is_empty() + && t == "composer-installer" + { + warnings.push("The package type 'composer-installer' is deprecated. Please distribute your custom installers as plugins from now on. See https://getcomposer.org/doc/articles/plugins.md for plugin documentation.".to_string()); } // check for require-dev overrides @@ -236,13 +238,13 @@ impl ConfigValidator { let mut packages: IndexMap<String, Box<PhpMixed>> = require; packages.extend(require_dev); for (package, version) in &packages { - if let PhpMixed::String(version_str) = version.as_ref() { - if Preg::is_match(r"{#}", version_str) { - warnings.push(format!( + if let PhpMixed::String(version_str) = version.as_ref() + && Preg::is_match(r"{#}", version_str) + { + warnings.push(format!( "The package \"{}\" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.", package )); - } } } @@ -280,15 +282,15 @@ impl ConfigValidator { // check for empty psr-0/psr-4 namespace prefixes if let Some(PhpMixed::Array(autoload)) = manifest.get("autoload") { - if let Some(PhpMixed::Array(psr0)) = autoload.get("psr-0").map(|v| v.as_ref()) { - if psr0.contains_key("") { - warnings.push("Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance".to_string()); - } + if let Some(PhpMixed::Array(psr0)) = autoload.get("psr-0").map(|v| v.as_ref()) + && psr0.contains_key("") + { + warnings.push("Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance".to_string()); } - if let Some(PhpMixed::Array(psr4)) = autoload.get("psr-4").map(|v| v.as_ref()) { - if psr4.contains_key("") { - warnings.push("Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance".to_string()); - } + if let Some(PhpMixed::Array(psr4)) = autoload.get("psr-4").map(|v| v.as_ref()) + && psr4.contains_key("") + { + warnings.push("Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance".to_string()); } } diff --git a/crates/shirabe/src/util/filesystem.rs b/crates/shirabe/src/util/filesystem.rs index cb0e4a5..50112ea 100644 --- a/crates/shirabe/src/util/filesystem.rs +++ b/crates/shirabe/src/util/filesystem.rs @@ -51,7 +51,7 @@ impl Filesystem { .depth(0) .r#in(dir); - finder.len() == 0 + finder.is_empty() } pub fn empty_directory( @@ -519,11 +519,7 @@ impl Filesystem { // Returning early-formatted Result is not possible without changing signature; panic to surface in tests. panic!( "{}", - format!( - "$from ({}) and $to ({}) must be absolute paths.", - from.to_string(), - to.to_string() - ) + format!("$from ({}) and $to ({}) must be absolute paths.", from, to) ); } @@ -584,11 +580,7 @@ impl Filesystem { if !self.is_absolute_path(from) || !self.is_absolute_path(to) { panic!( "{}", - format!( - "$from ({}) and $to ({}) must be absolute paths.", - from.to_string(), - to.to_string() - ) + format!("$from ({}) and $to ({}) must be absolute paths.", from, to) ); } @@ -722,8 +714,8 @@ impl Filesystem { for chunk in explode("/", &path) { if ".." == chunk && (strlen(&absolute) > 0 || up) { array_pop(&mut parts); - up = !(parts.len() == 0 || ".." == end(&parts).unwrap_or_default()); - } else if "." != chunk && "" != chunk { + up = !(parts.is_empty() || ".." == end(&parts).unwrap_or_default()); + } else if "." != chunk && !chunk.is_empty() { parts.push(chunk.clone()); up = ".." != chunk; } diff --git a/crates/shirabe/src/util/git.rs b/crates/shirabe/src/util/git.rs index 5916f9b..1467a29 100644 --- a/crates/shirabe/src/util/git.rs +++ b/crates/shirabe/src/util/git.rs @@ -118,7 +118,7 @@ impl Git { map.insert("%url%".to_string(), url.to_string()); map.insert( "%sanitizedUrl%".to_string(), - Preg::replace(r"{://([^@]+?):(.+?)@}", "://", &url), + Preg::replace(r"{://([^@]+?):(.+?)@}", "://", url), ); array_map( @@ -198,10 +198,8 @@ impl Git { counter += 1; } - if collect_outputs { - if let Some(out) = command_output { - *out = PhpMixed::String(implode("", &outputs)); - } + if collect_outputs && let Some(out) = command_output { + *out = PhpMixed::String(implode("", &outputs)); } status @@ -222,7 +220,7 @@ impl Git { // capture username/password from URL if there is one and we have no auth configured yet let mut output = String::new(); self.process.borrow_mut().execute_args( - &vec!["git".to_string(), "remote".to_string(), "-v".to_string()], + &["git".to_string(), "remote".to_string(), "-v".to_string()], &mut output, cwd.map(|s| s.to_string()), ); @@ -252,7 +250,7 @@ impl Git { if Preg::is_match3( &format!( "{{^(?:https?|git)://{}/(.*)}}", - Self::get_github_domains_regex(&*self.config.borrow()) + Self::get_github_domains_regex(&self.config.borrow()) ), url, Some(&mut m), @@ -276,7 +274,7 @@ impl Git { if run_commands_inline( &proto_url, - &mut *self.process.borrow_mut(), + &mut self.process.borrow_mut(), &mut last_command, command_output.as_deref_mut(), ) == 0 @@ -286,17 +284,11 @@ impl Git { messages.push(format!( "- {}\n{}", proto_url, - Preg::replace( - r"#^#m", - " ", - &self.process.borrow().get_error_output().to_string() - ) + Preg::replace(r"#^#m", " ", self.process.borrow().get_error_output()) )); - if initial_clone { - if let Some(ref orig) = orig_cwd { - self.filesystem.borrow_mut().remove_directory(orig); - } + if initial_clone && let Some(ref orig) = orig_cwd { + self.filesystem.borrow_mut().remove_directory(orig); } } @@ -326,7 +318,7 @@ impl Git { let bypass_ssh_for_github = Preg::is_match( &format!( "{{^git@{}:(.+?)\\.git$}}i", - Self::get_github_domains_regex(&*self.config.borrow()) + Self::get_github_domains_regex(&self.config.borrow()) ), url, ) && !in_array( @@ -345,7 +337,7 @@ impl Git { if bypass_ssh_for_github || 0 != run_commands_inline( url, - &mut *self.process.borrow_mut(), + &mut self.process.borrow_mut(), &mut last_command, command_output.as_deref_mut(), ) @@ -357,14 +349,14 @@ impl Git { let github_matched = Preg::is_match3( &format!( "{{^git@{}:(.+?)\\.git$}}i", - Self::get_github_domains_regex(&*self.config.borrow()) + Self::get_github_domains_regex(&self.config.borrow()) ), url, Some(&mut m), ) || Preg::is_match3( &format!( "{{^https?://{}/(.*?)(?:\\.git)?$}}i", - Self::get_github_domains_regex(&*self.config.borrow()) + Self::get_github_domains_regex(&self.config.borrow()) ), url, Some(&mut m), @@ -408,7 +400,7 @@ impl Git { ); if run_commands_inline( &auth_url, - &mut *self.process.borrow_mut(), + &mut self.process.borrow_mut(), &mut last_command, command_output.as_deref_mut(), ) == 0 @@ -419,18 +411,15 @@ impl Git { credentials = vec![rawurlencode(&username), rawurlencode(&password)]; error_msg = self.process.borrow().get_error_output().to_string(); } - } else if { - let bb_matched = Preg::is_match3( - r"{^(https?)://(bitbucket\.org)/(.*?)(?:\.git)?$}i", - url, - Some(&mut m), - ) || Preg::is_match3( - r"{^(git)@(bitbucket\.org):(.+?\.git)$}i", - url, - Some(&mut m), - ); - bb_matched - } { + } else if Preg::is_match3( + r"{^(https?)://(bitbucket\.org)/(.*?)(?:\.git)?$}i", + url, + Some(&mut m), + ) || Preg::is_match3( + r"{^(git)@(bitbucket\.org):(.+?\.git)$}i", + url, + Some(&mut m), + ) { // bitbucket either through oauth or app password, with fallback to ssh. let mut bitbucket_util = Bitbucket::new( self.io.clone(), @@ -493,7 +482,7 @@ impl Git { if run_commands_inline( &auth_url, - &mut *self.process.borrow_mut(), + &mut self.process.borrow_mut(), &mut last_command, command_output.as_deref_mut(), ) == 0 @@ -540,7 +529,7 @@ impl Git { ); if run_commands_inline( &auth_url, - &mut *self.process.borrow_mut(), + &mut self.process.borrow_mut(), &mut last_command, command_output.as_deref_mut(), ) == 0 @@ -559,7 +548,7 @@ impl Git { ); if run_commands_inline( &ssh_url, - &mut *self.process.borrow_mut(), + &mut self.process.borrow_mut(), &mut last_command, command_output.as_deref_mut(), ) == 0 @@ -568,24 +557,21 @@ impl Git { } error_msg = self.process.borrow().get_error_output().to_string(); - } else if { - let gl_matched = Preg::is_match3( - &format!( - "{{^(git)@{}:(.+?\\.git)$}}i", - Self::get_gitlab_domains_regex(&*self.config.borrow()) - ), - url, - Some(&mut m), - ) || Preg::is_match3( - &format!( - "{{^(https?)://{}/(.*)}}i", - Self::get_gitlab_domains_regex(&*self.config.borrow()) - ), - url, - Some(&mut m), - ); - gl_matched - } { + } else if Preg::is_match3( + &format!( + "{{^(git)@{}:(.+?\\.git)$}}i", + Self::get_gitlab_domains_regex(&self.config.borrow()) + ), + url, + Some(&mut m), + ) || Preg::is_match3( + &format!( + "{{^(https?)://{}/(.*)}}i", + Self::get_gitlab_domains_regex(&self.config.borrow()) + ), + url, + Some(&mut m), + ) { let mut m1 = m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(); let m2 = m.get(&CaptureKey::ByIndex(2)).cloned().unwrap_or_default(); let m3 = m.get(&CaptureKey::ByIndex(3)).cloned().unwrap_or_default(); @@ -649,7 +635,7 @@ impl Git { if run_commands_inline( &auth_url, - &mut *self.process.borrow_mut(), + &mut self.process.borrow_mut(), &mut last_command, command_output.as_deref_mut(), ) == 0 @@ -668,7 +654,7 @@ impl Git { let mut auth_parts: Option<String> = None; if str_contains(&m2, "@") { let parts = explode("@", &m2); - auth_parts = parts.get(0).cloned(); + auth_parts = parts.first().cloned(); m2 = parts.get(1).cloned().unwrap_or_default(); } @@ -677,14 +663,14 @@ impl Git { auth = Some(self.io.get_authentication(&m2)); } else if self.io.is_interactive() { let mut default_username: Option<String> = None; - if let Some(ref parts) = auth_parts { - if !parts.is_empty() { - if str_contains(parts, ":") { - let split = explode(":", parts); - default_username = split.get(0).cloned(); - } else { - default_username = Some(parts.clone()); - } + if let Some(ref parts) = auth_parts + && !parts.is_empty() + { + if str_contains(parts, ":") { + let split = explode(":", parts); + default_username = split.first().cloned(); + } else { + default_username = Some(parts.clone()); } } @@ -742,9 +728,9 @@ impl Git { if run_commands_inline( &auth_url, - &mut *self.process.borrow_mut(), + &mut self.process.borrow_mut(), &mut last_command, - command_output.as_deref_mut(), + command_output, ) == 0 { self.io.borrow_mut().set_authentication( @@ -768,10 +754,8 @@ impl Git { } } - if initial_clone { - if let Some(ref orig) = orig_cwd { - self.filesystem.borrow_mut().remove_directory(orig); - } + if initial_clone && let Some(ref orig) = orig_cwd { + self.filesystem.borrow_mut().remove_directory(orig); } let mut last_command_str = match &last_command { @@ -822,7 +806,7 @@ impl Git { let mut output = String::new(); if is_dir(dir) && self.process.borrow_mut().execute_args( - &vec![ + &[ "git".to_string(), "rev-parse".to_string(), "--git-dir".to_string(), @@ -933,12 +917,12 @@ impl Git { if self.check_ref_is_in_mirror(dir, r#ref)? { if Preg::is_match(r"{^[a-f0-9]{40}$}", r#ref) && pretty_version.is_some() { let branch = - Preg::replace(r"{(?:^dev-|(?:\.x)?-dev$)}i", "", &pretty_version.unwrap()); + Preg::replace(r"{(?:^dev-|(?:\.x)?-dev$)}i", "", pretty_version.unwrap()); let mut branches: Option<String> = None; let mut tags: Option<String> = None; let mut output = String::new(); if self.process.borrow_mut().execute_args( - &vec!["git".to_string(), "branch".to_string()], + &["git".to_string(), "branch".to_string()], &mut output, Some(dir.to_string()), ) == 0 @@ -947,7 +931,7 @@ impl Git { } let mut output = String::new(); if self.process.borrow_mut().execute_args( - &vec!["git".to_string(), "tag".to_string()], + &["git".to_string(), "tag".to_string()], &mut output, Some(dir.to_string()), ) == 0 @@ -988,10 +972,10 @@ impl Git { process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, ) -> String { let git_version = Self::get_version(process); - if let Some(v) = git_version { - if version_compare(&v, "2.10.0-rc0", ">=") { - return " --no-show-signature".to_string(); - } + if let Some(v) = git_version + && version_compare(&v, "2.10.0-rc0", ">=") + { + return " --no-show-signature".to_string(); } String::new() @@ -1063,7 +1047,7 @@ impl Git { let mut output = String::new(); if is_dir(dir) && self.process.borrow_mut().execute_args( - &vec![ + &[ "git".to_string(), "rev-parse".to_string(), "--git-dir".to_string(), @@ -1075,7 +1059,7 @@ impl Git { { let mut ignored_output = String::new(); let exit_code = self.process.borrow_mut().execute_args( - &vec![ + &[ "git".to_string(), "rev-parse".to_string(), "--quiet".to_string(), @@ -1137,7 +1121,7 @@ impl Git { if is_local_path_repository { let mut output = String::new(); self.process.borrow_mut().execute_args( - &vec![ + &[ "git".to_string(), "remote".to_string(), "show".to_string(), @@ -1279,7 +1263,7 @@ impl Git { let mut ignored_output = String::new(); if self.process.borrow_mut().execute_args( - &vec!["git".to_string(), "--version".to_string()], + &["git".to_string(), "--version".to_string()], &mut ignored_output, Option::<&str>::None, ) != 0 diff --git a/crates/shirabe/src/util/github.rs b/crates/shirabe/src/util/github.rs index 766d75b..204d95e 100644 --- a/crates/shirabe/src/util/github.rs +++ b/crates/shirabe/src/util/github.rs @@ -257,7 +257,7 @@ impl GitHub { ); return Ok(false); } - return Err(te.into()); + return Err(te); } } diff --git a/crates/shirabe/src/util/gitlab.rs b/crates/shirabe/src/util/gitlab.rs index 3938a07..86b7620 100644 --- a/crates/shirabe/src/util/gitlab.rs +++ b/crates/shirabe/src/util/gitlab.rs @@ -478,18 +478,14 @@ impl GitLab { pub fn is_oauth_expired(&self, origin_url: &str) -> bool { let auth_tokens = self.config.borrow_mut().get("gitlab-oauth"); - if let Some(map) = auth_tokens.as_array() { - if let Some(token_info) = map.get(origin_url) { - if let Some(token_map) = token_info.as_array() { - if let Some(expires_at) = token_map.get("expires-at") { - if let Some(expires_at_int) = expires_at.as_int() { - if expires_at_int < time() { - return true; - } - } - } - } - } + if let Some(map) = auth_tokens.as_array() + && let Some(token_info) = map.get(origin_url) + && let Some(token_map) = token_info.as_array() + && let Some(expires_at) = token_map.get("expires-at") + && let Some(expires_at_int) = expires_at.as_int() + && expires_at_int < time() + { + return true; } false diff --git a/crates/shirabe/src/util/hg.rs b/crates/shirabe/src/util/hg.rs index c8f5489..d20cf16 100644 --- a/crates/shirabe/src/util/hg.rs +++ b/crates/shirabe/src/util/hg.rs @@ -60,61 +60,59 @@ impl Hg { &mut matches, ); - if matched { - if self + if matched + && self .io .has_authentication(matches.get("host").map(|s| s.as_str()).unwrap_or("")) - { - let authenticated_url = if matches.get("proto").map(|s| s.as_str()) == Some("ssh") { - let user = if let Some(u) = matches.get("user") { - format!("{}@", rawurlencode(u)) - } else { - String::new() - }; - format!( - "{}://{}{}{}", - matches.get("proto").unwrap_or(&String::new()), - user, - matches.get("host").unwrap_or(&String::new()), - matches.get("path").unwrap_or(&String::new()), - ) + { + let authenticated_url = if matches.get("proto").map(|s| s.as_str()) == Some("ssh") { + let user = if let Some(u) = matches.get("user") { + format!("{}@", rawurlencode(u)) } else { - let auth = self - .io - .get_authentication(matches.get("host").map(|s| s.as_str()).unwrap_or("")); - format!( - "{}://{}:{}@{}{}", - matches.get("proto").unwrap_or(&String::new()), - rawurlencode( - auth.get("username") - .and_then(|s| s.as_deref()) - .unwrap_or("") - ), - rawurlencode( - auth.get("password") - .and_then(|s| s.as_deref()) - .unwrap_or("") - ), - matches.get("host").unwrap_or(&String::new()), - matches.get("path").unwrap_or(&String::new()), - ) + String::new() }; + format!( + "{}://{}{}{}", + matches.get("proto").unwrap_or(&String::new()), + user, + matches.get("host").unwrap_or(&String::new()), + matches.get("path").unwrap_or(&String::new()), + ) + } else { + let auth = self + .io + .get_authentication(matches.get("host").map(|s| s.as_str()).unwrap_or("")); + format!( + "{}://{}:{}@{}{}", + matches.get("proto").unwrap_or(&String::new()), + rawurlencode( + auth.get("username") + .and_then(|s| s.as_deref()) + .unwrap_or("") + ), + rawurlencode( + auth.get("password") + .and_then(|s| s.as_deref()) + .unwrap_or("") + ), + matches.get("host").unwrap_or(&String::new()), + matches.get("path").unwrap_or(&String::new()), + ) + }; - let command = command_callable(authenticated_url); - let mut ignored_output = String::new(); - if self - .process - .borrow_mut() - .execute_args(&command, &mut ignored_output, cwd) - == 0 - { - return Ok(()); - } - - let error = self.process.borrow().get_error_output().to_string(); - return self - .throw_exception(&format!("Failed to clone {}, \n\n{}", url, error), &url); + let command = command_callable(authenticated_url); + let mut ignored_output = String::new(); + if self + .process + .borrow_mut() + .execute_args(&command, &mut ignored_output, cwd) + == 0 + { + return Ok(()); } + + let error = self.process.borrow().get_error_output().to_string(); + return self.throw_exception(&format!("Failed to clone {}, \n\n{}", url, error), &url); } let error = format!( @@ -150,13 +148,12 @@ impl Hg { &mut output, (), ) == 0 - { - if let Some(matches) = Preg::is_match_with_indexed_captures( + && let Some(matches) = Preg::is_match_with_indexed_captures( r"/^.+? (\d+(?:\.\d+)+)(?:\+.*?)?\)?\r?\n/", &output, - ) { - return matches.into_iter().nth(1); - } + ) + { + return matches.into_iter().nth(1); } None }) diff --git a/crates/shirabe/src/util/http/curl_downloader.rs b/crates/shirabe/src/util/http/curl_downloader.rs index 3a47d4f..c03da7a 100644 --- a/crates/shirabe/src/util/http/curl_downloader.rs +++ b/crates/shirabe/src/util/http/curl_downloader.rs @@ -270,12 +270,7 @@ impl CurlDownloader { self.init_download(resolve, reject, origin, url, options, copy_to, attributes) } - /// @param mixed[] $options - /// - /// @param array{retryAuthFailure?: bool, redirects?: int<0, max>, retries?: int<0, max>, storeAuth?: 'prompt'|bool, ipResolve?: 4|6|null} $attributes - /// @param non-empty-string $url - /// - /// @return int internal job id + #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn init_download( &mut self, resolve: Box<dyn Fn(PhpMixed) + Send + Sync>, @@ -444,27 +439,26 @@ impl CurlDownloader { // $options['http']['header'] = array_diff($options['http']['header'], ['Connection: close']); // $options['http']['header'][] = 'Connection: keep-alive'; - if let Some(PhpMixed::Array(http)) = options.get_mut("http") { - if let Some(boxed) = http.get_mut("header") { - if let PhpMixed::List(list) = boxed.as_mut() { - let headers: Vec<String> = list - .iter() - .filter_map(|b| match b.as_ref() { - PhpMixed::String(s) => Some(s.clone()), - _ => None, - }) - .collect(); - let diffed = array_diff(&headers, &["Connection: close".to_string()]); - let mut new_list: Vec<Box<PhpMixed>> = diffed - .into_iter() - .map(|s| Box::new(PhpMixed::String(s))) - .collect(); - new_list.push(Box::new(PhpMixed::String( - "Connection: keep-alive".to_string(), - ))); - *list = new_list; - } - } + if let Some(PhpMixed::Array(http)) = options.get_mut("http") + && let Some(boxed) = http.get_mut("header") + && let PhpMixed::List(list) = boxed.as_mut() + { + let headers: Vec<String> = list + .iter() + .filter_map(|b| match b.as_ref() { + PhpMixed::String(s) => Some(s.clone()), + _ => None, + }) + .collect(); + let diffed = array_diff(&headers, &["Connection: close".to_string()]); + let mut new_list: Vec<Box<PhpMixed>> = diffed + .into_iter() + .map(|s| Box::new(PhpMixed::String(s))) + .collect(); + new_list.push(Box::new(PhpMixed::String( + "Connection: keep-alive".to_string(), + ))); + *list = new_list; } let version = curl_version(); @@ -1085,9 +1079,10 @@ impl CurlDownloader { ); // Gzipped responses with missing Content-Length header cannot be detected during the file download // because $progress['size_download'] refers to the gzipped size downloaded, not the actual file size - if let Some(c_str) = c.as_deref() { - if Platform::strlen(c_str) >= max_file_size { - anyhow::bail!( + if let Some(c_str) = c.as_deref() + && Platform::strlen(c_str) >= max_file_size + { + anyhow::bail!( MaxFileSizeExceededException(TransportException::new( format!( "Maximum allowed download size reached. Downloaded {} of allowed {} bytes", @@ -1099,7 +1094,6 @@ impl CurlDownloader { .0 .message ); - } } contents = PhpMixed::String(c.unwrap_or_default()); } else { @@ -1193,8 +1187,7 @@ impl CurlDownloader { // handle 3xx redirects, 304 Not Modified is excluded let sc = status_code.unwrap_or(0); - if sc >= 300 - && sc <= 399 + if (300..=399).contains(&sc) && sc != 304 && job .get("attributes") @@ -1228,7 +1221,7 @@ impl CurlDownloader { } // fail 4xx and 5xx responses and capture the response - if sc >= 400 && sc <= 599 { + if (400..=599).contains(&sc) { let method_is_get = !job .get("options") .and_then(|v| v.as_array()) @@ -1480,48 +1473,48 @@ impl CurlDownloader { .and_then(|v| v.as_string()) .unwrap_or("") .to_string(); - if let Some(primary_ip) = primary_ip { - if primary_ip.as_string() != Some(&prev_primary_ip) { - let prevent_ip_access_callable = self - .jobs - .get(&i) - .and_then(|j| j.get("options")) - .and_then(|v| v.as_array()) - .and_then(|a| a.get("prevent_ip_access_callable")) - .is_some(); - // PHP: is_callable($cb = $job['options']['prevent_ip_access_callable']) && $cb($primaryIp) - // TODO(phase-c): prevent_ip_access_callable is a caller-supplied callable - // carried inside the options array as PhpMixed; invoking it needs a typed - // callable model (options would have to hold an Rc<dyn Fn>), which the - // PhpMixed-keyed options map cannot express yet. - let blocked = prevent_ip_access_callable && false; - if blocked { - let job = self.jobs.get(&i).cloned().unwrap_or_default(); - self.reject_job( - &job, - anyhow::anyhow!( - TransportException::new( - format!( - "IP \"{}\" is blocked for \"{}\".", - primary_ip.clone(), - progress_now - .get("url") - .cloned() - .unwrap_or(PhpMixed::Null), - ), - 0, - ) - .message - ), - ); - } + if let Some(primary_ip) = primary_ip + && primary_ip.as_string() != Some(&prev_primary_ip) + { + let prevent_ip_access_callable = self + .jobs + .get(&i) + .and_then(|j| j.get("options")) + .and_then(|v| v.as_array()) + .and_then(|a| a.get("prevent_ip_access_callable")) + .is_some(); + // PHP: is_callable($cb = $job['options']['prevent_ip_access_callable']) && $cb($primaryIp) + // TODO(phase-c): prevent_ip_access_callable is a caller-supplied callable + // carried inside the options array as PhpMixed; invoking it needs a typed + // callable model (options would have to hold an Rc<dyn Fn>), which the + // PhpMixed-keyed options map cannot express yet. + // The callable that would actually decide blocking cannot be invoked yet + // (see TODO above), so no IP is treated as blocked for now. + let _ = prevent_ip_access_callable; + let blocked = false; + if blocked { + let job = self.jobs.get(&i).cloned().unwrap_or_default(); + self.reject_job( + &job, + anyhow::anyhow!( + TransportException::new( + format!( + "IP \"{}\" is blocked for \"{}\".", + primary_ip.clone(), + progress_now.get("url").cloned().unwrap_or(PhpMixed::Null), + ), + 0, + ) + .message + ), + ); + } - if let Some(job) = self.jobs.get_mut(&i) { - job.insert( - "primaryIp".to_string(), - PhpMixed::String(primary_ip.as_string().unwrap_or("").to_string()), - ); - } + if let Some(job) = self.jobs.get_mut(&i) { + job.insert( + "primaryIp".to_string(), + PhpMixed::String(primary_ip.as_string().unwrap_or("").to_string()), + ); } } @@ -1538,46 +1531,46 @@ impl CurlDownloader { response: &CurlResponse, ) -> anyhow::Result<Result<String, TransportException>> { let mut target_url = String::new(); - if let Some(location_header) = response.inner.get_header("location") { - if !location_header.is_empty() { - if !parse_url(&location_header, shirabe_php_shim::PHP_URL_SCHEME).is_null() { - // Absolute URL; e.g. https://example.com/composer - target_url = location_header.clone(); - } else if !parse_url(&location_header, shirabe_php_shim::PHP_URL_HOST).is_null() { - // Scheme relative; e.g. //example.com/foo - let job_url = job.get("url").and_then(|v| v.as_string()).unwrap_or(""); - target_url = format!( - "{}:{}", - parse_url(job_url, shirabe_php_shim::PHP_URL_SCHEME) - .as_string() - .unwrap_or(""), - location_header - ); - } else if location_header.starts_with('/') { - // Absolute path; e.g. /foo - let job_url = job.get("url").and_then(|v| v.as_string()).unwrap_or(""); - let url_host = parse_url(job_url, shirabe_php_shim::PHP_URL_HOST); - let url_host_str = url_host.as_string().unwrap_or(""); + if let Some(location_header) = response.inner.get_header("location") + && !location_header.is_empty() + { + if !parse_url(&location_header, shirabe_php_shim::PHP_URL_SCHEME).is_null() { + // Absolute URL; e.g. https://example.com/composer + target_url = location_header.clone(); + } else if !parse_url(&location_header, shirabe_php_shim::PHP_URL_HOST).is_null() { + // Scheme relative; e.g. //example.com/foo + let job_url = job.get("url").and_then(|v| v.as_string()).unwrap_or(""); + target_url = format!( + "{}:{}", + parse_url(job_url, shirabe_php_shim::PHP_URL_SCHEME) + .as_string() + .unwrap_or(""), + location_header + ); + } else if location_header.starts_with('/') { + // Absolute path; e.g. /foo + let job_url = job.get("url").and_then(|v| v.as_string()).unwrap_or(""); + let url_host = parse_url(job_url, shirabe_php_shim::PHP_URL_HOST); + let url_host_str = url_host.as_string().unwrap_or(""); - // Replace path using hostname as an anchor. - target_url = Preg::replace( - &format!( - r"{{^(.+(?://|@){}(?::\d+)?)(?:[/\?].*)?$}}", - preg_quote(url_host_str, None) - ), - &format!("\\1{}", location_header), - job_url, - ); - } else { - // Relative path; e.g. foo - // This actually differs from PHP which seems to add duplicate slashes. - let job_url = job.get("url").and_then(|v| v.as_string()).unwrap_or(""); - target_url = Preg::replace( - r"{^(.+/)[^/?]*(?:\?.*)?$}", - &format!("\\1{}", location_header), - job_url, - ); - } + // Replace path using hostname as an anchor. + target_url = Preg::replace( + &format!( + r"{{^(.+(?://|@){}(?::\d+)?)(?:[/\?].*)?$}}", + preg_quote(url_host_str, None) + ), + &format!("\\1{}", location_header), + job_url, + ); + } else { + // Relative path; e.g. foo + // This actually differs from PHP which seems to add duplicate slashes. + let job_url = job.get("url").and_then(|v| v.as_string()).unwrap_or(""); + target_url = Preg::replace( + r"{^(.+/)[^/?]*(?:\?.*)?$}", + &format!("\\1{}", location_header), + job_url, + ); } } @@ -1772,7 +1765,7 @@ impl CurlDownloader { PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(), _ => IndexMap::new(), }; - let origin = Url::get_origin(&*self.config.borrow(), url); + let origin = Url::get_origin(&self.config.borrow(), url); let copy_to = job .get("filename") diff --git a/crates/shirabe/src/util/http/proxy_manager.rs b/crates/shirabe/src/util/http/proxy_manager.rs index eac3cb2..37d73c0 100644 --- a/crates/shirabe/src/util/http/proxy_manager.rs +++ b/crates/shirabe/src/util/http/proxy_manager.rs @@ -110,10 +110,10 @@ impl ProxyManager { fn get_proxy_env(env_name: &str) -> (Option<String>, String) { for name in [env_name.to_lowercase(), env_name.to_uppercase()] { - if let Ok(val) = std::env::var(&name) { - if !val.is_empty() { - return (Some(val), name); - } + if let Ok(val) = std::env::var(&name) + && !val.is_empty() + { + return (Some(val), name); } } (None, String::new()) diff --git a/crates/shirabe/src/util/http/response.rs b/crates/shirabe/src/util/http/response.rs index ad55fa2..e1da15d 100644 --- a/crates/shirabe/src/util/http/response.rs +++ b/crates/shirabe/src/util/http/response.rs @@ -69,12 +69,11 @@ impl Response { shirabe_external_packages::composer::pcre::CaptureKey, String, > = indexmap::IndexMap::new(); - if Preg::match3(&pattern, header, Some(&mut matches)) { - if let Some(s) = + if Preg::match3(&pattern, header, Some(&mut matches)) + && let Some(s) = matches.get(&shirabe_external_packages::composer::pcre::CaptureKey::ByIndex(1)) - { - value = Some(s.clone()); - } + { + value = Some(s.clone()); } } value diff --git a/crates/shirabe/src/util/http_downloader.rs b/crates/shirabe/src/util/http_downloader.rs index 9279518..929dd67 100644 --- a/crates/shirabe/src/util/http_downloader.rs +++ b/crates/shirabe/src/util/http_downloader.rs @@ -110,12 +110,12 @@ impl HttpDownloader { disable_tls: bool, ) -> Self { let disabled = Platform::get_env("COMPOSER_DISABLE_NETWORK") - .map_or(false, |s| !s.is_empty() && s != "0"); + .is_some_and(|s| !s.is_empty() && s != "0"); // Setup TLS options // The cafile option can be set via config.json let mut self_options: IndexMap<String, PhpMixed> = IndexMap::new(); - if disable_tls == false { + if !disable_tls { self_options = StreamContextFactory::get_tls_defaults(&options, ()).unwrap_or_default(); } @@ -174,7 +174,7 @@ impl HttpDownloader { /// Download a file synchronously pub fn get(&mut self, url: &str, options: IndexMap<String, PhpMixed>) -> Result<Response> { - if "" == url { + if url.is_empty() { return Err(InvalidArgumentException { message: "$url must not be an empty string".to_string(), code: 0, @@ -202,7 +202,7 @@ impl HttpDownloader { url: &str, options: IndexMap<String, PhpMixed>, ) -> Result<Response> { - if "" == url { + if url.is_empty() { return Err(InvalidArgumentException { message: "$url must not be an empty string".to_string(), code: 0, @@ -229,7 +229,7 @@ impl HttpDownloader { to: &str, options: IndexMap<String, PhpMixed>, ) -> Result<Response> { - if "" == url { + if url.is_empty() { return Err(InvalidArgumentException { message: "$url must not be an empty string".to_string(), code: 0, @@ -256,7 +256,7 @@ impl HttpDownloader { to: &str, options: IndexMap<String, PhpMixed>, ) -> Result<Response> { - if "" == url { + if url.is_empty() { return Err(InvalidArgumentException { message: "$url must not be an empty string".to_string(), code: 0, @@ -296,7 +296,7 @@ impl HttpDownloader { let id = self.id_gen; self.id_gen += 1; - let origin = Url::get_origin(&*self.config.borrow(), &request.url); + let origin = Url::get_origin(&self.config.borrow(), &request.url); if !sync && !self.allow_async { return Err(LogicException { @@ -680,21 +680,21 @@ impl HttpDownloader { } let versions_key = format!("{}-versions", r#type); - if let Some(versions_value) = data.get(&versions_key) { - if !shirabe_php_shim::empty(versions_value) { - let version_parser: VersionParser = VersionParser::new(); - let constraint = version_parser - .parse_constraints(versions_value.as_string().unwrap_or(""))?; - let composer_constraint = SimpleConstraint::new( - "==".to_string(), - version_parser - .normalize(&composer::get_version(), None)? - .to_string(), - None, - ); - if !constraint.matches(&composer_constraint.into()) { - continue; - } + if let Some(versions_value) = data.get(&versions_key) + && !shirabe_php_shim::empty(versions_value) + { + let version_parser: VersionParser = VersionParser::new(); + let constraint = + version_parser.parse_constraints(versions_value.as_string().unwrap_or(""))?; + let composer_constraint = SimpleConstraint::new( + "==".to_string(), + version_parser + .normalize(&composer::get_version(), None)? + .to_string(), + None, + ); + if !constraint.matches(&composer_constraint.into()) { + continue; } } @@ -761,13 +761,11 @@ impl HttpDownloader { /// @return ?string[] pub fn get_exception_hints(e: &anyhow::Error) -> Option<Vec<String>> { let e_as_transport: Option<&TransportException> = e.downcast_ref::<TransportException>(); - if e_as_transport.is_none() { - return None; - } + e_as_transport?; let e_as_transport = e_as_transport.unwrap(); - if false != strpos(e_as_transport.get_message(), "Resolving timed out").is_some() - || false != strpos(e_as_transport.get_message(), "Could not resolve host").is_some() + if strpos(e_as_transport.get_message(), "Resolving timed out").is_some() + || strpos(e_as_transport.get_message(), "Could not resolve host").is_some() { Silencer::suppress(None); let mut ctx_options: IndexMap<String, PhpMixed> = IndexMap::new(); @@ -814,10 +812,10 @@ impl HttpDownloader { PhpMixed::Array(m) => m.get("allow_self_signed").cloned(), _ => None, }); - if let Some(v) = allow_self_signed { - if !shirabe_php_shim::empty(&v) { - return false; - } + if let Some(v) = allow_self_signed + && !shirabe_php_shim::empty(&v) + { + return false; } true diff --git a/crates/shirabe/src/util/ini_helper.rs b/crates/shirabe/src/util/ini_helper.rs index a0f3fd5..5789411 100644 --- a/crates/shirabe/src/util/ini_helper.rs +++ b/crates/shirabe/src/util/ini_helper.rs @@ -14,7 +14,7 @@ impl IniHelper { pub fn get_message() -> String { let mut paths = Self::get_all(); - if paths.first().map_or(false, |s| s.is_empty()) { + if paths.first().is_some_and(|s| s.is_empty()) { paths.remove(0); } diff --git a/crates/shirabe/src/util/loop.rs b/crates/shirabe/src/util/loop.rs index 8cbd49d..2a0e6d3 100644 --- a/crates/shirabe/src/util/loop.rs +++ b/crates/shirabe/src/util/loop.rs @@ -18,9 +18,8 @@ impl Loop { ) -> Self { http_downloader.borrow_mut().enable_async(); - let process_executor = process_executor.map(|pe| { + let process_executor = process_executor.inspect(|pe| { pe.borrow_mut().enable_async(); - pe }); Self { @@ -51,10 +50,10 @@ impl Loop { // on a multi-thread runtime these futures should be driven concurrently instead of in order. // The PHP progress bar is tied to the worker active-job count and is also deferred until then. for promise in promises { - if let Err(e) = promise.await { - if uncaught.is_none() { - uncaught = Some(e); - } + if let Err(e) = promise.await + && uncaught.is_none() + { + uncaught = Some(e); } } diff --git a/crates/shirabe/src/util/no_proxy_pattern.rs b/crates/shirabe/src/util/no_proxy_pattern.rs index 512b881..34491ba 100644 --- a/crates/shirabe/src/util/no_proxy_pattern.rs +++ b/crates/shirabe/src/util/no_proxy_pattern.rs @@ -135,7 +135,7 @@ impl NoProxyPattern { matched = rule_ipdata.ip == url_ipdata.ip; } else { // Match host and port - let haystack = substr(&url.name, -(strlen(&rule.name) as i64), None); + let haystack = substr(&url.name, -strlen(&rule.name), None); matched = stripos(&haystack, &rule.name) == Some(0); } @@ -260,7 +260,7 @@ impl NoProxyPattern { // Check for a CIDR prefix-length if strpos(&host, "/").is_some() { let parts = explode("/", &host); - host = parts.get(0).cloned().unwrap_or_default(); + host = parts.first().cloned().unwrap_or_default(); let prefix_str = parts.get(1).cloned().unwrap_or_default(); if !allow_prefix || !self.validate_int(&prefix_str, 0, 128) { @@ -446,7 +446,7 @@ impl NoProxyPattern { // Check for square-bracket notation // PHP: if ($hostName[0] === '[') - if host_name.chars().next() == Some('[') { + if host_name.starts_with('[') { let index = strpos(&host_name, "]"); // The smallest ip6 address is :: diff --git a/crates/shirabe/src/util/package_info.rs b/crates/shirabe/src/util/package_info.rs index df34951..4e02dab 100644 --- a/crates/shirabe/src/util/package_info.rs +++ b/crates/shirabe/src/util/package_info.rs @@ -8,10 +8,10 @@ impl PackageInfo { pub fn get_view_source_url(package: PackageInterfaceHandle) -> Option<String> { if let Some(complete) = package.as_complete() { let support = complete.get_support(); - if let Some(source) = support.get("source") { - if source != "" { - return Some(source.clone()); - } + if let Some(source) = support.get("source") + && !source.is_empty() + { + return Some(source.clone()); } } diff --git a/crates/shirabe/src/util/perforce.rs b/crates/shirabe/src/util/perforce.rs index 937e305..3f73f7d 100644 --- a/crates/shirabe/src/util/perforce.rs +++ b/crates/shirabe/src/util/perforce.rs @@ -85,7 +85,7 @@ impl Perforce { pub fn check_server_exists(url: &str, process_executor: &mut ProcessExecutor) -> bool { let mut ignored_output = String::new(); process_executor.execute_args( - &vec![ + &[ "p4".to_string(), "-p".to_string(), url.to_string(), @@ -208,10 +208,10 @@ impl Perforce { self.p4_stream = Some(stream.to_string()); let index = strrpos(stream, "/"); // Stream format is //depot/stream, while non-streaming depot is //depot - if let Some(i) = index { - if (i as i64) > 2 { - self.p4_depot_type = Some("stream".to_string()); - } + if let Some(i) = index + && (i as i64) > 2 + { + self.p4_depot_type = Some("stream".to_string()); } } @@ -295,7 +295,7 @@ impl Perforce { let res_array = explode(PHP_EOL, &result); for line in &res_array { let fields = explode("=", line); - if strcmp(name, fields.get(0).map(|s| s.as_str()).unwrap_or("")) == 0 { + if strcmp(name, fields.first().map(|s| s.as_str()).unwrap_or("")) == 0 { let field1 = fields.get(1).cloned().unwrap_or_default(); let index = strpos(&field1, " "); let value = match index { @@ -705,7 +705,7 @@ impl Perforce { )); let result = self.command_result.clone(); let res_array = explode(PHP_EOL, &result); - let last_commit = res_array.get(0).cloned().unwrap_or_default(); + let last_commit = res_array.first().cloned().unwrap_or_default(); let last_commit_arr = explode(" ", &last_commit); let last_commit_num = last_commit_arr.get(1).cloned().unwrap_or_default(); diff --git a/crates/shirabe/src/util/platform.rs b/crates/shirabe/src/util/platform.rs index 7c9f569..7560072 100644 --- a/crates/shirabe/src/util/platform.rs +++ b/crates/shirabe/src/util/platform.rs @@ -151,23 +151,21 @@ impl Platform { return Ok(home); } - if Self::is_windows() { - if let Some(home) = Self::get_env("USERPROFILE") { - return Ok(home); - } + if Self::is_windows() + && let Some(home) = Self::get_env("USERPROFILE") + { + return Ok(home); } if function_exists("posix_getuid") && function_exists("posix_getpwuid") { let info = posix_getpwuid(posix_getuid()); - if is_array(&info) { - if let Some(arr) = info.as_array() { - if let Some(dir) = arr.get("dir") { - if let Some(s) = dir.as_string() { - return Ok(s.to_string()); - } - } - } + if is_array(&info) + && let Some(arr) = info.as_array() + && let Some(dir) = arr.get("dir") + && let Some(s) = dir.as_string() + { + return Ok(s.to_string()); } } @@ -335,10 +333,10 @@ impl Platform { } // Check if formatted mode is S_IFCHR - if let Some(arr) = stat.as_array() { - if let Some(mode) = arr.get("mode").and_then(|v| v.as_int()) { - return 0o020000 == (mode & 0o170000); - } + if let Some(arr) = stat.as_array() + && let Some(mode) = arr.get("mode").and_then(|v| v.as_int()) + { + return 0o020000 == (mode & 0o170000); } false @@ -368,18 +366,16 @@ impl Platform { if function_exists("posix_getpwuid") && function_exists("posix_geteuid") { let process_user = posix_getpwuid(posix_geteuid()); - if is_array(&process_user) { - if let Some(arr) = process_user.as_array() { - if arr - .get("name") - .and_then(|v| v.as_string()) - .map(|s| s == "vagrant") - .unwrap_or(false) - { - *cached = Some(true); - return true; - } - } + if is_array(&process_user) + && let Some(arr) = process_user.as_array() + && arr + .get("name") + .and_then(|v| v.as_string()) + .map(|s| s == "vagrant") + .unwrap_or(false) + { + *cached = Some(true); + return true; } } diff --git a/crates/shirabe/src/util/process_executor.rs b/crates/shirabe/src/util/process_executor.rs index 42bd0c8..ca31290 100644 --- a/crates/shirabe/src/util/process_executor.rs +++ b/crates/shirabe/src/util/process_executor.rs @@ -251,16 +251,16 @@ impl ProcessExecutor { if !Platform::is_windows() && tty { // PHP: try { $process->setTty(true); } catch (RuntimeException $e) { /* ignore */ } - if let Err(e) = process.set_tty(true) { - if e.downcast_ref::<SymfonyProcessRuntimeException>().is_none() { - return Err(e); - } - // ignore TTY enabling errors + if let Err(e) = process.set_tty(true) + && e.downcast_ref::<SymfonyProcessRuntimeException>().is_none() + { + return Err(e); } + // ignore TTY enabling errors } // PHP: $callback = is_callable($output) ? $output : fn($type, $buffer) => $this->outputHandler($type, $buffer); - let output_is_callable = output.as_deref().map(|o| is_callable(o)).unwrap_or(false); + let output_is_callable = output.as_deref().map(is_callable).unwrap_or(false); let _callback: Box<dyn Fn(&str, &str)> = if output_is_callable { // TODO(phase-c): the user-supplied $output is a PhpMixed callable that cannot be // invoked without a typed callable model (Rc<dyn Fn>); deferred with the callable model. @@ -291,20 +291,20 @@ impl ProcessExecutor { }), ); - let result: Result<()> = (|| -> Result<()> { + let result: Result<()> = { let _ = process.run(/* callback */ Some(Box::new(|_t: &str, _b: &str| {}))); - let output_is_callable_inner = - output.as_deref().map(|o| is_callable(o)).unwrap_or(false); - if self.capture_output && !output_is_callable_inner { - if let Some(out) = output.as_mut() { - **out = PhpMixed::String(process.get_output()); - } + let output_is_callable_inner = output.as_deref().map(is_callable).unwrap_or(false); + if self.capture_output + && !output_is_callable_inner + && let Some(out) = output.as_mut() + { + **out = PhpMixed::String(process.get_output()); } self.error_output = process.get_error_output(); Ok(()) - })(); + }; let final_result: Result<()> = match result { Ok(()) => Ok(()), Err(e) => { @@ -369,7 +369,7 @@ impl ProcessExecutor { } Ok(self - .run_process(command, cwd, env, tty, output.as_deref_mut())? + .run_process(command, cwd, env, tty, output)? .unwrap_or(0)) } @@ -466,33 +466,31 @@ impl ProcessExecutor { self.output_command_run(&command, cwd.as_deref(), true); - let process_result: Result<Process> = (|| -> Result<Process> { - if is_string(&command) { - Ok(Process::from_shell_commandline( - command.as_string().unwrap_or(""), - cwd.as_deref(), - None, - None, - Some(Self::get_timeout() as f64), - )) - } else if let PhpMixed::List(ref list) = command { - Ok(Process::new( - list.iter() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect(), - cwd.clone(), - None, - None, - Some(Self::get_timeout() as f64), - )) - } else { - Err(LogicException { - message: "Invalid command type".to_string(), - code: 0, - } - .into()) + let process_result: Result<Process> = (if is_string(&command) { + Ok(Process::from_shell_commandline( + command.as_string().unwrap_or(""), + cwd.as_deref(), + None, + None, + Some(Self::get_timeout() as f64), + )) + } else if let PhpMixed::List(ref list) = command { + Ok(Process::new( + list.iter() + .map(|v| v.as_string().unwrap_or("").to_string()) + .collect(), + cwd.clone(), + None, + None, + Some(Self::get_timeout() as f64), + )) + } else { + Err(LogicException { + message: "Invalid command type".to_string(), + code: 0, } - })(); + .into()) + }); let process = match process_result { Ok(p) => p, Err(e) => { @@ -511,10 +509,10 @@ impl ProcessExecutor { } // PHP: $process->start($callback); — we operate on the stored job.process directly - if let Some(job) = self.jobs.get_mut(&id) { - if let Some(p) = job.process.as_mut() { - p.start(None); - } + if let Some(job) = self.jobs.get_mut(&id) + && let Some(p) = job.process.as_mut() + { + p.start(None); } } @@ -570,36 +568,34 @@ impl ProcessExecutor { let j = self.jobs.get(id).unwrap(); (j.status, j.process.is_some()) }; - if status == Self::STATUS_STARTED { - if has_process { - let is_running = self + if status == Self::STATUS_STARTED && has_process { + let is_running = self + .jobs + .get(id) + .and_then(|j| j.process.as_ref()) + .map(|p| p.is_running()) + .unwrap_or(false); + if !is_running { + // PHP: call_user_func($job['resolve'], $job['process']) — the .then handler + // marks the job completed/failed based on the process exit status. + let successful = self .jobs .get(id) .and_then(|j| j.process.as_ref()) - .map(|p| p.is_running()) + .map(|p| p.is_successful()) .unwrap_or(false); - if !is_running { - // PHP: call_user_func($job['resolve'], $job['process']) — the .then handler - // marks the job completed/failed based on the process exit status. - let successful = self - .jobs - .get(id) - .and_then(|j| j.process.as_ref()) - .map(|p| p.is_successful()) - .unwrap_or(false); - if let Some(job) = self.jobs.get_mut(id) { - job.status = if successful { - Self::STATUS_COMPLETED - } else { - Self::STATUS_FAILED - }; - } - self.mark_job_done(); + if let Some(job) = self.jobs.get_mut(id) { + job.status = if successful { + Self::STATUS_COMPLETED + } else { + Self::STATUS_FAILED + }; } + self.mark_job_done(); + } - if let Some(p) = self.jobs.get(id).and_then(|j| j.process.as_ref()) { - p.check_timeout()?; - } + if let Some(p) = self.jobs.get(id).and_then(|j| j.process.as_ref()) { + p.check_timeout()?; } } @@ -725,7 +721,7 @@ impl ProcessExecutor { /// Escapes a string to be used as a shell argument for Symfony Process. fn escape_argument(argument: &str) -> String { let mut argument = argument.to_string(); - if "" == argument { + if argument.is_empty() { return escapeshellarg(&argument); } @@ -792,7 +788,7 @@ impl ProcessExecutor { _ => vec![], } }; - if cmd.get(0).map(|s| s.as_str()) != Some("git") { + if cmd.first().map(|s| s.as_str()) != Some("git") { return false; } diff --git a/crates/shirabe/src/util/remote_filesystem.rs b/crates/shirabe/src/util/remote_filesystem.rs index 80b2617..1890a95 100644 --- a/crates/shirabe/src/util/remote_filesystem.rs +++ b/crates/shirabe/src/util/remote_filesystem.rs @@ -231,10 +231,10 @@ impl RemoteFilesystem { options.shift_remove("gitlab-token"); } - if let Some(http_opts) = options.get_mut("http") { - if let PhpMixed::Array(m) = http_opts { - m.insert("ignore_errors".to_string(), Box::new(PhpMixed::Bool(true))); - } + if let Some(http_opts) = options.get_mut("http") + && let PhpMixed::Array(m) = http_opts + { + m.insert("ignore_errors".to_string(), Box::new(PhpMixed::Bool(true))); } let mut degraded_packagist = false; @@ -399,12 +399,11 @@ impl RemoteFilesystem { te.set_headers(http_response_header.clone()); te.set_status_code(Self::find_status_code(&http_response_header)); } - if result.is_some() { - if let Ok(decoded) = + if result.is_some() + && let Ok(decoded) = self.decode_result(result.as_deref(), &http_response_header) - { - te.set_response(decoded); - } + { + te.set_response(decoded); } } caught_e = Some(e); @@ -421,13 +420,14 @@ impl RemoteFilesystem { error_message ); } - if let Some(e) = caught_e { - if !self.retry { - let msg_owned = format!("{}", e); - if !self.degraded_mode && strpos(&msg_owned, "Operation timed out").is_some() { - self.degraded_mode = true; - self.io.write_error3("", true, crate::io::NORMAL); - self.io.write_error3( + if let Some(e) = caught_e + && !self.retry + { + let msg_owned = format!("{}", e); + if !self.degraded_mode && strpos(&msg_owned, "Operation timed out").is_some() { + self.degraded_mode = true; + self.io.write_error3("", true, crate::io::NORMAL); + self.io.write_error3( &format!( "<error>{}</error>\n<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>", msg_owned, @@ -436,17 +436,16 @@ impl RemoteFilesystem { crate::io::NORMAL, ); - return self.get( - &self.origin_url.clone(), - &self.file_url.clone(), - additional_options, - self.file_name.clone(), - self.progress, - ); - } - - return Err(e); + return self.get( + &self.origin_url.clone(), + &self.file_url.clone(), + additional_options, + self.file_name.clone(), + self.progress, + ); } + + return Err(e); } let mut status_code: Option<i64> = None; @@ -465,10 +464,9 @@ impl RemoteFilesystem { && substr(&self.file_url, -4, None) == ".zip" && (location_header.is_none() || substr( - &parse_url(location_header.as_deref().unwrap_or(""), PHP_URL_PATH) + parse_url(location_header.as_deref().unwrap_or(""), PHP_URL_PATH) .as_string() - .unwrap_or("") - .to_string(), + .unwrap_or(""), -4, None, ) != ".zip") @@ -501,46 +499,48 @@ impl RemoteFilesystem { } let mut has_followed_redirect = false; - if let Some(code) = status_code { - if code >= 300 && code <= 399 && code != 304 && self.redirects < self.max_redirects { - has_followed_redirect = true; - result = self.handle_redirect( - &http_response_header, - additional_options.clone(), - result.clone(), - )?; - } + if let Some(code) = status_code + && (300..=399).contains(&code) + && code != 304 + && self.redirects < self.max_redirects + { + has_followed_redirect = true; + result = self.handle_redirect( + &http_response_header, + additional_options.clone(), + result.clone(), + )?; } - if let Some(code) = status_code { - if code >= 400 && code <= 599 { - if !self.retry { - if self.progress && !is_redirect { - self.io.overwrite_error4( - "Downloading (<error>failed</error>)", - false, - None, - crate::io::NORMAL, - ); - } - - let mut e = TransportException::new_with_code( - format!( - "The \"{}\" file could not be downloaded ({})", - self.file_url, http_response_header[0] - ), - code, + if let Some(code) = status_code + && (400..=599).contains(&code) + { + if !self.retry { + if self.progress && !is_redirect { + self.io.overwrite_error4( + "Downloading (<error>failed</error>)", + false, + None, + crate::io::NORMAL, ); - e.set_headers(http_response_header.clone()); - let decoded = self - .decode_result(result.as_deref(), &http_response_header) - .unwrap_or(None); - e.set_response(decoded); - e.set_status_code(Some(code)); - return Err(anyhow::anyhow!(e)); } - result = None; + + let mut e = TransportException::new_with_code( + format!( + "The \"{}\" file could not be downloaded ({})", + self.file_url, http_response_header[0] + ), + code, + ); + e.set_headers(http_response_header.clone()); + let decoded = self + .decode_result(result.as_deref(), &http_response_header) + .unwrap_or(None); + e.set_response(decoded); + e.set_status_code(Some(code)); + return Err(anyhow::anyhow!(e)); } + result = None; } if self.progress && !self.retry && !is_redirect { @@ -724,16 +724,15 @@ impl RemoteFilesystem { Err(e) => caught_e = Some(e), } - if let Some(ref r) = result { - if let Some(max) = max_file_size { - if Platform::strlen(r) >= max { - return Err(anyhow::anyhow!(MaxFileSizeExceededException::new(format!( - "Maximum allowed download size reached. Downloaded {} of allowed {} bytes", - Platform::strlen(r), - max - )))); - } - } + if let Some(ref r) = result + && let Some(max) = max_file_size + && Platform::strlen(r) >= max + { + return Err(anyhow::anyhow!(MaxFileSizeExceededException::new(format!( + "Maximum allowed download size reached. Downloaded {} of allowed {} bytes", + Platform::strlen(r), + max + )))); } if PHP_VERSION_ID >= 80400 { diff --git a/crates/shirabe/src/util/stream_context_factory.rs b/crates/shirabe/src/util/stream_context_factory.rs index 7d8ab3f..d73f3b4 100644 --- a/crates/shirabe/src/util/stream_context_factory.rs +++ b/crates/shirabe/src/util/stream_context_factory.rs @@ -51,19 +51,19 @@ impl StreamContextFactory { }; options = array_replace_recursive(options, default_options); - if let Some(PhpMixed::Array(http)) = options.get_mut("http") { - if let Some(header) = http.get("header").cloned() { - let fixed = Self::fix_http_header_field(&*header); - http.insert( - "header".to_string(), - Box::new(PhpMixed::List( - fixed - .into_iter() - .map(|s| Box::new(PhpMixed::String(s))) - .collect(), - )), - ); - } + if let Some(PhpMixed::Array(http)) = options.get_mut("http") + && let Some(header) = http.get("header").cloned() + { + let fixed = Self::fix_http_header_field(&header); + http.insert( + "header".to_string(), + Box::new(PhpMixed::List( + fixed + .into_iter() + .map(|s| Box::new(PhpMixed::String(s))) + .collect(), + )), + ); } Ok(stream_context_create(&options, Some(&default_params))) @@ -80,10 +80,8 @@ impl StreamContextFactory { .and_then(|v| v.as_array()) .map(|a| a.contains_key("header")) .unwrap_or(false); - if !has_header { - if let Some(PhpMixed::Array(http)) = options.get_mut("http") { - http.insert("header".to_string(), Box::new(PhpMixed::List(vec![]))); - } + if !has_header && let Some(PhpMixed::Array(http)) = options.get_mut("http") { + http.insert("header".to_string(), Box::new(PhpMixed::List(vec![]))); } // Convert string header to array let header_is_string = options @@ -92,16 +90,15 @@ impl StreamContextFactory { .and_then(|a| a.get("header")) .map(|v| matches!(**v, PhpMixed::String(_))) .unwrap_or(false); - if header_is_string { - if let Some(PhpMixed::Array(http)) = options.get_mut("http") { - if let Some(PhpMixed::String(header_str)) = http.get("header").map(|v| *v.clone()) { - let parts: Vec<Box<PhpMixed>> = header_str - .split("\r\n") - .map(|s| Box::new(PhpMixed::String(s.to_string()))) - .collect(); - http.insert("header".to_string(), Box::new(PhpMixed::List(parts))); - } - } + if header_is_string + && let Some(PhpMixed::Array(http)) = options.get_mut("http") + && let Some(PhpMixed::String(header_str)) = http.get("header").map(|v| *v.clone()) + { + let parts: Vec<Box<PhpMixed>> = header_str + .split("\r\n") + .map(|s| Box::new(PhpMixed::String(s.to_string()))) + .collect(); + http.insert("header".to_string(), Box::new(PhpMixed::List(parts))); } // Add stream proxy options if there is a proxy @@ -136,14 +133,11 @@ impl StreamContextFactory { // Header will be a Proxy-Authorization string or not set let proxy_http = proxy_options.get("http"); - if let Some(proxy_header) = proxy_http.and_then(|h| h.get("header")) { - if let Some(PhpMixed::Array(http)) = options.get_mut("http") { - if let Some(PhpMixed::List(headers)) = - http.get_mut("header").map(|v| &mut **v) - { - headers.push(Box::new(proxy_header.clone())); - } - } + if let Some(proxy_header) = proxy_http.and_then(|h| h.get("header")) + && let Some(PhpMixed::Array(http)) = options.get_mut("http") + && let Some(PhpMixed::List(headers)) = http.get_mut("header").map(|v| &mut **v) + { + headers.push(Box::new(proxy_header.clone())); } let proxy_options_flat: IndexMap<String, PhpMixed> = proxy_options @@ -226,10 +220,10 @@ impl StreamContextFactory { "" }, ); - if let Some(PhpMixed::Array(http)) = options.get_mut("http") { - if let Some(PhpMixed::List(headers)) = http.get_mut("header").map(|v| &mut **v) { - headers.push(Box::new(PhpMixed::String(user_agent))); - } + if let Some(PhpMixed::Array(http)) = options.get_mut("http") + && let Some(PhpMixed::List(headers)) = http.get_mut("header").map(|v| &mut **v) + { + headers.push(Box::new(PhpMixed::String(user_agent))); } } @@ -315,23 +309,23 @@ impl StreamContextFactory { d }; - if let Some(ssl_options) = options.get("ssl") { - if let Some(ssl_defaults_mixed) = defaults.get("ssl").cloned() { - let merged = array_replace_recursive( - match ssl_defaults_mixed { - PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(), - _ => IndexMap::new(), - }, - match ssl_options.clone() { - PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(), - _ => IndexMap::new(), - }, - ); - defaults.insert( - "ssl".to_string(), - PhpMixed::Array(merged.into_iter().map(|(k, v)| (k, Box::new(v))).collect()), - ); - } + if let Some(ssl_options) = options.get("ssl") + && let Some(ssl_defaults_mixed) = defaults.get("ssl").cloned() + { + let merged = array_replace_recursive( + match ssl_defaults_mixed { + PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(), + _ => IndexMap::new(), + }, + match ssl_options.clone() { + PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(), + _ => IndexMap::new(), + }, + ); + defaults.insert( + "ssl".to_string(), + PhpMixed::Array(merged.into_iter().map(|(k, v)| (k, Box::new(v))).collect()), + ); } // Attempt to find a local cafile or throw an exception if none pre-set. @@ -358,13 +352,13 @@ impl StreamContextFactory { .and_then(|a| a.get("cafile")) .and_then(|v| v.as_string()) .map(|s| s.to_string()); - if let Some(ref cafile) = cafile { - if !Filesystem::is_readable(cafile) || !CaBundle::validate_ca_file(cafile, logger) { - return Err(TransportException::new( - "The configured cafile was not valid or could not be read.".to_string(), - 0, - )); - } + if let Some(ref cafile) = cafile + && (!Filesystem::is_readable(cafile) || !CaBundle::validate_ca_file(cafile, logger)) + { + return Err(TransportException::new( + "The configured cafile was not valid or could not be read.".to_string(), + 0, + )); } let capath = defaults @@ -373,13 +367,13 @@ impl StreamContextFactory { .and_then(|a| a.get("capath")) .and_then(|v| v.as_string()) .map(|s| s.to_string()); - if let Some(ref capath) = capath { - if !shirabe_php_shim::is_dir(capath) || !Filesystem::is_readable(capath) { - return Err(TransportException::new( - "The configured capath was not valid or could not be read.".to_string(), - 0, - )); - } + if let Some(ref capath) = capath + && (!shirabe_php_shim::is_dir(capath) || !Filesystem::is_readable(capath)) + { + return Err(TransportException::new( + "The configured capath was not valid or could not be read.".to_string(), + 0, + )); } // Disable TLS compression to prevent CRIME attacks where supported. diff --git a/crates/shirabe/src/util/svn.rs b/crates/shirabe/src/util/svn.rs index 181fccf..269cb5d 100644 --- a/crates/shirabe/src/util/svn.rs +++ b/crates/shirabe/src/util/svn.rs @@ -372,24 +372,24 @@ impl Svn { .as_array() .and_then(|m| m.get(host_str)) .map(|v| (**v).clone()); - if let Some(entry) = auth_for_host { - if let Some(entry_arr) = entry.as_array() { - self.credentials = Some(SvnCredentials { - username: entry_arr - .get("username") - .and_then(|v| v.as_string()) - .unwrap_or("") - .to_string(), - password: entry_arr - .get("password") - .and_then(|v| v.as_string()) - .unwrap_or("") - .to_string(), - }); + if let Some(entry) = auth_for_host + && let Some(entry_arr) = entry.as_array() + { + self.credentials = Some(SvnCredentials { + username: entry_arr + .get("username") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(), + password: entry_arr + .get("password") + .and_then(|v| v.as_string()) + .unwrap_or("") + .to_string(), + }); - self.has_auth = Some(true); - return true; - } + self.has_auth = Some(true); + return true; } self.has_auth = Some(false); diff --git a/crates/shirabe/src/util/tar.rs b/crates/shirabe/src/util/tar.rs index 2d44392..95a6fde 100644 --- a/crates/shirabe/src/util/tar.rs +++ b/crates/shirabe/src/util/tar.rs @@ -47,10 +47,10 @@ impl Tar { "{}/composer.json", top_level_paths.keys().next().cloned().unwrap_or_default() ); - if !top_level_paths.is_empty() { - if let Some(file) = phar.get(&composer_json_path) { - return Ok(file.get_content()); - } + if !top_level_paths.is_empty() + && let Some(file) = phar.get(&composer_json_path) + { + return Ok(file.get_content()); } Err(anyhow::anyhow!(RuntimeException { diff --git a/crates/shirabe/src/util/url.rs b/crates/shirabe/src/util/url.rs index 064c850..534e318 100644 --- a/crates/shirabe/src/util/url.rs +++ b/crates/shirabe/src/util/url.rs @@ -166,7 +166,7 @@ impl Url { // e.g. https://api.github.com/repositories/9999999999?access_token=github_token let url = Preg::replace(r"([&?]access_token=)[^&]+", "$1***", &url); - let url = Preg::replace_callback( + Preg::replace_callback( r"(?i)^(?P<prefix>[a-z0-9]+://)?(?P<user>[^:/\s@]+):(?P<password>[^@\s/]+)@", |m| { let user = m @@ -185,8 +185,6 @@ impl Url { } }, &url, - ); - - url + ) } } diff --git a/crates/shirabe/src/util/zip.rs b/crates/shirabe/src/util/zip.rs index d76d805..4231db4 100644 --- a/crates/shirabe/src/util/zip.rs +++ b/crates/shirabe/src/util/zip.rs @@ -45,10 +45,10 @@ impl Zip { fn locate_file(zip: &ZipArchive, filename: &str) -> Result<i64> { // return root composer.json if it is there and is a file - if let Some(index) = zip.locate_name(filename) { - if zip.get_from_index(index).is_some() { - return Ok(index); - } + if let Some(index) = zip.locate_name(filename) + && zip.get_from_index(index).is_some() + { + return Ok(index); } let mut top_level_paths: IndexMap<String, bool> = IndexMap::new(); @@ -95,10 +95,10 @@ impl Zip { if !top_level_paths.is_empty() { let first_key = top_level_paths.keys().next().unwrap().clone(); - if let Some(index) = zip.locate_name(&format!("{}{}", first_key, filename)) { - if zip.get_from_index(index).is_some() { - return Ok(index); - } + if let Some(index) = zip.locate_name(&format!("{}{}", first_key, filename)) + && zip.get_from_index(index).is_some() + { + return Ok(index); } } |
