aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/repository/vcs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-20 08:33:49 +0900
committernsfisis <nsfisis@gmail.com>2026-05-20 08:33:57 +0900
commitf31b101ce1e921a026ba234b1f0a83b0392bc118 (patch)
treeb7ac2aa84d71ebd162cc21aeab0240e7e0544988 /crates/shirabe/src/repository/vcs
parent5e31fa33c3b5cf726a57a063b8e7a070869250fe (diff)
downloadphp-shirabe-f31b101ce1e921a026ba234b1f0a83b0392bc118.tar.gz
php-shirabe-f31b101ce1e921a026ba234b1f0a83b0392bc118.tar.zst
php-shirabe-f31b101ce1e921a026ba234b1f0a83b0392bc118.zip
fix(compile): fix all remaining compile errors
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/repository/vcs')
-rw-r--r--crates/shirabe/src/repository/vcs/forgejo_driver.rs37
-rw-r--r--crates/shirabe/src/repository/vcs/fossil_driver.rs16
-rw-r--r--crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs63
-rw-r--r--crates/shirabe/src/repository/vcs/git_driver.rs65
-rw-r--r--crates/shirabe/src/repository/vcs/github_driver.rs60
-rw-r--r--crates/shirabe/src/repository/vcs/gitlab_driver.rs96
-rw-r--r--crates/shirabe/src/repository/vcs/hg_driver.rs57
-rw-r--r--crates/shirabe/src/repository/vcs/perforce_driver.rs57
-rw-r--r--crates/shirabe/src/repository/vcs/svn_driver.rs24
-rw-r--r--crates/shirabe/src/repository/vcs/vcs_driver.rs61
10 files changed, 341 insertions, 195 deletions
diff --git a/crates/shirabe/src/repository/vcs/forgejo_driver.rs b/crates/shirabe/src/repository/vcs/forgejo_driver.rs
index 179f2db..f4a86c7 100644
--- a/crates/shirabe/src/repository/vcs/forgejo_driver.rs
+++ b/crates/shirabe/src/repository/vcs/forgejo_driver.rs
@@ -50,7 +50,13 @@ impl ForgejoDriver {
);
self.forgejo_url = Some(forgejo_url);
- self.inner.cache = Some(Cache::new(&*self.inner.io, cache_dir));
+ self.inner.cache = Some(Cache::new(
+ self.inner.io.clone_box(),
+ &cache_dir,
+ None,
+ None,
+ false,
+ ));
self.inner.cache.as_mut().map(|c| {
c.set_read_only(
self.inner
@@ -321,8 +327,10 @@ impl ForgejoDriver {
if !self.inner.info_cache.contains_key(identifier) {
let composer = if self.inner.should_cache(identifier) {
- if let Some(res) = self.inner.cache.as_ref().and_then(|c| c.read(identifier)) {
- JsonFile::parse_json(&res, None)?
+ if let Some(res) = self.inner.cache.as_mut().and_then(|c| c.read(identifier)) {
+ // TODO(phase-b): JsonFile::parse_json returns PhpMixed; convert into Option<IndexMap>
+ let _ = JsonFile::parse_json(Some(res.as_str()), None)?;
+ None
} else {
let file_content = self.get_file_content("composer.json", identifier)?;
let c = VcsDriverBase::finish_base_composer_information(
@@ -332,14 +340,21 @@ impl ForgejoDriver {
)?;
if self.inner.should_cache(identifier) {
if let Some(ref composer_map) = c {
- let encoded = JsonFile::encode_with_options(
- composer_map,
- shirabe_php_shim::JSON_UNESCAPED_UNICODE
- | shirabe_php_shim::JSON_UNESCAPED_SLASHES,
+ // TODO(phase-b): JsonFile::encode_with_options does not exist; use encode
+ let encoded = JsonFile::encode(
+ &PhpMixed::Array(
+ composer_map
+ .iter()
+ .map(|(k, v)| (k.clone(), Box::new(v.clone())))
+ .collect(),
+ ),
+ (shirabe_php_shim::JSON_UNESCAPED_UNICODE
+ | shirabe_php_shim::JSON_UNESCAPED_SLASHES)
+ as i64,
);
self.inner
.cache
- .as_ref()
+ .as_mut()
.map(|c| c.write(identifier, &encoded));
}
}
@@ -394,8 +409,7 @@ impl ForgejoDriver {
format!("{}/commit/{}", html_url, identifier)
};
- if let Some(PhpMixed::Array(ref mut support)) = composer_map.get_mut("support")
- {
+ if let Some(PhpMixed::Array(support)) = composer_map.get_mut("support") {
support
.insert("source".to_string(), Box::new(PhpMixed::String(source_url)));
}
@@ -419,8 +433,7 @@ impl ForgejoDriver {
.map(|r| r.html_url.clone())
.unwrap_or_default()
);
- if let Some(PhpMixed::Array(ref mut support)) = composer_map.get_mut("support")
- {
+ if let Some(PhpMixed::Array(support)) = composer_map.get_mut("support") {
support
.insert("issues".to_string(), Box::new(PhpMixed::String(issues_url)));
}
diff --git a/crates/shirabe/src/repository/vcs/fossil_driver.rs b/crates/shirabe/src/repository/vcs/fossil_driver.rs
index f0c3468..f773e3b 100644
--- a/crates/shirabe/src/repository/vcs/fossil_driver.rs
+++ b/crates/shirabe/src/repository/vcs/fossil_driver.rs
@@ -64,7 +64,7 @@ impl FossilDriver {
.into());
}
- let local_name = Preg::replace(r"{[^a-z0-9]}i", "-", &self.inner.url);
+ let local_name = Preg::replace(r"{[^a-z0-9]}i", "-", &self.inner.url)?;
self.repo_file = Some(format!("{}/{}.fossil", cache_repo_dir, local_name));
self.checkout_dir = format!("{}/{}/", cache_vcs_dir, local_name);
@@ -82,7 +82,7 @@ impl FossilDriver {
if self.inner.process.borrow_mut().execute_args(
&["fossil", "version"].map(|s| s.to_string()).to_vec(),
&mut ignored_output,
- None,
+ (),
) != 0
{
return Err(RuntimeException {
@@ -100,7 +100,7 @@ impl FossilDriver {
pub(crate) fn update_local_repo(&mut self) -> anyhow::Result<()> {
assert!(self.repo_file.is_some());
- let fs = Filesystem::new(None);
+ let mut fs = Filesystem::new(None);
fs.ensure_directory_exists(&self.checkout_dir)?;
if !is_writable(&dirname(&self.checkout_dir)) {
@@ -149,10 +149,10 @@ impl FossilDriver {
.map(|s| s.to_string())
.to_vec(),
&mut output,
- None,
+ (),
) != 0
{
- let output = self.inner.process.borrow().get_error_output();
+ let output = self.inner.process.borrow().get_error_output().to_string();
return Err(RuntimeException {
message: format!(
"Failed to clone {} to repository {}\n\n{}",
@@ -171,7 +171,7 @@ impl FossilDriver {
Some(self.checkout_dir.clone()),
) != 0
{
- let output = self.inner.process.borrow().get_error_output();
+ let output = self.inner.process.borrow().get_error_output().to_string();
return Err(RuntimeException {
message: format!(
"Failed to open repository {} in {}\n\n{}",
@@ -280,7 +280,7 @@ impl FossilDriver {
Some(self.checkout_dir.clone()),
);
for branch in self.inner.process.borrow().split_lines(&output) {
- let branch = Preg::replace(r"/^\*/", "", &branch.trim());
+ let branch = Preg::replace(r"/^\*/", "", &branch.trim())?;
let branch = branch.trim().to_string();
branches.insert(branch.clone(), branch);
}
@@ -310,7 +310,7 @@ impl FossilDriver {
return false;
}
- let process = ProcessExecutor::new(io);
+ let mut process = ProcessExecutor::new(io);
let mut output = String::new();
if process.execute_args(
&["fossil", "info"].map(|s| s.to_string()).to_vec(),
diff --git a/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs b/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
index 689c0e8..a5c6ed3 100644
--- a/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
+++ b/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
@@ -80,7 +80,7 @@ impl GitBitbucketDriver {
self.repository = m.get(&CaptureKey::ByIndex(2)).cloned().unwrap_or_default();
self.inner.origin_url = "bitbucket.org".to_string();
self.inner.cache = Some(Cache::new(
- &*self.inner.io,
+ self.inner.io.clone_box(),
&implode(
"/",
&[
@@ -97,6 +97,8 @@ impl GitBitbucketDriver {
],
),
None,
+ None,
+ false,
));
self.inner.cache.as_mut().unwrap().set_read_only(
self.inner
@@ -209,7 +211,11 @@ impl GitBitbucketDriver {
.and_then(|v| v.as_string())
.map(String::from);
- self.repo_data = repo_data;
+ // TODO(phase-b): unwrap PhpMixed::Array into the typed IndexMap stored on self
+ self.repo_data = match repo_data {
+ PhpMixed::Array(m) => m.into_iter().map(|(k, v)| (k, *v)).collect(),
+ _ => IndexMap::new(),
+ };
Ok(true)
}
@@ -226,13 +232,20 @@ impl GitBitbucketDriver {
if !self.inner.info_cache.contains_key(identifier) {
let mut composer: Option<IndexMap<String, PhpMixed>> = None;
if self.inner.should_cache(identifier) && {
- let res = self
- .inner
- .cache
- .as_ref()
- .and_then(|c| c.read(identifier).ok().flatten());
+ let res = self.inner.cache.as_mut().and_then(|c| c.read(identifier));
if let Some(res) = res {
- composer = Some(JsonFile::parse_json(&res, None)?);
+ // TODO(phase-b): wrap parsed PhpMixed::Array into the IndexMap-shaped composer slot
+ composer = Some(
+ JsonFile::parse_json(Some(&res), None)?
+ .as_array()
+ .cloned()
+ .map(|m| {
+ m.into_iter()
+ .map(|(k, v)| (k, *v))
+ .collect::<IndexMap<String, PhpMixed>>()
+ })
+ .unwrap_or_default(),
+ );
true
} else {
false
@@ -248,7 +261,7 @@ impl GitBitbucketDriver {
)?;
if self.inner.should_cache(identifier) {
- self.inner.cache.as_ref().unwrap().write(
+ self.inner.cache.as_mut().unwrap().write(
identifier,
&JsonFile::encode_with_indent(
&PhpMixed::Array(
@@ -422,10 +435,10 @@ impl GitBitbucketDriver {
],
);
- Ok(Some(
- self.fetch_with_oauth_credentials(&resource, false)?
- .get_body(),
- ))
+ Ok(self
+ .fetch_with_oauth_credentials(&resource, false)?
+ .get_body()
+ .map(|s| s.to_string()))
}
/// @inheritDoc
@@ -465,7 +478,8 @@ impl GitBitbucketDriver {
/// @inheritDoc
pub fn get_source(&self, identifier: &str) -> IndexMap<String, String> {
if let Some(fallback) = self.fallback_driver.as_ref() {
- return fallback.get_source(identifier);
+ // TODO(phase-b): trait returns Result; flatten for the inherent signature here
+ return fallback.get_source(identifier).unwrap_or_default();
}
let mut m: IndexMap<String, String> = IndexMap::new();
@@ -481,7 +495,8 @@ impl GitBitbucketDriver {
/// @inheritDoc
pub fn get_dist(&self, identifier: &str) -> Option<IndexMap<String, String>> {
if let Some(fallback) = self.fallback_driver.as_ref() {
- return fallback.get_dist(identifier);
+ // TODO(phase-b): trait returns Result; flatten for the inherent signature here
+ return fallback.get_dist(identifier).ok().flatten();
}
let url = sprintf(
@@ -685,7 +700,8 @@ impl GitBitbucketDriver {
None,
)?;
- if let Some(te) = e.downcast_ref::<TransportException>() {
+ {
+ let te = &e;
let code = te.get_code();
let in_set = in_array(
PhpMixed::Int(code),
@@ -703,7 +719,7 @@ impl GitBitbucketDriver {
if !self.inner.io.has_authentication(&self.inner.origin_url)
&& bitbucket_util.authorize_oauth(&self.inner.origin_url)
{
- return self.inner.get_contents(url);
+ return self.inner.get_contents(url).map_err(anyhow::Error::from);
}
if !self.inner.io.is_interactive() && fetching_repo_data {
@@ -714,15 +730,15 @@ impl GitBitbucketDriver {
.insert("url".to_string(), PhpMixed::String("dummy".to_string()));
return Ok(Response::new(
headers,
- 200,
- IndexMap::new(),
- "null".to_string(),
- ));
+ Some(200),
+ vec![],
+ Some("null".to_string()),
+ )??);
}
}
}
- Err(e)
+ Err(e.into())
}
}
}
@@ -786,7 +802,8 @@ impl GitBitbucketDriver {
r"/https:\/\/([^@]+@)?/",
"https://",
m.get("href").and_then(|v| v.as_string()).unwrap_or(""),
- );
+ )
+ .unwrap_or_default();
}
}
}
diff --git a/crates/shirabe/src/repository/vcs/git_driver.rs b/crates/shirabe/src/repository/vcs/git_driver.rs
index 07836bf..7ab185f 100644
--- a/crates/shirabe/src/repository/vcs/git_driver.rs
+++ b/crates/shirabe/src/repository/vcs/git_driver.rs
@@ -29,6 +29,24 @@ pub struct GitDriver {
}
impl GitDriver {
+ pub fn new(
+ repo_config: IndexMap<String, shirabe_php_shim::PhpMixed>,
+ io: Box<dyn IOInterface>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ http_downloader: std::rc::Rc<
+ std::cell::RefCell<crate::util::http_downloader::HttpDownloader>,
+ >,
+ process: std::rc::Rc<std::cell::RefCell<ProcessExecutor>>,
+ ) -> Self {
+ Self {
+ inner: VcsDriverBase::new(repo_config, io, config, http_downloader, process),
+ tags: None,
+ branches: None,
+ root_identifier: None,
+ repo_dir: String::new(),
+ }
+ }
+
pub fn initialize(&mut self) -> anyhow::Result<()> {
let cache_url;
if Filesystem::is_local_path(&self.inner.url) {
@@ -65,12 +83,16 @@ impl GitDriver {
self.repo_dir = format!(
"{}/{}/",
cache_vcs_dir,
- Preg::replace(r"{[^a-z0-9.]}i", "-", Url::sanitize(self.inner.url.clone()))?
+ Preg::replace(
+ r"{[^a-z0-9.]}i",
+ "-",
+ &Url::sanitize(self.inner.url.clone())
+ )?
);
GitUtil::clean_env(&self.inner.process);
- let fs = Filesystem::new(None);
+ let mut fs = Filesystem::new(None);
fs.ensure_directory_exists(&dirname(&self.repo_dir))?;
if !is_writable(&dirname(&self.repo_dir)) {
@@ -96,8 +118,8 @@ impl GitDriver {
.into());
}
- let git_util = GitUtil::new(
- &*self.inner.io,
+ let mut git_util = GitUtil::new(
+ self.inner.io.clone_box(),
std::rc::Rc::clone(&self.inner.config),
std::rc::Rc::clone(&self.inner.process),
std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(None))),
@@ -113,10 +135,10 @@ impl GitDriver {
}
.into());
}
- self.inner.io.write_error3(shirabe_php_shim::PhpMixed::String(format!(
+ self.inner.io.write_error3(&format!(
"<error>Failed to update {}, package information from this repository may be outdated</error>",
self.inner.url
- )), true, io_interface::NORMAL);
+ ), true, io_interface::NORMAL);
}
cache_url = self.inner.url.clone();
@@ -134,12 +156,15 @@ impl GitDriver {
.unwrap_or("")
.to_string();
self.inner.cache = Some(Cache::new(
- &*self.inner.io,
- format!(
+ self.inner.io.clone_box(),
+ &format!(
"{}/{}",
cache_repo_dir,
- Preg::replace(r"{[^a-z0-9.]}i", "-", Url::sanitize(cache_url))?
+ Preg::replace(r"{[^a-z0-9.]}i", "-", &Url::sanitize(cache_url))?
),
+ None,
+ None,
+ false,
));
self.inner.cache.as_mut().map(|c| {
c.set_read_only(
@@ -159,15 +184,15 @@ impl GitDriver {
if self.root_identifier.is_none() {
self.root_identifier = Some("master".to_string());
- let git_util = GitUtil::new(
- &*self.inner.io,
+ let mut git_util = GitUtil::new(
+ self.inner.io.clone_box(),
std::rc::Rc::clone(&self.inner.config),
std::rc::Rc::clone(&self.inner.process),
std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(None))),
);
if !Filesystem::is_local_path(&self.inner.url) {
let default_branch =
- git_util.get_mirror_default_branch(&self.inner.url, &self.repo_dir, false)?;
+ git_util.get_mirror_default_branch(&self.inner.url, &self.repo_dir, false);
if let Some(branch) = default_branch {
self.root_identifier = Some(branch.clone());
return Ok(branch);
@@ -269,7 +294,7 @@ impl GitDriver {
let command = GitUtil::build_rev_list_command(
&self.inner.process,
- &[
+ vec![
"-n1".to_string(),
"--format=%at".to_string(),
identifier.to_string(),
@@ -406,7 +431,11 @@ impl GitDriver {
{
return Ok(true);
}
- GitUtil::check_for_repo_ownership_error(&process.borrow().get_error_output(), &url);
+ GitUtil::check_for_repo_ownership_error(
+ &process.borrow().get_error_output(),
+ &url,
+ Some(io),
+ )?;
}
if !deep {
@@ -421,7 +450,7 @@ impl GitDriver {
"GitDriver::supports requires Rc<RefCell<Config>>: not yet ported"
));
#[allow(unreachable_code)]
- let git_util = GitUtil::new(
+ let mut git_util = GitUtil::new(
io.clone_box(),
todo!(),
std::rc::Rc::clone(&process),
@@ -430,7 +459,7 @@ impl GitDriver {
GitUtil::clean_env(&process);
let result = git_util.run_commands(
- &[vec![
+ vec![vec![
"git".to_string(),
"ls-remote".to_string(),
"--heads".to_string(),
@@ -438,7 +467,9 @@ impl GitDriver {
"%url%".to_string(),
]],
url,
- &sys_get_temp_dir(),
+ Some(&sys_get_temp_dir()),
+ false,
+ None,
);
match result {
Ok(_) => Ok(true),
diff --git a/crates/shirabe/src/repository/vcs/github_driver.rs b/crates/shirabe/src/repository/vcs/github_driver.rs
index 93bfcdb..17463c1 100644
--- a/crates/shirabe/src/repository/vcs/github_driver.rs
+++ b/crates/shirabe/src/repository/vcs/github_driver.rs
@@ -88,7 +88,7 @@ impl GitHubDriver {
self.inner.origin_url = "github.com".to_string();
}
self.inner.cache = Some(Cache::new(
- self.inner.io.as_ref(),
+ self.inner.io.clone_box(),
&format!(
"{}/{}/{}/{}",
self.inner
@@ -186,7 +186,11 @@ impl GitHubDriver {
pub fn get_source(&self, identifier: &str) -> IndexMap<String, PhpMixed> {
if let Some(ref git_driver) = self.git_driver {
- return git_driver.get_source(identifier);
+ return git_driver
+ .get_source(identifier)
+ .into_iter()
+ .map(|(k, v)| (k, PhpMixed::String(v)))
+ .collect();
}
let url = if self.is_private {
// Private GitHub repositories should be accessed using the
@@ -239,17 +243,21 @@ impl GitHubDriver {
&& self
.inner
.cache
- .as_ref()
+ .as_mut()
.and_then(|c| c.read(identifier))
.is_some()
{
let res = self
.inner
.cache
- .as_ref()
+ .as_mut()
.and_then(|c| c.read(identifier))
.unwrap_or_default();
- JsonFile::parse_json(&res, None)?
+ // TODO(phase-b): cached payload is JSON string; parse to PhpMixed -> Option<IndexMap>
+ let parsed = JsonFile::parse_json(Some(&res), None)?;
+ parsed
+ .as_array()
+ .map(|m| m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect())
} else {
let file_content = self.get_file_content("composer.json", identifier)?;
let composer = VcsDriverBase::finish_base_composer_information(
@@ -260,11 +268,17 @@ impl GitHubDriver {
if self.inner.should_cache(identifier) {
if let Some(ref composer_map) = composer {
- self.inner.cache.as_ref().map(|c| {
+ let php_value: PhpMixed = PhpMixed::Array(
+ composer_map
+ .iter()
+ .map(|(k, v)| (k.clone(), Box::new(v.clone())))
+ .collect(),
+ );
+ self.inner.cache.as_mut().map(|c| {
c.write(
identifier,
- &JsonFile::encode_with_options(
- composer_map,
+ &JsonFile::encode(
+ &php_value,
shirabe_php_shim::JSON_UNESCAPED_UNICODE
| shirabe_php_shim::JSON_UNESCAPED_SLASHES,
),
@@ -410,10 +424,11 @@ impl GitHubDriver {
] {
let mut options: IndexMap<String, PhpMixed> = IndexMap::new();
options.insert("retry-auth-failure".to_string(), PhpMixed::Bool(false));
- let response = self.inner.http_downloader.borrow_mut().get(
- file_url,
- &PhpMixed::Array(options.into_iter().map(|(k, v)| (k, Box::new(v))).collect()),
- );
+ let response = self
+ .inner
+ .http_downloader
+ .borrow_mut()
+ .get(file_url, options);
let response = match response {
Ok(r) => r,
Err(_) => continue,
@@ -1004,7 +1019,8 @@ impl GitHubDriver {
std::rc::Rc::clone(&self.inner.config),
Some(std::rc::Rc::clone(&self.inner.process)),
Some(std::rc::Rc::clone(&self.inner.http_downloader)),
- )?;
+ )
+ .map_err(|err| TransportException::new(err.to_string(), 0))?;
match e.code {
401 | 404 => {
@@ -1018,12 +1034,8 @@ impl GitHubDriver {
}
if !self.inner.io.is_interactive() {
- self.attempt_clone_fallback(Some(&e)).map_err(|err| {
- TransportException {
- message: err.to_string(),
- code: 0,
- }
- })?;
+ self.attempt_clone_fallback(Some(&e))
+ .map_err(|err| TransportException::new(err.to_string(), 0))?;
let mut req = IndexMap::new();
req.insert("url".to_string(), PhpMixed::String("dummy".to_string()));
@@ -1088,12 +1100,8 @@ impl GitHubDriver {
}
if !self.inner.io.is_interactive() && fetching_repo_data {
- self.attempt_clone_fallback(Some(&e)).map_err(|err| {
- TransportException {
- message: err.to_string(),
- code: 0,
- }
- })?;
+ self.attempt_clone_fallback(Some(&e))
+ .map_err(|err| TransportException::new(err.to_string(), 0))?;
let mut req = IndexMap::new();
req.insert("url".to_string(), PhpMixed::String("dummy".to_string()));
@@ -1286,7 +1294,7 @@ impl GitHubDriver {
repo_config.insert("url".to_string(), PhpMixed::String(url.to_string()));
let mut git_driver = GitDriver::new(
repo_config,
- self.inner.io.clone(),
+ self.inner.io.clone_box(),
self.inner.config.clone(),
std::rc::Rc::clone(&self.inner.http_downloader),
std::rc::Rc::clone(&self.inner.process),
diff --git a/crates/shirabe/src/repository/vcs/gitlab_driver.rs b/crates/shirabe/src/repository/vcs/gitlab_driver.rs
index e00bbf8..3efb38c 100644
--- a/crates/shirabe/src/repository/vcs/gitlab_driver.rs
+++ b/crates/shirabe/src/repository/vcs/gitlab_driver.rs
@@ -183,7 +183,7 @@ impl GitLabDriver {
.unwrap_or_default();
self.inner.cache = Some(Cache::new(
- self.inner.io.as_ref(),
+ self.inner.io.clone_box(),
&format!(
"{}/{}/{}/{}",
self.inner
@@ -240,17 +240,28 @@ impl GitLabDriver {
&& self
.inner
.cache
- .as_ref()
+ .as_mut()
.and_then(|c| c.read(identifier))
.is_some()
{
let res = self
.inner
.cache
- .as_ref()
+ .as_mut()
.and_then(|c| c.read(identifier))
.unwrap_or_default();
- JsonFile::parse_json(&res, None)?
+ // TODO(phase-b): cached payload is wrapped to satisfy outer Option type
+ Some(
+ JsonFile::parse_json(Some(&res), None)?
+ .as_array()
+ .cloned()
+ .map(|m| {
+ m.into_iter()
+ .map(|(k, v)| (k, *v))
+ .collect::<IndexMap<String, PhpMixed>>()
+ })
+ .unwrap_or_default(),
+ )
} else {
let file_content = self.get_file_content("composer.json", identifier)?;
let composer = VcsDriverBase::finish_base_composer_information(
@@ -261,11 +272,17 @@ impl GitLabDriver {
if self.inner.should_cache(identifier) {
if let Some(ref composer_map) = composer {
- self.inner.cache.as_ref().map(|c| {
+ self.inner.cache.as_mut().map(|c| {
c.write(
identifier,
- &JsonFile::encode_with_options(
- composer_map,
+ &JsonFile::encode(
+ &PhpMixed::Array(
+ composer_map
+ .clone()
+ .into_iter()
+ .map(|(k, v)| (k, Box::new(v)))
+ .collect(),
+ ),
shirabe_php_shim::JSON_UNESCAPED_UNICODE
| shirabe_php_shim::JSON_UNESCAPED_SLASHES,
),
@@ -281,7 +298,7 @@ impl GitLabDriver {
if let Some(ref mut composer) = composer {
// specials for gitlab (this data is only available if authentication is provided)
if composer.contains_key("support")
- && !is_array(composer.get("support").cloned().unwrap_or(PhpMixed::Null))
+ && !is_array(&composer.get("support").cloned().unwrap_or(PhpMixed::Null))
{
composer.insert("support".to_string(), PhpMixed::Array(IndexMap::new()));
}
@@ -501,7 +518,11 @@ impl GitLabDriver {
pub fn get_source(&self, identifier: &str) -> IndexMap<String, PhpMixed> {
if let Some(ref git_driver) = self.git_driver {
- return git_driver.get_source(identifier);
+ return git_driver
+ .get_source(identifier)
+ .into_iter()
+ .map(|(k, v)| (k, PhpMixed::String(v)))
+ .collect();
}
let mut result = IndexMap::new();
@@ -747,7 +768,7 @@ impl GitLabDriver {
repo_config.insert("url".to_string(), PhpMixed::String(url.to_string()));
let mut git_driver = GitDriver::new(
repo_config,
- self.inner.io.clone(),
+ self.inner.io.clone_box(),
self.inner.config.clone(),
std::rc::Rc::clone(&self.inner.http_downloader),
std::rc::Rc::clone(&self.inner.process),
@@ -766,10 +787,9 @@ impl GitLabDriver {
match response_result {
Ok(response) => {
if fetching_repo_data {
- let json = response.decode_json().map_err(|e| TransportException {
- message: e.to_string(),
- code: 0,
- })?;
+ let json = response
+ .decode_json()
+ .map_err(|e| TransportException::new(e.to_string(), 0))?;
let json_map = match json {
PhpMixed::Array(ref m) => m.clone(),
_ => IndexMap::new(),
@@ -815,10 +835,7 @@ impl GitLabDriver {
);
self.attempt_clone_fallback()
- .map_err(|e| TransportException {
- message: e.to_string(),
- code: 0,
- })?;
+ .map_err(|e| TransportException::new(e.to_string(), 0))?;
let mut req = IndexMap::new();
req.insert("url".to_string(), PhpMixed::String("dummy".to_string()));
@@ -841,23 +858,26 @@ impl GitLabDriver {
.and_then(|v| v.as_string())
== Some("disabled")
{
- return Err(TransportException {
- message: "The GitLab repository is disabled in the project"
- .to_string(),
- code: 400,
- });
+ return Err(TransportException::new(
+ "The GitLab repository is disabled in the project".to_string(),
+ 400,
+ ));
}
- if !empty(&json_map.get("id").cloned().unwrap_or(PhpMixed::Null)) {
+ if !empty(
+ &*json_map
+ .get("id")
+ .cloned()
+ .unwrap_or(Box::new(PhpMixed::Null)),
+ ) {
self.is_private = false;
}
- return Err(TransportException {
- message:
- "GitLab API seems to not be authenticated as it did not return a default_branch"
+ return Err(TransportException::new(
+ "GitLab API seems to not be authenticated as it did not return a default_branch"
.to_string(),
- code: 401,
- });
+ 401,
+ ));
}
}
@@ -869,7 +889,8 @@ impl GitLabDriver {
std::rc::Rc::clone(&self.inner.config),
Some(std::rc::Rc::clone(&self.inner.process)),
Some(std::rc::Rc::clone(&self.inner.http_downloader)),
- )?;
+ )
+ .map_err(|err| TransportException::new(err.to_string(), 0))?;
match e.code {
401 | 404 => {
@@ -885,16 +906,14 @@ impl GitLabDriver {
if git_lab_util.is_oauth_expired(&self.inner.origin_url)
&& git_lab_util
.authorize_oauth_refresh(&self.scheme, &self.inner.origin_url)
+ .map_err(|err| TransportException::new(err.to_string(), 0))?
{
return self.inner.get_contents(url);
}
if !self.inner.io.is_interactive() {
self.attempt_clone_fallback()
- .map_err(|err| TransportException {
- message: err.to_string(),
- code: 0,
- })?;
+ .map_err(|err| TransportException::new(err.to_string(), 0))?;
let mut req = IndexMap::new();
req.insert("url".to_string(), PhpMixed::String("dummy".to_string()));
@@ -935,10 +954,7 @@ impl GitLabDriver {
if !self.inner.io.is_interactive() && fetching_repo_data {
self.attempt_clone_fallback()
- .map_err(|err| TransportException {
- message: err.to_string(),
- code: 0,
- })?;
+ .map_err(|err| TransportException::new(err.to_string(), 0))?;
let mut req = IndexMap::new();
req.insert("url".to_string(), PhpMixed::String("dummy".to_string()));
@@ -1095,7 +1111,9 @@ impl GitLabDriver {
false,
) || (port_number.is_some()
&& in_array(
- PhpMixed::String(Preg::replace(r"{:\d+}", "", &guessed_domain)),
+ PhpMixed::String(
+ Preg::replace(r"{:\d+}", "", &guessed_domain).unwrap_or_default(),
+ ),
configured_domains,
false,
))
diff --git a/crates/shirabe/src/repository/vcs/hg_driver.rs b/crates/shirabe/src/repository/vcs/hg_driver.rs
index f7c0c16..eb1be8f 100644
--- a/crates/shirabe/src/repository/vcs/hg_driver.rs
+++ b/crates/shirabe/src/repository/vcs/hg_driver.rs
@@ -10,7 +10,7 @@ use crate::util::hg::Hg as HgUtils;
use crate::util::url::Url;
use chrono::{DateTime, Utc};
use indexmap::IndexMap;
-use shirabe_external_packages::composer::pcre::preg::Preg;
+use shirabe_external_packages::composer::pcre::preg::{CaptureKey, Preg};
use shirabe_php_shim::{RuntimeException, dirname, is_dir, is_writable};
#[derive(Debug)]
@@ -43,10 +43,10 @@ impl HgDriver {
}
let sanitized =
- Preg::replace(r"{[^a-z0-9]}i", "-", Url::sanitize(self.inner.url.clone()));
+ Preg::replace(r"{[^a-z0-9]}i", "-", &Url::sanitize(self.inner.url.clone()))?;
self.repo_dir = format!("{}/{}/", cache_vcs_dir, sanitized);
- let fs = Filesystem::new(None);
+ let mut fs = Filesystem::new(None);
fs.ensure_directory_exists(&cache_vcs_dir)?;
if !is_writable(&dirname(&self.repo_dir)) {
@@ -84,10 +84,10 @@ impl HgDriver {
Some(self.repo_dir.clone()),
) != 0
{
- self.inner.io.write_error3(format!("<error>Failed to update {}, package information from this repository may be outdated ({})</error>", self.inner.url, self.inner.process.borrow().get_error_output()).into(), true, crate::io::io_interface::NORMAL);
+ self.inner.io.write_error3(&format!("<error>Failed to update {}, package information from this repository may be outdated ({})</error>", self.inner.url, self.inner.process.borrow().get_error_output()), true, crate::io::io_interface::NORMAL);
}
} else {
- let fs2 = Filesystem::new(None);
+ let mut fs2 = Filesystem::new(None);
fs2.remove_directory(&self.repo_dir)?;
let repo_dir = self.repo_dir.clone();
@@ -222,10 +222,13 @@ impl HgDriver {
);
for tag in self.inner.process.borrow().split_lines(&output) {
if !tag.is_empty() {
- if let Some(m) = Preg::match_(r"^([^\s]+)\s+\d+:(.*)$", &tag) {
+ let mut m: IndexMap<CaptureKey, String> = IndexMap::new();
+ if Preg::match_strict_groups3(r"^([^\s]+)\s+\d+:(.*)$", &tag, Some(&mut m))
+ .unwrap_or(false)
+ {
tags.insert(
- m.get("1").cloned().unwrap_or_default(),
- m.get("2").cloned().unwrap_or_default(),
+ m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(),
+ m.get(&CaptureKey::ByIndex(2)).cloned().unwrap_or_default(),
);
}
}
@@ -251,10 +254,20 @@ impl HgDriver {
);
for branch in self.inner.process.borrow().split_lines(&output) {
if !branch.is_empty() {
- if let Some(m) = Preg::match_(r"^([^\s]+)\s+\d+:([a-f0-9]+)", &branch) {
- let name = m.get("1").cloned().unwrap_or_default();
+ let mut m: IndexMap<CaptureKey, String> = IndexMap::new();
+ if Preg::match_strict_groups3(
+ r"^([^\s]+)\s+\d+:([a-f0-9]+)",
+ &branch,
+ Some(&mut m),
+ )
+ .unwrap_or(false)
+ {
+ let name = m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default();
if !name.starts_with('-') {
- branches.insert(name, m.get("2").cloned().unwrap_or_default());
+ branches.insert(
+ name,
+ m.get(&CaptureKey::ByIndex(2)).cloned().unwrap_or_default(),
+ );
}
}
}
@@ -268,10 +281,20 @@ impl HgDriver {
);
for branch in self.inner.process.borrow().split_lines(&output) {
if !branch.is_empty() {
- if let Some(m) = Preg::match_(r"^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$", &branch) {
- let name = m.get("1").cloned().unwrap_or_default();
+ let mut m: IndexMap<CaptureKey, String> = IndexMap::new();
+ if Preg::match_strict_groups3(
+ r"^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$",
+ &branch,
+ Some(&mut m),
+ )
+ .unwrap_or(false)
+ {
+ let name = m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default();
if !name.starts_with('-') {
- bookmarks.insert(name, m.get("2").cloned().unwrap_or_default());
+ bookmarks.insert(
+ name,
+ m.get(&CaptureKey::ByIndex(2)).cloned().unwrap_or_default(),
+ );
}
}
}
@@ -301,7 +324,7 @@ impl HgDriver {
return false;
}
- let process = crate::util::process_executor::ProcessExecutor::new(io);
+ let mut process = crate::util::process_executor::ProcessExecutor::new(io);
let mut output = String::new();
if process.execute_args(
&["hg", "summary"].map(|s| s.to_string()).to_vec(),
@@ -317,14 +340,14 @@ impl HgDriver {
return false;
}
- let process = crate::util::process_executor::ProcessExecutor::new(io);
+ let mut process = crate::util::process_executor::ProcessExecutor::new(io);
let mut ignored = String::new();
let exit = process.execute_args(
&["hg", "identify", "--", url]
.map(|s| s.to_string())
.to_vec(),
&mut ignored,
- None,
+ (),
);
exit == 0
diff --git a/crates/shirabe/src/repository/vcs/perforce_driver.rs b/crates/shirabe/src/repository/vcs/perforce_driver.rs
index e3aa868..a5b0d02 100644
--- a/crates/shirabe/src/repository/vcs/perforce_driver.rs
+++ b/crates/shirabe/src/repository/vcs/perforce_driver.rs
@@ -44,9 +44,9 @@ impl PerforceDriver {
let repo_config = self.inner.repo_config.clone();
self.init_perforce(&repo_config)?;
self.perforce.as_mut().unwrap().p4_login()?;
- self.perforce.as_mut().unwrap().check_stream()?;
+ self.perforce.as_mut().unwrap().check_stream();
self.perforce.as_mut().unwrap().write_p4_client_spec()?;
- self.perforce.as_mut().unwrap().connect_client()?;
+ self.perforce.as_mut().unwrap().connect_client();
Ok(())
}
@@ -73,21 +73,26 @@ impl PerforceDriver {
let repo_dir = format!("{}/{}", cache_vcs_dir, self.depot);
self.perforce = Some(Perforce::create(
- repo_config,
- &self.inner.url,
- &repo_dir,
- &self.inner.process,
- self.inner.io.as_ref(),
- )?);
+ repo_config.clone(),
+ self.inner.url.clone(),
+ repo_dir,
+ std::rc::Rc::clone(&self.inner.process),
+ self.inner.io.clone_box(),
+ ));
Ok(())
}
- pub fn get_file_content(&self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
- self.perforce
- .as_ref()
+ pub fn get_file_content(
+ &mut self,
+ file: &str,
+ identifier: &str,
+ ) -> anyhow::Result<Option<String>> {
+ Ok(self
+ .perforce
+ .as_mut()
.unwrap()
- .get_file_content(file, identifier)
+ .get_file_content(file, identifier))
}
pub fn get_change_date(
@@ -101,12 +106,12 @@ impl PerforceDriver {
&self.branch
}
- pub fn get_branches(&self) -> anyhow::Result<IndexMap<String, String>> {
- self.perforce.as_ref().unwrap().get_branches()
+ pub fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(self.perforce.as_mut().unwrap().get_branches())
}
- pub fn get_tags(&self) -> anyhow::Result<IndexMap<String, String>> {
- self.perforce.as_ref().unwrap().get_tags()
+ pub fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(self.perforce.as_mut().unwrap().get_tags())
}
pub fn get_dist(&self, _identifier: &str) -> Option<IndexMap<String, PhpMixed>> {
@@ -130,7 +135,13 @@ impl PerforceDriver {
);
source.insert(
"p4user".to_string(),
- PhpMixed::String(self.perforce.as_ref().unwrap().get_user().to_string()),
+ PhpMixed::String(
+ self.perforce
+ .as_ref()
+ .unwrap()
+ .get_user()
+ .unwrap_or_default(),
+ ),
);
source
}
@@ -139,13 +150,13 @@ impl PerforceDriver {
&self.inner.url
}
- pub fn has_composer_file(&self, identifier: &str) -> bool {
+ pub fn has_composer_file(&mut self, identifier: &str) -> bool {
let path = format!("//{}/{}", self.depot, identifier);
self.perforce
- .as_ref()
+ .as_mut()
.unwrap()
.get_composer_information(&path)
- .map_or(false, |info| !info.is_empty())
+ .map_or(false, |info| info.map_or(false, |i| !i.is_empty()))
}
pub fn get_contents(&self, _url: &str) -> anyhow::Result<Response> {
@@ -156,15 +167,15 @@ impl PerforceDriver {
.into())
}
- pub fn supports(io: &dyn IOInterface, config: &Config, url: &str, deep: bool) -> bool {
+ pub fn supports(io: &dyn IOInterface, _config: &Config, url: &str, deep: bool) -> bool {
if deep || Preg::is_match(r"#\b(perforce|p4)\b#i", url).unwrap_or(false) {
- return Perforce::check_server_exists(url, &ProcessExecutor::new(io));
+ return Perforce::check_server_exists(url, &mut ProcessExecutor::new(io));
}
false
}
pub fn cleanup(&mut self) -> anyhow::Result<()> {
- self.perforce.as_mut().unwrap().cleanup_client_spec()?;
+ self.perforce.as_mut().unwrap().cleanup_client_spec();
self.perforce = None;
Ok(())
}
diff --git a/crates/shirabe/src/repository/vcs/svn_driver.rs b/crates/shirabe/src/repository/vcs/svn_driver.rs
index 8218563..27fccc3 100644
--- a/crates/shirabe/src/repository/vcs/svn_driver.rs
+++ b/crates/shirabe/src/repository/vcs/svn_driver.rs
@@ -94,7 +94,7 @@ impl SvnDriver {
.get("cache-repo-dir")
.as_string()
.unwrap_or(""),
- Preg::replace(r"{[^a-z0-9.]}i", "-", Url::sanitize(self.base_url.clone())),
+ Preg::replace(r"{[^a-z0-9.]}i", "-", &Url::sanitize(self.base_url.clone()))?,
),
None,
None,
@@ -137,10 +137,7 @@ impl SvnDriver {
}
pub(crate) fn should_cache(&self, identifier: &str) -> bool {
- self.inner.cache.is_some()
- && Preg::is_match(r"{@\d+$}", identifier)
- .unwrap_or(false)
- .unwrap_or(false)
+ self.inner.cache.is_some() && Preg::is_match(r"{@\d+$}", identifier).unwrap_or(false)
}
pub fn get_composer_information(
@@ -166,11 +163,11 @@ impl SvnDriver {
.write(&format!("{}.json", identifier), &res)?;
}
- let parsed = JsonFile::parse_json(&res, None)?;
- self.inner
- .info_cache
- .insert(identifier.to_string(), parsed.clone());
- return Ok(parsed);
+ let parsed = JsonFile::parse_json(Some(res.as_str()), None)?;
+ // TODO(phase-b): info_cache expects Option<IndexMap<String, PhpMixed>>;
+ // PhpMixed → IndexMap conversion is non-trivial here. Skip insert/return.
+ let _ = parsed;
+ return Ok(None);
}
}
@@ -473,10 +470,7 @@ impl SvnDriver {
pub fn supports(io: &dyn IOInterface, _config: &Config, url: &str, deep: bool) -> bool {
let url = Self::normalize_url(url);
- if Preg::is_match(r"#(^svn://|^svn\+ssh://|svn\.)#i", &url)
- .unwrap_or(false)
- .unwrap_or(false)
- {
+ if Preg::is_match(r"#(^svn://|^svn\+ssh://|svn\.)#i", &url).unwrap_or(false) {
return true;
}
@@ -496,7 +490,7 @@ impl SvnDriver {
url.clone(),
],
&mut ignored_output,
- None,
+ (),
);
if exit == 0 {
diff --git a/crates/shirabe/src/repository/vcs/vcs_driver.rs b/crates/shirabe/src/repository/vcs/vcs_driver.rs
index e356a6f..45c998b 100644
--- a/crates/shirabe/src/repository/vcs/vcs_driver.rs
+++ b/crates/shirabe/src/repository/vcs/vcs_driver.rs
@@ -70,12 +70,21 @@ impl VcsDriverBase {
}
pub fn get_contents(&self, url: &str) -> anyhow::Result<Response, TransportException> {
- let options = self
+ let options_mixed = self
.repo_config
.get("options")
.cloned()
.unwrap_or(PhpMixed::Array(IndexMap::new()));
- self.http_downloader.borrow_mut().get(url, &options)
+ // TODO(phase-b): convert PhpMixed::Array options into IndexMap<String, PhpMixed> properly.
+ let options: IndexMap<String, PhpMixed> = match options_mixed {
+ PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(),
+ _ => IndexMap::new(),
+ };
+ // TODO(phase-b): map anyhow::Error from HttpDownloader::get into TransportException.
+ self.http_downloader
+ .borrow_mut()
+ .get(url, options)
+ .map_err(|e| TransportException::new(e.to_string(), 0))
}
// Helper for concrete drivers: produces the same value as the trait default
@@ -155,9 +164,15 @@ pub trait VcsDriver: VcsDriverInterface {
) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
if !self.info_cache().contains_key(identifier) {
if self.should_cache(identifier) {
- if let Some(res) = self.cache().and_then(|c| c.read(identifier)) {
- let parsed = JsonFile::parse_json(&res, None)?;
- self.info_cache_mut().insert(identifier.to_string(), parsed);
+ if let Some(res) = self.cache_mut().and_then(|c| c.read(identifier)) {
+ let parsed = JsonFile::parse_json(Some(&res), None)?;
+ // TODO(phase-b): unwrap PhpMixed::Array into IndexMap<String, PhpMixed>.
+ let parsed_map: Option<IndexMap<String, PhpMixed>> = match parsed {
+ PhpMixed::Array(a) => Some(a.into_iter().map(|(k, v)| (k, *v)).collect()),
+ _ => None,
+ };
+ self.info_cache_mut()
+ .insert(identifier.to_string(), parsed_map);
return Ok(self.info_cache().get(identifier).and_then(|v| v.clone()));
}
}
@@ -166,11 +181,18 @@ pub trait VcsDriver: VcsDriverInterface {
if self.should_cache(identifier) {
if let Some(ref composer_map) = composer {
- let encoded = JsonFile::encode_with_options(
- composer_map,
+ // TODO(phase-b): use a dedicated encode-with-options helper; reuse encode for now.
+ let composer_mixed = PhpMixed::Array(
+ composer_map
+ .iter()
+ .map(|(k, v)| (k.clone(), Box::new(v.clone())))
+ .collect(),
+ );
+ let encoded = JsonFile::encode(
+ &composer_mixed,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
);
- self.cache().map(|c| c.write(identifier, &encoded));
+ self.cache_mut().map(|c| c.write(identifier, &encoded));
}
}
@@ -194,14 +216,14 @@ pub trait VcsDriver: VcsDriverInterface {
};
let composer = JsonFile::parse_json(
- &composer_file_content,
+ Some(&composer_file_content),
Some(&format!("{}:composer.json", identifier)),
)?;
- let mut composer = match composer {
- None => return Ok(None),
- Some(c) if c.is_empty() => return Ok(None),
- Some(c) => c,
+ // TODO(phase-b): unwrap PhpMixed::Array into IndexMap<String, PhpMixed>.
+ let mut composer: IndexMap<String, PhpMixed> = match composer {
+ PhpMixed::Array(a) if !a.is_empty() => a.into_iter().map(|(k, v)| (k, *v)).collect(),
+ _ => return Ok(None),
};
if !composer.contains_key("time")
@@ -235,12 +257,21 @@ pub trait VcsDriver: VcsDriverInterface {
}
fn get_contents(&self, url: &str) -> anyhow::Result<Response, TransportException> {
- let options = self
+ let options_mixed = self
.repo_config()
.get("options")
.cloned()
.unwrap_or(PhpMixed::Array(IndexMap::new()));
- self.http_downloader().borrow_mut().get(url, &options)
+ // TODO(phase-b): convert PhpMixed::Array options into IndexMap<String, PhpMixed> properly.
+ let options: IndexMap<String, PhpMixed> = match options_mixed {
+ PhpMixed::Array(a) => a.into_iter().map(|(k, v)| (k, *v)).collect(),
+ _ => IndexMap::new(),
+ };
+ // TODO(phase-b): map anyhow::Error from HttpDownloader::get into TransportException.
+ self.http_downloader()
+ .borrow_mut()
+ .get(url, options)
+ .map_err(|e| TransportException::new(e.to_string(), 0))
}
fn cleanup(&self) {}