aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/repository/vcs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-06 22:40:30 +0900
committernsfisis <nsfisis@gmail.com>2026-06-06 22:54:44 +0900
commitc028a9d5c737de5d2b259638a0a76b999364a262 (patch)
tree36c7678a335d284e6d2139346660c77f1e124ddc /crates/shirabe/src/repository/vcs
parent33550b03c1724fbc8c1c8630c3b03fca1f0c0dc7 (diff)
downloadphp-shirabe-c028a9d5c737de5d2b259638a0a76b999364a262.tar.gz
php-shirabe-c028a9d5c737de5d2b259638a0a76b999364a262.tar.zst
php-shirabe-c028a9d5c737de5d2b259638a0a76b999364a262.zip
feat(vcs): implement VcsDriverInterface for all VCS drivers
Reconcile the VcsDriverInterface trait with the concrete drivers so every driver implements it as in PHP, where each driver extends VcsDriver. - Make cache-mutating getters take &mut self in the trait, matching the inherent methods' lazy-cache semantics; update vcs_repository consumers. - Change supports() to take Rc<RefCell<Config>> and return Result<bool>, completing GitDriver::supports deep ls-remote and its config wiring. - Add base get_composer_information to Git/Hg/Fossil/Perforce and an impl VcsDriverInterface block to every driver, delegating to inherent methods and absorbing type differences in the impl. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/repository/vcs')
-rw-r--r--crates/shirabe/src/repository/vcs/forgejo_driver.rs92
-rw-r--r--crates/shirabe/src/repository/vcs/fossil_driver.rs103
-rw-r--r--crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs81
-rw-r--r--crates/shirabe/src/repository/vcs/git_driver.rs107
-rw-r--r--crates/shirabe/src/repository/vcs/github_driver.rs92
-rw-r--r--crates/shirabe/src/repository/vcs/gitlab_driver.rs92
-rw-r--r--crates/shirabe/src/repository/vcs/hg_driver.rs105
-rw-r--r--crates/shirabe/src/repository/vcs/perforce_driver.rs100
-rw-r--r--crates/shirabe/src/repository/vcs/svn_driver.rs87
-rw-r--r--crates/shirabe/src/repository/vcs/vcs_driver.rs53
-rw-r--r--crates/shirabe/src/repository/vcs/vcs_driver_interface.rs21
11 files changed, 827 insertions, 106 deletions
diff --git a/crates/shirabe/src/repository/vcs/forgejo_driver.rs b/crates/shirabe/src/repository/vcs/forgejo_driver.rs
index 30a0932..c93ee70 100644
--- a/crates/shirabe/src/repository/vcs/forgejo_driver.rs
+++ b/crates/shirabe/src/repository/vcs/forgejo_driver.rs
@@ -463,8 +463,8 @@ impl ForgejoDriver {
.and_then(|v| v.clone()))
}
- pub fn get_source(&mut self, identifier: &str) -> IndexMap<String, String> {
- if let Some(ref mut git_driver) = self.git_driver {
+ pub fn get_source(&self, identifier: &str) -> IndexMap<String, String> {
+ if let Some(ref git_driver) = self.git_driver {
return git_driver.get_source(identifier);
}
@@ -490,17 +490,17 @@ impl ForgejoDriver {
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- config: &Config,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
_deep: bool,
- ) -> bool {
+ ) -> anyhow::Result<bool> {
let forgejo_url = ForgejoUrl::try_from(Some(url));
if forgejo_url.is_none() {
- return false;
+ return Ok(false);
}
let forgejo_url = forgejo_url.unwrap();
- let forgejo_domains = config.get("forgejo-domains");
+ let forgejo_domains = config.borrow().get("forgejo-domains");
let in_domains = if let Some(list) = forgejo_domains.as_list() {
list.iter().any(|d| {
d.as_string().map_or(false, |s| {
@@ -511,7 +511,7 @@ impl ForgejoDriver {
false
};
if !in_domains {
- return false;
+ return Ok(false);
}
if !extension_loaded("openssl") {
@@ -524,10 +524,10 @@ impl ForgejoDriver {
io_interface::VERBOSE,
);
- return false;
+ return Ok(false);
}
- true
+ Ok(true)
}
fn setup_git_driver(&mut self, url: &str) -> Result<()> {
@@ -687,3 +687,77 @@ impl ForgejoDriver {
}
}
}
+
+impl crate::repository::vcs::VcsDriverInterface for ForgejoDriver {
+ fn initialize(&mut self) -> anyhow::Result<()> {
+ ForgejoDriver::initialize(self)
+ }
+
+ fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ ForgejoDriver::get_composer_information(self, identifier)
+ }
+
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ ForgejoDriver::get_file_content(self, file, identifier)
+ }
+
+ fn get_change_date(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<chrono::DateTime<chrono::Utc>>> {
+ ForgejoDriver::get_change_date(self, identifier)
+ }
+
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ ForgejoDriver::get_root_identifier(self)
+ }
+
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ ForgejoDriver::get_branches(self)
+ }
+
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ ForgejoDriver::get_tags(self)
+ }
+
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(ForgejoDriver::get_dist(self, identifier))
+ }
+
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(ForgejoDriver::get_source(self, identifier))
+ }
+
+ fn get_url(&self) -> String {
+ ForgejoDriver::get_url(self)
+ }
+
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ match self.get_composer_information(identifier) {
+ Ok(info) => Ok(info.is_some()),
+ Err(e) => {
+ if e.downcast_ref::<TransportException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
+
+ fn cleanup(&mut self) -> anyhow::Result<()> {
+ Ok(())
+ }
+
+ fn supports(
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ ForgejoDriver::supports(io, config, url, deep)
+ }
+}
diff --git a/crates/shirabe/src/repository/vcs/fossil_driver.rs b/crates/shirabe/src/repository/vcs/fossil_driver.rs
index 1e34f21..5b7ccc1 100644
--- a/crates/shirabe/src/repository/vcs/fossil_driver.rs
+++ b/crates/shirabe/src/repository/vcs/fossil_driver.rs
@@ -8,6 +8,7 @@ use shirabe_php_shim::{PhpMixed, RuntimeException, dirname, is_dir, is_file, is_
use crate::cache::Cache;
use crate::config::Config;
+use crate::downloader::TransportException;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
use crate::repository::vcs::VcsDriverBase;
@@ -292,28 +293,28 @@ impl FossilDriver {
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- config: &Config,
+ _config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
deep: bool,
- ) -> bool {
+ ) -> anyhow::Result<bool> {
if Preg::is_match(
r"#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i",
url,
)
.unwrap_or(false)
{
- return true;
+ return Ok(true);
}
if Preg::is_match(r"!/fossil/|\.fossil!", url).unwrap_or(false) {
- return true;
+ return Ok(true);
}
// local filesystem
if Filesystem::is_local_path(url) {
let url = Filesystem::get_platform_path(url);
if !is_dir(&url) {
- return false;
+ return Ok(false);
}
let mut process = ProcessExecutor::new(Some(io));
@@ -324,10 +325,98 @@ impl FossilDriver {
Some(url),
) == 0
{
- return true;
+ return Ok(true);
}
}
- false
+ Ok(false)
+ }
+
+ pub fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ if let Some(cached) = self.inner.read_cached_composer(identifier)? {
+ return Ok(cached);
+ }
+
+ let file_content = self.get_file_content("composer.json", identifier)?;
+ let composer =
+ VcsDriverBase::finish_base_composer_information(identifier, file_content, || {
+ self.get_change_date(identifier)
+ })?;
+
+ self.inner.write_cached_composer(identifier, composer)
+ }
+}
+
+impl crate::repository::vcs::VcsDriverInterface for FossilDriver {
+ fn initialize(&mut self) -> anyhow::Result<()> {
+ FossilDriver::initialize(self)
+ }
+
+ fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ FossilDriver::get_composer_information(self, identifier)
+ }
+
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ FossilDriver::get_file_content(self, file, identifier)
+ }
+
+ fn get_change_date(&mut self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>> {
+ FossilDriver::get_change_date(self, identifier)
+ }
+
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ Ok(FossilDriver::get_root_identifier(self))
+ }
+
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ FossilDriver::get_branches(self)
+ }
+
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ FossilDriver::get_tags(self)
+ }
+
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(FossilDriver::get_dist(self, identifier))
+ }
+
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(FossilDriver::get_source(self, identifier))
+ }
+
+ fn get_url(&self) -> String {
+ FossilDriver::get_url(self)
+ }
+
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ match self.get_composer_information(identifier) {
+ Ok(info) => Ok(info.is_some()),
+ Err(e) => {
+ if e.downcast_ref::<TransportException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
+
+ fn cleanup(&mut self) -> anyhow::Result<()> {
+ Ok(())
+ }
+
+ fn supports(
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ FossilDriver::supports(io, config, url, deep)
}
}
diff --git a/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs b/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
index 644ac90..2a8d374 100644
--- a/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
+++ b/crates/shirabe/src/repository/vcs/git_bitbucket_driver.rs
@@ -858,17 +858,17 @@ impl GitBitbucketDriver {
/// @inheritDoc
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- _config: &Config,
+ _config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
_deep: bool,
- ) -> bool {
+ ) -> anyhow::Result<bool> {
if !Preg::is_match(
r"#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)?$#i",
url,
)
.unwrap_or(false)
{
- return false;
+ return Ok(false);
}
if !extension_loaded("openssl") {
@@ -881,9 +881,80 @@ impl GitBitbucketDriver {
// PHP: writeError(..., true, io_interface::VERBOSE)
// TODO(phase-b): io_interface::VERBOSE verbosity argument
- return false;
+ return Ok(false);
+ }
+
+ Ok(true)
+ }
+}
+
+impl crate::repository::vcs::VcsDriverInterface for GitBitbucketDriver {
+ fn initialize(&mut self) -> anyhow::Result<()> {
+ GitBitbucketDriver::initialize(self)
+ }
+
+ fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ GitBitbucketDriver::get_composer_information(self, identifier)
+ }
+
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ GitBitbucketDriver::get_file_content(self, file, identifier)
+ }
+
+ fn get_change_date(&mut self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>> {
+ GitBitbucketDriver::get_change_date(self, identifier)
+ }
+
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ GitBitbucketDriver::get_root_identifier(self)
+ }
+
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ GitBitbucketDriver::get_branches(self)
+ }
+
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ GitBitbucketDriver::get_tags(self)
+ }
+
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(GitBitbucketDriver::get_dist(self, identifier))
+ }
+
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(GitBitbucketDriver::get_source(self, identifier))
+ }
+
+ fn get_url(&self) -> String {
+ GitBitbucketDriver::get_url(self)
+ }
+
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ match self.get_composer_information(identifier) {
+ Ok(info) => Ok(info.is_some()),
+ Err(e) => {
+ if e.downcast_ref::<TransportException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
}
+ }
- true
+ fn cleanup(&mut self) -> anyhow::Result<()> {
+ Ok(())
+ }
+
+ fn supports(
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ GitBitbucketDriver::supports(io, config, url, deep)
}
}
diff --git a/crates/shirabe/src/repository/vcs/git_driver.rs b/crates/shirabe/src/repository/vcs/git_driver.rs
index 01aa759..4878ffe 100644
--- a/crates/shirabe/src/repository/vcs/git_driver.rs
+++ b/crates/shirabe/src/repository/vcs/git_driver.rs
@@ -12,6 +12,7 @@ use shirabe_php_shim::{
use crate::cache::Cache;
use crate::config::Config;
+use crate::downloader::TransportException;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
use crate::repository::vcs::VcsDriverBase;
@@ -19,6 +20,7 @@ use crate::util::Filesystem;
use crate::util::Git as GitUtil;
use crate::util::ProcessExecutor;
use crate::util::Url;
+use shirabe_php_shim::PhpMixed;
#[derive(Debug)]
pub struct GitDriver {
@@ -401,7 +403,7 @@ impl GitDriver {
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- _config: &Config,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
deep: bool,
) -> anyhow::Result<bool> {
@@ -446,22 +448,15 @@ impl GitDriver {
let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(Some(
io.clone(),
))));
- // TODO(phase-b): supports() takes &Config; GitUtil now needs Rc<RefCell<Config>>.
- // Skipping clean Rc construction since we cannot reconstruct one from a borrowed &Config.
- let _ = _config;
- return Err(anyhow::anyhow!(
- "GitDriver::supports requires Rc<RefCell<Config>>: not yet ported"
- ));
- #[allow(unreachable_code)]
let mut git_util = GitUtil::new(
io.clone(),
- todo!(),
+ config.clone(),
process.clone(),
std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(None))),
);
GitUtil::clean_env(&process);
- let result = git_util.run_commands(
+ match git_util.run_commands(
vec![vec![
"git".to_string(),
"ls-remote".to_string(),
@@ -473,63 +468,91 @@ impl GitDriver {
Some(&sys_get_temp_dir()),
false,
None,
- );
- match result {
+ ) {
Ok(_) => Ok(true),
- Err(_) => Ok(false),
+ Err(e) => {
+ if e.downcast_ref::<RuntimeException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
}
}
+
+ pub fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ if let Some(cached) = self.inner.read_cached_composer(identifier)? {
+ return Ok(cached);
+ }
+
+ let file_content = self.get_file_content("composer.json", identifier)?;
+ let composer =
+ VcsDriverBase::finish_base_composer_information(identifier, file_content, || {
+ self.get_change_date(identifier)
+ })?;
+
+ self.inner.write_cached_composer(identifier, composer)
+ }
}
-// TODO(phase-b): implement VcsDriverInterface for GitDriver — signatures here
-// differ from the trait (some &mut self vs &self, different return shapes), so
-// each method delegates via todo!() until reconciled.
impl crate::repository::vcs::VcsDriverInterface for GitDriver {
fn initialize(&mut self) -> anyhow::Result<()> {
GitDriver::initialize(self)
}
fn get_composer_information(
- &self,
- _identifier: &str,
- ) -> anyhow::Result<Option<IndexMap<String, shirabe_php_shim::PhpMixed>>> {
- todo!()
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ GitDriver::get_composer_information(self, identifier)
}
- fn get_file_content(&self, _file: &str, _identifier: &str) -> anyhow::Result<Option<String>> {
- todo!()
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ GitDriver::get_file_content(self, file, identifier)
}
- fn get_change_date(&self, _identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>> {
- todo!()
+ fn get_change_date(&mut self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>> {
+ GitDriver::get_change_date(self, identifier)
}
- fn get_root_identifier(&self) -> anyhow::Result<String> {
- todo!()
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ GitDriver::get_root_identifier(self)
}
- fn get_branches(&self) -> anyhow::Result<IndexMap<String, String>> {
- todo!()
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ GitDriver::get_branches(self)
}
- fn get_tags(&self) -> anyhow::Result<IndexMap<String, String>> {
- todo!()
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ GitDriver::get_tags(self)
}
- fn get_dist(&self, _identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
- todo!()
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(GitDriver::get_dist(self, identifier))
}
- fn get_source(&self, _identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
- todo!()
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(GitDriver::get_source(self, identifier))
}
fn get_url(&self) -> String {
GitDriver::get_url(self)
}
- fn has_composer_file(&self, _identifier: &str) -> anyhow::Result<bool> {
- todo!()
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ match self.get_composer_information(identifier) {
+ Ok(info) => Ok(info.is_some()),
+ Err(e) => {
+ if e.downcast_ref::<TransportException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
+ }
}
fn cleanup(&mut self) -> anyhow::Result<()> {
@@ -537,11 +560,11 @@ impl crate::repository::vcs::VcsDriverInterface for GitDriver {
}
fn supports(
- _io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- _config: &Config,
- _url: &str,
- _deep: bool,
- ) -> bool {
- todo!()
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ GitDriver::supports(io, config, url, deep)
}
}
diff --git a/crates/shirabe/src/repository/vcs/github_driver.rs b/crates/shirabe/src/repository/vcs/github_driver.rs
index 093cd03..b3d5e05 100644
--- a/crates/shirabe/src/repository/vcs/github_driver.rs
+++ b/crates/shirabe/src/repository/vcs/github_driver.rs
@@ -939,10 +939,10 @@ impl GitHubDriver {
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- config: &Config,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
_deep: bool,
- ) -> bool {
+ ) -> anyhow::Result<bool> {
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if !Preg::is_match_strict_groups3(
r"#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/([^/]+?)(?:\.git|/)?$#",
@@ -951,7 +951,7 @@ impl GitHubDriver {
)
.unwrap_or(false)
{
- return false;
+ return Ok(false);
}
let origin_url = matches
@@ -968,10 +968,10 @@ impl GitHubDriver {
PhpMixed::String(strtolower(
&Preg::replace(r"{^www\.}i", "", &origin_url).unwrap_or_default(),
)),
- &config.get("github-domains"),
+ &config.borrow().get("github-domains"),
false,
) {
- return false;
+ return Ok(false);
}
if !extension_loaded("openssl") {
@@ -984,10 +984,10 @@ impl GitHubDriver {
io_interface::VERBOSE,
);
- return false;
+ return Ok(false);
}
- true
+ Ok(true)
}
/// Gives back the loaded <github-api>/repos/<owner>/<repo> result
@@ -1324,3 +1324,81 @@ impl GitHubDriver {
None
}
}
+
+impl crate::repository::vcs::VcsDriverInterface for GitHubDriver {
+ fn initialize(&mut self) -> anyhow::Result<()> {
+ GitHubDriver::initialize(self)
+ }
+
+ fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ GitHubDriver::get_composer_information(self, identifier)
+ }
+
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ GitHubDriver::get_file_content(self, file, identifier)
+ }
+
+ fn get_change_date(&mut self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>> {
+ GitHubDriver::get_change_date(self, identifier)
+ }
+
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ GitHubDriver::get_root_identifier(self)
+ }
+
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ GitHubDriver::get_branches(self)
+ }
+
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ GitHubDriver::get_tags(self)
+ }
+
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(GitHubDriver::get_dist(self, identifier).map(|m| {
+ m.into_iter()
+ .map(|(k, v)| (k, v.as_string().unwrap_or("").to_string()))
+ .collect()
+ }))
+ }
+
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(GitHubDriver::get_source(self, identifier)
+ .into_iter()
+ .map(|(k, v)| (k, v.as_string().unwrap_or("").to_string()))
+ .collect())
+ }
+
+ fn get_url(&self) -> String {
+ GitHubDriver::get_url(self)
+ }
+
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ match self.get_composer_information(identifier) {
+ Ok(info) => Ok(info.is_some()),
+ Err(e) => {
+ if e.downcast_ref::<TransportException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
+
+ fn cleanup(&mut self) -> anyhow::Result<()> {
+ Ok(())
+ }
+
+ fn supports(
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ GitHubDriver::supports(io, config, url, deep)
+ }
+}
diff --git a/crates/shirabe/src/repository/vcs/gitlab_driver.rs b/crates/shirabe/src/repository/vcs/gitlab_driver.rs
index 3e2cd38..84a569f 100644
--- a/crates/shirabe/src/repository/vcs/gitlab_driver.rs
+++ b/crates/shirabe/src/repository/vcs/gitlab_driver.rs
@@ -972,14 +972,14 @@ impl GitLabDriver {
/// repository given.
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- config: &Config,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
_deep: bool,
- ) -> bool {
+ ) -> anyhow::Result<bool> {
let mut match_: IndexMap<CaptureKey, String> = IndexMap::new();
if !Preg::is_match_strict_groups3(Self::URL_REGEX, url, Some(&mut match_)).unwrap_or(false)
{
- return false;
+ return Ok(false);
}
let scheme = match_
@@ -1005,14 +1005,14 @@ impl GitLabDriver {
);
if Self::determine_origin(
- &config.get("gitlab-domains"),
+ &config.borrow().get("gitlab-domains"),
guessed_domain,
&mut url_parts,
match_.get(&CaptureKey::ByName("port".to_string())).cloned(),
)
.is_none()
{
- return false;
+ return Ok(false);
}
if scheme == "https" && !extension_loaded("openssl") {
@@ -1025,10 +1025,10 @@ impl GitLabDriver {
io_interface::VERBOSE,
);
- return false;
+ return Ok(false);
}
- true
+ Ok(true)
}
/// Gives back the loaded <gitlab-api>/projects/<owner>/<repo> result
@@ -1122,3 +1122,81 @@ impl GitLabDriver {
None
}
}
+
+impl crate::repository::vcs::VcsDriverInterface for GitLabDriver {
+ fn initialize(&mut self) -> anyhow::Result<()> {
+ GitLabDriver::initialize(self)
+ }
+
+ fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ GitLabDriver::get_composer_information(self, identifier)
+ }
+
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ GitLabDriver::get_file_content(self, file, identifier)
+ }
+
+ fn get_change_date(&mut self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>> {
+ GitLabDriver::get_change_date(self, identifier)
+ }
+
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ GitLabDriver::get_root_identifier(self)
+ }
+
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ GitLabDriver::get_branches(self)
+ }
+
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ GitLabDriver::get_tags(self)
+ }
+
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(GitLabDriver::get_dist(self, identifier).map(|m| {
+ m.into_iter()
+ .map(|(k, v)| (k, v.as_string().unwrap_or("").to_string()))
+ .collect()
+ }))
+ }
+
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(GitLabDriver::get_source(self, identifier)
+ .into_iter()
+ .map(|(k, v)| (k, v.as_string().unwrap_or("").to_string()))
+ .collect())
+ }
+
+ fn get_url(&self) -> String {
+ GitLabDriver::get_url(self)
+ }
+
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ match self.get_composer_information(identifier) {
+ Ok(info) => Ok(info.is_some()),
+ Err(e) => {
+ if e.downcast_ref::<TransportException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
+
+ fn cleanup(&mut self) -> anyhow::Result<()> {
+ Ok(())
+ }
+
+ fn supports(
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ GitLabDriver::supports(io, config, url, deep)
+ }
+}
diff --git a/crates/shirabe/src/repository/vcs/hg_driver.rs b/crates/shirabe/src/repository/vcs/hg_driver.rs
index 9079d71..1686f5d 100644
--- a/crates/shirabe/src/repository/vcs/hg_driver.rs
+++ b/crates/shirabe/src/repository/vcs/hg_driver.rs
@@ -2,6 +2,7 @@
use crate::cache::Cache;
use crate::config::Config;
+use crate::downloader::TransportException;
use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
use crate::io::io_interface;
@@ -12,7 +13,7 @@ use crate::util::Url;
use chrono::{DateTime, Utc};
use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::{CaptureKey, Preg};
-use shirabe_php_shim::{RuntimeException, dirname, is_dir, is_writable};
+use shirabe_php_shim::{PhpMixed, RuntimeException, dirname, is_dir, is_writable};
#[derive(Debug)]
pub struct HgDriver {
@@ -311,23 +312,23 @@ impl HgDriver {
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- config: &Config,
+ _config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
deep: bool,
- ) -> bool {
+ ) -> anyhow::Result<bool> {
if Preg::is_match(
r"#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i",
url,
)
.unwrap_or(false)
{
- return true;
+ return Ok(true);
}
if Filesystem::is_local_path(url) {
let url = Filesystem::get_platform_path(url);
if !is_dir(&url) {
- return false;
+ return Ok(false);
}
let mut process = crate::util::ProcessExecutor::new(Some(io.clone()));
@@ -338,12 +339,12 @@ impl HgDriver {
Some(url),
) == 0
{
- return true;
+ return Ok(true);
}
}
if !deep {
- return false;
+ return Ok(false);
}
let mut process = crate::util::ProcessExecutor::new(Some(io));
@@ -356,6 +357,94 @@ impl HgDriver {
(),
);
- exit == 0
+ Ok(exit == 0)
+ }
+
+ pub fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ if let Some(cached) = self.inner.read_cached_composer(identifier)? {
+ return Ok(cached);
+ }
+
+ let file_content = self.get_file_content("composer.json", identifier)?;
+ let composer =
+ VcsDriverBase::finish_base_composer_information(identifier, file_content, || {
+ self.get_change_date(identifier)
+ })?;
+
+ self.inner.write_cached_composer(identifier, composer)
+ }
+}
+
+impl crate::repository::vcs::VcsDriverInterface for HgDriver {
+ fn initialize(&mut self) -> anyhow::Result<()> {
+ HgDriver::initialize(self)
+ }
+
+ fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ HgDriver::get_composer_information(self, identifier)
+ }
+
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ HgDriver::get_file_content(self, file, identifier)
+ }
+
+ fn get_change_date(&mut self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>> {
+ HgDriver::get_change_date(self, identifier)
+ }
+
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ HgDriver::get_root_identifier(self)
+ }
+
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ HgDriver::get_branches(self)
+ }
+
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ HgDriver::get_tags(self)
+ }
+
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(HgDriver::get_dist(self, identifier))
+ }
+
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(HgDriver::get_source(self, identifier))
+ }
+
+ fn get_url(&self) -> String {
+ HgDriver::get_url(self)
+ }
+
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ match self.get_composer_information(identifier) {
+ Ok(info) => Ok(info.is_some()),
+ Err(e) => {
+ if e.downcast_ref::<TransportException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
+
+ fn cleanup(&mut self) -> anyhow::Result<()> {
+ Ok(())
+ }
+
+ fn supports(
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ HgDriver::supports(io, config, url, deep)
}
}
diff --git a/crates/shirabe/src/repository/vcs/perforce_driver.rs b/crates/shirabe/src/repository/vcs/perforce_driver.rs
index 03948b3..d653869 100644
--- a/crates/shirabe/src/repository/vcs/perforce_driver.rs
+++ b/crates/shirabe/src/repository/vcs/perforce_driver.rs
@@ -169,14 +169,34 @@ impl PerforceDriver {
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- _config: &Config,
+ _config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
deep: bool,
- ) -> bool {
+ ) -> anyhow::Result<bool> {
if deep || Preg::is_match(r"#\b(perforce|p4)\b#i", url).unwrap_or(false) {
- return Perforce::check_server_exists(url, &mut ProcessExecutor::new(Some(io)));
+ return Ok(Perforce::check_server_exists(
+ url,
+ &mut ProcessExecutor::new(Some(io)),
+ ));
}
- false
+ Ok(false)
+ }
+
+ pub fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ if let Some(cached) = self.inner.read_cached_composer(identifier)? {
+ return Ok(cached);
+ }
+
+ let file_content = self.get_file_content("composer.json", identifier)?;
+ let composer =
+ VcsDriverBase::finish_base_composer_information(identifier, file_content, || {
+ self.get_change_date(identifier)
+ })?;
+
+ self.inner.write_cached_composer(identifier, composer)
}
pub fn cleanup(&mut self) -> anyhow::Result<()> {
@@ -193,3 +213,75 @@ impl PerforceDriver {
&self.branch
}
}
+
+impl crate::repository::vcs::VcsDriverInterface for PerforceDriver {
+ fn initialize(&mut self) -> anyhow::Result<()> {
+ PerforceDriver::initialize(self)
+ }
+
+ fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ PerforceDriver::get_composer_information(self, identifier)
+ }
+
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ PerforceDriver::get_file_content(self, file, identifier)
+ }
+
+ fn get_change_date(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<chrono::DateTime<chrono::Utc>>> {
+ PerforceDriver::get_change_date(self, identifier)
+ }
+
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ Ok(PerforceDriver::get_root_identifier(self).to_string())
+ }
+
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ PerforceDriver::get_branches(self)
+ }
+
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ PerforceDriver::get_tags(self)
+ }
+
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(PerforceDriver::get_dist(self, identifier).map(|m| {
+ m.into_iter()
+ .map(|(k, v)| (k, v.as_string().unwrap_or("").to_string()))
+ .collect()
+ }))
+ }
+
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(PerforceDriver::get_source(self, identifier)
+ .into_iter()
+ .map(|(k, v)| (k, v.as_string().unwrap_or("").to_string()))
+ .collect())
+ }
+
+ fn get_url(&self) -> String {
+ PerforceDriver::get_url(self).to_string()
+ }
+
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ Ok(PerforceDriver::has_composer_file(self, identifier))
+ }
+
+ fn cleanup(&mut self) -> anyhow::Result<()> {
+ PerforceDriver::cleanup(self)
+ }
+
+ fn supports(
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ PerforceDriver::supports(io, config, url, deep)
+ }
+}
diff --git a/crates/shirabe/src/repository/vcs/svn_driver.rs b/crates/shirabe/src/repository/vcs/svn_driver.rs
index fc5abb9..3d344ec 100644
--- a/crates/shirabe/src/repository/vcs/svn_driver.rs
+++ b/crates/shirabe/src/repository/vcs/svn_driver.rs
@@ -481,18 +481,18 @@ impl SvnDriver {
pub fn supports(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- _config: &Config,
+ _config: std::rc::Rc<std::cell::RefCell<Config>>,
url: &str,
deep: bool,
- ) -> bool {
+ ) -> Result<bool> {
let url = Self::normalize_url(url);
if Preg::is_match(r"#(^svn://|^svn\+ssh://|svn\.)#i", &url).unwrap_or(false) {
- return true;
+ return Ok(true);
}
// proceed with deep check for local urls since they are fast to process
if !deep && !Filesystem::is_local_path(&url) {
- return false;
+ return Ok(false);
}
let mut process = ProcessExecutor::new(Some(io));
@@ -511,24 +511,24 @@ impl SvnDriver {
if exit == 0 {
// This is definitely a Subversion repository.
- return true;
+ return Ok(true);
}
// Subversion client 1.7 and older
if stripos(&process.get_error_output(), "authorization failed:").is_some() {
// This is likely a remote Subversion repository that requires
// authentication. We will handle actual authentication later.
- return true;
+ return Ok(true);
}
// Subversion client 1.8 and newer
if stripos(&process.get_error_output(), "Authentication failed").is_some() {
// This is likely a remote Subversion or newer repository that requires
// authentication. We will handle actual authentication later.
- return true;
+ return Ok(true);
}
- false
+ Ok(false)
}
/// An absolute path (leading '/') is converted to a file:// url.
@@ -607,3 +607,74 @@ impl SvnDriver {
)
}
}
+
+impl crate::repository::vcs::VcsDriverInterface for SvnDriver {
+ fn initialize(&mut self) -> anyhow::Result<()> {
+ SvnDriver::initialize(self)
+ }
+
+ fn get_composer_information(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ SvnDriver::get_composer_information(self, identifier)
+ }
+
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>> {
+ SvnDriver::get_file_content(self, file, identifier)
+ }
+
+ fn get_change_date(&mut self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>> {
+ SvnDriver::get_change_date(self, identifier)
+ }
+
+ fn get_root_identifier(&mut self) -> anyhow::Result<String> {
+ Ok(SvnDriver::get_root_identifier(self))
+ }
+
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(self.get_branches().clone())
+ }
+
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(self.get_tags().clone())
+ }
+
+ fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>> {
+ Ok(SvnDriver::get_dist(self, identifier))
+ }
+
+ fn get_source(&self, identifier: &str) -> anyhow::Result<IndexMap<String, String>> {
+ Ok(SvnDriver::get_source(self, identifier))
+ }
+
+ fn get_url(&self) -> String {
+ SvnDriver::get_url(self).to_string()
+ }
+
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool> {
+ match self.get_composer_information(identifier) {
+ Ok(info) => Ok(info.is_some()),
+ Err(e) => {
+ if e.downcast_ref::<TransportException>().is_some() {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
+
+ fn cleanup(&mut self) -> anyhow::Result<()> {
+ Ok(())
+ }
+
+ fn supports(
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
+ config: std::rc::Rc<std::cell::RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool> {
+ SvnDriver::supports(io, config, url, deep)
+ }
+}
diff --git a/crates/shirabe/src/repository/vcs/vcs_driver.rs b/crates/shirabe/src/repository/vcs/vcs_driver.rs
index 8c3b571..d87924a 100644
--- a/crates/shirabe/src/repository/vcs/vcs_driver.rs
+++ b/crates/shirabe/src/repository/vcs/vcs_driver.rs
@@ -130,6 +130,57 @@ impl VcsDriverBase {
Ok(Some(composer))
}
+
+ // Caching layer of the base `getComposerInformation`. Concrete drivers that
+ // inherit the base implementation thread their own `get_file_content` /
+ // `get_change_date` fetch between these two calls; splitting read and write
+ // keeps each `self.inner` borrow disjoint from the fetch's `self` borrow.
+ // Returns `Some(_)` when the value is already known (in-memory or on-disk
+ // cache), or `None` when the caller must fetch it.
+ pub fn read_cached_composer(
+ &mut self,
+ identifier: &str,
+ ) -> anyhow::Result<Option<Option<IndexMap<String, PhpMixed>>>> {
+ if self.info_cache.contains_key(identifier) {
+ return Ok(Some(
+ self.info_cache.get(identifier).and_then(|v| v.clone()),
+ ));
+ }
+ if self.should_cache(identifier) {
+ if let Some(res) = self.cache.as_mut().and_then(|c| c.read(identifier)) {
+ let parsed = JsonFile::parse_json(Some(&res), None)?;
+ let composer: Option<IndexMap<String, PhpMixed>> = parsed
+ .as_array()
+ .map(|m| m.iter().map(|(k, v)| (k.clone(), (**v).clone())).collect());
+ self.info_cache
+ .insert(identifier.to_string(), composer.clone());
+ return Ok(Some(composer));
+ }
+ }
+ Ok(None)
+ }
+
+ pub fn write_cached_composer(
+ &mut self,
+ identifier: &str,
+ composer: Option<IndexMap<String, PhpMixed>>,
+ ) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>> {
+ if self.should_cache(identifier) {
+ let encoded = JsonFile::encode_with_options(
+ &composer
+ .clone()
+ .map(PhpMixed::from)
+ .unwrap_or(PhpMixed::Null),
+ JsonEncodeOptions {
+ pretty_print: false,
+ ..Default::default()
+ },
+ );
+ self.cache.as_mut().map(|c| c.write(identifier, &encoded));
+ }
+ self.info_cache.insert(identifier.to_string(), composer);
+ Ok(self.info_cache.get(identifier).and_then(|v| v.clone()))
+ }
}
// TODO(phase-b): the constructor is `final` in PHP; concrete implementations must replicate the
@@ -245,7 +296,7 @@ pub trait VcsDriver: VcsDriverInterface {
}
fn has_composer_file(&mut self, identifier: &str) -> bool {
- match self.get_composer_information(identifier) {
+ match VcsDriver::get_composer_information(self, identifier) {
Ok(Some(_)) => true,
_ => false,
}
diff --git a/crates/shirabe/src/repository/vcs/vcs_driver_interface.rs b/crates/shirabe/src/repository/vcs/vcs_driver_interface.rs
index c002dc5..e845300 100644
--- a/crates/shirabe/src/repository/vcs/vcs_driver_interface.rs
+++ b/crates/shirabe/src/repository/vcs/vcs_driver_interface.rs
@@ -12,19 +12,19 @@ pub trait VcsDriverInterface: std::fmt::Debug {
fn initialize(&mut self) -> anyhow::Result<()>;
fn get_composer_information(
- &self,
+ &mut self,
identifier: &str,
) -> anyhow::Result<Option<IndexMap<String, PhpMixed>>>;
- fn get_file_content(&self, file: &str, identifier: &str) -> anyhow::Result<Option<String>>;
+ fn get_file_content(&mut self, file: &str, identifier: &str) -> anyhow::Result<Option<String>>;
- fn get_change_date(&self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>>;
+ fn get_change_date(&mut self, identifier: &str) -> anyhow::Result<Option<DateTime<Utc>>>;
- fn get_root_identifier(&self) -> anyhow::Result<String>;
+ fn get_root_identifier(&mut self) -> anyhow::Result<String>;
- fn get_branches(&self) -> anyhow::Result<IndexMap<String, String>>;
+ fn get_branches(&mut self) -> anyhow::Result<IndexMap<String, String>>;
- fn get_tags(&self) -> anyhow::Result<IndexMap<String, String>>;
+ fn get_tags(&mut self) -> anyhow::Result<IndexMap<String, String>>;
fn get_dist(&self, identifier: &str) -> anyhow::Result<Option<IndexMap<String, String>>>;
@@ -32,11 +32,16 @@ pub trait VcsDriverInterface: std::fmt::Debug {
fn get_url(&self) -> String;
- fn has_composer_file(&self, identifier: &str) -> anyhow::Result<bool>;
+ fn has_composer_file(&mut self, identifier: &str) -> anyhow::Result<bool>;
fn cleanup(&mut self) -> anyhow::Result<()>;
- fn supports(io: Rc<RefCell<dyn IOInterface>>, config: &Config, url: &str, deep: bool) -> bool
+ fn supports(
+ io: Rc<RefCell<dyn IOInterface>>,
+ config: Rc<RefCell<Config>>,
+ url: &str,
+ deep: bool,
+ ) -> anyhow::Result<bool>
where
Self: Sized;
}