aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/downloader/file_downloader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe/src/downloader/file_downloader.rs')
-rw-r--r--crates/shirabe/src/downloader/file_downloader.rs79
1 files changed, 43 insertions, 36 deletions
diff --git a/crates/shirabe/src/downloader/file_downloader.rs b/crates/shirabe/src/downloader/file_downloader.rs
index 6286918a..9742fd70 100644
--- a/crates/shirabe/src/downloader/file_downloader.rs
+++ b/crates/shirabe/src/downloader/file_downloader.rs
@@ -51,7 +51,10 @@ pub static RESPONSE_HEADERS: LazyLock<Mutex<IndexMap<String, Vec<String>>>> =
#[derive(Debug)]
pub struct FileDownloader {
/// @var IOInterface
- pub(crate) io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ ///
+ /// Behind a RefCell so `get_local_changes` can temporarily swap in a NullIO through `&self`
+ /// (PHP: `$this->io = new NullIO;` ... restore), now that the downloader methods take `&self`.
+ pub(crate) io: std::cell::RefCell<std::rc::Rc<std::cell::RefCell<dyn IOInterface>>>,
/// @var Config
pub(crate) config: std::rc::Rc<std::cell::RefCell<Config>>,
/// @var HttpDownloader
@@ -72,7 +75,10 @@ pub struct FileDownloader {
/// this write needs guarding, so it is the only field isolated behind a lock.
last_cache_writes: Mutex<IndexMap<String, String>>,
/// @var array<string, string[]> Map of package name to list of paths
- additional_cleanup_paths: IndexMap<String, Vec<String>>,
+ ///
+ /// Behind a RefCell so add/remove_cleanup_path work through `&self` (needed since install()
+ /// mutates it while downloads of other packages may be in flight on sibling futures).
+ additional_cleanup_paths: std::cell::RefCell<IndexMap<String, Vec<String>>>,
}
impl FileDownloader {
@@ -106,7 +112,7 @@ impl FileDownloader {
});
let this = Self {
- io,
+ io: std::cell::RefCell::new(io),
config,
http_downloader,
event_dispatcher,
@@ -114,14 +120,14 @@ impl FileDownloader {
process,
filesystem,
last_cache_writes: Mutex::new(IndexMap::new()),
- additional_cleanup_paths: IndexMap::new(),
+ additional_cleanup_paths: std::cell::RefCell::new(IndexMap::new()),
};
if let Some(cache) = &this.cache
&& cache.borrow().gc_is_necessary()
{
// PHP: writeError('Running cache garbage collection', true, io_interface::VERY_VERBOSE)
- this.io.write_error("Running cache garbage collection");
+ this.io.borrow().write_error("Running cache garbage collection");
let ttl = this
.config
.borrow_mut()
@@ -148,15 +154,13 @@ impl DownloaderInterface for FileDownloader {
"dist".to_owned()
}
- fn as_change_report_interface(
- &mut self,
- ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
/// @inheritDoc
async fn download(
- &mut self,
+ &self,
package: PackageInterfaceHandle,
path: &str,
_prev_package: Option<PackageInterfaceHandle>,
@@ -234,7 +238,7 @@ impl DownloaderInterface for FileDownloader {
if from_cache {
if output {
- self.io.write_error3(
+ self.io.borrow().write_error3(
&format!(
" - Loading <info>{}</info> (<comment>{}</comment>) from cache",
package.get_name(),
@@ -260,7 +264,7 @@ impl DownloaderInterface for FileDownloader {
}
} else {
if output {
- self.io.write_error(&format!(
+ self.io.borrow().write_error(&format!(
" - Downloading <info>{}</info> (<comment>{}</comment>)",
package.get_name(),
package.get_full_pretty_version(
@@ -272,7 +276,7 @@ impl DownloaderInterface for FileDownloader {
let add_copy_result = self
.http_downloader
- .borrow_mut()
+ .borrow()
.add_copy(&url.processed, &file_name, package.get_transport_options())
.await;
match add_copy_result {
@@ -367,20 +371,20 @@ impl DownloaderInterface for FileDownloader {
let code = e
.downcast_ref::<TransportException>()
.map_or(0, |te| te.get_code());
- if self.io.is_debug() {
- self.io.write_error(&format!(
+ if self.io.borrow().is_debug() {
+ self.io.borrow().write_error(&format!(
" Failed downloading {}: [{}] {}: {}",
package.get_name(),
get_class(&PhpMixed::Null),
code,
e
));
- self.io.write_error(&format!(
+ self.io.borrow().write_error(&format!(
" Trying the next URL for {}",
package.get_name()
));
} else {
- self.io.write_error(&format!(
+ self.io.borrow().write_error(&format!(
" Failed downloading {}, trying the next URL ({}: {})",
package.get_name(),
code,
@@ -433,7 +437,7 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn prepare(
- &mut self,
+ &self,
_type: &str,
_package: PackageInterfaceHandle,
_path: &str,
@@ -444,7 +448,7 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn cleanup(
- &mut self,
+ &self,
_type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -477,6 +481,7 @@ impl DownloaderInterface for FileDownloader {
if let Some(paths) = self
.additional_cleanup_paths
+ .borrow()
.get(&package.get_name())
.cloned()
{
@@ -499,13 +504,13 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn install(
- &mut self,
+ &self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
) -> anyhow::Result<Option<PhpMixed>> {
if output {
- self.io.write_error(&format!(
+ self.io.borrow().write_error(&format!(
" - {}",
InstallOperation::format(package.clone(), false)
));
@@ -556,12 +561,12 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn update(
- &mut self,
+ &self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
) -> anyhow::Result<Option<PhpMixed>> {
- self.io.write_error(&format!(
+ self.io.borrow().write_error(&format!(
" - {}{}",
UpdateOperation::format(initial.clone(), target.clone(), false),
self.get_install_operation_appendix(target.clone(), path)
@@ -574,22 +579,18 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn remove(
- &mut self,
+ &self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
) -> anyhow::Result<Option<PhpMixed>> {
if output {
- self.io.write_error(&format!(
+ self.io.borrow().write_error(&format!(
" - {}",
UninstallOperation::format(package, false)
));
}
- let result = self
- .filesystem
- .borrow_mut()
- .remove_directory_async(path)
- .await?;
+ let result = Filesystem::remove_directory_async_via(&self.filesystem, path).await?;
if !result {
return Err(RuntimeException {
message: format!("Could not completely delete {}, aborting.", path),
@@ -606,15 +607,16 @@ impl ChangeReportInterface for FileDownloader {
/// @inheritDoc
/// @throws \RuntimeException
fn get_local_changes(
- &mut self,
+ &self,
package: PackageInterfaceHandle,
path: &str,
) -> anyhow::Result<Option<String>> {
let prev_io = std::mem::replace(
- &mut self.io,
+ &mut *self.io.borrow_mut(),
std::rc::Rc::new(std::cell::RefCell::new(NullIO::new())),
);
self.io
+ .borrow()
.borrow_mut()
.load_configuration(&mut self.config.borrow_mut())?;
@@ -652,7 +654,7 @@ impl ChangeReportInterface for FileDownloader {
Ok(output)
})();
- self.io = prev_io;
+ *self.io.borrow_mut() = prev_io;
let (e, output) = match result {
Ok(output) => (None, output),
@@ -660,7 +662,7 @@ impl ChangeReportInterface for FileDownloader {
};
if let Some(err) = e {
- if self.io.is_debug() {
+ if self.io.borrow().is_debug() {
return Err(err);
}
@@ -712,15 +714,20 @@ impl FileDownloader {
}
}
- pub(crate) fn add_cleanup_path(&mut self, package: PackageInterfaceHandle, path: &str) {
+ pub(crate) fn add_cleanup_path(&self, package: PackageInterfaceHandle, path: &str) {
self.additional_cleanup_paths
+ .borrow_mut()
.entry(package.get_name())
.or_default()
.push(path.to_string());
}
- pub(crate) fn remove_cleanup_path(&mut self, package: PackageInterfaceHandle, path: &str) {
- if let Some(paths) = self.additional_cleanup_paths.get_mut(&package.get_name()) {
+ pub(crate) fn remove_cleanup_path(&self, package: PackageInterfaceHandle, path: &str) {
+ if let Some(paths) = self
+ .additional_cleanup_paths
+ .borrow_mut()
+ .get_mut(&package.get_name())
+ {
// PHP: array_search($path, ..., true)
let idx = paths.iter().position(|p| p == path);
if let Some(i) = idx {