aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/factory.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe/src/factory.rs')
-rw-r--r--crates/shirabe/src/factory.rs313
1 files changed, 174 insertions, 139 deletions
diff --git a/crates/shirabe/src/factory.rs b/crates/shirabe/src/factory.rs
index 321d590..6dc2fbd 100644
--- a/crates/shirabe/src/factory.rs
+++ b/crates/shirabe/src/factory.rs
@@ -116,7 +116,7 @@ impl Factory {
let appdata = Platform::get_env("APPDATA").unwrap_or_default();
return Ok(format!(
"{}/Composer",
- trim(&strtr(&appdata, "\\", "/"), "/")
+ trim(&strtr(&appdata, "\\", "/"), Some("/"))
));
}
@@ -168,7 +168,7 @@ impl Factory {
cache_dir = format!("{}/cache", home);
}
- return Ok(trim(&strtr(&cache_dir, "\\", "/"), "/"));
+ return Ok(trim(&strtr(&cache_dir, "\\", "/"), Some("/")));
}
let user_dir = Self::get_user_dir()?;
@@ -233,11 +233,12 @@ impl Factory {
io: Option<&dyn IOInterface>,
cwd: Option<&str>,
) -> anyhow::Result<Config> {
- let cwd = cwd
- .map(|s| s.to_string())
- .unwrap_or_else(|| Platform::get_cwd(true));
+ let cwd = match cwd {
+ Some(s) => s.to_string(),
+ None => Platform::get_cwd(true)?,
+ };
- let mut config = Config::new(true, cwd);
+ let mut config = Config::new(true, Some(cwd));
// determine and add main dirs to the config
let home = Self::get_home_dir()?;
@@ -256,10 +257,11 @@ impl Factory {
"config".to_string(),
PhpMixed::Array(inner.into_iter().map(|(k, v)| (k, Box::new(v))).collect()),
);
- config.merge(defaults, Config::SOURCE_DEFAULT);
+ config.merge(&defaults, Config::SOURCE_DEFAULT);
// load global config
- let file = JsonFile::new(format!("{}/config.json", config.get_str("home")?), None, io)?;
+ let global_config_path = format!("{}/config.json", config.get_str("home")?);
+ let mut file = JsonFile::new(global_config_path.clone(), None, io.map(|i| i.clone_box()))?;
if file.exists() {
if let Some(io_ref) = io {
io_ref.write_error3(
@@ -268,15 +270,29 @@ impl Factory {
crate::io::io_interface::DEBUG,
);
}
+ // TODO(phase-b): validate_json_schema takes ownership of JsonFile; recreate it
Self::validate_json_schema(
io,
- ValidateJsonInput::File(file.clone()),
+ ValidateJsonInput::File(JsonFile::new(
+ global_config_path.clone(),
+ None,
+ io.map(|i| i.clone_box()),
+ )?),
JsonFile::LAX_SCHEMA,
None,
)?;
- config.merge(file.read()?, file.get_path().to_string());
+ let read_data = match file.read()? {
+ PhpMixed::Array(map) => map
+ .into_iter()
+ .map(|(k, v)| (k, *v))
+ .collect::<IndexMap<_, _>>(),
+ _ => IndexMap::new(),
+ };
+ let file_path_owned = file.get_path().to_string();
+ config.merge(&read_data, &file_path_owned);
}
- config.set_config_source(JsonConfigSource::new(file.clone(), false));
+ // TODO(phase-b): set_config_source takes Box<dyn ConfigSourceInterface>
+ config.set_config_source(Box::new(JsonConfigSource::new(file, false)));
let htaccess_protect = config.get("htaccess-protect").as_bool().unwrap_or(false);
if htaccess_protect {
@@ -305,7 +321,8 @@ impl Factory {
}
// load global auth file
- let auth_file = JsonFile::new(format!("{}/auth.json", config.get_str("home")?), None, io)?;
+ let auth_file_path = format!("{}/auth.json", config.get_str("home")?);
+ let mut auth_file = JsonFile::new(auth_file_path.clone(), None, io.map(|i| i.clone_box()))?;
if auth_file.exists() {
if let Some(io_ref) = io {
io_ref.write_error3(
@@ -314,26 +331,36 @@ impl Factory {
crate::io::io_interface::DEBUG,
);
}
+ // TODO(phase-b): validate_json_schema takes ownership; recreate JsonFile
Self::validate_json_schema(
io,
- ValidateJsonInput::File(auth_file.clone()),
+ ValidateJsonInput::File(JsonFile::new(
+ auth_file_path.clone(),
+ None,
+ io.map(|i| i.clone_box()),
+ )?),
JsonFile::AUTH_SCHEMA,
None,
)?;
+ let read_data: IndexMap<String, PhpMixed> = match auth_file.read()? {
+ PhpMixed::Array(map) => map.into_iter().map(|(k, v)| (k, *v)).collect(),
+ _ => IndexMap::new(),
+ };
let mut wrapped: IndexMap<String, PhpMixed> = IndexMap::new();
wrapped.insert(
"config".to_string(),
PhpMixed::Array(
- auth_file
- .read()?
+ read_data
.into_iter()
.map(|(k, v)| (k, Box::new(v)))
.collect(),
),
);
- config.merge(wrapped, auth_file.get_path().to_string());
+ let auth_path_owned = auth_file.get_path().to_string();
+ config.merge(&wrapped, &auth_path_owned);
}
- config.set_auth_config_source(JsonConfigSource::new(auth_file, true));
+ // TODO(phase-b): set_auth_config_source takes Box<dyn ConfigSourceInterface>
+ config.set_auth_config_source(Box::new(JsonConfigSource::new(auth_file, true)));
Self::load_composer_auth_env(&mut config, io)?;
@@ -343,7 +370,7 @@ impl Factory {
pub fn get_composer_file() -> anyhow::Result<String> {
let env = Platform::get_env("COMPOSER");
if let Some(env_str) = env {
- let env_trimmed = trim(&env_str, " \t\n\r\0\u{0B}");
+ let env_trimmed = trim(&env_str, Some(" \t\n\r\0\u{0B}"));
if env_trimmed != "" {
if is_dir(&env_trimmed) {
return Err(anyhow::anyhow!(RuntimeException {
@@ -385,24 +412,21 @@ impl Factory {
let mut styles: IndexMap<String, OutputFormatterStyle> = IndexMap::new();
styles.insert(
"highlight".to_string(),
- OutputFormatterStyle::new(Some("red".to_string()), None, Vec::new()),
+ OutputFormatterStyle::new(Some("red"), None, Some(vec![])),
);
styles.insert(
"warning".to_string(),
- OutputFormatterStyle::new(
- Some("black".to_string()),
- Some("yellow".to_string()),
- Vec::new(),
- ),
+ OutputFormatterStyle::new(Some("black"), Some("yellow"), Some(vec![])),
);
styles
}
pub fn create_output() -> ConsoleOutput {
- let styles = Self::create_additional_styles();
- let formatter = OutputFormatter::new(false, styles);
-
- ConsoleOutput::new_with_formatter(ConsoleOutput::VERBOSITY_NORMAL, None, formatter)
+ let _styles = Self::create_additional_styles();
+ // TODO(phase-b): OutputFormatter::new signature and ConsoleOutput::new_with_formatter missing
+ todo!(
+ "create_output: wire OutputFormatter into ConsoleOutput once the symfony console stubs are completed"
+ )
}
/// Creates a Composer instance
@@ -424,7 +448,10 @@ impl Factory {
}
}
- let cwd = cwd.unwrap_or_else(|| Platform::get_cwd(true));
+ let cwd = match cwd {
+ Some(s) => s,
+ None => Platform::get_cwd(true)?,
+ };
// load Composer configuration
if local_config.is_none() {
@@ -437,7 +464,7 @@ impl Factory {
if let Some(LocalConfigInput::Path(path)) = &local_config {
composer_file = Some(path.clone());
- let file = JsonFile::new(path.clone(), None, Some(io))?;
+ let mut file = JsonFile::new(path.clone(), None, Some(io.clone_box()))?;
if !file.exists() {
let message = if path == "./composer.json" || path == "composer.json" {
@@ -473,7 +500,11 @@ impl Factory {
}
}
- local_config_data = file.read()?.as_array().cloned().unwrap_or_default();
+ local_config_data = file
+ .read()?
+ .as_array()
+ .map(|m| m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect())
+ .unwrap_or_default();
local_config_source = file.get_path().to_string();
} else if let Some(LocalConfigInput::Data(data)) = local_config {
local_config_data = data;
@@ -504,7 +535,7 @@ impl Factory {
false,
)));
- let local_auth_file = JsonFile::new(
+ let mut local_auth_file = JsonFile::new(
format!(
"{}/auth.json",
dirname(&realpath(composer_file_path).unwrap_or_default())
@@ -554,7 +585,8 @@ impl Factory {
if full_load {
// load auth configs into the IO instance
- io.load_configuration(&mut *config.borrow_mut())?;
+ // TODO(phase-b): load_configuration requires &mut IOInterface; create_composer takes &dyn IOInterface
+ // io.load_configuration(&mut *config.borrow_mut())?;
// load existing Composer\InstalledVersions instance if available and scripts/plugins are allowed, as they might need it
// we only load if the InstalledVersions class wasn't defined yet so that this is only loaded once
@@ -578,7 +610,9 @@ impl Factory {
let http_downloader = std::rc::Rc::new(std::cell::RefCell::new(
Self::create_http_downloader(io, &config, IndexMap::new())?,
));
- let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(io)));
+ let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(Some(
+ io.clone_box(),
+ ))));
let r#loop = std::rc::Rc::new(std::cell::RefCell::new(Loop::new(
std::rc::Rc::clone(&http_downloader),
Some(std::rc::Rc::clone(&process)),
@@ -586,23 +620,25 @@ impl Factory {
composer.set_loop(r#loop.clone());
// initialize event dispatcher
- let mut dispatcher = EventDispatcher::new(
- composer.as_partial(),
- io.clone_box(),
- Some(std::rc::Rc::clone(&process)),
- );
- dispatcher.set_run_scripts(!disable_scripts);
- composer.set_event_dispatcher(dispatcher.clone());
+ let dispatcher = {
+ let mut d = EventDispatcher::new(
+ composer.as_partial(),
+ io.clone_box(),
+ Some(std::rc::Rc::clone(&process)),
+ );
+ d.set_run_scripts(!disable_scripts);
+ std::rc::Rc::new(std::cell::RefCell::new(d))
+ };
+ composer.set_event_dispatcher(std::rc::Rc::clone(&dispatcher));
// initialize repository manager
- let rm = RepositoryFactory::manager(
+ let mut rm = RepositoryFactory::manager(
io,
&config,
Some(std::rc::Rc::clone(&http_downloader)),
- Some(dispatcher.clone()),
+ Some(std::rc::Rc::clone(&dispatcher)),
Some(std::rc::Rc::clone(&process)),
)?;
- composer.set_repository_manager(rm.clone());
// force-set the version of the global package if not defined as
// guessing it adds no value and only takes time
@@ -616,9 +652,12 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(&process),
parser.clone(),
+ Some(io.clone_box()),
);
+ // TODO(phase-b): RepositoryManager is a PHP class — both composer.set_repository_manager()
+ // and self.load_root_package() want ownership. Use a placeholder rm for the loader.
let mut loader = self.load_root_package(
- rm.clone(),
+ todo!("share RepositoryManager via Rc<RefCell<>>"),
std::rc::Rc::clone(&config),
parser,
guesser,
@@ -632,24 +671,28 @@ impl Factory {
"Composer\\Package\\RootPackage",
Some(&cwd),
)?;
- composer.set_package(package);
+ // TODO(phase-b): set_package expects RootPackageInterface; loader returns BasePackage
+ // composer.set_package(package);
+ let _ = package;
// load local repository
self.add_local_repository(
io,
- rm.clone(),
+ &mut rm,
&vendor_dir,
composer.get_package(),
Some(&process),
);
+ composer.set_repository_manager(rm);
// initialize installation manager
let im = self.create_installation_manager(
r#loop.clone(),
io.clone_box(),
- Some(dispatcher.clone()),
+ Some(std::rc::Rc::clone(&dispatcher)),
);
- composer.set_installation_manager(im.clone());
+ // TODO(phase-b): set_installation_manager takes ownership; im needs sharing for create_default_installers
+ composer.set_installation_manager(im);
if let PartialComposerOrComposer::Full(ref mut composer_full) = composer {
// initialize download manager
@@ -663,7 +706,8 @@ impl Factory {
composer_full.set_download_manager(dm.clone());
// initialize autoload generator
- let generator = AutoloadGenerator::new(&dispatcher, io.clone_box());
+ let generator =
+ AutoloadGenerator::new(std::rc::Rc::clone(&dispatcher), Some(io.clone_box()));
composer_full.set_autoload_generator(generator);
// initialize archive manager
@@ -694,6 +738,7 @@ impl Factory {
);
}
+ // TODO(phase-b): InstallationManager is a PHP class — needs Rc<RefCell<>> sharing
let locker = Locker::new(
io.clone_box(),
JsonFile::new(
@@ -703,27 +748,29 @@ impl Factory {
Platform::get_dev_null()
},
None,
- Some(io),
+ Some(io.clone_box()),
)?,
- im.clone(),
- file_get_contents(composer_file_path).unwrap_or_default(),
+ todo!("InstallationManager clone"),
+ &file_get_contents(composer_file_path).unwrap_or_default(),
std::rc::Rc::clone(&process),
);
composer_full.set_locker(locker);
} else {
+ let lock_contents = JsonFile::encode(
+ &PhpMixed::Array(
+ local_config_data
+ .iter()
+ .map(|(k, v)| (k.clone(), Box::new(v.clone())))
+ .collect(),
+ ),
+ 448,
+ );
+ // TODO(phase-b): InstallationManager is a PHP class — needs Rc<RefCell<>> sharing
let locker = Locker::new(
io.clone_box(),
- JsonFile::new(Platform::get_dev_null(), None, Some(io))?,
- im.clone(),
- JsonFile::encode(
- &PhpMixed::Array(
- local_config_data
- .iter()
- .map(|(k, v)| (k.clone(), Box::new(v.clone())))
- .collect(),
- ),
- 448,
- ),
+ JsonFile::new(Platform::get_dev_null(), None, Some(io.clone_box()))?,
+ todo!("InstallationManager clone"),
+ &lock_contents,
std::rc::Rc::clone(&process),
);
composer_full.set_locker(locker);
@@ -748,24 +795,25 @@ impl Factory {
global_composer.as_ref(),
disable_plugins,
);
- composer_full.set_plugin_manager(pm.clone());
-
+ // TODO(phase-b): PluginManager is a PHP class; sharing pm before transferring requires Rc<RefCell<>>
if composer_full.is_global() {
pm.set_running_in_global_dir(true);
}
-
pm.load_installed_plugins();
+ composer_full.set_plugin_manager(pm);
}
if full_load {
let init_event = Event::from_name(PluginEvents::INIT.to_string());
composer
- .get_event_dispatcher_mut()
+ .get_event_dispatcher()
+ .borrow_mut()
.dispatch(Some(init_event.get_name()), Some(init_event))?;
// once everything is initialized we can
// purge packages from local repos if they have been deleted on the filesystem
- self.purge_packages(rm.get_local_repository(), &im);
+ // TODO(phase-b): rm and im are owned by composer at this point; need to access via composer
+ // self.purge_packages(rm.get_local_repository(), &mut im)?;
}
Ok(composer)
@@ -789,7 +837,7 @@ impl Factory {
fn add_local_repository(
&self,
io: &dyn IOInterface,
- mut rm: RepositoryManager,
+ rm: &mut RepositoryManager,
vendor_dir: &str,
root_package: &dyn RootPackageInterface,
process: Option<&std::rc::Rc<std::cell::RefCell<ProcessExecutor>>>,
@@ -865,9 +913,12 @@ impl Factory {
config: &std::rc::Rc<std::cell::RefCell<Config>>,
http_downloader: &std::rc::Rc<std::cell::RefCell<HttpDownloader>>,
process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>,
- event_dispatcher: Option<&EventDispatcher>,
+ event_dispatcher: Option<&std::rc::Rc<std::cell::RefCell<EventDispatcher>>>,
) -> anyhow::Result<std::rc::Rc<std::cell::RefCell<DownloadManager>>> {
- let mut cache: Option<Cache> = None;
+ // TODO(phase-b): cache is shared across all downloaders; PHP class semantics requires
+ // either Rc<RefCell<Cache>> (with corresponding signature changes everywhere) or
+ // making Cache cloneable. For now we don't construct a cache and pass None below.
+ let _cache: Option<Cache> = None;
if config
.borrow_mut()
.get("cache-files-ttl")
@@ -875,19 +926,13 @@ impl Factory {
.unwrap_or(0)
> 0
{
- let mut c = Cache::new(
- io,
+ let _ = Cache::new(
+ io.clone_box(),
&config.borrow_mut().get_str("cache-files-dir")?,
- "a-z0-9_./",
- );
- c.set_read_only(
- config
- .borrow_mut()
- .get("cache-read-only")
- .and_then(|v| v.as_bool())
- .unwrap_or(false),
+ Some("a-z0-9_./"),
+ None,
+ false,
);
- cache = Some(c);
}
let fs = std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(Some(
@@ -895,8 +940,8 @@ impl Factory {
))));
let mut dm = DownloadManager::new(io.clone_box(), false, Some(std::rc::Rc::clone(&fs)));
- let preferred = config.borrow_mut().get("preferred-install").cloned();
- match preferred.as_ref().and_then(|v| v.as_string()) {
+ let preferred = config.borrow_mut().get("preferred-install");
+ match preferred.as_string() {
Some("dist") => {
dm.set_prefer_dist(true);
}
@@ -908,7 +953,7 @@ impl Factory {
}
}
- if let Some(PhpMixed::Array(prefs)) = preferred {
+ if let PhpMixed::Array(prefs) = preferred {
dm.set_preferences(
prefs
.into_iter()
@@ -977,7 +1022,7 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(http_downloader),
event_dispatcher.cloned(),
- cache.clone(),
+ None, // TODO(phase-b): shared Cache requires Rc<RefCell<Cache>>; see _cache
std::rc::Rc::clone(&fs),
std::rc::Rc::clone(&process),
)),
@@ -989,7 +1034,7 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(http_downloader),
event_dispatcher.cloned(),
- cache.clone(),
+ None, // TODO(phase-b): shared Cache requires Rc<RefCell<Cache>>; see _cache
std::rc::Rc::clone(&fs),
std::rc::Rc::clone(&process),
)),
@@ -1001,7 +1046,7 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(http_downloader),
event_dispatcher.cloned(),
- cache.clone(),
+ None, // TODO(phase-b): shared Cache requires Rc<RefCell<Cache>>; see _cache
std::rc::Rc::clone(&fs),
std::rc::Rc::clone(&process),
)),
@@ -1013,7 +1058,7 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(http_downloader),
event_dispatcher.cloned(),
- cache.clone(),
+ None, // TODO(phase-b): shared Cache requires Rc<RefCell<Cache>>; see _cache
std::rc::Rc::clone(&fs),
std::rc::Rc::clone(&process),
)),
@@ -1025,7 +1070,7 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(http_downloader),
event_dispatcher.cloned(),
- cache.clone(),
+ None, // TODO(phase-b): shared Cache requires Rc<RefCell<Cache>>; see _cache
std::rc::Rc::clone(&fs),
std::rc::Rc::clone(&process),
)),
@@ -1037,7 +1082,7 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(http_downloader),
event_dispatcher.cloned(),
- cache.clone(),
+ None, // TODO(phase-b): shared Cache requires Rc<RefCell<Cache>>; see _cache
std::rc::Rc::clone(&fs),
std::rc::Rc::clone(&process),
)),
@@ -1049,7 +1094,7 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(http_downloader),
event_dispatcher.cloned(),
- cache.clone(),
+ None, // TODO(phase-b): shared Cache requires Rc<RefCell<Cache>>; see _cache
Some(std::rc::Rc::clone(&fs)),
Some(std::rc::Rc::clone(&process)),
)),
@@ -1061,7 +1106,7 @@ impl Factory {
std::rc::Rc::clone(&config),
std::rc::Rc::clone(http_downloader),
event_dispatcher.cloned(),
- cache.clone(),
+ None, // TODO(phase-b): shared Cache requires Rc<RefCell<Cache>>; see _cache
std::rc::Rc::clone(&fs),
std::rc::Rc::clone(&process),
)),
@@ -1094,19 +1139,17 @@ impl Factory {
global_composer: Option<&PartialComposer>,
disable_plugins: DisablePlugins,
) -> PluginManager {
- PluginManager::new(
- io.clone_box(),
- composer.clone(),
- global_composer.cloned(),
- disable_plugins,
- )
+ // TODO(phase-b): PluginManager::new takes ownership of Composer/PartialComposer; PHP
+ // class semantics requires Rc<RefCell<>> for shared access. Stubbed for now.
+ let _ = (io, composer, global_composer, disable_plugins);
+ todo!("PluginManager::new requires shared Composer/PartialComposer")
}
pub fn create_installation_manager(
&self,
r#loop: std::rc::Rc<std::cell::RefCell<Loop>>,
io: Box<dyn IOInterface>,
- event_dispatcher: Option<EventDispatcher>,
+ event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>,
) -> InstallationManager {
InstallationManager::new(r#loop, io, event_dispatcher)
}
@@ -1127,7 +1170,7 @@ impl Factory {
.borrow_mut()
.get_str("bin-dir")
.unwrap_or_default(),
- "/",
+ Some("/"),
);
let bin_compat = composer
.get_config()
@@ -1140,31 +1183,20 @@ impl Factory {
.borrow_mut()
.get_str("vendor-dir")
.unwrap_or_default(),
- "/",
+ Some("/"),
);
- let binary_installer = BinaryInstaller::new(
+ // TODO(phase-b): BinaryInstaller is a PHP class so it can't be cloned. Sharing requires
+ // Rc<RefCell<BinaryInstaller>>; for now construct one per installer.
+ let _binary_installer = BinaryInstaller::new(
io.clone_box(),
- bin_dir,
- bin_compat,
+ bin_dir.clone(),
+ bin_compat.clone(),
Some(std::rc::Rc::clone(&fs)),
- vendor_dir,
+ Some(vendor_dir.clone()),
);
- let mut im = im.clone();
- im.add_installer(Box::new(LibraryInstaller::new(
- io.clone_box(),
- composer.as_partial(),
- None,
- Some(std::rc::Rc::clone(&fs)),
- binary_installer.clone(),
- )));
- im.add_installer(Box::new(PluginInstaller::new(
- io.clone_box(),
- composer.as_partial(),
- Some(std::rc::Rc::clone(&fs)),
- binary_installer.clone(),
- )));
- im.add_installer(Box::new(MetapackageInstaller::new(io.clone_box())));
+ // TODO(phase-b): InstallationManager not clone-able; need shared Rc<RefCell<>>
+ let _ = im;
}
fn purge_packages(
@@ -1240,7 +1272,7 @@ impl Factory {
static mut WARNED: bool = false;
let mut disable_tls = false;
// allow running the config command if disable-tls is in the arg list, even if openssl is missing, to allow disabling it via the config command
- let argv = Platform::server_argv().unwrap_or_default();
+ let argv = shirabe_php_shim::server_argv();
if !argv.is_empty()
&& argv.contains(&"disable-tls".to_string())
&& (argv.contains(&"conf".to_string()) || argv.contains(&"config".to_string()))
@@ -1301,12 +1333,13 @@ impl Factory {
http_downloader_options =
array_replace_recursive(http_downloader_options, options.clone());
}
- let http_downloader = match HttpDownloader::new_full(
+ let http_downloader_result: anyhow::Result<HttpDownloader> = Ok(HttpDownloader::new(
io.clone_box(),
std::rc::Rc::clone(config),
http_downloader_options,
disable_tls,
- ) {
+ ));
+ let http_downloader = match http_downloader_result {
Ok(h) => h,
Err(e) => {
if let Some(te) = e.downcast_ref::<TransportException>() {
@@ -1372,13 +1405,14 @@ impl Factory {
if !matches!(auth_data_assoc, PhpMixed::Null) {
let mut wrapped: IndexMap<String, PhpMixed> = IndexMap::new();
wrapped.insert("config".to_string(), auth_data_assoc);
- config.merge(wrapped, "COMPOSER_AUTH".to_string());
+ config.merge(&wrapped, "COMPOSER_AUTH");
}
Ok(())
}
fn use_xdg() -> bool {
- for key in array_keys(&Platform::server_env()) {
+ // PHP: array_keys($_SERVER) — iterate env-style server vars
+ for (key, _) in std::env::vars() {
if strpos(&key, "XDG_") == Some(0) {
return true;
}
@@ -1398,7 +1432,7 @@ impl Factory {
}));
}
- Ok(trim(&strtr(&home, "\\", "/"), "/"))
+ Ok(trim(&strtr(&home, "\\", "/"), Some("/")))
}
fn validate_json_schema(
@@ -1412,7 +1446,7 @@ impl Factory {
}
let result = match file_or_data {
- ValidateJsonInput::File(file) => file.validate_schema(schema),
+ ValidateJsonInput::File(mut file) => file.validate_schema(schema, None),
ValidateJsonInput::Data(data) => {
let source = source.ok_or_else(|| {
anyhow::anyhow!(InvalidArgumentException {
@@ -1422,7 +1456,7 @@ impl Factory {
code: 0,
})
})?;
- JsonFile::validate_json_schema(source, &data, schema)
+ JsonFile::validate_json_schema(source, &data, schema, None)
}
};
@@ -1484,7 +1518,10 @@ impl PartialComposerOrComposer {
Self::Partial(p) => p.set_loop(r#loop),
}
}
- fn set_event_dispatcher(&mut self, dispatcher: EventDispatcher) {
+ fn set_event_dispatcher(
+ &mut self,
+ dispatcher: std::rc::Rc<std::cell::RefCell<EventDispatcher>>,
+ ) {
match self {
Self::Full(c) => c.set_event_dispatcher(dispatcher),
Self::Partial(p) => p.set_event_dispatcher(dispatcher),
@@ -1520,18 +1557,16 @@ impl PartialComposerOrComposer {
Self::Partial(p) => p.get_config(),
}
}
- fn get_event_dispatcher_mut(&mut self) -> &mut EventDispatcher {
+ fn get_event_dispatcher(&self) -> &std::rc::Rc<std::cell::RefCell<EventDispatcher>> {
match self {
- Self::Full(c) => c.get_event_dispatcher_mut(),
- Self::Partial(p) => p.get_event_dispatcher_mut(),
+ Self::Full(c) => c.get_event_dispatcher(),
+ Self::Partial(p) => p.get_event_dispatcher(),
}
}
fn as_partial(&self) -> PartialComposer {
- // TODO(phase-b): exact clone semantics differ across Composer/PartialComposer.
- match self {
- Self::Full(_) => PartialComposer::default(),
- Self::Partial(p) => p.clone(),
- }
+ // TODO(phase-b): PHP class semantics requires sharing PartialComposer by reference;
+ // currently returning a fresh default since PartialComposer is not Clone.
+ PartialComposer::default()
}
fn into_partial(self) -> PartialComposer {
match self {