aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--crates/shirabe/src/command/status_command.rs12
-rw-r--r--crates/shirabe/src/downloader/change_report_interface.rs2
-rw-r--r--crates/shirabe/src/downloader/download_manager.rs47
-rw-r--r--crates/shirabe/src/downloader/downloader_interface.rs22
-rw-r--r--crates/shirabe/src/downloader/file_downloader.rs18
-rw-r--r--crates/shirabe/src/downloader/fossil_downloader.rs201
-rw-r--r--crates/shirabe/src/downloader/git_downloader.rs1382
-rw-r--r--crates/shirabe/src/downloader/gzip_downloader.rs18
-rw-r--r--crates/shirabe/src/downloader/hg_downloader.rs155
-rw-r--r--crates/shirabe/src/downloader/path_downloader.rs18
-rw-r--r--crates/shirabe/src/downloader/perforce_downloader.rs204
-rw-r--r--crates/shirabe/src/downloader/phar_downloader.rs18
-rw-r--r--crates/shirabe/src/downloader/rar_downloader.rs18
-rw-r--r--crates/shirabe/src/downloader/svn_downloader.rs214
-rw-r--r--crates/shirabe/src/downloader/tar_downloader.rs18
-rw-r--r--crates/shirabe/src/downloader/vcs_downloader.rs52
-rw-r--r--crates/shirabe/src/downloader/xz_downloader.rs18
-rw-r--r--crates/shirabe/src/downloader/zip_downloader.rs18
-rw-r--r--crates/shirabe/src/factory.rs52
-rw-r--r--crates/shirabe/src/util/sync_helper.rs20
20 files changed, 1338 insertions, 1169 deletions
diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs
index 01c1b5e..457c546 100644
--- a/crates/shirabe/src/command/status_command.rs
+++ b/crates/shirabe/src/command/status_command.rs
@@ -128,13 +128,11 @@ impl StatusCommand {
Some(d) => d,
None => continue,
};
- // TODO(phase-b): downloader borrow lifetime tied to dm.borrow() temporary; restructure later.
- let dm_borrow = dm.borrow();
- let downloader: &dyn crate::downloader::DownloaderInterface =
- match dm_borrow.get_downloader_for_package(package.clone())? {
- Some(d) => d,
- None => continue,
- };
+ let downloader_handle = match dm.borrow().get_downloader_for_package(package.clone())? {
+ Some(d) => d,
+ None => continue,
+ };
+ let mut downloader = downloader_handle.borrow_mut();
// TODO(phase-b): isinstance checks using ChangeReportInterface/VcsCapableDownloaderInterface/DvcsDownloaderInterface
if let Some(change_reporter) = downloader.as_change_report_interface() {
diff --git a/crates/shirabe/src/downloader/change_report_interface.rs b/crates/shirabe/src/downloader/change_report_interface.rs
index 5e770f7..718b2c1 100644
--- a/crates/shirabe/src/downloader/change_report_interface.rs
+++ b/crates/shirabe/src/downloader/change_report_interface.rs
@@ -6,7 +6,7 @@ use crate::package::PackageInterfaceHandle;
pub trait ChangeReportInterface {
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>>;
diff --git a/crates/shirabe/src/downloader/download_manager.rs b/crates/shirabe/src/downloader/download_manager.rs
index 7d5d76d..e0998e9 100644
--- a/crates/shirabe/src/downloader/download_manager.rs
+++ b/crates/shirabe/src/downloader/download_manager.rs
@@ -31,7 +31,7 @@ pub struct DownloadManager {
/// @var Filesystem
filesystem: std::rc::Rc<std::cell::RefCell<Filesystem>>,
/// @var array<string, DownloaderInterface>
- downloaders: IndexMap<String, Box<dyn DownloaderInterface>>,
+ downloaders: IndexMap<String, std::rc::Rc<std::cell::RefCell<dyn DownloaderInterface>>>,
}
impl DownloadManager {
@@ -91,7 +91,7 @@ impl DownloadManager {
pub fn set_downloader(
&mut self,
r#type: &str,
- downloader: Box<dyn DownloaderInterface>,
+ downloader: std::rc::Rc<std::cell::RefCell<dyn DownloaderInterface>>,
) -> &mut Self {
let r#type = strtolower(r#type);
self.downloaders.insert(r#type, downloader);
@@ -103,7 +103,10 @@ impl DownloadManager {
///
/// @param string $type installation type
/// @throws \InvalidArgumentException if downloader for provided type is not registered
- pub fn get_downloader(&self, r#type: &str) -> Result<&dyn DownloaderInterface> {
+ pub fn get_downloader(
+ &self,
+ r#type: &str,
+ ) -> Result<std::rc::Rc<std::cell::RefCell<dyn DownloaderInterface>>> {
let r#type = strtolower(r#type);
if !self.downloaders.contains_key(&r#type) {
return Err(InvalidArgumentException {
@@ -119,7 +122,7 @@ impl DownloadManager {
.into());
}
- Ok(self.downloaders.get(&r#type).unwrap().as_ref())
+ Ok(self.downloaders.get(&r#type).unwrap().clone())
}
/// Returns downloader for already installed package.
@@ -131,7 +134,7 @@ impl DownloadManager {
pub fn get_downloader_for_package(
&self,
package: PackageInterfaceHandle,
- ) -> Result<Option<&dyn DownloaderInterface>> {
+ ) -> Result<Option<std::rc::Rc<std::cell::RefCell<dyn DownloaderInterface>>>> {
let installation_source = package.get_installation_source();
if "metapackage" == package.get_type() {
@@ -153,13 +156,14 @@ impl DownloadManager {
.into());
};
- if installation_source.as_deref() != Some(&downloader.get_installation_source()) {
+ let downloader_installation_source = downloader.borrow().get_installation_source();
+ if installation_source.as_deref() != Some(&downloader_installation_source) {
return Err(LogicException {
message: sprintf(
"Downloader \"%s\" is a %s type downloader and can not be used to download %s for package %s",
&[
- PhpMixed::String(shirabe_php_shim::get_class_obj(downloader)),
- PhpMixed::String(downloader.get_installation_source()),
+ PhpMixed::String(shirabe_php_shim::get_class_obj(&*downloader.borrow())),
+ PhpMixed::String(downloader_installation_source),
PhpMixed::String(installation_source.clone().unwrap_or_default()),
PhpMixed::String(package.to_string()),
],
@@ -172,13 +176,13 @@ impl DownloadManager {
Ok(Some(downloader))
}
- pub fn get_downloader_type(&self, downloader: &dyn DownloaderInterface) -> String {
+ pub fn get_downloader_type(
+ &self,
+ downloader: &std::rc::Rc<std::cell::RefCell<dyn DownloaderInterface>>,
+ ) -> String {
// PHP: array_search($downloader, $this->downloaders)
for (r#type, candidate) in &self.downloaders {
- if std::ptr::eq(
- candidate.as_ref() as *const dyn DownloaderInterface as *const (),
- downloader as *const dyn DownloaderInterface as *const (),
- ) {
+ if std::rc::Rc::ptr_eq(candidate, downloader) {
return r#type.clone();
}
}
@@ -238,6 +242,7 @@ impl DownloadManager {
};
let result = match downloader
+ .borrow_mut()
.download3(package.clone(), &target_dir, prev_package.clone())
.await
{
@@ -299,6 +304,7 @@ impl DownloadManager {
let target_dir = self.normalize_target_dir(target_dir);
if let Some(downloader) = self.get_downloader_for_package(package.clone())? {
return downloader
+ .borrow_mut()
.prepare(r#type, package, &target_dir, prev_package)
.await;
}
@@ -321,7 +327,7 @@ impl DownloadManager {
) -> Result<Option<PhpMixed>> {
let target_dir = self.normalize_target_dir(target_dir);
if let Some(downloader) = self.get_downloader_for_package(package.clone())? {
- return downloader.install2(package, &target_dir).await;
+ return downloader.borrow_mut().install2(package, &target_dir).await;
}
Ok(None)
@@ -353,16 +359,20 @@ impl DownloadManager {
// if we have a downloader present before, but not after, the package became a metapackage and its files should be removed
if downloader.is_none() {
return initial_downloader
+ .as_ref()
.unwrap()
+ .borrow_mut()
.remove2(initial, &target_dir)
.await;
}
- let initial_type = self.get_downloader_type(initial_downloader.unwrap());
- let target_type = self.get_downloader_type(downloader.unwrap());
+ let initial_type = self.get_downloader_type(initial_downloader.as_ref().unwrap());
+ let target_type = self.get_downloader_type(downloader.as_ref().unwrap());
if initial_type == target_type {
match downloader
+ .as_ref()
.unwrap()
+ .borrow_mut()
.update(initial.clone(), target.clone(), &target_dir)
.await
{
@@ -399,7 +409,9 @@ impl DownloadManager {
// we wipe the dir and do a new install instead of updating it
// PHP: return $promise->then(fn () => $this->install($target, $targetDir));
let _ = initial_downloader
+ .as_ref()
.unwrap()
+ .borrow_mut()
.remove2(initial, &target_dir)
.await?;
self.install(target, &target_dir).await
@@ -417,7 +429,7 @@ impl DownloadManager {
) -> Result<Option<PhpMixed>> {
let target_dir = self.normalize_target_dir(target_dir);
if let Some(downloader) = self.get_downloader_for_package(package.clone())? {
- return downloader.remove2(package, &target_dir).await;
+ return downloader.borrow_mut().remove2(package, &target_dir).await;
}
Ok(None)
@@ -440,6 +452,7 @@ impl DownloadManager {
let target_dir = self.normalize_target_dir(target_dir);
if let Some(downloader) = self.get_downloader_for_package(package.clone())? {
return downloader
+ .borrow_mut()
.cleanup(r#type, package, &target_dir, prev_package)
.await;
}
diff --git a/crates/shirabe/src/downloader/downloader_interface.rs b/crates/shirabe/src/downloader/downloader_interface.rs
index 873438e..f63ac4e 100644
--- a/crates/shirabe/src/downloader/downloader_interface.rs
+++ b/crates/shirabe/src/downloader/downloader_interface.rs
@@ -8,7 +8,7 @@ pub trait DownloaderInterface: std::fmt::Debug {
fn get_installation_source(&self) -> String;
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -17,7 +17,7 @@ pub trait DownloaderInterface: std::fmt::Debug {
/// Convenience for the PHP default `$output = true` overload.
async fn download3(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -26,7 +26,7 @@ pub trait DownloaderInterface: std::fmt::Debug {
}
async fn prepare(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -34,7 +34,7 @@ pub trait DownloaderInterface: std::fmt::Debug {
) -> anyhow::Result<Option<PhpMixed>>;
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -42,7 +42,7 @@ pub trait DownloaderInterface: std::fmt::Debug {
/// Convenience for the PHP default `$output = true` overload.
async fn install2(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> anyhow::Result<Option<PhpMixed>> {
@@ -50,14 +50,14 @@ pub trait DownloaderInterface: std::fmt::Debug {
}
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
) -> anyhow::Result<Option<PhpMixed>>;
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -65,7 +65,7 @@ pub trait DownloaderInterface: std::fmt::Debug {
/// Convenience for the PHP default `$output = true` overload.
async fn remove2(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> anyhow::Result<Option<PhpMixed>> {
@@ -73,14 +73,16 @@ pub trait DownloaderInterface: std::fmt::Debug {
}
async fn cleanup(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
) -> anyhow::Result<Option<PhpMixed>>;
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
None
}
diff --git a/crates/shirabe/src/downloader/file_downloader.rs b/crates/shirabe/src/downloader/file_downloader.rs
index 55882f7..e0fc0c9 100644
--- a/crates/shirabe/src/downloader/file_downloader.rs
+++ b/crates/shirabe/src/downloader/file_downloader.rs
@@ -153,13 +153,15 @@ impl DownloaderInterface for FileDownloader {
"dist".to_owned()
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
/// @inheritDoc
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
_prev_package: Option<PackageInterfaceHandle>,
@@ -437,7 +439,7 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn prepare(
- &self,
+ &mut self,
_type: &str,
_package: PackageInterfaceHandle,
_path: &str,
@@ -448,7 +450,7 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn cleanup(
- &self,
+ &mut self,
_type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -503,7 +505,7 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -565,7 +567,7 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
@@ -583,7 +585,7 @@ impl DownloaderInterface for FileDownloader {
/// @inheritDoc
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -615,7 +617,7 @@ impl ChangeReportInterface for FileDownloader {
/// @inheritDoc
/// @throws \RuntimeException
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
diff --git a/crates/shirabe/src/downloader/fossil_downloader.rs b/crates/shirabe/src/downloader/fossil_downloader.rs
index 9a38578..d6b8095 100644
--- a/crates/shirabe/src/downloader/fossil_downloader.rs
+++ b/crates/shirabe/src/downloader/fossil_downloader.rs
@@ -4,6 +4,7 @@ use crate::config::Config;
use crate::downloader::ChangeReportInterface;
use crate::downloader::DownloaderInterface;
use crate::downloader::VcsCapableDownloaderInterface;
+use crate::downloader::VcsDownloader;
use crate::downloader::VcsDownloaderBase;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
@@ -11,6 +12,7 @@ use crate::package::PackageInterfaceHandle;
use crate::util::Filesystem;
use crate::util::ProcessExecutor;
use anyhow::Result;
+use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::Preg;
use shirabe_php_shim::{PhpMixed, RuntimeException};
@@ -31,30 +33,82 @@ impl FossilDownloader {
}
}
- pub(crate) async fn do_download(
+ fn execute(
&self,
+ command: Vec<String>,
+ cwd: Option<String>,
+ output: &mut String,
+ ) -> Result<()> {
+ if self
+ .inner
+ .process
+ .borrow_mut()
+ .execute(&command, output, cwd)?
+ != 0
+ {
+ return Err(RuntimeException {
+ message: format!(
+ "Failed to execute {}\n\n{}",
+ command.join(" "),
+ self.inner.process.borrow().get_error_output()
+ ),
+ code: 0,
+ }
+ .into());
+ }
+ Ok(())
+ }
+}
+
+impl VcsDownloader for FossilDownloader {
+ fn io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
+ self.inner.io.clone()
+ }
+
+ fn config(&self) -> &std::rc::Rc<std::cell::RefCell<Config>> {
+ &self.inner.config
+ }
+
+ fn process(&self) -> &std::rc::Rc<std::cell::RefCell<ProcessExecutor>> {
+ &self.inner.process
+ }
+
+ fn filesystem(&self) -> &std::rc::Rc<std::cell::RefCell<Filesystem>> {
+ &self.inner.filesystem
+ }
+
+ fn has_cleaned_changes(&self) -> &IndexMap<String, bool> {
+ &self.inner.has_cleaned_changes
+ }
+
+ fn has_cleaned_changes_mut(&mut self) -> &mut IndexMap<String, bool> {
+ &mut self.inner.has_cleaned_changes
+ }
+
+ async fn do_download(
+ &mut self,
_package: PackageInterfaceHandle,
- _path: String,
- _url: String,
+ _path: &str,
+ _url: &str,
_prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
Ok(None)
}
- pub(crate) async fn do_install(
- &self,
+ async fn do_install(
+ &mut self,
package: PackageInterfaceHandle,
- path: String,
- url: String,
+ path: &str,
+ url: &str,
) -> Result<Option<PhpMixed>> {
self.inner.config.borrow_mut().prohibit_url_by_config(
- &url,
+ url,
Some(self.inner.io.clone()),
&indexmap::IndexMap::new(),
)?;
let repo_file = format!("{}.fossil", path);
- let real_path = shirabe_php_shim::realpath(&path);
+ let real_path = shirabe_php_shim::realpath(path);
self.inner.io.write_error(&format!(
"Cloning {}",
@@ -67,7 +121,7 @@ impl FossilDownloader {
"fossil".to_string(),
"clone".to_string(),
"--".to_string(),
- url,
+ url.to_string(),
repo_file.clone(),
],
None,
@@ -101,15 +155,15 @@ impl FossilDownloader {
Ok(None)
}
- pub(crate) async fn do_update(
- &self,
+ async fn do_update(
+ &mut self,
_initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
- path: String,
- url: String,
+ path: &str,
+ url: &str,
) -> Result<Option<PhpMixed>> {
self.inner.config.borrow_mut().prohibit_url_by_config(
- &url,
+ url,
Some(self.inner.io.clone()),
&indexmap::IndexMap::new(),
)?;
@@ -119,7 +173,7 @@ impl FossilDownloader {
target.get_source_reference().unwrap_or_default()
));
- if !self.has_metadata_repository(&path) {
+ if !self.has_metadata_repository(path) {
return Err(RuntimeException {
message: format!(
"The .fslckout file is missing from {}, see https://getcomposer.org/commit-deps for more information",
@@ -129,7 +183,7 @@ impl FossilDownloader {
}.into());
}
- let real_path = shirabe_php_shim::realpath(&path);
+ let real_path = shirabe_php_shim::realpath(path);
let mut output = String::new();
self.execute(
vec!["fossil".to_string(), "pull".to_string()],
@@ -153,11 +207,11 @@ impl FossilDownloader {
Ok(None)
}
- pub(crate) fn get_commit_logs(
- &self,
- _from_reference: String,
- to_reference: String,
- path: String,
+ fn get_commit_logs(
+ &mut self,
+ _from_reference: &str,
+ to_reference: &str,
+ path: &str,
) -> Result<String> {
let mut output = String::new();
self.execute(
@@ -171,9 +225,9 @@ impl FossilDownloader {
"-n".to_string(),
"0".to_string(),
"before".to_string(),
- to_reference.clone(),
+ to_reference.to_string(),
],
- shirabe_php_shim::realpath(&path),
+ shirabe_php_shim::realpath(path),
&mut output,
)?;
@@ -197,33 +251,7 @@ impl FossilDownloader {
Ok(log)
}
- fn execute(
- &self,
- command: Vec<String>,
- cwd: Option<String>,
- output: &mut String,
- ) -> Result<()> {
- if self
- .inner
- .process
- .borrow_mut()
- .execute(&command, output, cwd)?
- != 0
- {
- return Err(RuntimeException {
- message: format!(
- "Failed to execute {}\n\n{}",
- command.join(" "),
- self.inner.process.borrow().get_error_output()
- ),
- code: 0,
- }
- .into());
- }
- Ok(())
- }
-
- pub(crate) fn has_metadata_repository(&self, path: &str) -> bool {
+ fn has_metadata_repository(&self, path: &str) -> bool {
std::path::Path::new(&format!("{}/.fslckout", path)).is_file()
|| std::path::Path::new(&format!("{}/_FOSSIL_", path)).is_file()
}
@@ -231,7 +259,7 @@ impl FossilDownloader {
impl ChangeReportInterface for FossilDownloader {
fn get_local_changes(
- &self,
+ &mut self,
_package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -258,12 +286,11 @@ impl VcsCapableDownloaderInterface for FossilDownloader {
}
}
-// TODO(phase-b): wire up VcsDownloader trait properly. FossilDownloader extends VcsDownloader
-// which implements DownloaderInterface in PHP. Delegating each trait method to todo!() until the
-// inner VcsDownloaderBase exposes the matching impl surface.
#[async_trait::async_trait(?Send)]
impl DownloaderInterface for FossilDownloader {
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
@@ -274,63 +301,63 @@ impl DownloaderInterface for FossilDownloader {
}
fn get_installation_source(&self) -> String {
- todo!()
+ <Self as VcsDownloader>::get_installation_source(self)
}
async fn download(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::download(self, package, path, prev_package).await
}
async fn prepare(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::prepare(self, r#type, package, path, prev_package).await
}
async fn install(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::install(self, package, path).await
}
async fn update(
- &self,
- _initial: PackageInterfaceHandle,
- _target: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ initial: PackageInterfaceHandle,
+ target: PackageInterfaceHandle,
+ path: &str,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::update(self, initial, target, path).await
}
async fn remove(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::remove(self, package, path).await
}
async fn cleanup(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::cleanup(self, r#type, package, path, prev_package).await
}
}
diff --git a/crates/shirabe/src/downloader/git_downloader.rs b/crates/shirabe/src/downloader/git_downloader.rs
index 34f89a4..26ff4aa 100644
--- a/crates/shirabe/src/downloader/git_downloader.rs
+++ b/crates/shirabe/src/downloader/git_downloader.rs
@@ -14,6 +14,7 @@ use crate::config::Config;
use crate::downloader::ChangeReportInterface;
use crate::downloader::DvcsDownloaderInterface;
use crate::downloader::VcsCapableDownloaderInterface;
+use crate::downloader::VcsDownloader;
use crate::downloader::VcsDownloaderBase;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
@@ -60,401 +61,6 @@ impl GitDownloader {
}
}
- pub(crate) async fn do_download(
- &mut self,
- package: PackageInterfaceHandle,
- _path: &str,
- url: &str,
- _prev_package: Option<PackageInterfaceHandle>,
- ) -> Result<Option<PhpMixed>> {
- // Do not create an extra local cache when repository is already local
- if Filesystem::is_local_path(url) {
- return Ok(None);
- }
-
- GitUtil::clean_env(&self.inner.process);
-
- let cache_path = format!(
- "{}/{}/",
- self.inner
- .config
- .borrow_mut()
- .get("cache-vcs-dir")
- .as_string()
- .unwrap_or(""),
- Preg::replace(r"{[^a-z0-9.]}i", "-", &Url::sanitize(url.to_string()))?,
- );
- let git_version = GitUtil::get_version(&self.inner.process);
-
- // --dissociate option is only available since git 2.3.0-rc0
- if git_version.is_some()
- && version_compare(git_version.as_deref().unwrap_or(""), "2.3.0-rc0", ">=")
- && Cache::is_usable(&cache_path)
- {
- self.inner.io.write_error3(
- &format!(
- " - Syncing <info>{}</info> (<comment>{}</comment>) into cache",
- package.get_name(),
- package
- .get_full_pretty_version(true, crate::package::DisplayMode::SourceRefIfDev),
- ),
- true,
- io_interface::NORMAL,
- );
- self.inner.io.write_error3(
- &sprintf(
- " Cloning to cache at %s",
- &[PhpMixed::String(cache_path.clone())],
- ),
- true,
- io_interface::DEBUG,
- );
- let r#ref = package.get_source_reference();
- let pretty_version = package.get_pretty_version();
- if self.git_util.fetch_ref_or_sync_mirror(
- url,
- &cache_path,
- r#ref.as_deref().unwrap_or(""),
- Some(&pretty_version),
- )? && is_dir(&cache_path)
- {
- self.cached_packages
- .entry(package.get_id())
- .or_insert_with(IndexMap::new)
- .insert(r#ref.as_deref().unwrap_or("").to_string(), true);
- }
- } else if git_version.is_none() {
- return Err(RuntimeException {
- message: "git was not found in your PATH, skipping source download".to_string(),
- code: 0,
- }
- .into());
- }
-
- Ok(None)
- }
-
- pub(crate) async fn do_install(
- &mut self,
- package: PackageInterfaceHandle,
- path: &str,
- url: &str,
- ) -> Result<Option<PhpMixed>> {
- GitUtil::clean_env(&self.inner.process);
- let path = self.normalize_path(path);
- let cache_path = format!(
- "{}/{}/",
- self.inner
- .config
- .borrow_mut()
- .get("cache-vcs-dir")
- .as_string()
- .unwrap_or(""),
- Preg::replace(r"{[^a-z0-9.]}i", "-", &Url::sanitize(url.to_string()))?,
- );
- let r#ref = package.get_source_reference().unwrap_or_default();
-
- let msg;
- let commands: Vec<Vec<String>>;
- let has_cached = self
- .cached_packages
- .get(&package.get_id())
- .and_then(|m| m.get(&r#ref))
- .copied()
- .unwrap_or(false);
- if has_cached {
- msg = format!("Cloning {} from cache", self.get_short_hash(&r#ref));
-
- let mut clone_flags: Vec<String> = vec![
- "--dissociate".to_string(),
- "--reference".to_string(),
- 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![];
- }
- }
- }
-
- commands = vec![
- {
- let mut base = vec![
- "git".to_string(),
- "clone".to_string(),
- "--no-checkout".to_string(),
- cache_path.clone(),
- path.clone(),
- ];
- base.extend(clone_flags);
- base
- },
- vec![
- "git".to_string(),
- "remote".to_string(),
- "set-url".to_string(),
- "origin".to_string(),
- "--".to_string(),
- "%sanitizedUrl%".to_string(),
- ],
- vec![
- "git".to_string(),
- "remote".to_string(),
- "add".to_string(),
- "composer".to_string(),
- "--".to_string(),
- "%sanitizedUrl%".to_string(),
- ],
- ];
- } else {
- msg = format!("Cloning {}", self.get_short_hash(&r#ref));
- commands = vec![
- vec![
- "git".to_string(),
- "clone".to_string(),
- "--no-checkout".to_string(),
- "--".to_string(),
- "%url%".to_string(),
- path.clone(),
- ],
- vec![
- "git".to_string(),
- "remote".to_string(),
- "add".to_string(),
- "composer".to_string(),
- "--".to_string(),
- "%url%".to_string(),
- ],
- vec![
- "git".to_string(),
- "fetch".to_string(),
- "composer".to_string(),
- ],
- vec![
- "git".to_string(),
- "remote".to_string(),
- "set-url".to_string(),
- "origin".to_string(),
- "--".to_string(),
- "%sanitizedUrl%".to_string(),
- ],
- vec![
- "git".to_string(),
- "remote".to_string(),
- "set-url".to_string(),
- "composer".to_string(),
- "--".to_string(),
- "%sanitizedUrl%".to_string(),
- ],
- ];
- if Platform::get_env("COMPOSER_DISABLE_NETWORK").is_some() {
- return Err(RuntimeException {
- message: format!(
- "The required git reference for {} is not in cache and network is disabled, aborting",
- package.get_name(),
- ),
- code: 0,
- }
- .into());
- }
- }
-
- self.inner.io.write_error3(&msg, true, io_interface::NORMAL);
-
- self.git_util
- .run_commands(commands, url, Some(&path), true, None)?;
-
- let source_url = package.get_source_url();
- if Some(url) != source_url.as_deref() && source_url.is_some() {
- self.update_origin_url(&path, source_url.as_deref().unwrap());
- } else {
- self.set_push_url(&path, url);
- }
-
- let pretty_version = package.get_pretty_version();
- if let Some(new_ref) =
- self.update_to_commit(package.clone(), &path, &r#ref, &pretty_version)?
- {
- if package.get_dist_reference() == package.get_source_reference() {
- // TODO(phase-b): set_dist_reference requires &mut PackageInterface
- // package.set_dist_reference(Some(new_ref.clone()));
- }
- // package.set_source_reference(Some(new_ref));
- let _ = new_ref;
- }
-
- Ok(None)
- }
-
- pub(crate) async fn do_update(
- &mut self,
- _initial: PackageInterfaceHandle,
- target: PackageInterfaceHandle,
- path: &str,
- url: &str,
- ) -> Result<Option<PhpMixed>> {
- GitUtil::clean_env(&self.inner.process);
- let path = self.normalize_path(path);
- if !self.has_metadata_repository(&path) {
- return Err(RuntimeException {
- message: format!(
- "The .git directory is missing from {}, see https://getcomposer.org/commit-deps for more information",
- path
- ),
- code: 0,
- }
- .into());
- }
-
- let cache_path = format!(
- "{}/{}/",
- self.inner
- .config
- .borrow_mut()
- .get("cache-vcs-dir")
- .as_string()
- .unwrap_or(""),
- Preg::replace(r"{[^a-z0-9.]}i", "-", &Url::sanitize(url.to_string()))?,
- );
- let r#ref = target.get_source_reference().unwrap_or_default();
-
- let msg;
- let remote_url;
- let has_cached = self
- .cached_packages
- .get(&target.get_id())
- .and_then(|m| m.get(&r#ref))
- .copied()
- .unwrap_or(false);
- if has_cached {
- msg = format!("Checking out {} from cache", self.get_short_hash(&r#ref));
- remote_url = cache_path.clone();
- } else {
- msg = format!("Checking out {}", self.get_short_hash(&r#ref));
- remote_url = "%url%".to_string();
- if Platform::get_env("COMPOSER_DISABLE_NETWORK").is_some() {
- return Err(RuntimeException {
- message: format!(
- "The required git reference for {} is not in cache and network is disabled, aborting",
- target.get_name(),
- ),
- code: 0,
- }
- .into());
- }
- }
-
- self.inner.io.write_error3(&msg, true, io_interface::NORMAL);
-
- let mut output = String::new();
- if self.inner.process.borrow_mut().execute_args(
- &vec![
- "git".to_string(),
- "rev-parse".to_string(),
- "--quiet".to_string(),
- "--verify".to_string(),
- format!("{}^{{commit}}", r#ref),
- ],
- &mut output,
- Some(path.clone()),
- ) != 0
- {
- let commands = vec![
- vec![
- "git".to_string(),
- "remote".to_string(),
- "set-url".to_string(),
- "composer".to_string(),
- "--".to_string(),
- remote_url.clone(),
- ],
- vec![
- "git".to_string(),
- "fetch".to_string(),
- "composer".to_string(),
- ],
- vec![
- "git".to_string(),
- "fetch".to_string(),
- "--tags".to_string(),
- "composer".to_string(),
- ],
- ];
-
- self.git_util
- .run_commands(commands, url, Some(&path), false, None)?;
- }
-
- let command = vec![
- "git".to_string(),
- "remote".to_string(),
- "set-url".to_string(),
- "composer".to_string(),
- "--".to_string(),
- "%sanitizedUrl%".to_string(),
- ];
- self.git_util
- .run_commands(vec![command], url, Some(&path), false, None)?;
-
- let pretty_version = target.get_pretty_version();
- if let Some(new_ref) =
- self.update_to_commit(target.clone(), &path, &r#ref, &pretty_version)?
- {
- if target.get_dist_reference() == target.get_source_reference() {
- // TODO(phase-b): set_dist_reference requires &mut PackageInterface
- // target.set_dist_reference(Some(new_ref.clone()));
- }
- // target.set_source_reference(Some(new_ref));
- let _ = new_ref;
- }
-
- 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()],
- &mut output,
- Some(path.clone()),
- ) == 0
- {
- let mut origin_match: IndexMap<CaptureKey, String> = IndexMap::new();
- let mut composer_match: IndexMap<CaptureKey, String> = IndexMap::new();
- if Preg::is_match3(
- r"{^origin\s+(?P<url>\S+)}m",
- &output,
- Some(&mut origin_match),
- )
- .unwrap_or(false)
- && Preg::is_match3(
- r"{^composer\s+(?P<url>\S+)}m",
- &output,
- Some(&mut composer_match),
- )
- .unwrap_or(false)
- {
- let origin_url = origin_match
- .get(&CaptureKey::ByName("url".to_string()))
- .cloned()
- .unwrap_or_default();
- let composer_url = composer_match
- .get(&CaptureKey::ByName("url".to_string()))
- .cloned()
- .unwrap_or_default();
- if origin_url == composer_url
- && Some(composer_url.as_str()) != target.get_source_url().as_deref()
- {
- update_origin_url = true;
- }
- }
- }
- if update_origin_url && target.get_source_url().is_some() {
- self.update_origin_url(&path, &target.get_source_url().unwrap());
- }
-
- Ok(None)
- }
-
pub fn get_unpushed_changes(
&self,
_package: PackageInterfaceHandle,
@@ -649,211 +255,6 @@ impl GitDownloader {
Ok(unpushed_changes)
}
- pub(crate) async fn clean_changes(
- &mut self,
- package: PackageInterfaceHandle,
- path: &str,
- update: bool,
- ) -> Result<Option<PhpMixed>> {
- GitUtil::clean_env(&self.inner.process);
- 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()
- || 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());
- }
- }
-
- let changes = match self.get_local_changes(package.clone(), &path)? {
- Some(c) => c,
- None => return Ok(None),
- };
-
- if !self.inner.io.is_interactive() {
- let discard_changes = self.inner.config.borrow_mut().get("discard-changes");
- if discard_changes.as_bool() == Some(true) {
- return self.discard_changes(&path).await;
- }
- if discard_changes.as_string() == Some("stash") {
- if !update {
- return self
- .inner
- .clean_changes(package.clone(), &path, update)
- .await;
- }
-
- return self.stash_changes(&path).await;
- }
-
- return self.inner.clean_changes(package, &path, update).await;
- }
-
- let changes: Vec<String> = array_map(
- |elem: &String| format!(" {}", elem),
- &Preg::split(r"{\s*\r?\n\s*}", &changes)?,
- );
- self.inner.io.write_error3(
- &format!(
- " <error>{} has modified files:</error>",
- package.get_pretty_name()
- ),
- true,
- io_interface::NORMAL,
- );
- let slice_end = 10_usize.min(changes.len());
- // TODO(phase-b): PHP passes the list directly to writeError; joined here so write_error3 takes &str
- self.inner
- .io
- .write_error3(&changes[..slice_end].join("\n"), true, io_interface::NORMAL);
- if (changes.len() as i64) > 10 {
- self.inner.io.write_error3(
- &format!(
- " <info>{} more files modified, choose \"v\" to view the full list</info>",
- changes.len() as i64 - 10
- ),
- true,
- io_interface::NORMAL,
- );
- }
-
- 'outer: loop {
- let answer = self
- .inner
- .io
- .ask(
- format!(
- " <info>Discard changes [y,n,v,{}?]?</info> ",
- if update { "s," } else { "" }
- ),
- PhpMixed::String("?".to_string()),
- )
- .as_string()
- .map(|s| s.to_string());
- let mut do_help = false;
- match answer.as_deref() {
- Some("y") => {
- self.discard_changes(&path).await?;
- break 'outer;
- }
- Some("s") => {
- if !update {
- // goto help;
- do_help = true;
- } else {
- self.stash_changes(&path).await?;
- break 'outer;
- }
- }
- Some("n") => {
- return Err(RuntimeException {
- message: "Update aborted".to_string(),
- code: 0,
- }
- .into());
- }
- Some("v") => {
- // TODO(phase-b): PHP passes list directly; joined here for &str arg
- self.inner
- .io
- .write_error3(&changes.join("\n"), true, io_interface::NORMAL);
- }
- Some("d") => {
- self.view_diff(&path);
- }
- _ => {
- // case '?': default:
- do_help = true;
- }
- }
-
- if do_help {
- // help:
- // TODO(phase-b): PHP passes list directly; joined here for &str arg
- self.inner.io.write_error3(
- &[
- format!(
- " y - discard changes and apply the {}",
- if update { "update" } else { "uninstall" }
- ),
- format!(
- " n - abort the {} and let you manually clean things up",
- if update { "update" } else { "uninstall" }
- ),
- " v - view modified files".to_string(),
- " d - view local modifications (diff)".to_string(),
- ]
- .join("\n"),
- true,
- io_interface::NORMAL,
- );
- if update {
- self.inner.io.write_error3(
- " s - stash changes and try to reapply them after the update",
- true,
- io_interface::NORMAL,
- );
- }
- self.inner
- .io
- .write_error3(" ? - print help", true, io_interface::NORMAL);
- }
- }
-
- Ok(None)
- }
-
- pub(crate) fn reapply_changes(&mut self, path: &str) -> Result<()> {
- let path = self.normalize_path(path);
- if self
- .has_stashed_changes
- .get(&path)
- .copied()
- .unwrap_or(false)
- {
- self.has_stashed_changes.shift_remove(&path);
- self.inner.io.write_error3(
- " <info>Re-applying stashed changes</info>",
- true,
- io_interface::NORMAL,
- );
- let mut output = String::new();
- if self.inner.process.borrow_mut().execute_args(
- &vec!["git".to_string(), "stash".to_string(), "pop".to_string()],
- &mut output,
- Some(path.clone()),
- ) != 0
- {
- return Err(RuntimeException {
- message: format!(
- "Failed to apply stashed changes:\n\n{}",
- self.inner.process.borrow().get_error_output()
- ),
- code: 0,
- }
- .into());
- }
- }
-
- self.has_discarded_changes.shift_remove(&path);
- Ok(())
- }
-
/// Updates the given path to the given commit ref
///
/// @throws \RuntimeException
@@ -1153,42 +554,6 @@ impl GitDownloader {
}
}
- pub(crate) fn get_commit_logs(
- &mut self,
- from_reference: &str,
- to_reference: &str,
- path: &str,
- ) -> Result<String> {
- let path = self.normalize_path(path);
- let mut args = vec![
- "--format=%h - %an: %s".to_string(),
- format!("{}..{}", from_reference, to_reference),
- ];
- args.extend(GitUtil::get_no_show_signature_flags(&self.inner.process));
- let command = GitUtil::build_rev_list_command(&self.inner.process, args);
-
- let mut output = String::new();
- if self
- .inner
- .process
- .borrow_mut()
- .execute_args(&command, &mut output, Some(path.clone()))
- != 0
- {
- return Err(RuntimeException {
- message: format!(
- "Failed to execute {}\n\n{}",
- implode(" ", &command),
- self.inner.process.borrow().get_error_output(),
- ),
- code: 0,
- }
- .into());
- }
-
- Ok(GitUtil::parse_rev_list_output(&output, &self.inner.process))
- }
-
/// @phpstan-return PromiseInterface<void|null>
/// @throws \RuntimeException
pub(crate) async fn discard_changes(&mut self, path: &str) -> Result<Option<PhpMixed>> {
@@ -1301,12 +666,6 @@ impl GitDownloader {
path
}
- pub(crate) fn has_metadata_repository(&self, path: &str) -> bool {
- let path = self.normalize_path(path);
-
- is_dir(&format!("{}/.git", path))
- }
-
pub(crate) fn get_short_hash(&self, reference: &str) -> String {
if !self.inner.io.is_verbose()
&& Preg::is_match(r"{^[0-9a-f]{40}$}", reference).unwrap_or(false)
@@ -1330,7 +689,7 @@ impl DvcsDownloaderInterface for GitDownloader {
impl ChangeReportInterface for GitDownloader {
fn get_local_changes(
- &self,
+ &mut self,
_package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -1379,13 +738,678 @@ impl VcsCapableDownloaderInterface for GitDownloader {
}
}
-// TODO(phase-b): GitDownloader extends VcsDownloader which implements DownloaderInterface.
-// Delegating each trait method to todo!() until the inner VcsDownloaderBase exposes the
-// matching impl surface.
+impl VcsDownloader for GitDownloader {
+ fn io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
+ self.inner.io.clone()
+ }
+
+ fn config(&self) -> &std::rc::Rc<std::cell::RefCell<Config>> {
+ &self.inner.config
+ }
+
+ fn process(&self) -> &std::rc::Rc<std::cell::RefCell<ProcessExecutor>> {
+ &self.inner.process
+ }
+
+ fn filesystem(&self) -> &std::rc::Rc<std::cell::RefCell<Filesystem>> {
+ &self.inner.filesystem
+ }
+
+ fn has_cleaned_changes(&self) -> &IndexMap<String, bool> {
+ &self.inner.has_cleaned_changes
+ }
+
+ fn has_cleaned_changes_mut(&mut self) -> &mut IndexMap<String, bool> {
+ &mut self.inner.has_cleaned_changes
+ }
+
+ async fn do_download(
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ url: &str,
+ prev_package: Option<PackageInterfaceHandle>,
+ ) -> Result<Option<PhpMixed>> {
+ // Do not create an extra local cache when repository is already local
+ if Filesystem::is_local_path(url) {
+ return Ok(None);
+ }
+
+ GitUtil::clean_env(&self.inner.process);
+
+ let cache_path = format!(
+ "{}/{}/",
+ self.inner
+ .config
+ .borrow_mut()
+ .get("cache-vcs-dir")
+ .as_string()
+ .unwrap_or(""),
+ Preg::replace(r"{[^a-z0-9.]}i", "-", &Url::sanitize(url.to_string()))?,
+ );
+ let git_version = GitUtil::get_version(&self.inner.process);
+
+ // --dissociate option is only available since git 2.3.0-rc0
+ if git_version.is_some()
+ && version_compare(git_version.as_deref().unwrap_or(""), "2.3.0-rc0", ">=")
+ && Cache::is_usable(&cache_path)
+ {
+ self.inner.io.write_error3(
+ &format!(
+ " - Syncing <info>{}</info> (<comment>{}</comment>) into cache",
+ package.get_name(),
+ package
+ .get_full_pretty_version(true, crate::package::DisplayMode::SourceRefIfDev),
+ ),
+ true,
+ io_interface::NORMAL,
+ );
+ self.inner.io.write_error3(
+ &sprintf(
+ " Cloning to cache at %s",
+ &[PhpMixed::String(cache_path.clone())],
+ ),
+ true,
+ io_interface::DEBUG,
+ );
+ let r#ref = package.get_source_reference();
+ let pretty_version = package.get_pretty_version();
+ if self.git_util.fetch_ref_or_sync_mirror(
+ url,
+ &cache_path,
+ r#ref.as_deref().unwrap_or(""),
+ Some(&pretty_version),
+ )? && is_dir(&cache_path)
+ {
+ self.cached_packages
+ .entry(package.get_id())
+ .or_insert_with(IndexMap::new)
+ .insert(r#ref.as_deref().unwrap_or("").to_string(), true);
+ }
+ } else if git_version.is_none() {
+ return Err(RuntimeException {
+ message: "git was not found in your PATH, skipping source download".to_string(),
+ code: 0,
+ }
+ .into());
+ }
+
+ Ok(None)
+ }
+
+ async fn do_install(
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ url: &str,
+ ) -> Result<Option<PhpMixed>> {
+ GitUtil::clean_env(&self.inner.process);
+ let path = self.normalize_path(path);
+ let cache_path = format!(
+ "{}/{}/",
+ self.inner
+ .config
+ .borrow_mut()
+ .get("cache-vcs-dir")
+ .as_string()
+ .unwrap_or(""),
+ Preg::replace(r"{[^a-z0-9.]}i", "-", &Url::sanitize(url.to_string()))?,
+ );
+ let r#ref = package.get_source_reference().unwrap_or_default();
+
+ let msg;
+ let commands: Vec<Vec<String>>;
+ let has_cached = self
+ .cached_packages
+ .get(&package.get_id())
+ .and_then(|m| m.get(&r#ref))
+ .copied()
+ .unwrap_or(false);
+ if has_cached {
+ msg = format!("Cloning {} from cache", self.get_short_hash(&r#ref));
+
+ let mut clone_flags: Vec<String> = vec![
+ "--dissociate".to_string(),
+ "--reference".to_string(),
+ 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![];
+ }
+ }
+ }
+
+ commands = vec![
+ {
+ let mut base = vec![
+ "git".to_string(),
+ "clone".to_string(),
+ "--no-checkout".to_string(),
+ cache_path.clone(),
+ path.clone(),
+ ];
+ base.extend(clone_flags);
+ base
+ },
+ vec![
+ "git".to_string(),
+ "remote".to_string(),
+ "set-url".to_string(),
+ "origin".to_string(),
+ "--".to_string(),
+ "%sanitizedUrl%".to_string(),
+ ],
+ vec![
+ "git".to_string(),
+ "remote".to_string(),
+ "add".to_string(),
+ "composer".to_string(),
+ "--".to_string(),
+ "%sanitizedUrl%".to_string(),
+ ],
+ ];
+ } else {
+ msg = format!("Cloning {}", self.get_short_hash(&r#ref));
+ commands = vec![
+ vec![
+ "git".to_string(),
+ "clone".to_string(),
+ "--no-checkout".to_string(),
+ "--".to_string(),
+ "%url%".to_string(),
+ path.clone(),
+ ],
+ vec![
+ "git".to_string(),
+ "remote".to_string(),
+ "add".to_string(),
+ "composer".to_string(),
+ "--".to_string(),
+ "%url%".to_string(),
+ ],
+ vec![
+ "git".to_string(),
+ "fetch".to_string(),
+ "composer".to_string(),
+ ],
+ vec![
+ "git".to_string(),
+ "remote".to_string(),
+ "set-url".to_string(),
+ "origin".to_string(),
+ "--".to_string(),
+ "%sanitizedUrl%".to_string(),
+ ],
+ vec![
+ "git".to_string(),
+ "remote".to_string(),
+ "set-url".to_string(),
+ "composer".to_string(),
+ "--".to_string(),
+ "%sanitizedUrl%".to_string(),
+ ],
+ ];
+ if Platform::get_env("COMPOSER_DISABLE_NETWORK").is_some() {
+ return Err(RuntimeException {
+ message: format!(
+ "The required git reference for {} is not in cache and network is disabled, aborting",
+ package.get_name(),
+ ),
+ code: 0,
+ }
+ .into());
+ }
+ }
+
+ self.inner.io.write_error3(&msg, true, io_interface::NORMAL);
+
+ self.git_util
+ .run_commands(commands, url, Some(&path), true, None)?;
+
+ let source_url = package.get_source_url();
+ if Some(url) != source_url.as_deref() && source_url.is_some() {
+ self.update_origin_url(&path, source_url.as_deref().unwrap());
+ } else {
+ self.set_push_url(&path, url);
+ }
+
+ let pretty_version = package.get_pretty_version();
+ if let Some(new_ref) =
+ self.update_to_commit(package.clone(), &path, &r#ref, &pretty_version)?
+ {
+ if package.get_dist_reference() == package.get_source_reference() {
+ // TODO(phase-b): set_dist_reference requires &mut PackageInterface
+ // package.set_dist_reference(Some(new_ref.clone()));
+ }
+ // package.set_source_reference(Some(new_ref));
+ let _ = new_ref;
+ }
+
+ Ok(None)
+ }
+
+ async fn do_update(
+ &mut self,
+ initial: PackageInterfaceHandle,
+ target: PackageInterfaceHandle,
+ path: &str,
+ url: &str,
+ ) -> Result<Option<PhpMixed>> {
+ GitUtil::clean_env(&self.inner.process);
+ let path = self.normalize_path(path);
+ if !self.has_metadata_repository(&path) {
+ return Err(RuntimeException {
+ message: format!(
+ "The .git directory is missing from {}, see https://getcomposer.org/commit-deps for more information",
+ path
+ ),
+ code: 0,
+ }
+ .into());
+ }
+
+ let cache_path = format!(
+ "{}/{}/",
+ self.inner
+ .config
+ .borrow_mut()
+ .get("cache-vcs-dir")
+ .as_string()
+ .unwrap_or(""),
+ Preg::replace(r"{[^a-z0-9.]}i", "-", &Url::sanitize(url.to_string()))?,
+ );
+ let r#ref = target.get_source_reference().unwrap_or_default();
+
+ let msg;
+ let remote_url;
+ let has_cached = self
+ .cached_packages
+ .get(&target.get_id())
+ .and_then(|m| m.get(&r#ref))
+ .copied()
+ .unwrap_or(false);
+ if has_cached {
+ msg = format!("Checking out {} from cache", self.get_short_hash(&r#ref));
+ remote_url = cache_path.clone();
+ } else {
+ msg = format!("Checking out {}", self.get_short_hash(&r#ref));
+ remote_url = "%url%".to_string();
+ if Platform::get_env("COMPOSER_DISABLE_NETWORK").is_some() {
+ return Err(RuntimeException {
+ message: format!(
+ "The required git reference for {} is not in cache and network is disabled, aborting",
+ target.get_name(),
+ ),
+ code: 0,
+ }
+ .into());
+ }
+ }
+
+ self.inner.io.write_error3(&msg, true, io_interface::NORMAL);
+
+ let mut output = String::new();
+ if self.inner.process.borrow_mut().execute_args(
+ &vec![
+ "git".to_string(),
+ "rev-parse".to_string(),
+ "--quiet".to_string(),
+ "--verify".to_string(),
+ format!("{}^{{commit}}", r#ref),
+ ],
+ &mut output,
+ Some(path.clone()),
+ ) != 0
+ {
+ let commands = vec![
+ vec![
+ "git".to_string(),
+ "remote".to_string(),
+ "set-url".to_string(),
+ "composer".to_string(),
+ "--".to_string(),
+ remote_url.clone(),
+ ],
+ vec![
+ "git".to_string(),
+ "fetch".to_string(),
+ "composer".to_string(),
+ ],
+ vec![
+ "git".to_string(),
+ "fetch".to_string(),
+ "--tags".to_string(),
+ "composer".to_string(),
+ ],
+ ];
+
+ self.git_util
+ .run_commands(commands, url, Some(&path), false, None)?;
+ }
+
+ let command = vec![
+ "git".to_string(),
+ "remote".to_string(),
+ "set-url".to_string(),
+ "composer".to_string(),
+ "--".to_string(),
+ "%sanitizedUrl%".to_string(),
+ ];
+ self.git_util
+ .run_commands(vec![command], url, Some(&path), false, None)?;
+
+ let pretty_version = target.get_pretty_version();
+ if let Some(new_ref) =
+ self.update_to_commit(target.clone(), &path, &r#ref, &pretty_version)?
+ {
+ if target.get_dist_reference() == target.get_source_reference() {
+ // TODO(phase-b): set_dist_reference requires &mut PackageInterface
+ // target.set_dist_reference(Some(new_ref.clone()));
+ }
+ // target.set_source_reference(Some(new_ref));
+ let _ = new_ref;
+ }
+
+ 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()],
+ &mut output,
+ Some(path.clone()),
+ ) == 0
+ {
+ let mut origin_match: IndexMap<CaptureKey, String> = IndexMap::new();
+ let mut composer_match: IndexMap<CaptureKey, String> = IndexMap::new();
+ if Preg::is_match3(
+ r"{^origin\s+(?P<url>\S+)}m",
+ &output,
+ Some(&mut origin_match),
+ )
+ .unwrap_or(false)
+ && Preg::is_match3(
+ r"{^composer\s+(?P<url>\S+)}m",
+ &output,
+ Some(&mut composer_match),
+ )
+ .unwrap_or(false)
+ {
+ let origin_url = origin_match
+ .get(&CaptureKey::ByName("url".to_string()))
+ .cloned()
+ .unwrap_or_default();
+ let composer_url = composer_match
+ .get(&CaptureKey::ByName("url".to_string()))
+ .cloned()
+ .unwrap_or_default();
+ if origin_url == composer_url
+ && Some(composer_url.as_str()) != target.get_source_url().as_deref()
+ {
+ update_origin_url = true;
+ }
+ }
+ }
+ if update_origin_url && target.get_source_url().is_some() {
+ self.update_origin_url(&path, &target.get_source_url().unwrap());
+ }
+
+ Ok(None)
+ }
+
+ async fn clean_changes(
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ update: bool,
+ ) -> Result<Option<PhpMixed>> {
+ GitUtil::clean_env(&self.inner.process);
+ 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()
+ || 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());
+ }
+ }
+
+ let changes = match self.get_local_changes(package.clone(), &path)? {
+ Some(c) => c,
+ None => return Ok(None),
+ };
+
+ if !self.inner.io.is_interactive() {
+ let discard_changes = self.inner.config.borrow_mut().get("discard-changes");
+ if discard_changes.as_bool() == Some(true) {
+ return self.discard_changes(&path).await;
+ }
+ if discard_changes.as_string() == Some("stash") {
+ if !update {
+ return self
+ .inner
+ .clean_changes(package.clone(), &path, update)
+ .await;
+ }
+
+ return self.stash_changes(&path).await;
+ }
+
+ return self.inner.clean_changes(package, &path, update).await;
+ }
+
+ let changes: Vec<String> = array_map(
+ |elem: &String| format!(" {}", elem),
+ &Preg::split(r"{\s*\r?\n\s*}", &changes)?,
+ );
+ self.inner.io.write_error3(
+ &format!(
+ " <error>{} has modified files:</error>",
+ package.get_pretty_name()
+ ),
+ true,
+ io_interface::NORMAL,
+ );
+ let slice_end = 10_usize.min(changes.len());
+ // TODO(phase-b): PHP passes the list directly to writeError; joined here so write_error3 takes &str
+ self.inner
+ .io
+ .write_error3(&changes[..slice_end].join("\n"), true, io_interface::NORMAL);
+ if (changes.len() as i64) > 10 {
+ self.inner.io.write_error3(
+ &format!(
+ " <info>{} more files modified, choose \"v\" to view the full list</info>",
+ changes.len() as i64 - 10
+ ),
+ true,
+ io_interface::NORMAL,
+ );
+ }
+
+ 'outer: loop {
+ let answer = self
+ .inner
+ .io
+ .ask(
+ format!(
+ " <info>Discard changes [y,n,v,{}?]?</info> ",
+ if update { "s," } else { "" }
+ ),
+ PhpMixed::String("?".to_string()),
+ )
+ .as_string()
+ .map(|s| s.to_string());
+ let mut do_help = false;
+ match answer.as_deref() {
+ Some("y") => {
+ self.discard_changes(&path).await?;
+ break 'outer;
+ }
+ Some("s") => {
+ if !update {
+ // goto help;
+ do_help = true;
+ } else {
+ self.stash_changes(&path).await?;
+ break 'outer;
+ }
+ }
+ Some("n") => {
+ return Err(RuntimeException {
+ message: "Update aborted".to_string(),
+ code: 0,
+ }
+ .into());
+ }
+ Some("v") => {
+ // TODO(phase-b): PHP passes list directly; joined here for &str arg
+ self.inner
+ .io
+ .write_error3(&changes.join("\n"), true, io_interface::NORMAL);
+ }
+ Some("d") => {
+ self.view_diff(&path);
+ }
+ _ => {
+ // case '?': default:
+ do_help = true;
+ }
+ }
+
+ if do_help {
+ // help:
+ // TODO(phase-b): PHP passes list directly; joined here for &str arg
+ self.inner.io.write_error3(
+ &[
+ format!(
+ " y - discard changes and apply the {}",
+ if update { "update" } else { "uninstall" }
+ ),
+ format!(
+ " n - abort the {} and let you manually clean things up",
+ if update { "update" } else { "uninstall" }
+ ),
+ " v - view modified files".to_string(),
+ " d - view local modifications (diff)".to_string(),
+ ]
+ .join("\n"),
+ true,
+ io_interface::NORMAL,
+ );
+ if update {
+ self.inner.io.write_error3(
+ " s - stash changes and try to reapply them after the update",
+ true,
+ io_interface::NORMAL,
+ );
+ }
+ self.inner
+ .io
+ .write_error3(" ? - print help", true, io_interface::NORMAL);
+ }
+ }
+
+ Ok(None)
+ }
+
+ fn reapply_changes(&mut self, path: &str) -> Result<()> {
+ let path = self.normalize_path(path);
+ if self
+ .has_stashed_changes
+ .get(&path)
+ .copied()
+ .unwrap_or(false)
+ {
+ self.has_stashed_changes.shift_remove(&path);
+ self.inner.io.write_error3(
+ " <info>Re-applying stashed changes</info>",
+ true,
+ io_interface::NORMAL,
+ );
+ let mut output = String::new();
+ if self.inner.process.borrow_mut().execute_args(
+ &vec!["git".to_string(), "stash".to_string(), "pop".to_string()],
+ &mut output,
+ Some(path.clone()),
+ ) != 0
+ {
+ return Err(RuntimeException {
+ message: format!(
+ "Failed to apply stashed changes:\n\n{}",
+ self.inner.process.borrow().get_error_output()
+ ),
+ code: 0,
+ }
+ .into());
+ }
+ }
+
+ self.has_discarded_changes.shift_remove(&path);
+ Ok(())
+ }
+
+ fn get_commit_logs(
+ &mut self,
+ from_reference: &str,
+ to_reference: &str,
+ path: &str,
+ ) -> Result<String> {
+ let path = self.normalize_path(path);
+ let mut args = vec![
+ "--format=%h - %an: %s".to_string(),
+ format!("{}..{}", from_reference, to_reference),
+ ];
+ args.extend(GitUtil::get_no_show_signature_flags(&self.inner.process));
+ let command = GitUtil::build_rev_list_command(&self.inner.process, args);
+
+ let mut output = String::new();
+ if self
+ .inner
+ .process
+ .borrow_mut()
+ .execute_args(&command, &mut output, Some(path.clone()))
+ != 0
+ {
+ return Err(RuntimeException {
+ message: format!(
+ "Failed to execute {}\n\n{}",
+ implode(" ", &command),
+ self.inner.process.borrow().get_error_output(),
+ ),
+ code: 0,
+ }
+ .into());
+ }
+
+ Ok(GitUtil::parse_rev_list_output(&output, &self.inner.process))
+ }
+
+ fn has_metadata_repository(&self, path: &str) -> bool {
+ let path = self.normalize_path(path);
+
+ is_dir(&format!("{}/.git", path))
+ }
+}
+
#[async_trait::async_trait(?Send)]
impl crate::downloader::DownloaderInterface for GitDownloader {
fn get_installation_source(&self) -> String {
- todo!()
+ <Self as VcsDownloader>::get_installation_source(self)
}
fn as_dvcs_downloader_interface(
@@ -1394,7 +1418,9 @@ impl crate::downloader::DownloaderInterface for GitDownloader {
Some(self)
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
@@ -1405,59 +1431,59 @@ impl crate::downloader::DownloaderInterface for GitDownloader {
}
async fn download(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
_output: bool,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::download(self, package, path, prev_package).await
}
async fn prepare(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::prepare(self, r#type, package, path, prev_package).await
}
async fn install(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::install(self, package, path).await
}
async fn update(
- &self,
- _initial: PackageInterfaceHandle,
- _target: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ initial: PackageInterfaceHandle,
+ target: PackageInterfaceHandle,
+ path: &str,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::update(self, initial, target, path).await
}
async fn remove(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::remove(self, package, path).await
}
async fn cleanup(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::cleanup(self, r#type, package, path, prev_package).await
}
}
diff --git a/crates/shirabe/src/downloader/gzip_downloader.rs b/crates/shirabe/src/downloader/gzip_downloader.rs
index 337e298..0c47b67 100644
--- a/crates/shirabe/src/downloader/gzip_downloader.rs
+++ b/crates/shirabe/src/downloader/gzip_downloader.rs
@@ -132,7 +132,7 @@ impl GzipDownloader {
impl ChangeReportInterface for GzipDownloader {
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -146,12 +146,14 @@ impl crate::downloader::DownloaderInterface for GzipDownloader {
self.inner.get_installation_source()
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -163,7 +165,7 @@ impl crate::downloader::DownloaderInterface for GzipDownloader {
}
async fn prepare(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -175,7 +177,7 @@ impl crate::downloader::DownloaderInterface for GzipDownloader {
}
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -184,7 +186,7 @@ impl crate::downloader::DownloaderInterface for GzipDownloader {
}
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
@@ -193,7 +195,7 @@ impl crate::downloader::DownloaderInterface for GzipDownloader {
}
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -202,7 +204,7 @@ impl crate::downloader::DownloaderInterface for GzipDownloader {
}
async fn cleanup(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
diff --git a/crates/shirabe/src/downloader/hg_downloader.rs b/crates/shirabe/src/downloader/hg_downloader.rs
index c5a65a0..a9a5bf8 100644
--- a/crates/shirabe/src/downloader/hg_downloader.rs
+++ b/crates/shirabe/src/downloader/hg_downloader.rs
@@ -4,6 +4,7 @@ use crate::config::Config;
use crate::downloader::ChangeReportInterface;
use crate::downloader::DownloaderInterface;
use crate::downloader::VcsCapableDownloaderInterface;
+use crate::downloader::VcsDownloader;
use crate::downloader::VcsDownloaderBase;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
@@ -12,6 +13,7 @@ use crate::util::Filesystem;
use crate::util::Hg as HgUtils;
use crate::util::ProcessExecutor;
use anyhow::Result;
+use indexmap::IndexMap;
use shirabe_php_shim::{PhpMixed, RuntimeException};
#[derive(Debug)]
@@ -30,13 +32,39 @@ impl HgDownloader {
inner: VcsDownloaderBase::new(io, config, Some(process), Some(fs)),
}
}
+}
- pub(crate) async fn do_download(
- &self,
- package: PackageInterfaceHandle,
- path: String,
- url: String,
- prev_package: Option<PackageInterfaceHandle>,
+impl VcsDownloader for HgDownloader {
+ fn io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
+ self.inner.io.clone()
+ }
+
+ fn config(&self) -> &std::rc::Rc<std::cell::RefCell<Config>> {
+ &self.inner.config
+ }
+
+ fn process(&self) -> &std::rc::Rc<std::cell::RefCell<ProcessExecutor>> {
+ &self.inner.process
+ }
+
+ fn filesystem(&self) -> &std::rc::Rc<std::cell::RefCell<Filesystem>> {
+ &self.inner.filesystem
+ }
+
+ fn has_cleaned_changes(&self) -> &IndexMap<String, bool> {
+ &self.inner.has_cleaned_changes
+ }
+
+ fn has_cleaned_changes_mut(&mut self) -> &mut IndexMap<String, bool> {
+ &mut self.inner.has_cleaned_changes
+ }
+
+ async fn do_download(
+ &mut self,
+ _package: PackageInterfaceHandle,
+ _path: &str,
+ _url: &str,
+ _prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
if HgUtils::get_version(&self.inner.process).is_none() {
return Err(RuntimeException {
@@ -49,11 +77,11 @@ impl HgDownloader {
Ok(None)
}
- pub(crate) async fn do_install(
- &self,
+ async fn do_install(
+ &mut self,
package: PackageInterfaceHandle,
- path: String,
- url: String,
+ path: &str,
+ url: &str,
) -> Result<Option<PhpMixed>> {
let hg_utils = HgUtils::new(
self.inner.io.clone(),
@@ -61,7 +89,7 @@ impl HgDownloader {
&self.inner.process,
);
- let path_clone = path.clone();
+ let path_clone = path.to_string();
let clone_command = move |url: String| -> Vec<String> {
vec![
"hg".to_string(),
@@ -71,7 +99,7 @@ impl HgDownloader {
path_clone.clone(),
]
};
- hg_utils.run_command(clone_command, url, Some(path.clone()));
+ hg_utils.run_command(clone_command, url.to_string(), Some(path.to_string()));
let command = vec![
"hg".to_string(),
@@ -86,7 +114,7 @@ impl HgDownloader {
if self.inner.process.borrow_mut().execute_args(
&command,
&mut ignored_output,
- shirabe_php_shim::realpath(&path),
+ shirabe_php_shim::realpath(path),
) != 0
{
return Err(RuntimeException {
@@ -103,12 +131,12 @@ impl HgDownloader {
Ok(None)
}
- pub(crate) async fn do_update(
- &self,
- initial: PackageInterfaceHandle,
+ async fn do_update(
+ &mut self,
+ _initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
- path: String,
- url: String,
+ path: &str,
+ url: &str,
) -> Result<Option<PhpMixed>> {
let hg_utils = HgUtils::new(
self.inner.io.clone(),
@@ -125,7 +153,7 @@ impl HgDownloader {
target.get_source_reference().unwrap_or_default()
));
- if !self.has_metadata_repository(path.clone()) {
+ if !self.has_metadata_repository(path) {
return Err(RuntimeException {
message: format!(
"The .hg directory is missing from {}, see https://getcomposer.org/commit-deps for more information",
@@ -138,7 +166,7 @@ impl HgDownloader {
let pull_command = |url: String| -> Vec<String> {
vec!["hg".to_string(), "pull".to_string(), "--".to_string(), url]
};
- hg_utils.run_command(pull_command, url.clone(), Some(path.clone()));
+ hg_utils.run_command(pull_command, url.to_string(), Some(path.to_string()));
let ref_clone = ref_.clone();
let up_command = move |_url: String| -> Vec<String> {
@@ -149,16 +177,16 @@ impl HgDownloader {
ref_clone.clone(),
]
};
- hg_utils.run_command(up_command, url, Some(path));
+ hg_utils.run_command(up_command, url.to_string(), Some(path.to_string()));
Ok(None)
}
- pub(crate) fn get_commit_logs(
- &self,
- from_reference: String,
- to_reference: String,
- path: String,
+ fn get_commit_logs(
+ &mut self,
+ from_reference: &str,
+ to_reference: &str,
+ path: &str,
) -> Result<String> {
let command = vec![
"hg".to_string(),
@@ -173,7 +201,7 @@ impl HgDownloader {
if self.inner.process.borrow_mut().execute_args(
&command,
&mut output,
- shirabe_php_shim::realpath(&path),
+ shirabe_php_shim::realpath(path),
) != 0
{
return Err(RuntimeException {
@@ -190,14 +218,14 @@ impl HgDownloader {
Ok(output)
}
- pub(crate) fn has_metadata_repository(&self, path: String) -> bool {
+ fn has_metadata_repository(&self, path: &str) -> bool {
std::path::Path::new(&format!("{}/.hg", path)).is_dir()
}
}
impl ChangeReportInterface for HgDownloader {
fn get_local_changes(
- &self,
+ &mut self,
_package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -228,12 +256,11 @@ impl VcsCapableDownloaderInterface for HgDownloader {
}
}
-// TODO(phase-b): wire up VcsDownloader trait properly. HgDownloader extends VcsDownloader which
-// implements DownloaderInterface in PHP. Delegating each trait method to todo!() until the inner
-// VcsDownloaderBase exposes the matching impl surface.
#[async_trait::async_trait(?Send)]
impl DownloaderInterface for HgDownloader {
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
@@ -244,63 +271,63 @@ impl DownloaderInterface for HgDownloader {
}
fn get_installation_source(&self) -> String {
- todo!()
+ <Self as VcsDownloader>::get_installation_source(self)
}
async fn download(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::download(self, package, path, prev_package).await
}
async fn prepare(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::prepare(self, r#type, package, path, prev_package).await
}
async fn install(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::install(self, package, path).await
}
async fn update(
- &self,
- _initial: PackageInterfaceHandle,
- _target: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ initial: PackageInterfaceHandle,
+ target: PackageInterfaceHandle,
+ path: &str,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::update(self, initial, target, path).await
}
async fn remove(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::remove(self, package, path).await
}
async fn cleanup(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::cleanup(self, r#type, package, path, prev_package).await
}
}
diff --git a/crates/shirabe/src/downloader/path_downloader.rs b/crates/shirabe/src/downloader/path_downloader.rs
index 3eb2a48..99d72e7 100644
--- a/crates/shirabe/src/downloader/path_downloader.rs
+++ b/crates/shirabe/src/downloader/path_downloader.rs
@@ -537,7 +537,7 @@ impl VcsCapableDownloaderInterface for PathDownloader {
impl crate::downloader::ChangeReportInterface for PathDownloader {
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> anyhow::Result<Option<String>> {
@@ -555,7 +555,9 @@ impl DownloaderInterface for PathDownloader {
self.inner.get_installation_source()
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
@@ -566,7 +568,7 @@ impl DownloaderInterface for PathDownloader {
}
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -578,7 +580,7 @@ impl DownloaderInterface for PathDownloader {
}
async fn prepare(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -590,7 +592,7 @@ impl DownloaderInterface for PathDownloader {
}
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -599,7 +601,7 @@ impl DownloaderInterface for PathDownloader {
}
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
@@ -608,7 +610,7 @@ impl DownloaderInterface for PathDownloader {
}
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -617,7 +619,7 @@ impl DownloaderInterface for PathDownloader {
}
async fn cleanup(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
diff --git a/crates/shirabe/src/downloader/perforce_downloader.rs b/crates/shirabe/src/downloader/perforce_downloader.rs
index e33b159..2d91c60 100644
--- a/crates/shirabe/src/downloader/perforce_downloader.rs
+++ b/crates/shirabe/src/downloader/perforce_downloader.rs
@@ -4,6 +4,7 @@ use crate::config::Config;
use crate::downloader::ChangeReportInterface;
use crate::downloader::DownloaderInterface;
use crate::downloader::VcsCapableDownloaderInterface;
+use crate::downloader::VcsDownloader;
use crate::downloader::VcsDownloaderBase;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
@@ -37,46 +38,6 @@ impl PerforceDownloader {
}
}
- pub(crate) async fn do_download(
- &self,
- _package: PackageInterfaceHandle,
- _path: String,
- _url: String,
- _prev_package: Option<PackageInterfaceHandle>,
- ) -> Result<Option<PhpMixed>> {
- Ok(None)
- }
-
- pub async fn do_install(
- &mut self,
- package: PackageInterfaceHandle,
- path: String,
- url: String,
- ) -> Result<Option<PhpMixed>> {
- let source_ref = package.get_source_reference().map(|s| s.to_string());
- let label = self.get_label_from_source_reference(source_ref.clone().unwrap_or_default());
-
- self.inner.io.write_error(&format!(
- "Cloning {}",
- source_ref.clone().unwrap_or_default()
- ));
- self.init_perforce(package, path.clone(), url);
- self.perforce
- .as_mut()
- .unwrap()
- .set_stream(&source_ref.clone().unwrap_or_default());
- self.perforce.as_mut().unwrap().p4_login();
- self.perforce.as_mut().unwrap().write_p4_client_spec();
- self.perforce.as_mut().unwrap().connect_client();
- self.perforce
- .as_mut()
- .unwrap()
- .sync_code_base(label.as_deref());
- self.perforce.as_mut().unwrap().cleanup_client_spec();
-
- Ok(None)
- }
-
fn get_label_from_source_reference(&self, source_ref: String) -> Option<String> {
let pos = source_ref.find('@');
if let Some(pos) = pos {
@@ -116,42 +77,108 @@ impl PerforceDownloader {
repository.get_repo_config().clone()
}
- pub(crate) async fn do_update(
+ pub fn set_perforce(&mut self, perforce: Perforce) {
+ self.perforce = Some(perforce);
+ }
+}
+
+impl VcsDownloader for PerforceDownloader {
+ fn io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
+ self.inner.io.clone()
+ }
+
+ fn config(&self) -> &std::rc::Rc<std::cell::RefCell<Config>> {
+ &self.inner.config
+ }
+
+ fn process(&self) -> &std::rc::Rc<std::cell::RefCell<ProcessExecutor>> {
+ &self.inner.process
+ }
+
+ fn filesystem(&self) -> &std::rc::Rc<std::cell::RefCell<Filesystem>> {
+ &self.inner.filesystem
+ }
+
+ fn has_cleaned_changes(&self) -> &IndexMap<String, bool> {
+ &self.inner.has_cleaned_changes
+ }
+
+ fn has_cleaned_changes_mut(&mut self) -> &mut IndexMap<String, bool> {
+ &mut self.inner.has_cleaned_changes
+ }
+
+ async fn do_download(
+ &mut self,
+ _package: PackageInterfaceHandle,
+ _path: &str,
+ _url: &str,
+ _prev_package: Option<PackageInterfaceHandle>,
+ ) -> Result<Option<PhpMixed>> {
+ Ok(None)
+ }
+
+ async fn do_install(
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ url: &str,
+ ) -> Result<Option<PhpMixed>> {
+ let source_ref = package.get_source_reference().map(|s| s.to_string());
+ let label = self.get_label_from_source_reference(source_ref.clone().unwrap_or_default());
+
+ self.inner.io.write_error(&format!(
+ "Cloning {}",
+ source_ref.clone().unwrap_or_default()
+ ));
+ self.init_perforce(package, path.to_string(), url.to_string());
+ self.perforce
+ .as_mut()
+ .unwrap()
+ .set_stream(&source_ref.clone().unwrap_or_default());
+ self.perforce.as_mut().unwrap().p4_login();
+ self.perforce.as_mut().unwrap().write_p4_client_spec();
+ self.perforce.as_mut().unwrap().connect_client();
+ self.perforce
+ .as_mut()
+ .unwrap()
+ .sync_code_base(label.as_deref());
+ self.perforce.as_mut().unwrap().cleanup_client_spec();
+
+ Ok(None)
+ }
+
+ async fn do_update(
&mut self,
_initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
- path: String,
- url: String,
+ path: &str,
+ url: &str,
) -> Result<Option<PhpMixed>> {
self.do_install(target, path, url).await
}
- pub(crate) fn get_commit_logs(
+ fn get_commit_logs(
&mut self,
- from_reference: String,
- to_reference: String,
- _path: String,
+ from_reference: &str,
+ to_reference: &str,
+ _path: &str,
) -> Result<String> {
Ok(self
.perforce
.as_mut()
.unwrap()
- .get_commit_logs(&from_reference, &to_reference)
+ .get_commit_logs(from_reference, to_reference)
.unwrap_or_default())
}
- pub fn set_perforce(&mut self, perforce: Perforce) {
- self.perforce = Some(perforce);
- }
-
- pub(crate) fn has_metadata_repository(&self, _path: &str) -> bool {
+ fn has_metadata_repository(&self, _path: &str) -> bool {
true
}
}
impl ChangeReportInterface for PerforceDownloader {
fn get_local_changes(
- &self,
+ &mut self,
_package: PackageInterfaceHandle,
_path: &str,
) -> Result<Option<String>> {
@@ -169,12 +196,11 @@ impl VcsCapableDownloaderInterface for PerforceDownloader {
}
}
-// TODO(phase-b): wire up VcsDownloader trait properly. PerforceDownloader extends VcsDownloader
-// which implements DownloaderInterface in PHP. Delegating each trait method to todo!() until the
-// inner VcsDownloaderBase exposes the matching impl surface.
#[async_trait::async_trait(?Send)]
impl DownloaderInterface for PerforceDownloader {
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
@@ -185,63 +211,63 @@ impl DownloaderInterface for PerforceDownloader {
}
fn get_installation_source(&self) -> String {
- todo!()
+ <Self as VcsDownloader>::get_installation_source(self)
}
async fn download(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::download(self, package, path, prev_package).await
}
async fn prepare(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::prepare(self, r#type, package, path, prev_package).await
}
async fn install(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::install(self, package, path).await
}
async fn update(
- &self,
- _initial: PackageInterfaceHandle,
- _target: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ initial: PackageInterfaceHandle,
+ target: PackageInterfaceHandle,
+ path: &str,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::update(self, initial, target, path).await
}
async fn remove(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::remove(self, package, path).await
}
async fn cleanup(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::cleanup(self, r#type, package, path, prev_package).await
}
}
diff --git a/crates/shirabe/src/downloader/phar_downloader.rs b/crates/shirabe/src/downloader/phar_downloader.rs
index 46fdd84..8180764 100644
--- a/crates/shirabe/src/downloader/phar_downloader.rs
+++ b/crates/shirabe/src/downloader/phar_downloader.rs
@@ -66,7 +66,7 @@ impl PharDownloader {
impl ChangeReportInterface for PharDownloader {
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -80,12 +80,14 @@ impl DownloaderInterface for PharDownloader {
self.inner.get_installation_source()
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -97,7 +99,7 @@ impl DownloaderInterface for PharDownloader {
}
async fn prepare(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -109,7 +111,7 @@ impl DownloaderInterface for PharDownloader {
}
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -118,7 +120,7 @@ impl DownloaderInterface for PharDownloader {
}
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
@@ -127,7 +129,7 @@ impl DownloaderInterface for PharDownloader {
}
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -136,7 +138,7 @@ impl DownloaderInterface for PharDownloader {
}
async fn cleanup(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
diff --git a/crates/shirabe/src/downloader/rar_downloader.rs b/crates/shirabe/src/downloader/rar_downloader.rs
index 4385bc3..5676a96 100644
--- a/crates/shirabe/src/downloader/rar_downloader.rs
+++ b/crates/shirabe/src/downloader/rar_downloader.rs
@@ -146,7 +146,7 @@ impl RarDownloader {
impl ChangeReportInterface for RarDownloader {
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -160,12 +160,14 @@ impl crate::downloader::DownloaderInterface for RarDownloader {
self.inner.get_installation_source()
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -177,7 +179,7 @@ impl crate::downloader::DownloaderInterface for RarDownloader {
}
async fn prepare(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -189,7 +191,7 @@ impl crate::downloader::DownloaderInterface for RarDownloader {
}
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -198,7 +200,7 @@ impl crate::downloader::DownloaderInterface for RarDownloader {
}
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
@@ -207,7 +209,7 @@ impl crate::downloader::DownloaderInterface for RarDownloader {
}
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -216,7 +218,7 @@ impl crate::downloader::DownloaderInterface for RarDownloader {
}
async fn cleanup(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
diff --git a/crates/shirabe/src/downloader/svn_downloader.rs b/crates/shirabe/src/downloader/svn_downloader.rs
index 1e00c03..ef0fd16 100644
--- a/crates/shirabe/src/downloader/svn_downloader.rs
+++ b/crates/shirabe/src/downloader/svn_downloader.rs
@@ -9,6 +9,7 @@ use crate::config::Config;
use crate::downloader::ChangeReportInterface;
use crate::downloader::DownloaderInterface;
use crate::downloader::VcsCapableDownloaderInterface;
+use crate::downloader::VcsDownloader;
use crate::downloader::VcsDownloaderBase;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
@@ -37,12 +38,85 @@ impl SvnDownloader {
}
}
- pub(crate) async fn do_download(
- &mut self,
+ pub(crate) fn execute(
+ &self,
package: PackageInterfaceHandle,
- path: &str,
+ base_url: &str,
+ command: Vec<String>,
url: &str,
- prev_package: Option<PackageInterfaceHandle>,
+ cwd: Option<&str>,
+ path: Option<&str>,
+ ) -> anyhow::Result<String> {
+ let mut util = SvnUtil::new(
+ base_url.to_string(),
+ self.inner.io.clone(),
+ self.inner.config.clone(),
+ Some(self.inner.process.clone()),
+ );
+ util.set_cache_credentials(self.cache_credentials);
+ util.execute(command, url, cwd, path, self.inner.io.is_verbose())
+ .map_err(|e| {
+ anyhow::anyhow!(
+ "{} could not be downloaded, {}",
+ package.get_pretty_name(),
+ e
+ )
+ })
+ }
+
+ 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(),
+ &mut output,
+ Some(path.to_string()),
+ ) != 0
+ {
+ return Err(RuntimeException {
+ message: format!(
+ "Could not reset changes\n\n:{}",
+ self.inner.process.borrow().get_error_output()
+ ),
+ code: 0,
+ }
+ .into());
+ }
+
+ Ok(None)
+ }
+}
+
+impl VcsDownloader for SvnDownloader {
+ fn io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
+ self.inner.io.clone()
+ }
+
+ fn config(&self) -> &std::rc::Rc<std::cell::RefCell<Config>> {
+ &self.inner.config
+ }
+
+ fn process(&self) -> &std::rc::Rc<std::cell::RefCell<ProcessExecutor>> {
+ &self.inner.process
+ }
+
+ fn filesystem(&self) -> &std::rc::Rc<std::cell::RefCell<Filesystem>> {
+ &self.inner.filesystem
+ }
+
+ fn has_cleaned_changes(&self) -> &IndexMap<String, bool> {
+ &self.inner.has_cleaned_changes
+ }
+
+ fn has_cleaned_changes_mut(&mut self) -> &mut IndexMap<String, bool> {
+ &mut self.inner.has_cleaned_changes
+ }
+
+ async fn do_download(
+ &mut self,
+ _package: PackageInterfaceHandle,
+ _path: &str,
+ url: &str,
+ _prev_package: Option<PackageInterfaceHandle>,
) -> anyhow::Result<Option<PhpMixed>> {
SvnUtil::clean_env();
let mut util = SvnUtil::new(
@@ -62,7 +136,7 @@ impl SvnDownloader {
Ok(None)
}
- pub(crate) async fn do_install(
+ async fn do_install(
&mut self,
package: PackageInterfaceHandle,
path: &str,
@@ -109,9 +183,9 @@ impl SvnDownloader {
Ok(None)
}
- pub(crate) async fn do_update(
+ async fn do_update(
&mut self,
- initial: PackageInterfaceHandle,
+ _initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
url: &str,
@@ -160,33 +234,7 @@ impl SvnDownloader {
Ok(None)
}
- pub(crate) fn execute(
- &self,
- package: PackageInterfaceHandle,
- base_url: &str,
- command: Vec<String>,
- url: &str,
- cwd: Option<&str>,
- path: Option<&str>,
- ) -> anyhow::Result<String> {
- let mut util = SvnUtil::new(
- base_url.to_string(),
- self.inner.io.clone(),
- self.inner.config.clone(),
- Some(self.inner.process.clone()),
- );
- util.set_cache_credentials(self.cache_credentials);
- util.execute(command, url, cwd, path, self.inner.io.is_verbose())
- .map_err(|e| {
- anyhow::anyhow!(
- "{} could not be downloaded, {}",
- package.get_pretty_name(),
- e
- )
- })
- }
-
- pub(crate) async fn clean_changes(
+ async fn clean_changes(
&mut self,
package: PackageInterfaceHandle,
path: &str,
@@ -294,8 +342,8 @@ impl SvnDownloader {
Ok(None)
}
- pub(crate) fn get_commit_logs(
- &self,
+ fn get_commit_logs(
+ &mut self,
from_reference: &str,
to_reference: &str,
path: &str,
@@ -384,35 +432,14 @@ 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(),
- &mut output,
- Some(path.to_string()),
- ) != 0
- {
- return Err(RuntimeException {
- message: format!(
- "Could not reset changes\n\n:{}",
- self.inner.process.borrow().get_error_output()
- ),
- code: 0,
- }
- .into());
- }
-
- Ok(None)
- }
-
- pub(crate) fn has_metadata_repository(&self, path: &str) -> bool {
+ fn has_metadata_repository(&self, path: &str) -> bool {
is_dir(&format!("{}/.svn", path))
}
}
impl ChangeReportInterface for SvnDownloader {
fn get_local_changes(
- &self,
+ &mut self,
_package: PackageInterfaceHandle,
path: &str,
) -> anyhow::Result<Option<String>> {
@@ -445,16 +472,15 @@ impl VcsCapableDownloaderInterface for SvnDownloader {
}
}
-// TODO(phase-b): wire up VcsDownloader trait properly. SvnDownloader extends VcsDownloader which
-// implements DownloaderInterface in PHP. Delegating each trait method to todo!() until the inner
-// VcsDownloaderBase exposes the matching impl surface.
#[async_trait::async_trait(?Send)]
impl DownloaderInterface for SvnDownloader {
fn get_installation_source(&self) -> String {
- todo!()
+ <Self as VcsDownloader>::get_installation_source(self)
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
@@ -465,59 +491,59 @@ impl DownloaderInterface for SvnDownloader {
}
async fn download(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
_output: bool,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::download(self, package, path, prev_package).await
}
async fn prepare(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::prepare(self, r#type, package, path, prev_package).await
}
async fn install(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::install(self, package, path).await
}
async fn update(
- &self,
- _initial: PackageInterfaceHandle,
- _target: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ initial: PackageInterfaceHandle,
+ target: PackageInterfaceHandle,
+ path: &str,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::update(self, initial, target, path).await
}
async fn remove(
- &self,
- _package: PackageInterfaceHandle,
- _path: &str,
+ &mut self,
+ package: PackageInterfaceHandle,
+ path: &str,
_output: bool,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::remove(self, package, path).await
}
async fn cleanup(
- &self,
- _type: &str,
- _package: PackageInterfaceHandle,
- _path: &str,
- _prev_package: Option<PackageInterfaceHandle>,
+ &mut self,
+ r#type: &str,
+ package: PackageInterfaceHandle,
+ path: &str,
+ prev_package: Option<PackageInterfaceHandle>,
) -> anyhow::Result<Option<PhpMixed>> {
- todo!()
+ <Self as VcsDownloader>::cleanup(self, r#type, package, path, prev_package).await
}
}
diff --git a/crates/shirabe/src/downloader/tar_downloader.rs b/crates/shirabe/src/downloader/tar_downloader.rs
index 6cf1176..8835e7d 100644
--- a/crates/shirabe/src/downloader/tar_downloader.rs
+++ b/crates/shirabe/src/downloader/tar_downloader.rs
@@ -61,7 +61,7 @@ impl TarDownloader {
impl ChangeReportInterface for TarDownloader {
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -75,12 +75,14 @@ impl DownloaderInterface for TarDownloader {
self.inner.get_installation_source()
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -92,7 +94,7 @@ impl DownloaderInterface for TarDownloader {
}
async fn prepare(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -104,7 +106,7 @@ impl DownloaderInterface for TarDownloader {
}
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -113,7 +115,7 @@ impl DownloaderInterface for TarDownloader {
}
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
@@ -122,7 +124,7 @@ impl DownloaderInterface for TarDownloader {
}
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -131,7 +133,7 @@ impl DownloaderInterface for TarDownloader {
}
async fn cleanup(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
diff --git a/crates/shirabe/src/downloader/vcs_downloader.rs b/crates/shirabe/src/downloader/vcs_downloader.rs
index 493440c..0637f08 100644
--- a/crates/shirabe/src/downloader/vcs_downloader.rs
+++ b/crates/shirabe/src/downloader/vcs_downloader.rs
@@ -93,13 +93,9 @@ pub trait VcsDownloader:
DownloaderInterface + ChangeReportInterface + VcsCapableDownloaderInterface
{
fn io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>>;
- fn io_mut(&mut self) -> &mut dyn IOInterface;
fn config(&self) -> &std::rc::Rc<std::cell::RefCell<Config>>;
- fn config_mut(&mut self) -> &mut std::rc::Rc<std::cell::RefCell<Config>>;
fn process(&self) -> &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>;
- fn process_mut(&mut self) -> &mut std::rc::Rc<std::cell::RefCell<ProcessExecutor>>;
fn filesystem(&self) -> &std::rc::Rc<std::cell::RefCell<Filesystem>>;
- fn filesystem_mut(&mut self) -> &mut std::rc::Rc<std::cell::RefCell<Filesystem>>;
fn has_cleaned_changes(&self) -> &IndexMap<String, bool>;
fn has_cleaned_changes_mut(&mut self) -> &mut IndexMap<String, bool>;
@@ -130,7 +126,12 @@ pub trait VcsDownloader:
) -> Result<Option<PhpMixed>>;
/// Fetches the commit logs between two commits
- fn get_commit_logs(&self, from_reference: &str, to_reference: &str, path: &str) -> String;
+ fn get_commit_logs(
+ &mut self,
+ from_reference: &str,
+ to_reference: &str,
+ path: &str,
+ ) -> Result<String>;
/// Checks if VCS metadata repository has been initialized
/// repository example: .git|.svn|.hg
@@ -174,7 +175,7 @@ pub trait VcsDownloader:
return Err(e);
}
if self.io().is_debug() {
- self.io_mut().write_error3(
+ self.io().write_error3(
&format!("Failed: [{}] {}", get_class_err(&e), e,),
true,
io_interface::NORMAL,
@@ -185,7 +186,7 @@ pub trait VcsDownloader:
.collect(),
)) > 0
{
- self.io_mut().write_error3(
+ self.io().write_error3(
" Failed, trying the next URL",
true,
io_interface::NORMAL,
@@ -219,9 +220,7 @@ pub trait VcsDownloader:
self.has_cleaned_changes_mut()
.insert(prev_package.unwrap().get_unique_name(), true);
} else if r#type == "install" {
- self.filesystem_mut()
- .borrow_mut()
- .empty_directory(path, true)?;
+ self.filesystem().borrow_mut().empty_directory(path, true)?;
} else if r#type == "uninstall" {
self.clean_changes(package, path, false).await?;
}
@@ -245,7 +244,7 @@ pub trait VcsDownloader:
})
.unwrap_or(false)
{
- self.reapply_changes(path);
+ self.reapply_changes(path)?;
self.has_cleaned_changes_mut()
.shift_remove(&prev_package.unwrap().get_unique_name());
}
@@ -269,7 +268,7 @@ pub trait VcsDownloader:
.into());
}
- self.io_mut().write_error3(
+ self.io().write_error3(
&format!(" - {}: ", InstallOperation::format(package.clone(), false)),
false,
io_interface::NORMAL,
@@ -290,7 +289,7 @@ pub trait VcsDownloader:
return Err(e);
}
if self.io().is_debug() {
- self.io_mut().write_error3(
+ self.io().write_error3(
&format!("Failed: [{}] {}", get_class_err(&e), e,),
true,
io_interface::NORMAL,
@@ -301,7 +300,7 @@ pub trait VcsDownloader:
.collect(),
)) > 0
{
- self.io_mut().write_error3(
+ self.io().write_error3(
" Failed, trying the next URL",
true,
io_interface::NORMAL,
@@ -339,7 +338,7 @@ pub trait VcsDownloader:
.into());
}
- self.io_mut().write_error3(
+ self.io().write_error3(
&format!(
" - {}: ",
UpdateOperation::format(initial.clone(), target.clone(), false),
@@ -369,7 +368,7 @@ pub trait VcsDownloader:
return Err(e);
}
if self.io().is_debug() {
- self.io_mut().write_error3(
+ self.io().write_error3(
&format!("Failed: [{}] {}", get_class_err(&e), e,),
true,
io_interface::NORMAL,
@@ -380,7 +379,7 @@ pub trait VcsDownloader:
.collect(),
)) > 0
{
- self.io_mut().write_error3(
+ self.io().write_error3(
" Failed, trying the next URL",
true,
io_interface::NORMAL,
@@ -397,11 +396,11 @@ pub trait VcsDownloader:
let initial_ref = initial.get_source_reference().unwrap_or_default();
let target_ref = target.get_source_reference().unwrap_or_default();
let mut message = "Pulling in changes:";
- let mut logs = self.get_commit_logs(&initial_ref, &target_ref, path);
+ let mut logs = self.get_commit_logs(&initial_ref, &target_ref, path)?;
if trim(&logs, None) == "" {
message = "Rolling back changes:";
- logs = self.get_commit_logs(&target_ref, &initial_ref, path);
+ logs = self.get_commit_logs(&target_ref, &initial_ref, path)?;
}
if trim(&logs, None) != "" {
@@ -414,10 +413,9 @@ pub trait VcsDownloader:
// escape angle brackets for proper output in the console
logs = str_replace("<", "\\<", &logs);
- self.io_mut()
+ self.io()
.write_error3(&format!(" {}", message), true, io_interface::NORMAL);
- self.io_mut()
- .write_error3(&logs, true, io_interface::NORMAL);
+ self.io().write_error3(&logs, true, io_interface::NORMAL);
}
}
@@ -435,14 +433,14 @@ pub trait VcsDownloader:
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<PhpMixed>> {
- self.io_mut().write_error3(
+ self.io().write_error3(
&format!(" - {}", UninstallOperation::format(package, false)),
true,
io_interface::NORMAL,
);
let result = self
- .filesystem_mut()
+ .filesystem()
.borrow_mut()
.remove_directory_async(path)
.await?;
@@ -481,7 +479,7 @@ pub trait VcsDownloader:
/// @param bool $update if true (update) the changes can be stashed and reapplied after an update,
/// if false (remove) the changes should be assumed to be lost if the operation is not aborted
async fn clean_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
_update: bool,
@@ -499,7 +497,9 @@ pub trait VcsDownloader:
}
/// Reapply previously stashed changes if applicable, only called after an update (regardless if successful or not)
- fn reapply_changes(&self, _path: &str) {}
+ fn reapply_changes(&mut self, _path: &str) -> Result<()> {
+ Ok(())
+ }
fn prepare_urls(&self, mut urls: Vec<String>) -> Vec<String> {
for index in 0..urls.len() {
diff --git a/crates/shirabe/src/downloader/xz_downloader.rs b/crates/shirabe/src/downloader/xz_downloader.rs
index 976497a..10a7edf 100644
--- a/crates/shirabe/src/downloader/xz_downloader.rs
+++ b/crates/shirabe/src/downloader/xz_downloader.rs
@@ -80,7 +80,7 @@ impl XzDownloader {
impl ChangeReportInterface for XzDownloader {
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -94,12 +94,14 @@ impl crate::downloader::DownloaderInterface for XzDownloader {
self.inner.get_installation_source()
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -111,7 +113,7 @@ impl crate::downloader::DownloaderInterface for XzDownloader {
}
async fn prepare(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -123,7 +125,7 @@ impl crate::downloader::DownloaderInterface for XzDownloader {
}
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -132,7 +134,7 @@ impl crate::downloader::DownloaderInterface for XzDownloader {
}
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
@@ -141,7 +143,7 @@ impl crate::downloader::DownloaderInterface for XzDownloader {
}
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -150,7 +152,7 @@ impl crate::downloader::DownloaderInterface for XzDownloader {
}
async fn cleanup(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
diff --git a/crates/shirabe/src/downloader/zip_downloader.rs b/crates/shirabe/src/downloader/zip_downloader.rs
index 3fda248..90772ce 100644
--- a/crates/shirabe/src/downloader/zip_downloader.rs
+++ b/crates/shirabe/src/downloader/zip_downloader.rs
@@ -556,7 +556,7 @@ impl ZipDownloader {
impl ChangeReportInterface for ZipDownloader {
fn get_local_changes(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
) -> Result<Option<String>> {
@@ -573,12 +573,14 @@ impl crate::downloader::DownloaderInterface for ZipDownloader {
self.inner.get_installation_source()
}
- fn as_change_report_interface(&self) -> Option<&dyn crate::downloader::ChangeReportInterface> {
+ fn as_change_report_interface(
+ &mut self,
+ ) -> Option<&mut dyn crate::downloader::ChangeReportInterface> {
Some(self)
}
async fn download(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
prev_package: Option<PackageInterfaceHandle>,
@@ -590,7 +592,7 @@ impl crate::downloader::DownloaderInterface for ZipDownloader {
}
async fn prepare(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
@@ -602,7 +604,7 @@ impl crate::downloader::DownloaderInterface for ZipDownloader {
}
async fn install(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -611,7 +613,7 @@ impl crate::downloader::DownloaderInterface for ZipDownloader {
}
async fn update(
- &self,
+ &mut self,
initial: PackageInterfaceHandle,
target: PackageInterfaceHandle,
path: &str,
@@ -620,7 +622,7 @@ impl crate::downloader::DownloaderInterface for ZipDownloader {
}
async fn remove(
- &self,
+ &mut self,
package: PackageInterfaceHandle,
path: &str,
output: bool,
@@ -629,7 +631,7 @@ impl crate::downloader::DownloaderInterface for ZipDownloader {
}
async fn cleanup(
- &self,
+ &mut self,
r#type: &str,
package: PackageInterfaceHandle,
path: &str,
diff --git a/crates/shirabe/src/factory.rs b/crates/shirabe/src/factory.rs
index 24ac2e0..90d8593 100644
--- a/crates/shirabe/src/factory.rs
+++ b/crates/shirabe/src/factory.rs
@@ -1011,52 +1011,52 @@ impl Factory {
dm.set_downloader(
"git",
- Box::new(GitDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(GitDownloader::new(
io.clone(),
config.clone(),
Some(process.clone()),
Some(fs.clone()),
- )),
+ ))),
);
dm.set_downloader(
"svn",
- Box::new(SvnDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(SvnDownloader::new(
io.clone(),
config.clone(),
process.clone(),
fs.clone(),
- )),
+ ))),
);
dm.set_downloader(
"fossil",
- Box::new(FossilDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(FossilDownloader::new(
io.clone(),
config.clone(),
process.clone(),
fs.clone(),
- )),
+ ))),
);
dm.set_downloader(
"hg",
- Box::new(HgDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(HgDownloader::new(
io.clone(),
config.clone(),
process.clone(),
fs.clone(),
- )),
+ ))),
);
dm.set_downloader(
"perforce",
- Box::new(PerforceDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(PerforceDownloader::new(
io.clone(),
config.clone(),
process.clone(),
fs.clone(),
- )),
+ ))),
);
dm.set_downloader(
"zip",
- Box::new(ZipDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(ZipDownloader::new(
io.clone(),
config.clone(),
http_downloader.clone(),
@@ -1064,11 +1064,11 @@ impl Factory {
cache.clone(),
fs.clone(),
process.clone(),
- )),
+ ))),
);
dm.set_downloader(
"rar",
- Box::new(RarDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(RarDownloader::new(
io.clone(),
config.clone(),
http_downloader.clone(),
@@ -1076,11 +1076,11 @@ impl Factory {
cache.clone(),
fs.clone(),
process.clone(),
- )),
+ ))),
);
dm.set_downloader(
"tar",
- Box::new(TarDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(TarDownloader::new(
io.clone(),
config.clone(),
http_downloader.clone(),
@@ -1088,11 +1088,11 @@ impl Factory {
cache.clone(),
fs.clone(),
process.clone(),
- )),
+ ))),
);
dm.set_downloader(
"gzip",
- Box::new(GzipDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(GzipDownloader::new(
io.clone(),
config.clone(),
http_downloader.clone(),
@@ -1100,11 +1100,11 @@ impl Factory {
cache.clone(),
fs.clone(),
process.clone(),
- )),
+ ))),
);
dm.set_downloader(
"xz",
- Box::new(XzDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(XzDownloader::new(
io.clone(),
config.clone(),
http_downloader.clone(),
@@ -1112,11 +1112,11 @@ impl Factory {
cache.clone(),
fs.clone(),
process.clone(),
- )),
+ ))),
);
dm.set_downloader(
"phar",
- Box::new(PharDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(PharDownloader::new(
io.clone(),
config.clone(),
http_downloader.clone(),
@@ -1124,11 +1124,11 @@ impl Factory {
cache.clone(),
fs.clone(),
process.clone(),
- )),
+ ))),
);
dm.set_downloader(
"file",
- Box::new(FileDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(FileDownloader::new(
io.clone(),
config.clone(),
http_downloader.clone(),
@@ -1136,11 +1136,11 @@ impl Factory {
cache.clone(),
Some(fs.clone()),
Some(process.clone()),
- )),
+ ))),
);
dm.set_downloader(
"path",
- Box::new(PathDownloader::new(
+ std::rc::Rc::new(std::cell::RefCell::new(PathDownloader::new(
io.clone(),
config.clone(),
http_downloader.clone(),
@@ -1148,7 +1148,7 @@ impl Factory {
cache.clone(),
fs.clone(),
process.clone(),
- )),
+ ))),
);
Ok(std::rc::Rc::new(std::cell::RefCell::new(dm)))
diff --git a/crates/shirabe/src/util/sync_helper.rs b/crates/shirabe/src/util/sync_helper.rs
index 4181b23..6220f5c 100644
--- a/crates/shirabe/src/util/sync_helper.rs
+++ b/crates/shirabe/src/util/sync_helper.rs
@@ -8,7 +8,7 @@ use anyhow::Result;
use shirabe_php_shim::PhpMixed;
pub enum DownloaderOrManager<'a> {
- Interface(&'a dyn DownloaderInterface),
+ Interface(&'a std::rc::Rc<std::cell::RefCell<dyn DownloaderInterface>>),
Manager(&'a std::rc::Rc<std::cell::RefCell<DownloadManager>>),
}
@@ -20,7 +20,7 @@ impl<'a> DownloaderOrManager<'a> {
prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
match self {
- Self::Interface(d) => d.download3(package, path, prev_package).await,
+ Self::Interface(d) => d.borrow_mut().download3(package, path, prev_package).await,
Self::Manager(d) => d.borrow().download(package, path, prev_package).await,
}
}
@@ -33,7 +33,11 @@ impl<'a> DownloaderOrManager<'a> {
prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
match self {
- Self::Interface(d) => d.prepare(r#type, package, path, prev_package).await,
+ Self::Interface(d) => {
+ d.borrow_mut()
+ .prepare(r#type, package, path, prev_package)
+ .await
+ }
Self::Manager(d) => {
d.borrow()
.prepare(r#type, package, path, prev_package)
@@ -48,7 +52,7 @@ impl<'a> DownloaderOrManager<'a> {
path: &str,
) -> Result<Option<PhpMixed>> {
match self {
- Self::Interface(d) => d.install2(package, path).await,
+ Self::Interface(d) => d.borrow_mut().install2(package, path).await,
Self::Manager(d) => d.borrow().install(package, path).await,
}
}
@@ -60,7 +64,7 @@ impl<'a> DownloaderOrManager<'a> {
path: &str,
) -> Result<Option<PhpMixed>> {
match self {
- Self::Interface(d) => d.update(package, prev_package, path).await,
+ Self::Interface(d) => d.borrow_mut().update(package, prev_package, path).await,
Self::Manager(d) => d.borrow().update(package, prev_package, path).await,
}
}
@@ -73,7 +77,11 @@ impl<'a> DownloaderOrManager<'a> {
prev_package: Option<PackageInterfaceHandle>,
) -> Result<Option<PhpMixed>> {
match self {
- Self::Interface(d) => d.cleanup(r#type, package, path, prev_package).await,
+ Self::Interface(d) => {
+ d.borrow_mut()
+ .cleanup(r#type, package, path, prev_package)
+ .await
+ }
Self::Manager(d) => {
d.borrow()
.cleanup(r#type, package, path, prev_package)