aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/installer
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe/src/installer')
-rw-r--r--crates/shirabe/src/installer/binary_installer.rs82
-rw-r--r--crates/shirabe/src/installer/installation_manager.rs12
-rw-r--r--crates/shirabe/src/installer/installer_interface.rs2
-rw-r--r--crates/shirabe/src/installer/library_installer.rs42
-rw-r--r--crates/shirabe/src/installer/plugin_installer.rs2
-rw-r--r--crates/shirabe/src/installer/project_installer.rs6
-rw-r--r--crates/shirabe/src/installer/suggested_packages_reporter.rs2
7 files changed, 89 insertions, 59 deletions
diff --git a/crates/shirabe/src/installer/binary_installer.rs b/crates/shirabe/src/installer/binary_installer.rs
index e6677ed..c7b880b 100644
--- a/crates/shirabe/src/installer/binary_installer.rs
+++ b/crates/shirabe/src/installer/binary_installer.rs
@@ -1,7 +1,8 @@
//! ref: composer/src/Composer/Installer/BinaryInstaller.php
use crate::io::io_interface;
-use shirabe_external_packages::composer::pcre::preg::Preg;
+use indexmap::IndexMap;
+use shirabe_external_packages::composer::pcre::preg::{CaptureKey, Preg};
use shirabe_php_shim::{
PhpMixed, basename, basename_with_suffix, chmod, dirname, fclose, fgets, file_exists,
file_get_contents, file_put_contents, fopen, is_dir, is_file, is_link, realpath, rmdir, substr,
@@ -21,7 +22,7 @@ pub struct BinaryInstaller {
pub(crate) bin_dir: String,
pub(crate) bin_compat: String,
pub(crate) io: Box<dyn IOInterface>,
- pub(crate) filesystem: Filesystem,
+ pub(crate) filesystem: std::rc::Rc<std::cell::RefCell<Filesystem>>,
vendor_dir: Option<String>,
}
@@ -30,10 +31,11 @@ impl BinaryInstaller {
io: Box<dyn IOInterface>,
bin_dir: String,
bin_compat: String,
- filesystem: Option<Filesystem>,
+ filesystem: Option<std::rc::Rc<std::cell::RefCell<Filesystem>>>,
vendor_dir: Option<String>,
) -> Self {
- let filesystem = filesystem.unwrap_or_else(|| Filesystem::new(None));
+ let filesystem = filesystem
+ .unwrap_or_else(|| std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(None))));
Self {
bin_dir,
bin_compat,
@@ -59,30 +61,30 @@ impl BinaryInstaller {
for bin in &binaries {
let mut bin_path = format!("{}/{}", install_path, bin);
if !file_exists(&bin_path) {
- self.io.write_error(
- PhpMixed::String(format!(
+ self.io.write_error3(
+ &format!(
" <warning>Skipped installation of bin {} for package {}: file not found in package</warning>",
bin,
package.get_name(),
- )),
+ ),
true,
io_interface::NORMAL,
);
continue;
}
if is_dir(&bin_path) {
- self.io.write_error(
- PhpMixed::String(format!(
+ self.io.write_error3(
+ &format!(
" <warning>Skipped installation of bin {} for package {}: found a directory at that path</warning>",
bin,
package.get_name(),
- )),
+ ),
true,
io_interface::NORMAL,
);
continue;
}
- if !self.filesystem.is_absolute_path(&bin_path) {
+ if !self.filesystem.borrow_mut().is_absolute_path(&bin_path) {
// in case a custom installer returned a relative path for the
// $package, we can now safely turn it into a absolute path (as we
// already checked the binary's existence). The following helpers
@@ -94,12 +96,12 @@ impl BinaryInstaller {
if file_exists(&link) {
if !is_link(&link) {
if warn_on_overwrite {
- self.io.write_error(
- PhpMixed::String(format!(
+ self.io.write_error3(
+ &format!(
" Skipped installation of bin {} for package {}: name conflicts with an existing file",
bin,
package.get_name(),
- )),
+ ),
true,
io_interface::NORMAL,
);
@@ -108,7 +110,7 @@ impl BinaryInstaller {
}
if realpath(&link) == realpath(&bin_path) {
// It is a linked binary from a previous installation, which can be replaced with a proxy file
- self.filesystem.unlink(&link);
+ self.filesystem.borrow_mut().unlink(&link);
}
}
@@ -142,15 +144,17 @@ impl BinaryInstaller {
let link = format!("{}/{}", self.bin_dir, basename(bin));
if is_link(&link) || file_exists(&link) {
// still checking for symlinks here for legacy support
- self.filesystem.unlink(&link);
+ self.filesystem.borrow_mut().unlink(&link);
}
if is_file(&format!("{}.bat", link)) {
- self.filesystem.unlink(&format!("{}.bat", link));
+ self.filesystem
+ .borrow_mut()
+ .unlink(&format!("{}.bat", link));
}
}
// attempt removing the bin dir in case it is left empty
- if is_dir(&self.bin_dir) && self.filesystem.is_dir_empty(&self.bin_dir) {
+ if is_dir(&self.bin_dir) && self.filesystem.borrow_mut().is_dir_empty(&self.bin_dir) {
let bin_dir = self.bin_dir.clone();
let _ = Silencer::call(|| {
rmdir(&bin_dir);
@@ -167,10 +171,20 @@ impl BinaryInstaller {
let handle = fopen(bin, "r");
let line = fgets(handle.clone()).unwrap_or_default();
fclose(handle);
- if let Some(m) =
- Preg::is_match_strict_groups(r"{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m", &line)
+ let mut m: IndexMap<CaptureKey, String> = IndexMap::new();
+ if Preg::is_match_strict_groups3(
+ r"{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m",
+ &line,
+ Some(&mut m),
+ )
+ .unwrap_or(false)
{
- return trim(m.get(1).map(|s| s.as_str()).unwrap_or(""), None);
+ return trim(
+ m.get(&CaptureKey::ByIndex(1))
+ .map(|s| s.as_str())
+ .unwrap_or(""),
+ None,
+ );
}
"php".to_string()
@@ -194,12 +208,12 @@ impl BinaryInstaller {
self.install_unixy_proxy_binaries(bin_path, &link);
link.push_str(".bat");
if file_exists(&link) {
- self.io.write_error(
- PhpMixed::String(format!(
+ self.io.write_error3(
+ &format!(
" Skipped installation of bin {}.bat proxy for package {}: a .bat proxy was already installed",
bin,
package.get_name(),
- )),
+ ),
true,
io_interface::NORMAL,
);
@@ -227,13 +241,18 @@ impl BinaryInstaller {
}
pub(crate) fn initialize_bin_dir(&mut self) {
- self.filesystem.ensure_directory_exists(&self.bin_dir);
+ self.filesystem
+ .borrow_mut()
+ .ensure_directory_exists(&self.bin_dir);
// TODO(phase-b): PHP assigns realpath(...) even when realpath returns false
self.bin_dir = realpath(&self.bin_dir).unwrap_or_default();
}
pub(crate) fn generate_windows_proxy_code(&self, bin: &str, link: &str) -> String {
- let bin_path = self.filesystem.find_shortest_path(link, bin, false);
+ let bin_path = self
+ .filesystem
+ .borrow_mut()
+ .find_shortest_path(link, bin, false);
let caller = Self::determine_binary_caller(bin);
// if the target is a php file, we run the unixy proxy file
@@ -266,7 +285,10 @@ impl BinaryInstaller {
}
pub(crate) fn generate_unixy_proxy_code(&self, bin: &str, link: &str) -> String {
- let bin_path = self.filesystem.find_shortest_path(link, bin, false);
+ let bin_path = self
+ .filesystem
+ .borrow_mut()
+ .find_shortest_path(link, bin, false);
let bin_dir = ProcessExecutor::escape(&dirname(&bin_path));
let bin_file = basename(&bin_path);
@@ -289,6 +311,7 @@ impl BinaryInstaller {
};
let bin_path_exported = self
.filesystem
+ .borrow()
.find_shortest_path_code(link, bin, false, true);
let mut stream_proxy_code = String::new();
let mut stream_hint = String::new();
@@ -301,7 +324,7 @@ impl BinaryInstaller {
let vendor_dir_real = realpath(vendor_dir).unwrap_or_else(|| vendor_dir.clone());
globals_code.push_str(&format!(
"$GLOBALS['_composer_autoload_path'] = {};\n",
- self.filesystem.find_shortest_path_code(
+ self.filesystem.borrow_mut().find_shortest_path_code(
link,
&format!("{}/autoload.php", vendor_dir_real),
false,
@@ -311,9 +334,10 @@ impl BinaryInstaller {
}
// Add workaround for PHPUnit process isolation
if let Some(vendor_dir) = &self.vendor_dir {
- if self.filesystem.normalize_path(bin)
+ if self.filesystem.borrow().normalize_path(bin)
== self
.filesystem
+ .borrow()
.normalize_path(&format!("{}/phpunit/phpunit/phpunit", vendor_dir))
{
// workaround issue on PHPUnit 6.5+ running on PHP 8+
diff --git a/crates/shirabe/src/installer/installation_manager.rs b/crates/shirabe/src/installer/installation_manager.rs
index 59e029a..3789729 100644
--- a/crates/shirabe/src/installer/installation_manager.rs
+++ b/crates/shirabe/src/installer/installation_manager.rs
@@ -412,8 +412,8 @@ impl InstallationManager {
if !["update", "install", "uninstall"].contains(&op_type.as_str()) {
// output alias ops in debug verbosity as they have no output otherwise
if self.io.is_debug() {
- self.io.write_error(
- PhpMixed::String(format!(" - {}", operation.show(false))),
+ self.io.write_error3(
+ &format!(" - {}", operation.show(false)),
true,
io_interface::NORMAL,
);
@@ -696,12 +696,12 @@ impl InstallationManager {
),
);
- promises.push(self.loop_.borrow().get_http_downloader().add(
+ promises.push(self.loop_.borrow().get_http_downloader().borrow_mut().add(
&url,
&PhpMixed::Array(
opts.into_iter().map(|(k, v)| (k, Box::new(v))).collect(),
),
- ));
+ )?);
}
continue;
@@ -767,10 +767,10 @@ impl InstallationManager {
PhpMixed::Array(http.into_iter().map(|(k, v)| (k, Box::new(v))).collect()),
);
- promises.push(self.loop_.borrow().get_http_downloader().add(
+ promises.push(self.loop_.borrow().get_http_downloader().borrow_mut().add(
repo_url,
&PhpMixed::Array(opts.into_iter().map(|(k, v)| (k, Box::new(v))).collect()),
- ));
+ )?);
}
let _ = self.loop_.borrow_mut().wait(promises, None);
diff --git a/crates/shirabe/src/installer/installer_interface.rs b/crates/shirabe/src/installer/installer_interface.rs
index cf700be..a9e8d9b 100644
--- a/crates/shirabe/src/installer/installer_interface.rs
+++ b/crates/shirabe/src/installer/installer_interface.rs
@@ -4,7 +4,7 @@ use crate::package::package_interface::PackageInterface;
use crate::repository::installed_repository_interface::InstalledRepositoryInterface;
use shirabe_external_packages::react::promise::promise_interface::PromiseInterface;
-pub trait InstallerInterface {
+pub trait InstallerInterface: std::fmt::Debug {
fn supports(&self, package_type: &str) -> bool;
fn is_installed(
diff --git a/crates/shirabe/src/installer/library_installer.rs b/crates/shirabe/src/installer/library_installer.rs
index 17404e2..0bc87f9 100644
--- a/crates/shirabe/src/installer/library_installer.rs
+++ b/crates/shirabe/src/installer/library_installer.rs
@@ -30,7 +30,7 @@ pub struct LibraryInstaller {
pub(crate) download_manager: Option<std::rc::Rc<std::cell::RefCell<DownloadManager>>>,
pub(crate) io: Box<dyn IOInterface>,
pub(crate) r#type: Option<String>,
- pub(crate) filesystem: Filesystem,
+ pub(crate) filesystem: std::rc::Rc<std::cell::RefCell<Filesystem>>,
pub(crate) binary_installer: BinaryInstaller,
}
@@ -40,31 +40,34 @@ impl LibraryInstaller {
io: Box<dyn IOInterface>,
composer: PartialComposer,
r#type: Option<String>,
- filesystem: Option<Filesystem>,
+ filesystem: Option<std::rc::Rc<std::cell::RefCell<Filesystem>>>,
binary_installer: Option<BinaryInstaller>,
) -> Self {
// PHP: $this->downloadManager = $composer instanceof Composer ? $composer->getDownloadManager() : null;
- let download_manager = if let Some(full_composer) =
- (composer.as_any() as &dyn Any).downcast_ref::<Composer>()
- {
- // TODO(phase-b): clone or borrow the DownloadManager from the full Composer
- Some(todo!("composer.get_download_manager() as DownloadManager"))
- } else {
- None
- };
+ let download_manager =
+ if let Some(full_composer) = composer.as_any().downcast_ref::<Composer>() {
+ // TODO(phase-b): clone or borrow the DownloadManager from the full Composer
+ Some(todo!("composer.get_download_manager() as DownloadManager"))
+ } else {
+ None
+ };
- let filesystem = filesystem.unwrap_or_else(|| Filesystem::new(None));
+ let filesystem = filesystem
+ .unwrap_or_else(|| std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(None))));
let vendor_dir = rtrim(
- // TODO(phase-b): composer.get_config().get("vendor-dir") returns a PhpMixed/String
- &composer.get_config().get("vendor-dir"),
+ // TODO(phase-b): composer.get_config().borrow_mut().get("vendor-dir") returns a PhpMixed/String
+ &composer.get_config().borrow_mut().get("vendor-dir"),
Some("/"),
);
let binary_installer = binary_installer.unwrap_or_else(|| {
BinaryInstaller::new(
// TODO(phase-b): pass io by reference/clone
todo!("io reference"),
- rtrim(&composer.get_config().get("bin-dir"), Some("/")),
- composer.get_config().get("bin-compat"),
+ rtrim(
+ &composer.get_config().borrow_mut().get("bin-dir"),
+ Some("/"),
+ ),
+ composer.get_config().borrow_mut().get("bin-compat"),
// TODO(phase-b): pass filesystem reference
todo!("filesystem reference"),
vendor_dir.clone(),
@@ -163,6 +166,7 @@ impl LibraryInstaller {
}
self.filesystem
+ .borrow_mut()
.rename(&initial_download_path, &target_download_path);
}
@@ -185,7 +189,9 @@ impl LibraryInstaller {
}
pub(crate) fn initialize_vendor_dir(&mut self) {
- self.filesystem.ensure_directory_exists(&self.vendor_dir);
+ self.filesystem
+ .borrow_mut()
+ .ensure_directory_exists(&self.vendor_dir);
// TODO(phase-b): realpath returns Option<String>; PHP assigns to vendorDir even when false
self.vendor_dir = realpath(&self.vendor_dir).unwrap();
}
@@ -232,7 +238,7 @@ impl InstallerInterface for LibraryInstaller {
return true;
}
- if Platform::is_windows() && self.filesystem.is_junction(&install_path) {
+ if Platform::is_windows() && self.filesystem.borrow_mut().is_junction(&install_path) {
return true;
}
@@ -393,7 +399,7 @@ impl InstallerInterface for LibraryInstaller {
if strpos(package.get_name(), "/").is_some() {
let package_vendor_dir = shirabe_php_shim::dirname(&download_path);
if shirabe_php_shim::is_dir(&package_vendor_dir)
- && filesystem.is_dir_empty(&package_vendor_dir)
+ && filesystem.borrow().is_dir_empty(&package_vendor_dir)
{
Silencer::call(|| {
rmdir(&package_vendor_dir);
diff --git a/crates/shirabe/src/installer/plugin_installer.rs b/crates/shirabe/src/installer/plugin_installer.rs
index 77bd669..bb04947 100644
--- a/crates/shirabe/src/installer/plugin_installer.rs
+++ b/crates/shirabe/src/installer/plugin_installer.rs
@@ -23,7 +23,7 @@ impl PluginInstaller {
pub fn new(
io: Box<dyn IOInterface>,
composer: PartialComposer,
- fs: Option<Filesystem>,
+ fs: Option<std::rc::Rc<std::cell::RefCell<Filesystem>>>,
binary_installer: Option<BinaryInstaller>,
) -> Self {
Self {
diff --git a/crates/shirabe/src/installer/project_installer.rs b/crates/shirabe/src/installer/project_installer.rs
index f8b0bba..906e2c0 100644
--- a/crates/shirabe/src/installer/project_installer.rs
+++ b/crates/shirabe/src/installer/project_installer.rs
@@ -12,14 +12,14 @@ use shirabe_php_shim::InvalidArgumentException;
pub struct ProjectInstaller {
install_path: String,
download_manager: std::rc::Rc<std::cell::RefCell<DownloadManager>>,
- filesystem: Filesystem,
+ filesystem: std::rc::Rc<std::cell::RefCell<Filesystem>>,
}
impl ProjectInstaller {
pub fn new(
install_path: &str,
dm: std::rc::Rc<std::cell::RefCell<DownloadManager>>,
- fs: Filesystem,
+ fs: std::rc::Rc<std::cell::RefCell<Filesystem>>,
) -> Self {
let install_path = format!("{}/", install_path.replace('\\', "/").trim_end_matches('/'));
Self {
@@ -50,7 +50,7 @@ impl InstallerInterface for ProjectInstaller {
) -> anyhow::Result<Option<Box<dyn PromiseInterface>>> {
let install_path = &self.install_path;
if std::path::Path::new(install_path).exists()
- && !self.filesystem.is_dir_empty(install_path)
+ && !self.filesystem.borrow().is_dir_empty(install_path)
{
return Err(InvalidArgumentException {
message: format!("Project directory {} is not empty.", install_path),
diff --git a/crates/shirabe/src/installer/suggested_packages_reporter.rs b/crates/shirabe/src/installer/suggested_packages_reporter.rs
index 31a34d8..c820009 100644
--- a/crates/shirabe/src/installer/suggested_packages_reporter.rs
+++ b/crates/shirabe/src/installer/suggested_packages_reporter.rs
@@ -161,7 +161,7 @@ impl SuggestedPackagesReporter {
let mut installed_names: Vec<String> = Vec::new();
if installed_repo.is_some() && !suggested_packages.is_empty() {
for package in installed_repo.unwrap().get_packages() {
- installed_names.extend(package.get_names());
+ installed_names.extend(package.get_names(true));
}
}