aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/shirabe-class-map-generator/src/class_map.rs8
-rw-r--r--crates/shirabe-external-packages/src/symfony/finder/finder.rs1
-rw-r--r--crates/shirabe-php-shim/src/lib.rs8
-rw-r--r--crates/shirabe/src/cache.rs99
-rw-r--r--crates/shirabe/src/command/create_project_command.rs3
-rw-r--r--crates/shirabe/src/command/self_update_command.rs9
-rw-r--r--crates/shirabe/src/dependency_resolver/pool.rs9
-rw-r--r--crates/shirabe/src/dependency_resolver/solver.rs6
-rw-r--r--crates/shirabe/src/downloader/path_downloader.rs1
-rw-r--r--crates/shirabe/src/installer.rs29
-rw-r--r--crates/shirabe/src/json/json_file.rs11
-rw-r--r--crates/shirabe/src/package/locker.rs1
-rw-r--r--crates/shirabe/src/repository/array_repository.rs34
-rw-r--r--crates/shirabe/src/repository/composer_repository.rs10
-rw-r--r--crates/shirabe/src/repository/composite_repository.rs13
-rw-r--r--crates/shirabe/src/repository/filter_repository.rs26
-rw-r--r--crates/shirabe/src/repository/handle.rs3
-rw-r--r--crates/shirabe/src/repository/installed_array_repository.rs12
-rw-r--r--crates/shirabe/src/repository/installed_filesystem_repository.rs7
-rw-r--r--crates/shirabe/src/repository/installed_repository.rs6
-rw-r--r--crates/shirabe/src/repository/lock_array_repository.rs7
-rw-r--r--crates/shirabe/src/repository/platform_repository.rs6
-rw-r--r--crates/shirabe/src/repository/repository_interface.rs5
-rw-r--r--crates/shirabe/src/repository/root_package_repository.rs6
-rw-r--r--crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs5
-rw-r--r--crates/shirabe/src/repository/vcs/vcs_driver.rs12
-rw-r--r--crates/shirabe/src/repository/vcs_repository.rs1
-rw-r--r--crates/shirabe/src/repository/writable_array_repository.rs5
-rw-r--r--crates/shirabe/src/util/process_executor.rs1
29 files changed, 176 insertions, 168 deletions
diff --git a/crates/shirabe-class-map-generator/src/class_map.rs b/crates/shirabe-class-map-generator/src/class_map.rs
index 10e7869..264fd35 100644
--- a/crates/shirabe-class-map-generator/src/class_map.rs
+++ b/crates/shirabe-class-map-generator/src/class_map.rs
@@ -2,7 +2,7 @@
use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::Preg;
-use shirabe_php_shim::{Countable, OutOfBoundsException, rtrim, strpos, strtr};
+use shirabe_php_shim::{OutOfBoundsException, rtrim, strpos, strtr};
#[derive(Debug, Clone)]
pub struct PsrViolationEntry {
@@ -137,9 +137,3 @@ impl ClassMap {
&self.psr_violations
}
}
-
-impl Countable for ClassMap {
- fn count(&self) -> i64 {
- self.map.len() as i64
- }
-}
diff --git a/crates/shirabe-external-packages/src/symfony/finder/finder.rs b/crates/shirabe-external-packages/src/symfony/finder/finder.rs
index 59a6ad1..a77a364 100644
--- a/crates/shirabe-external-packages/src/symfony/finder/finder.rs
+++ b/crates/shirabe-external-packages/src/symfony/finder/finder.rs
@@ -104,7 +104,6 @@ impl Finder {
std::iter::empty()
}
- /// PHP: Finder implements Countable.
pub fn len(&self) -> usize {
todo!()
}
diff --git a/crates/shirabe-php-shim/src/lib.rs b/crates/shirabe-php-shim/src/lib.rs
index 433b8db..f47e221 100644
--- a/crates/shirabe-php-shim/src/lib.rs
+++ b/crates/shirabe-php-shim/src/lib.rs
@@ -890,10 +890,6 @@ pub trait JsonSerializable {
fn json_serialize(&self) -> PhpMixed;
}
-pub trait Countable {
- fn count(&self) -> i64;
-}
-
pub fn in_array(_needle: PhpMixed, _haystack: &PhpMixed, _strict: bool) -> bool {
todo!()
}
@@ -959,6 +955,10 @@ pub fn touch2(_path: &str, _mtime: i64) -> bool {
todo!()
}
+pub fn touch3(_path: &str, _mtime: i64, _atime: i64) -> bool {
+ todo!()
+}
+
/// PHP `PHP_OS_FAMILY` constant: the family of the host OS.
/// One of "Windows", "BSD", "Darwin", "Solaris", "Linux", "Unknown".
pub fn php_os_family() -> &'static str {
diff --git a/crates/shirabe/src/cache.rs b/crates/shirabe/src/cache.rs
index 74e3c15..47665d0 100644
--- a/crates/shirabe/src/cache.rs
+++ b/crates/shirabe/src/cache.rs
@@ -4,12 +4,12 @@ use std::sync::Mutex;
use anyhow::Result;
use chrono::Utc;
-use shirabe_external_packages::composer::pcre::Preg;
+use shirabe_external_packages::composer::pcre::{CaptureKey, Preg};
use shirabe_external_packages::symfony::finder::Finder;
use shirabe_php_shim::{
- abs, bin2hex, date_format_to_strftime, dirname, file_exists, file_get_contents,
- file_put_contents, filemtime, hash_file, is_dir, is_writable, mkdir, random_bytes, random_int,
- rename, time, unlink,
+ ErrorException, abs, bin2hex, clearstatcache, date_format_to_strftime, dirname,
+ disk_free_space, file_exists, file_get_contents, file_put_contents, filemtime, function_exists,
+ hash_file, is_dir, is_writable, mkdir, random_bytes, random_int, rename, time, unlink,
};
use crate::io::IOInterface;
@@ -129,18 +129,62 @@ impl Cache {
.write_error(&format!("Writing {}{} into cache", self.root, file));
let temp_file_name = format!("{}{}{}.tmp", self.root, file, bin2hex(&random_bytes(5)),);
- // TODO(phase-b): use anyhow::Result<Result<T, E>> to model PHP try/catch (ErrorException)
- let attempt: Result<bool> = {
- let put = file_put_contents(&temp_file_name, contents.as_bytes());
- Ok(put.is_some()
- && put != Some(-1)
- && rename(&temp_file_name, &format!("{}{}", self.root, file)))
- };
+ let dest = format!("{}{}", self.root, file);
+ let attempt = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
+ file_put_contents(&temp_file_name, contents.as_bytes()).is_some()
+ && rename(&temp_file_name, &dest)
+ }));
return match attempt {
Ok(b) => Ok(b),
- Err(e) => {
- // TODO(phase-b): downcast e to ErrorException; handle partial write cleanup
- Err(e)
+ Err(payload) => {
+ let e: ErrorException = match payload.downcast::<ErrorException>() {
+ Ok(boxed) => *boxed,
+ Err(payload) => std::panic::resume_unwind(payload),
+ };
+
+ // If the write failed despite isEnabled checks passing earlier, rerun the isEnabled checks to
+ // see if they are still current and recreate the cache dir if needed. Refs https://github.com/composer/composer/issues/11076
+ if was_enabled {
+ clearstatcache();
+ self.enabled = None;
+
+ return self.write(&file, contents);
+ }
+
+ self.io.write_error(&format!(
+ "<warning>Failed to write into cache: {}</warning>",
+ e.message,
+ ));
+ let mut m = indexmap::IndexMap::new();
+ if Preg::match3(
+ r"{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}",
+ &e.message,
+ Some(&mut m),
+ )? {
+ // Remove partial file.
+ unlink(&temp_file_name);
+
+ let free_space = if function_exists("disk_free_space") {
+ disk_free_space(&dirname(&temp_file_name))
+ .map(|space| space.to_string())
+ .unwrap_or_default()
+ } else {
+ "unknown".to_string()
+ };
+ let message = format!(
+ "<warning>Writing {} into cache failed after {} of {} bytes written, only {} bytes of free space available</warning>",
+ temp_file_name,
+ m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(),
+ m.get(&CaptureKey::ByIndex(2)).cloned().unwrap_or_default(),
+ free_space,
+ );
+
+ self.io.write_error(&message);
+
+ return Ok(false);
+ }
+
+ Err(e.into())
}
};
}
@@ -185,21 +229,22 @@ impl Cache {
.unwrap_or_default();
let full_path = format!("{}{}", self.root, file);
if file_exists(&full_path) {
- // TODO(phase-b): use anyhow::Result<Result<T, E>> to model PHP try/catch
- let touch_result: Result<()> = {
- shirabe_php_shim::touch(
+ let touch_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
+ shirabe_php_shim::touch3(
&full_path,
- // TODO(phase-b): PHP touch signature accepts (filename, mtime, atime)
+ filemtime(&full_path).unwrap_or(0),
+ time(),
);
- Ok(())
- };
- if touch_result.is_err() {
- // fallback in case the above failed due to incorrect ownership
- // see https://github.com/composer/composer/issues/4070
- Silencer::call(|| {
- shirabe_php_shim::touch(&full_path);
- Ok(())
- })?;
+ }));
+ if let Err(payload) = touch_result {
+ match payload.downcast::<ErrorException>() {
+ Ok(_) => {
+ // fallback in case the above failed due to incorrect ownership
+ // see https://github.com/composer/composer/issues/4070
+ Silencer::call(|| Ok(shirabe_php_shim::touch(&full_path)))?;
+ }
+ Err(payload) => std::panic::resume_unwind(payload),
+ }
}
self.io
diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs
index f8fc511..c49d2fc 100644
--- a/crates/shirabe/src/command/create_project_command.rs
+++ b/crates/shirabe/src/command/create_project_command.rs
@@ -472,8 +472,7 @@ impl CreateProjectCommand {
}
}
Err(e) => {
- // TODO(phase-b): catch only PluginBlockedException
- if let Some(_pbe) = e.downcast_ref::<PluginBlockedException>() {
+ if e.downcast_ref::<PluginBlockedException>().is_some() {
io.write_error("<error>Hint: To allow running the config command recommended below before dependencies are installed, run create-project with --no-install.</error>");
io.write_error(&format!(
"<error>You can then cd into {}, configure allow-plugins, and finally run a composer install to complete the process.</error>",
diff --git a/crates/shirabe/src/command/self_update_command.rs b/crates/shirabe/src/command/self_update_command.rs
index edc2db8..5948d34 100644
--- a/crates/shirabe/src/command/self_update_command.rs
+++ b/crates/shirabe/src/command/self_update_command.rs
@@ -26,6 +26,7 @@ use crate::config::Config;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::downloader::FilesystemException;
+use crate::downloader::TransportException;
use crate::factory::Factory;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
@@ -435,15 +436,17 @@ impl SelfUpdateCommand {
) {
Ok(r) => r.get_body().map(|s| s.to_string()),
Err(e) => {
- // TODO(phase-b): TransportException::get_status_code mapping from anyhow::Error
- if false && e.to_string().contains("404") {
+ if e.downcast_ref::<TransportException>()
+ .and_then(|te| te.get_status_code())
+ == Some(404)
+ {
return Err(InvalidArgumentException {
message: format!("Version \"{}\" could not be found.", update_version),
code: 0,
}
.into());
}
- return Err(e.into());
+ return Err(e);
}
};
io.write_error3(" ", false, io_interface::NORMAL);
diff --git a/crates/shirabe/src/dependency_resolver/pool.rs b/crates/shirabe/src/dependency_resolver/pool.rs
index 06878e1..b12d760 100644
--- a/crates/shirabe/src/dependency_resolver/pool.rs
+++ b/crates/shirabe/src/dependency_resolver/pool.rs
@@ -3,7 +3,7 @@
use std::fmt;
use indexmap::IndexMap;
-use shirabe_php_shim::{Countable, STR_PAD_LEFT, abs, str_pad};
+use shirabe_php_shim::{STR_PAD_LEFT, abs, str_pad};
use shirabe_semver::compiling_matcher::CompilingMatcher;
use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::SimpleConstraint;
@@ -381,13 +381,6 @@ impl Pool {
}
}
-impl Countable for Pool {
- /// Returns how many packages have been loaded into the pool
- fn count(&self) -> i64 {
- self.packages.len() as i64
- }
-}
-
impl fmt::Display for Pool {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut str = String::from("Pool:\n");
diff --git a/crates/shirabe/src/dependency_resolver/solver.rs b/crates/shirabe/src/dependency_resolver/solver.rs
index 28e1e7f..3d2113e 100644
--- a/crates/shirabe/src/dependency_resolver/solver.rs
+++ b/crates/shirabe/src/dependency_resolver/solver.rs
@@ -274,10 +274,10 @@ impl Solver {
);
if self.problems.len() > 0 {
- // TODO(phase-b): SolverProblemsException stores `Rc<RefCell<Rule>>` which is not
+ // 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 `Send + Sync` requirement
- // is removed (single-threaded `Rc` model) or the exception type is reworked.
+ // placeholder error preserves control flow until the solver error path is reworked to
+ // a dedicated (non-anyhow) error type or the exception drops its dyn Rule payload.
let _ = SolverProblemsException::new(
std::mem::take(&mut self.problems),
std::mem::take(&mut self.learned_pool),
diff --git a/crates/shirabe/src/downloader/path_downloader.rs b/crates/shirabe/src/downloader/path_downloader.rs
index d44bd8a..66f84b6 100644
--- a/crates/shirabe/src/downloader/path_downloader.rs
+++ b/crates/shirabe/src/downloader/path_downloader.rs
@@ -371,7 +371,6 @@ impl DownloaderInterface for PathDownloader {
let mut is_fallback = false;
if Self::STRATEGY_SYMLINK == current_strategy {
- // TODO(phase-b): PHP catches IOException; shim symfony filesystem returns anyhow::Result.
let symlink_result: Result<anyhow::Result<()>> =
(|| {
if Platform::is_windows() {
diff --git a/crates/shirabe/src/installer.rs b/crates/shirabe/src/installer.rs
index b770b48..1578fc1 100644
--- a/crates/shirabe/src/installer.rs
+++ b/crates/shirabe/src/installer.rs
@@ -353,7 +353,7 @@ impl Installer {
.into();
let mut installed_repo = InstalledRepository::new(vec![
locked_repository_handle,
- self.create_platform_repo(false).into(),
+ self.create_platform_repo(false)?.into(),
crate::repository::RepositoryInterfaceHandle::new(RootPackageRepository::new(
RootPackageInterfaceHandle::dup(&self.package),
)),
@@ -575,7 +575,7 @@ impl Installer {
local_repo: crate::repository::RepositoryInterfaceHandle,
do_install: bool,
) -> anyhow::Result<i64> {
- let platform_repo = self.create_platform_repo(true);
+ let platform_repo = self.create_platform_repo(true)?;
let aliases = self.get_root_aliases(true);
let mut locked_repository: Option<crate::repository::LockArrayRepositoryHandle> = None;
@@ -685,8 +685,9 @@ impl Installer {
solver = None;
}
Err(e) => {
- // TODO(phase-b): SolverProblemsException contains dyn Rule which isn't Send+Sync
- // so anyhow::Error::downcast_ref can't extract it. Skipping detection.
+ // TODO(phase-c): SolverProblemsException contains dyn Rule which isn't Send+Sync
+ // so anyhow::Error::downcast_ref can't extract it. Skipping detection until the
+ // solver error path moves off anyhow (see solver.rs).
let _ = (&repository_set, &request, &pool);
return Err(e);
}
@@ -973,7 +974,7 @@ impl Installer {
solver = None;
}
Err(e) => {
- // TODO(phase-b): SolverProblemsException can't be downcast (dyn Rule not Send+Sync)
+ // TODO(phase-c): SolverProblemsException can't be downcast (dyn Rule not Send+Sync); see solver.rs
let _ = (&repository_set, &request, &pool);
return Err(e);
}
@@ -1020,7 +1021,7 @@ impl Installer {
"<info>Verifying lock file contents can be installed on current platform.</info>",
);
- let platform_repo = self.create_platform_repo(false);
+ let platform_repo = self.create_platform_repo(false)?;
// creating repository set
let policy = self.create_policy(false, None)?;
// use aliases from lock file only, so empty root aliases here
@@ -1127,7 +1128,7 @@ impl Installer {
}
}
Err(e) => {
- // TODO(phase-b): SolverProblemsException can't be downcast (dyn Rule not Send+Sync)
+ // TODO(phase-c): SolverProblemsException can't be downcast (dyn Rule not Send+Sync); see solver.rs
let _ = (&repository_set, &request, &pool);
return Err(e);
}
@@ -1258,7 +1259,10 @@ impl Installer {
Ok(0)
}
- pub(crate) fn create_platform_repo(&mut self, for_update: bool) -> PlatformRepositoryHandle {
+ pub(crate) fn create_platform_repo(
+ &mut self,
+ for_update: bool,
+ ) -> anyhow::Result<PlatformRepositoryHandle> {
let platform_overrides: IndexMap<String, PhpMixed> = if for_update {
self.config
.borrow_mut()
@@ -1279,11 +1283,10 @@ impl Installer {
.collect()
};
- // TODO(phase-b): PlatformRepository::new returns Result, propagate
- PlatformRepositoryHandle::new(
- PlatformRepository::new(vec![], platform_overrides)
- .expect("PlatformRepository::new should not fail"),
- )
+ Ok(PlatformRepositoryHandle::new(PlatformRepository::new(
+ vec![],
+ platform_overrides,
+ )?))
}
fn create_repository_set(
diff --git a/crates/shirabe/src/json/json_file.rs b/crates/shirabe/src/json/json_file.rs
index a185084..cf92a77 100644
--- a/crates/shirabe/src/json/json_file.rs
+++ b/crates/shirabe/src/json/json_file.rs
@@ -404,9 +404,9 @@ impl JsonFile {
validator.check(&data_converted, &schema_data)?;
if !validator.is_valid() {
- // TODO(phase-b): Validator::get_errors currently returns Vec<String>; original PHP
- // exposes [{property, message}, ...]. Until shim is enriched, surface raw error
- // strings without prop/message splitting.
+ // TODO(phase-c): Validator::get_errors currently returns Vec<String>; original PHP
+ // exposes [{property, message}, ...]. Until the validator shim is enriched, surface raw
+ // error strings without prop/message splitting.
let errors: Vec<String> = validator.get_errors();
return Err(JsonValidationException::new(
format!("\"{}\" does not match the expected JSON schema", source),
@@ -431,8 +431,9 @@ impl JsonFile {
let json = match json {
Some(j) => j,
None => {
- // PHP: self::throwEncodeError(json_last_error());
- // TODO(phase-b): throw an error; downstream callers expect a String
+ // PHP: self::throwEncodeError(json_last_error()), which throws \RuntimeException.
+ // TODO(phase-c): faithfully propagating this requires encode/encode_with_options to
+ // return Result<String>, a signature change rippling across ~53 call sites.
Self::throw_encode_error(json_last_error()).unwrap_or_default();
String::new()
}
diff --git a/crates/shirabe/src/package/locker.rs b/crates/shirabe/src/package/locker.rs
index 2546780..ed53143 100644
--- a/crates/shirabe/src/package/locker.rs
+++ b/crates/shirabe/src/package/locker.rs
@@ -606,7 +606,6 @@ impl Locker {
let is_locked = match self.is_locked_result() {
Ok(b) => b,
Err(e) => {
- // TODO(phase-b): catch only ParsingException
if e.downcast_ref::<ParsingException>().is_some() {
false
} else {
diff --git a/crates/shirabe/src/repository/array_repository.rs b/crates/shirabe/src/repository/array_repository.rs
index 1eeb428..df25235 100644
--- a/crates/shirabe/src/repository/array_repository.rs
+++ b/crates/shirabe/src/repository/array_repository.rs
@@ -7,7 +7,7 @@ use std::rc::Weak;
use anyhow::Result;
use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::Preg;
-use shirabe_php_shim::{Countable, LogicException, implode, preg_quote, strtolower};
+use shirabe_php_shim::{implode, preg_quote, strtolower};
use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::SimpleConstraint;
@@ -39,19 +39,10 @@ impl ArrayRepository {
if self.packages.borrow().is_none() {
self.initialize();
}
-
- if self.packages.borrow().is_none() {
- // TODO(phase-b): propagate the error.
- // PHP: throw new \LogicException('initialize failed to initialize the packages array')
- panic!(
- "{}",
- LogicException {
- message: "initialize failed to initialize the packages array".to_string(),
- code: 0,
- }
- .message
- );
- }
+ assert!(
+ self.packages.borrow().is_some(),
+ "initialize failed to initialize the packages array"
+ );
self.packages
.borrow()
@@ -155,25 +146,22 @@ impl ArrayRepository {
}
}
-impl Countable for ArrayRepository {
+impl RepositoryInterface for ArrayRepository {
/// Returns the number of packages in this repository
- ///
- /// @return 0|positive-int Number of packages
- fn count(&self) -> i64 {
+ fn count(&self) -> anyhow::Result<usize> {
if self.packages.borrow().is_none() {
self.initialize();
}
- self.packages.borrow().as_ref().unwrap().len() as i64
+ Ok(self.packages.borrow().as_ref().unwrap().len())
}
-}
-impl RepositoryInterface for ArrayRepository {
fn get_repo_name(&self) -> String {
+ let count = self.count().expect("ArrayRepository::count is infallible");
format!(
"array repo (defining {} package{})",
- self.count(),
- if self.count() > 1 { "s" } else { "" },
+ count,
+ if count > 1 { "s" } else { "" },
)
}
diff --git a/crates/shirabe/src/repository/composer_repository.rs b/crates/shirabe/src/repository/composer_repository.rs
index f634e23..f07eb73 100644
--- a/crates/shirabe/src/repository/composer_repository.rs
+++ b/crates/shirabe/src/repository/composer_repository.rs
@@ -4,7 +4,7 @@ use indexmap::IndexMap;
use shirabe_external_packages::composer::metadata_minifier::MetadataMinifier;
use shirabe_external_packages::composer::pcre::{CaptureKey, Preg};
use shirabe_php_shim::{
- Countable, InvalidArgumentException, LogicException, PHP_EOL, PhpMixed, RuntimeException,
+ InvalidArgumentException, LogicException, PHP_EOL, PhpMixed, RuntimeException,
UnexpectedValueException, extension_loaded, hash, http_build_query, in_array, json_decode,
parse_url_all, realpath, strtolower, strtr, urlencode, var_export,
};
@@ -1212,7 +1212,7 @@ impl ComposerRepository {
}
}
- if Countable::count(&self.inner) > 0 {
+ if self.inner.count()? > 0 {
for (k, v) in self.inner.get_providers(package_name.to_string())? {
let mut entry: IndexMap<String, PhpMixed> = IndexMap::new();
entry.insert("name".to_string(), PhpMixed::String(v.name));
@@ -3401,13 +3401,11 @@ fn clone_root_data(rd: &RootData) -> RootData {
}
}
-impl shirabe_php_shim::Countable for ComposerRepository {
- fn count(&self) -> i64 {
+impl RepositoryInterface for ComposerRepository {
+ fn count(&self) -> anyhow::Result<usize> {
self.inner.count()
}
-}
-impl RepositoryInterface for ComposerRepository {
fn has_package(&self, package: PackageInterfaceHandle) -> bool {
self.inner.has_package(package)
}
diff --git a/crates/shirabe/src/repository/composite_repository.rs b/crates/shirabe/src/repository/composite_repository.rs
index 97fad44..dafedfc 100644
--- a/crates/shirabe/src/repository/composite_repository.rs
+++ b/crates/shirabe/src/repository/composite_repository.rs
@@ -62,13 +62,16 @@ impl CompositeRepository {
}
}
-impl shirabe_php_shim::Countable for CompositeRepository {
- fn count(&self) -> i64 {
- self.repositories.iter().map(|r| r.count()).sum()
+impl RepositoryInterface for CompositeRepository {
+ fn count(&self) -> anyhow::Result<usize> {
+ let mut total = 0;
+ for repository in &self.repositories {
+ total += repository.count()?;
+ }
+
+ Ok(total)
}
-}
-impl RepositoryInterface for CompositeRepository {
fn get_repo_name(&self) -> String {
let names: Vec<String> = self
.repositories
diff --git a/crates/shirabe/src/repository/filter_repository.rs b/crates/shirabe/src/repository/filter_repository.rs
index a49382a..0e05c25 100644
--- a/crates/shirabe/src/repository/filter_repository.rs
+++ b/crates/shirabe/src/repository/filter_repository.rs
@@ -148,26 +148,20 @@ impl FilterRepository {
}
}
-impl shirabe_php_shim::Countable for FilterRepository {
- fn count(&self) -> i64 {
- if self.repo.count() > 0 {
- // TODO(phase-b): propagate the error
- // self.get_packages()?.len() as i64
- self.repo
- .get_packages()
- .map(|pkgs| {
- pkgs.iter()
- .filter(|p| self.is_allowed(&p.get_name()))
- .count() as i64
- })
- .unwrap_or(0)
+impl RepositoryInterface for FilterRepository {
+ fn count(&self) -> anyhow::Result<usize> {
+ if self.repo.count()? > 0 {
+ Ok(self
+ .repo
+ .get_packages()?
+ .iter()
+ .filter(|p| self.is_allowed(&p.get_name()))
+ .count())
} else {
- 0
+ Ok(0)
}
}
-}
-impl RepositoryInterface for FilterRepository {
fn has_package(&self, package: PackageInterfaceHandle) -> bool {
self.repo.has_package(package)
}
diff --git a/crates/shirabe/src/repository/handle.rs b/crates/shirabe/src/repository/handle.rs
index aa79d5e..6721bb2 100644
--- a/crates/shirabe/src/repository/handle.rs
+++ b/crates/shirabe/src/repository/handle.rs
@@ -4,7 +4,6 @@ use std::cell::{Ref, RefCell, RefMut};
use std::rc::{Rc, Weak};
use indexmap::IndexMap;
-use shirabe_php_shim::Countable;
use shirabe_semver::constraint::AnyConstraint;
use crate::package::BasePackageHandle;
@@ -84,7 +83,7 @@ impl RepositoryInterfaceHandle {
.map(PlatformRepositoryHandle::from_rc)
}
- pub fn count(&self) -> i64 {
+ pub fn count(&self) -> anyhow::Result<usize> {
self.0.borrow().count()
}
diff --git a/crates/shirabe/src/repository/installed_array_repository.rs b/crates/shirabe/src/repository/installed_array_repository.rs
index 64098e9..487a6da 100644
--- a/crates/shirabe/src/repository/installed_array_repository.rs
+++ b/crates/shirabe/src/repository/installed_array_repository.rs
@@ -1,7 +1,6 @@
//! ref: composer/src/Composer/Repository/InstalledArrayRepository.php
use indexmap::IndexMap;
-use shirabe_php_shim::Countable;
use shirabe_semver::constraint::AnyConstraint;
use crate::package::BasePackageHandle;
@@ -41,7 +40,10 @@ impl InstalledRepositoryInterface for InstalledArrayRepository {
}
fn is_fresh(&self) -> bool {
- self.inner.count() == 0
+ self.inner
+ .count()
+ .expect("WritableArrayRepository::count is infallible")
+ == 0
}
}
@@ -87,13 +89,11 @@ impl WritableRepositoryInterface for InstalledArrayRepository {
}
}
-impl Countable for InstalledArrayRepository {
- fn count(&self) -> i64 {
+impl RepositoryInterface for InstalledArrayRepository {
+ fn count(&self) -> anyhow::Result<usize> {
todo!()
}
-}
-impl RepositoryInterface for InstalledArrayRepository {
fn has_package(&self, _package: PackageInterfaceHandle) -> bool {
todo!()
}
diff --git a/crates/shirabe/src/repository/installed_filesystem_repository.rs b/crates/shirabe/src/repository/installed_filesystem_repository.rs
index 1f6be2c..185749e 100644
--- a/crates/shirabe/src/repository/installed_filesystem_repository.rs
+++ b/crates/shirabe/src/repository/installed_filesystem_repository.rs
@@ -2,7 +2,6 @@
use anyhow::Result;
use indexmap::IndexMap;
-use shirabe_php_shim::Countable;
use shirabe_semver::constraint::AnyConstraint;
use crate::json::JsonFile;
@@ -97,13 +96,11 @@ impl WritableRepositoryInterface for InstalledFilesystemRepository {
}
}
-impl Countable for InstalledFilesystemRepository {
- fn count(&self) -> i64 {
+impl RepositoryInterface for InstalledFilesystemRepository {
+ fn count(&self) -> anyhow::Result<usize> {
todo!()
}
-}
-impl RepositoryInterface for InstalledFilesystemRepository {
fn has_package(&self, _package: PackageInterfaceHandle) -> bool {
todo!()
}
diff --git a/crates/shirabe/src/repository/installed_repository.rs b/crates/shirabe/src/repository/installed_repository.rs
index 8b611ae..f6b9643 100644
--- a/crates/shirabe/src/repository/installed_repository.rs
+++ b/crates/shirabe/src/repository/installed_repository.rs
@@ -381,13 +381,11 @@ impl InstalledRepository {
}
}
-impl shirabe_php_shim::Countable for InstalledRepository {
- fn count(&self) -> i64 {
+impl RepositoryInterface for InstalledRepository {
+ fn count(&self) -> anyhow::Result<usize> {
self.inner.count()
}
-}
-impl RepositoryInterface for InstalledRepository {
fn get_repo_name(&self) -> String {
let names: Vec<String> = self
.inner
diff --git a/crates/shirabe/src/repository/lock_array_repository.rs b/crates/shirabe/src/repository/lock_array_repository.rs
index 250ca90..390fae3 100644
--- a/crates/shirabe/src/repository/lock_array_repository.rs
+++ b/crates/shirabe/src/repository/lock_array_repository.rs
@@ -9,7 +9,6 @@ use crate::repository::{
RepositoryInterfaceWeakHandle, SearchResult,
};
use indexmap::IndexMap;
-use shirabe_php_shim::Countable;
use shirabe_semver::constraint::AnyConstraint;
#[derive(Debug)]
@@ -31,13 +30,11 @@ impl LockArrayRepository {
}
}
-impl Countable for LockArrayRepository {
- fn count(&self) -> i64 {
+impl RepositoryInterface for LockArrayRepository {
+ fn count(&self) -> anyhow::Result<usize> {
self.inner.count()
}
-}
-impl RepositoryInterface for LockArrayRepository {
fn has_package(&self, package: PackageInterfaceHandle) -> bool {
self.inner.has_package(package)
}
diff --git a/crates/shirabe/src/repository/platform_repository.rs b/crates/shirabe/src/repository/platform_repository.rs
index a35874d..1dec137 100644
--- a/crates/shirabe/src/repository/platform_repository.rs
+++ b/crates/shirabe/src/repository/platform_repository.rs
@@ -1939,13 +1939,11 @@ impl PlatformRepository {
}
}
-impl shirabe_php_shim::Countable for PlatformRepository {
- fn count(&self) -> i64 {
+impl crate::repository::RepositoryInterface for PlatformRepository {
+ fn count(&self) -> anyhow::Result<usize> {
self.inner.count()
}
-}
-impl crate::repository::RepositoryInterface for PlatformRepository {
fn has_package(&self, package: PackageInterfaceHandle) -> bool {
self.inner.has_package(package)
}
diff --git a/crates/shirabe/src/repository/repository_interface.rs b/crates/shirabe/src/repository/repository_interface.rs
index e3a5548..6dbc01d 100644
--- a/crates/shirabe/src/repository/repository_interface.rs
+++ b/crates/shirabe/src/repository/repository_interface.rs
@@ -4,7 +4,6 @@ use crate::package::BasePackageHandle;
use crate::package::PackageInterfaceHandle;
use crate::repository::AdvisoryProviderInterface;
use indexmap::IndexMap;
-use shirabe_php_shim::Countable;
use shirabe_semver::constraint::AnyConstraint;
pub enum FindPackageConstraint {
@@ -52,7 +51,9 @@ pub const SEARCH_FULLTEXT: i64 = 0;
pub const SEARCH_NAME: i64 = 1;
pub const SEARCH_VENDOR: i64 = 2;
-pub trait RepositoryInterface: Countable + std::fmt::Debug {
+pub trait RepositoryInterface: std::fmt::Debug {
+ fn count(&self) -> anyhow::Result<usize>;
+
fn has_package(&self, package: PackageInterfaceHandle) -> bool;
fn find_package(
diff --git a/crates/shirabe/src/repository/root_package_repository.rs b/crates/shirabe/src/repository/root_package_repository.rs
index 985f86e..4357ed6 100644
--- a/crates/shirabe/src/repository/root_package_repository.rs
+++ b/crates/shirabe/src/repository/root_package_repository.rs
@@ -25,13 +25,11 @@ impl RootPackageRepository {
}
}
-impl shirabe_php_shim::Countable for RootPackageRepository {
- fn count(&self) -> i64 {
+impl RepositoryInterface for RootPackageRepository {
+ fn count(&self) -> anyhow::Result<usize> {
self.inner.count()
}
-}
-impl RepositoryInterface for RootPackageRepository {
fn has_package(&self, package: PackageInterfaceHandle) -> bool {
self.inner.has_package(package)
}
diff --git a/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs b/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
index de1f814..7eb253a 100644
--- a/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
+++ b/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
@@ -707,7 +707,6 @@ impl GitBitbucketDriver {
match self.inner.get_contents(url) {
Ok(r) => Ok(r),
Err(e) => {
- // TODO(phase-b): only handle TransportException
let mut bitbucket_util = Bitbucket::new(
self.inner.io.clone(),
self.inner.config.clone(),
@@ -772,7 +771,9 @@ impl GitBitbucketDriver {
match self.setup_fallback_driver(&self.generate_ssh_url()) {
Ok(()) => Ok(true),
Err(e) => {
- // TODO(phase-b): only catch RuntimeException
+ // TODO(phase-c): PHP catches \RuntimeException (and all its subclasses), letting
+ // other exceptions propagate without this cleanup. Modeling that precisely needs the
+ // PHP exception hierarchy, which is intentionally not reproduced (see CLAUDE.md).
self.fallback_driver = None;
self.inner.io.write_error(&format!(
diff --git a/crates/shirabe/src/repository/vcs/vcs_driver.rs b/crates/shirabe/src/repository/vcs/vcs_driver.rs
index dc88387..1c05933 100644
--- a/crates/shirabe/src/repository/vcs/vcs_driver.rs
+++ b/crates/shirabe/src/repository/vcs/vcs_driver.rs
@@ -78,11 +78,13 @@ impl VcsDriverBase {
PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(),
_ => IndexMap::new(),
};
- // TODO(phase-b): map anyhow::Error from HttpDownloader::get into TransportException.
self.http_downloader
.borrow_mut()
.get(url, options)
- .map_err(|e| TransportException::new(e.to_string(), 0))
+ .map_err(|e| match e.downcast::<TransportException>() {
+ Ok(te) => te,
+ Err(other) => TransportException::new(other.to_string(), 0),
+ })
}
// Helper for concrete drivers: produces the same value as the trait default
@@ -319,11 +321,13 @@ pub trait VcsDriver: VcsDriverInterface {
PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(),
_ => IndexMap::new(),
};
- // TODO(phase-b): map anyhow::Error from HttpDownloader::get into TransportException.
self.http_downloader()
.borrow_mut()
.get(url, options)
- .map_err(|e| TransportException::new(e.to_string(), 0))
+ .map_err(|e| match e.downcast::<TransportException>() {
+ Ok(te) => te,
+ Err(other) => TransportException::new(other.to_string(), 0),
+ })
}
fn cleanup(&self) {}
diff --git a/crates/shirabe/src/repository/vcs_repository.rs b/crates/shirabe/src/repository/vcs_repository.rs
index 7817172..ef58fe2 100644
--- a/crates/shirabe/src/repository/vcs_repository.rs
+++ b/crates/shirabe/src/repository/vcs_repository.rs
@@ -315,7 +315,6 @@ impl VcsRepository {
}
Ok(None) => {}
Err(e) => {
- // TODO(phase-b): unify exception handling below
if let Some(te) = e.downcast_ref::<TransportException>() {
if self.should_rethrow_transport_exception(te) {
return Err(e);
diff --git a/crates/shirabe/src/repository/writable_array_repository.rs b/crates/shirabe/src/repository/writable_array_repository.rs
index 1c07b8c..bf9d094 100644
--- a/crates/shirabe/src/repository/writable_array_repository.rs
+++ b/crates/shirabe/src/repository/writable_array_repository.rs
@@ -5,7 +5,6 @@ use crate::repository::ArrayRepository;
use crate::repository::RepositoryInterface;
use crate::repository::RepositoryInterfaceWeakHandle;
use anyhow::Result;
-use shirabe_php_shim::Countable;
#[derive(Debug)]
pub struct WritableArrayRepository {
@@ -84,7 +83,7 @@ impl WritableArrayRepository {
self.inner.get_repo_name()
}
- pub fn count(&self) -> i64 {
- Countable::count(&self.inner)
+ pub fn count(&self) -> anyhow::Result<usize> {
+ self.inner.count()
}
}
diff --git a/crates/shirabe/src/util/process_executor.rs b/crates/shirabe/src/util/process_executor.rs
index 40a212b..b62debe 100644
--- a/crates/shirabe/src/util/process_executor.rs
+++ b/crates/shirabe/src/util/process_executor.rs
@@ -305,7 +305,6 @@ impl ProcessExecutor {
let final_result: Result<()> = match result {
Ok(()) => Ok(()),
Err(e) => {
- // TODO(phase-b): catch ProcessSignaledException
if let Some(pse) = e.downcast_ref::<ProcessSignaledException>() {
if signal_handler.is_triggered() {
// exiting as we were signaled and the child process exited too due to the signal