aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/downloader
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-17 11:52:08 +0900
committernsfisis <nsfisis@gmail.com>2026-05-17 11:52:20 +0900
commit93a7671c98a9f022d757781f8fe583a2d55df07b (patch)
tree66ad0cef7ac58823262280a6bf94961c1d73f92a /crates/shirabe/src/downloader
parent35690acf83fa4473311a18e970ecd8156e1e6ac0 (diff)
downloadphp-shirabe-93a7671c98a9f022d757781f8fe583a2d55df07b.tar.gz
php-shirabe-93a7671c98a9f022d757781f8fe583a2d55df07b.tar.zst
php-shirabe-93a7671c98a9f022d757781f8fe583a2d55df07b.zip
refactor(shirabe): convert PHP abstract classes to Rust traits
PHP abstract classes are represented as traits to better align with Rust's type system.
Diffstat (limited to 'crates/shirabe/src/downloader')
-rw-r--r--crates/shirabe/src/downloader/archive_downloader.rs118
-rw-r--r--crates/shirabe/src/downloader/vcs_downloader.rs313
2 files changed, 146 insertions, 285 deletions
diff --git a/crates/shirabe/src/downloader/archive_downloader.rs b/crates/shirabe/src/downloader/archive_downloader.rs
index 59704e3..03edffe 100644
--- a/crates/shirabe/src/downloader/archive_downloader.rs
+++ b/crates/shirabe/src/downloader/archive_downloader.rs
@@ -1,9 +1,5 @@
//! ref: composer/src/Composer/Downloader/ArchiveDownloader.php
-use crate::dependency_resolver::operation::install_operation::InstallOperation;
-use crate::downloader::file_downloader::FileDownloader;
-use crate::package::package_interface::PackageInterface;
-use crate::util::platform::Platform;
use anyhow::Result;
use indexmap::IndexMap;
use shirabe_external_packages::react::promise::promise_interface::PromiseInterface;
@@ -12,64 +8,84 @@ use shirabe_php_shim::{
DIRECTORY_SEPARATOR, RuntimeException, bin2hex, file_exists, is_dir, random_bytes, realpath,
};
-#[derive(Debug)]
-pub struct ArchiveDownloader {
- pub(crate) inner: FileDownloader,
- pub(crate) cleanup_executed: IndexMap<String, bool>,
-}
+use crate::dependency_resolver::operation::install_operation::InstallOperation;
+use crate::downloader::file_downloader::FileDownloader;
+use crate::package::package_interface::PackageInterface;
+use crate::util::platform::Platform;
+
+pub trait ArchiveDownloader {
+ fn inner(&self) -> &FileDownloader;
+ fn inner_mut(&mut self) -> &mut FileDownloader;
+ fn cleanup_executed(&self) -> &IndexMap<String, bool>;
+ fn cleanup_executed_mut(&mut self) -> &mut IndexMap<String, bool>;
+
+ fn extract(
+ &self,
+ package: &dyn PackageInterface,
+ file: &str,
+ path: &str,
+ ) -> Result<Box<dyn PromiseInterface>>;
-impl ArchiveDownloader {
- pub fn prepare(
+ fn prepare(
&mut self,
r#type: &str,
package: &dyn PackageInterface,
path: &str,
prev_package: Option<&dyn PackageInterface>,
) -> Result<Box<dyn PromiseInterface>> {
- self.cleanup_executed.remove(package.get_name());
-
- self.inner.prepare(r#type, package, path, prev_package)
+ self.cleanup_executed_mut().remove(package.get_name());
+ self.inner_mut()
+ .prepare(r#type, package, path, prev_package)
}
- pub fn cleanup(
+ fn cleanup(
&mut self,
r#type: &str,
package: &dyn PackageInterface,
path: &str,
prev_package: Option<&dyn PackageInterface>,
) -> Result<Box<dyn PromiseInterface>> {
- self.cleanup_executed
+ self.cleanup_executed_mut()
.insert(package.get_name().to_string(), true);
-
- self.inner.cleanup(r#type, package, path, prev_package)
+ self.inner_mut()
+ .cleanup(r#type, package, path, prev_package)
}
- pub fn install(
+ /// @inheritDoc
+ ///
+ /// @throws \RuntimeException
+ /// @throws \UnexpectedValueException
+ fn install(
&mut self,
package: &dyn PackageInterface,
path: &str,
output: bool,
) -> Result<Box<dyn PromiseInterface>> {
if output {
- self.inner.io.write_error(&format!(
+ self.inner().io.write_error(&format!(
" - {}{}",
InstallOperation::format(package, false),
self.get_install_operation_appendix(package, path)
));
}
- let vendor_dir = self.inner.config.get("vendor-dir");
+ let vendor_dir = self.inner().config.get("vendor-dir");
// clean up the target directory, unless it contains the vendor dir, as the vendor dir contains
// the archive to be extracted. This is the case when installing with create-project in the current directory
// but in that case we ensure the directory is empty already in ProjectInstaller so no need to empty it here.
- if !self.inner.filesystem.normalize_path(&vendor_dir).contains(
- &self
- .inner
- .filesystem
- .normalize_path(&format!("{}{}", path, DIRECTORY_SEPARATOR)),
- ) {
- self.inner.filesystem.empty_directory(path);
+ if !self
+ .inner()
+ .filesystem
+ .normalize_path(&vendor_dir)
+ .contains(
+ &self
+ .inner()
+ .filesystem
+ .normalize_path(&format!("{}{}", path, DIRECTORY_SEPARATOR)),
+ )
+ {
+ self.inner_mut().filesystem.empty_directory(path);
}
let temporary_dir;
@@ -80,33 +96,34 @@ impl ArchiveDownloader {
}
}
- self.inner.add_cleanup_path(package, &temporary_dir);
+ self.inner_mut().add_cleanup_path(package, &temporary_dir);
// avoid cleaning up $path if installing in "." for eg create-project as we can not
// delete the directory we are currently in on windows
if !is_dir(path) || realpath(path) != Platform::get_cwd() {
- self.inner.add_cleanup_path(package, path);
+ self.inner_mut().add_cleanup_path(package, path);
}
- self.inner
+ self.inner_mut()
.filesystem
.ensure_directory_exists(&temporary_dir);
- let file_name = self.inner.get_file_name(package, path);
+ let file_name = self.inner().get_file_name(package, path);
- let filesystem = &self.inner.filesystem;
+ let filesystem = &self.inner().filesystem;
let cleanup = move || {
// remove cache if the file was corrupted
- self.inner.clear_last_cache_write(package);
+ self.inner_mut().clear_last_cache_write(package);
// clean up
filesystem.remove_directory(&temporary_dir);
if is_dir(path) && realpath(path) != Platform::get_cwd() {
filesystem.remove_directory(path);
}
- self.inner.remove_cleanup_path(package, &temporary_dir);
+ self.inner_mut()
+ .remove_cleanup_path(package, &temporary_dir);
let realpath_result = realpath(path);
if let Some(realpath_val) = realpath_result {
- self.inner.remove_cleanup_path(package, &realpath_val);
+ self.inner_mut().remove_cleanup_path(package, &realpath_val);
}
};
@@ -155,7 +172,10 @@ impl ArchiveDownloader {
code: 0,
}.into());
}
- rename_recursively.as_ref().unwrap()(&file, &format!("{}/{}", to, file_basename))?;
+ rename_recursively.as_ref().unwrap()(
+ &file,
+ &format!("{}/{}", to, file_basename),
+ )?;
} else {
filesystem.rename(&file, &format!("{}/{}", to, file_basename));
}
@@ -179,7 +199,9 @@ impl ArchiveDownloader {
}
let content_dir = get_folder_content(&temporary_dir);
- let single_dir_at_top_level = content_dir.len() == 1 && is_dir(&content_dir[0].to_string_lossy().to_string());
+ let single_dir_at_top_level =
+ content_dir.len() == 1
+ && is_dir(&content_dir[0].to_string_lossy().to_string());
if rename_as_one {
// if the target $path is clear, we can rename the whole package in one go instead of looping over the contents
@@ -204,8 +226,8 @@ impl ArchiveDownloader {
Ok(promise.then(
Box::new(move || -> Result<()> {
- self.inner.remove_cleanup_path(package, &temporary_dir);
- self.inner.remove_cleanup_path(package, path);
+ self.inner_mut().remove_cleanup_path(package, &temporary_dir);
+ self.inner_mut().remove_cleanup_path(package, path);
Ok(())
}),
None,
@@ -218,20 +240,8 @@ impl ArchiveDownloader {
))
}
- pub fn get_install_operation_appendix(
- &self,
- _package: &dyn PackageInterface,
- _path: &str,
- ) -> &str {
+ /// @inheritDoc
+ fn get_install_operation_appendix(&self, _package: &dyn PackageInterface, _path: &str) -> &str {
": Extracting archive"
}
-
- pub(crate) fn extract(
- &self,
- _package: &dyn PackageInterface,
- _file: &str,
- _path: &str,
- ) -> Result<Box<dyn PromiseInterface>> {
- todo!()
- }
}
diff --git a/crates/shirabe/src/downloader/vcs_downloader.rs b/crates/shirabe/src/downloader/vcs_downloader.rs
index 37954d2..b76c242 100644
--- a/crates/shirabe/src/downloader/vcs_downloader.rs
+++ b/crates/shirabe/src/downloader/vcs_downloader.rs
@@ -23,40 +23,58 @@ use crate::package::version::version_parser::VersionParser;
use crate::util::filesystem::Filesystem;
use crate::util::process_executor::ProcessExecutor;
-#[derive(Debug)]
-pub struct VcsDownloader {
- pub(crate) io: Box<dyn IOInterface>,
- pub(crate) config: Config,
- pub(crate) process: ProcessExecutor,
- pub(crate) filesystem: Filesystem,
- /// @var array<string, true>
- pub(crate) has_cleaned_changes: IndexMap<String, bool>,
-}
+pub trait VcsDownloader:
+ DownloaderInterface + ChangeReportInterface + VcsCapableDownloaderInterface
+{
+ fn io(&self) -> &dyn IOInterface;
+ fn io_mut(&mut self) -> &mut dyn IOInterface;
+ fn config(&self) -> &Config;
+ fn config_mut(&mut self) -> &mut Config;
+ fn process(&self) -> &ProcessExecutor;
+ fn process_mut(&mut self) -> &mut ProcessExecutor;
+ fn filesystem(&self) -> &Filesystem;
+ fn filesystem_mut(&mut self) -> &mut Filesystem;
+ fn has_cleaned_changes(&self) -> &IndexMap<String, bool>;
+ fn has_cleaned_changes_mut(&mut self) -> &mut IndexMap<String, bool>;
-impl VcsDownloader {
- pub fn new(
- io: Box<dyn IOInterface>,
- config: Config,
- process: Option<ProcessExecutor>,
- fs: Option<Filesystem>,
- ) -> Self {
- // TODO(phase-b): ProcessExecutor::new takes &dyn IOInterface; Filesystem::new takes ProcessExecutor
- let process = process.unwrap_or_else(|| ProcessExecutor::new(&*io));
- let filesystem = fs.unwrap_or_else(|| Filesystem::new(&process));
- Self {
- io,
- config,
- process,
- filesystem,
- has_cleaned_changes: IndexMap::new(),
- }
- }
+ /// Downloads data needed to run an install/update later
+ fn do_download(
+ &mut self,
+ package: &dyn PackageInterface,
+ path: &str,
+ url: &str,
+ prev_package: Option<&dyn PackageInterface>,
+ ) -> Result<Box<dyn PromiseInterface>>;
+
+ /// Downloads specific package into specific folder.
+ fn do_install(
+ &mut self,
+ package: &dyn PackageInterface,
+ path: &str,
+ url: &str,
+ ) -> Result<Box<dyn PromiseInterface>>;
+
+ /// Updates specific package in specific folder from initial to target version.
+ fn do_update(
+ &mut self,
+ initial: &dyn PackageInterface,
+ target: &dyn PackageInterface,
+ path: &str,
+ url: &str,
+ ) -> Result<Box<dyn PromiseInterface>>;
+
+ /// Fetches the commit logs between two commits
+ fn get_commit_logs(&self, from_reference: &str, to_reference: &str, path: &str) -> String;
- pub fn get_installation_source(&self) -> String {
+ /// Checks if VCS metadata repository has been initialized
+ /// repository example: .git|.svn|.hg
+ fn has_metadata_repository(&self, path: &str) -> bool;
+
+ fn get_installation_source(&self) -> String {
"source".to_string()
}
- pub fn download(
+ fn download(
&mut self,
package: &dyn PackageInterface,
path: &str,
@@ -88,8 +106,8 @@ impl VcsDownloader {
if is_phpunit_exception {
return Err(e);
}
- if self.io.is_debug() {
- self.io.write_error(
+ if self.io().is_debug() {
+ self.io_mut().write_error(
PhpMixed::String(format!("Failed: [{}] {}", get_class(&e), e,)),
true,
IOInterface::NORMAL,
@@ -100,7 +118,7 @@ impl VcsDownloader {
.collect(),
)) > 0
{
- self.io.write_error(
+ self.io_mut().write_error(
PhpMixed::String(" Failed, trying the next URL".to_string()),
true,
IOInterface::NORMAL,
@@ -121,7 +139,7 @@ impl VcsDownloader {
Ok(shirabe_external_packages::react::promise::resolve(None))
}
- pub fn prepare(
+ fn prepare(
&mut self,
r#type: &str,
package: &dyn PackageInterface,
@@ -130,10 +148,10 @@ impl VcsDownloader {
) -> Result<Box<dyn PromiseInterface>> {
if r#type == "update" {
self.clean_changes(prev_package.unwrap(), path, true)?;
- self.has_cleaned_changes
+ self.has_cleaned_changes_mut()
.insert(prev_package.unwrap().get_unique_name(), true);
} else if r#type == "install" {
- self.filesystem.empty_directory(path);
+ self.filesystem_mut().empty_directory(path);
} else if r#type == "uninstall" {
self.clean_changes(package, path, false)?;
}
@@ -141,7 +159,7 @@ impl VcsDownloader {
Ok(shirabe_external_packages::react::promise::resolve(None))
}
- pub fn cleanup(
+ fn cleanup(
&mut self,
r#type: &str,
_package: &dyn PackageInterface,
@@ -150,18 +168,21 @@ impl VcsDownloader {
) -> Result<Box<dyn PromiseInterface>> {
if r#type == "update"
&& prev_package
- .map(|p| self.has_cleaned_changes.contains_key(&p.get_unique_name()))
+ .map(|p| {
+ self.has_cleaned_changes()
+ .contains_key(&p.get_unique_name())
+ })
.unwrap_or(false)
{
self.reapply_changes(path);
- self.has_cleaned_changes
+ self.has_cleaned_changes_mut()
.shift_remove(&prev_package.unwrap().get_unique_name());
}
Ok(shirabe_external_packages::react::promise::resolve(None))
}
- pub fn install(
+ fn install(
&mut self,
package: &dyn PackageInterface,
path: &str,
@@ -177,7 +198,7 @@ impl VcsDownloader {
.into());
}
- self.io.write_error(
+ self.io_mut().write_error(
PhpMixed::String(format!(
" - {}: ",
InstallOperation::format(package, false)
@@ -199,8 +220,8 @@ impl VcsDownloader {
if is_phpunit_exception {
return Err(e);
}
- if self.io.is_debug() {
- self.io.write_error(
+ if self.io().is_debug() {
+ self.io_mut().write_error(
PhpMixed::String(format!("Failed: [{}] {}", get_class(&e), e,)),
true,
IOInterface::NORMAL,
@@ -211,7 +232,7 @@ impl VcsDownloader {
.collect(),
)) > 0
{
- self.io.write_error(
+ self.io_mut().write_error(
PhpMixed::String(" Failed, trying the next URL".to_string()),
true,
IOInterface::NORMAL,
@@ -232,7 +253,7 @@ impl VcsDownloader {
Ok(shirabe_external_packages::react::promise::resolve(None))
}
- pub fn update(
+ fn update(
&mut self,
initial: &dyn PackageInterface,
target: &dyn PackageInterface,
@@ -249,7 +270,7 @@ impl VcsDownloader {
.into());
}
- self.io.write_error(
+ self.io_mut().write_error(
PhpMixed::String(format!(
" - {}: ",
UpdateOperation::format(initial, target, false),
@@ -277,8 +298,8 @@ impl VcsDownloader {
if is_phpunit_exception {
return Err(e);
}
- if self.io.is_debug() {
- self.io.write_error(
+ if self.io().is_debug() {
+ self.io_mut().write_error(
PhpMixed::String(format!("Failed: [{}] {}", get_class(&e), e,)),
true,
IOInterface::NORMAL,
@@ -289,7 +310,7 @@ impl VcsDownloader {
.collect(),
)) > 0
{
- self.io.write_error(
+ self.io_mut().write_error(
PhpMixed::String(" Failed, trying the next URL".to_string()),
true,
IOInterface::NORMAL,
@@ -302,7 +323,7 @@ impl VcsDownloader {
// print the commit logs if in verbose mode and VCS metadata is present
// because in case of missing metadata code would trigger another exception
- if exception.is_none() && self.io.is_verbose() && self.has_metadata_repository(path) {
+ if exception.is_none() && self.io().is_verbose() && self.has_metadata_repository(path) {
let mut message = "Pulling in changes:";
let mut logs = self.get_commit_logs(
initial.get_source_reference().unwrap_or(""),
@@ -329,12 +350,12 @@ impl VcsDownloader {
// escape angle brackets for proper output in the console
logs = str_replace("<", "\\<", &logs);
- self.io.write_error(
+ self.io_mut().write_error(
PhpMixed::String(format!(" {}", message)),
true,
IOInterface::NORMAL,
);
- self.io
+ self.io_mut()
.write_error(PhpMixed::String(logs), true, IOInterface::NORMAL);
}
}
@@ -348,12 +369,12 @@ impl VcsDownloader {
Ok(shirabe_external_packages::react::promise::resolve(None))
}
- pub fn remove(
+ fn remove(
&mut self,
package: &dyn PackageInterface,
path: &str,
) -> Result<Box<dyn PromiseInterface>> {
- self.io.write_error(
+ self.io_mut().write_error(
PhpMixed::String(format!(
" - {}",
UninstallOperation::format(package, false)
@@ -362,7 +383,7 @@ impl VcsDownloader {
IOInterface::NORMAL,
);
- let promise = self.filesystem.remove_directory_async(path);
+ let promise = self.filesystem_mut().remove_directory_async(path);
let path = path.to_string();
Ok(
@@ -380,9 +401,9 @@ impl VcsDownloader {
)
}
- pub fn get_vcs_reference(&self, package: &dyn PackageInterface, path: &str) -> Option<String> {
+ fn get_vcs_reference(&self, package: &dyn PackageInterface, path: &str) -> Option<String> {
let parser = VersionParser::new();
- let guesser = VersionGuesser::new(&self.config, &self.process, &parser, &*self.io);
+ let guesser = VersionGuesser::new(self.config(), self.process(), &parser, self.io());
let dumper = ArrayDumper::new();
let package_config = dumper.dump(package);
@@ -398,12 +419,9 @@ impl VcsDownloader {
/// Prompt the user to check if changes should be stashed/removed or the operation aborted
///
- /// @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
- ///
- /// @throws \RuntimeException in case the operation must be aborted
- /// @phpstan-return PromiseInterface<void|null>
- pub(crate) fn clean_changes(
+ /// @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
+ fn clean_changes(
&self,
package: &dyn PackageInterface,
path: &str,
@@ -421,90 +439,10 @@ impl VcsDownloader {
Ok(shirabe_external_packages::react::promise::resolve(None))
}
- /// Reapply previously stashes changes if applicable, only called after an update (regardless if successful or not)
- ///
- /// @throws \RuntimeException in case the operation must be aborted or the patch does not apply cleanly
- pub(crate) fn reapply_changes(&self, _path: &str) {}
-
- /// Downloads data needed to run an install/update later
- ///
- /// @param PackageInterface $package package instance
- /// @param string $path download path
- /// @param string $url package url
- /// @param PackageInterface|null $prevPackage previous package (in case of an update)
- /// @phpstan-return PromiseInterface<void|null>
- // TODO(phase-b): abstract; overridden by concrete subclasses (GitDownloader, SvnDownloader, ...)
- pub(crate) fn do_download(
- &mut self,
- _package: &dyn PackageInterface,
- _path: &str,
- _url: &str,
- _prev_package: Option<&dyn PackageInterface>,
- ) -> Result<Box<dyn PromiseInterface>> {
- todo!("abstract: implemented by subclass")
- }
-
- /// Downloads specific package into specific folder.
- ///
- /// @param PackageInterface $package package instance
- /// @param string $path download path
- /// @param string $url package url
- /// @phpstan-return PromiseInterface<void|null>
- // TODO(phase-b): abstract; overridden by concrete subclasses
- pub(crate) fn do_install(
- &mut self,
- _package: &dyn PackageInterface,
- _path: &str,
- _url: &str,
- ) -> Result<Box<dyn PromiseInterface>> {
- todo!("abstract: implemented by subclass")
- }
-
- /// Updates specific package in specific folder from initial to target version.
- ///
- /// @param PackageInterface $initial initial package
- /// @param PackageInterface $target updated package
- /// @param string $path download path
- /// @param string $url package url
- /// @phpstan-return PromiseInterface<void|null>
- // TODO(phase-b): abstract; overridden by concrete subclasses
- pub(crate) fn do_update(
- &mut self,
- _initial: &dyn PackageInterface,
- _target: &dyn PackageInterface,
- _path: &str,
- _url: &str,
- ) -> Result<Box<dyn PromiseInterface>> {
- todo!("abstract: implemented by subclass")
- }
-
- /// Fetches the commit logs between two commits
- ///
- /// @param string $fromReference the source reference
- /// @param string $toReference the target reference
- /// @param string $path the package path
- // TODO(phase-b): abstract; overridden by concrete subclasses
- pub(crate) fn get_commit_logs(
- &self,
- _from_reference: &str,
- _to_reference: &str,
- _path: &str,
- ) -> String {
- todo!("abstract: implemented by subclass")
- }
-
- /// Checks if VCS metadata repository has been initialized
- /// repository example: .git|.svn|.hg
- // TODO(phase-b): abstract; overridden by concrete subclasses
- pub(crate) fn has_metadata_repository(&self, _path: &str) -> bool {
- todo!("abstract: implemented by subclass")
- }
+ /// Reapply previously stashed changes if applicable, only called after an update (regardless if successful or not)
+ fn reapply_changes(&self, _path: &str) {}
- /// @param string[] $urls
- ///
- /// @return string[]
fn prepare_urls(&self, mut urls: Vec<String>) -> Vec<String> {
- // PHP: foreach ($urls as $index => $url) — mutates in place
for index in 0..urls.len() {
let mut url = urls[index].clone();
if Filesystem::is_local_path(&url) {
@@ -532,91 +470,4 @@ impl VcsDownloader {
urls
}
-
- // TODO(phase-b): get_local_changes belongs to ChangeReportInterface, implemented by subclasses
- pub(crate) fn get_local_changes(
- &self,
- _package: &dyn PackageInterface,
- _path: String,
- ) -> Option<String> {
- todo!("abstract: implemented by ChangeReportInterface subclasses")
- }
-}
-
-impl DownloaderInterface for VcsDownloader {
- fn get_installation_source(&self) -> String {
- VcsDownloader::get_installation_source(self)
- }
-
- fn download(
- &self,
- _package: &dyn PackageInterface,
- _path: &str,
- _prev_package: Option<&dyn PackageInterface>,
- ) -> Result<Box<dyn PromiseInterface>> {
- // TODO(phase-b): download mutates state; trait method takes &self
- todo!("download requires &mut self")
- }
-
- fn prepare(
- &self,
- _type: &str,
- _package: &dyn PackageInterface,
- _path: &str,
- _prev_package: Option<&dyn PackageInterface>,
- ) -> Result<Box<dyn PromiseInterface>> {
- // TODO(phase-b): prepare mutates state; trait method takes &self
- todo!("prepare requires &mut self")
- }
-
- fn install(
- &self,
- _package: &dyn PackageInterface,
- _path: &str,
- ) -> Result<Box<dyn PromiseInterface>> {
- // TODO(phase-b): install mutates state; trait method takes &self
- todo!("install requires &mut self")
- }
-
- fn update(
- &self,
- _initial: &dyn PackageInterface,
- _target: &dyn PackageInterface,
- _path: &str,
- ) -> Result<Box<dyn PromiseInterface>> {
- // TODO(phase-b): update mutates state; trait method takes &self
- todo!("update requires &mut self")
- }
-
- fn remove(
- &self,
- _package: &dyn PackageInterface,
- _path: &str,
- ) -> Result<Box<dyn PromiseInterface>> {
- // TODO(phase-b): remove mutates state; trait method takes &self
- todo!("remove requires &mut self")
- }
-
- fn cleanup(
- &self,
- _type: &str,
- _package: &dyn PackageInterface,
- _path: &str,
- _prev_package: Option<&dyn PackageInterface>,
- ) -> Result<Box<dyn PromiseInterface>> {
- // TODO(phase-b): cleanup mutates state; trait method takes &self
- todo!("cleanup requires &mut self")
- }
-}
-
-impl ChangeReportInterface for VcsDownloader {
- fn get_local_changes(&self, package: &dyn PackageInterface, path: String) -> Option<String> {
- VcsDownloader::get_local_changes(self, package, path)
- }
-}
-
-impl VcsCapableDownloaderInterface for VcsDownloader {
- fn get_vcs_reference(&self, package: &dyn PackageInterface, path: String) -> Option<String> {
- VcsDownloader::get_vcs_reference(self, package, &path)
- }
}