use super::candidate_error::{CandidateError, CandidateFailure};
use super::candidate_prediction::{CandidateRequest, PreparedCandidates, prepare_candidates};
use super::config_schema::PolicyConfig;
use super::policy_registry::{PolicyId, Severity};
use super::repository_facts::RepositoryFacts;
use super::repository_location::RepositoryLocation;
use super::rule_commit_index::IndexVsHead;
use super::rule_commit_sequencer::SequencerState;
use super::test_support::REAL_GIT;
use super::transaction_git::GitContext;
use super::worktree_identity::WorktreeIdentity;
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
#[derive(Clone, Debug)]
pub(crate) struct ScriptedFacts {
pub(crate) location: Result<RepositoryLocation, String>,
pub(crate) index: Result<IndexVsHead, String>,
pub(crate) sequencer: Result<SequencerState, String>,
pub(crate) remote_guess: Result<bool, String>,
pub(crate) asked: Vec<String>,
pub(crate) candidates_repository: Option<PathBuf>,
}
impl RepositoryFacts for ScriptedFacts {
fn location(&mut self) -> Result<RepositoryLocation, String> {
let name: String = String::from("location");
if !self.asked.contains(&name) {
self.asked.push(name);
}
return self.location.clone();
}
fn index_vs_head(&mut self) -> Result<IndexVsHead, String> {
self.asked.push(String::from("index"));
return self.index.clone();
}
fn sequencer_state(&mut self) -> Result<SequencerState, String> {
self.asked.push(String::from("sequencer"));
return self.sequencer.clone();
}
fn remote_guess_creates_branch(&mut self, target: &OsStr) -> Result<bool, String> {
self.asked
.push(format!("remote-guess:{}", target.to_string_lossy()));
return self.remote_guess.clone();
}
fn candidates(
&mut self,
request: &CandidateRequest,
) -> Result<PreparedCandidates, CandidateError> {
self.asked.push(String::from("candidates"));
match &self.candidates_repository {
Some(directory) => {
return prepare_candidates(
Path::new(REAL_GIT),
&[OsString::from("-C"), directory.as_os_str().to_os_string()],
&[],
request,
);
}
None => {
return Err(CandidateError::new(
CandidateFailure::GitNotStarted,
"the scripted facts prepare no candidates",
));
}
}
}
fn asked_location(&self) -> Option<Result<RepositoryLocation, String>> {
if self.asked.contains(&String::from("location")) {
return Some(self.location.clone());
}
return None;
}
fn transaction_context(&self) -> GitContext {
return GitContext {
real_git: PathBuf::from(REAL_GIT),
overlay: Vec::new(),
global_prefix: Vec::new(),
};
}
}
pub(crate) fn main_worktree(root: &str, prefix: &str) -> RepositoryLocation {
return RepositoryLocation {
identity: WorktreeIdentity::MainWorktree {
common_dir: PathBuf::from(format!("{root}/.git")),
git_dir: PathBuf::from(format!("{root}/.git")),
worktree_root: PathBuf::from(root),
},
prefix: prefix.as_bytes().to_vec(),
};
}
pub(crate) fn linked_worktree(main: &str, root: &str) -> RepositoryLocation {
return RepositoryLocation {
identity: WorktreeIdentity::LinkedWorktree {
common_dir: PathBuf::from(format!("{main}/.git")),
git_dir: PathBuf::from(format!("{main}/.git/worktrees/linked")),
worktree_root: PathBuf::from(root),
},
prefix: Vec::<u8>::new(),
};
}
pub(crate) fn outside_worktree() -> RepositoryLocation {
return RepositoryLocation {
identity: WorktreeIdentity::OutsideWorktree,
prefix: Vec::<u8>::new(),
};
}
pub(crate) fn scripted_facts() -> ScriptedFacts {
return ScriptedFacts {
location: Ok(main_worktree("/r", "")),
index: Ok(IndexVsHead::Matches),
sequencer: Ok(SequencerState::NotInProgress),
remote_guess: Ok(false),
asked: Vec::<String>::new(),
candidates_repository: None,
};
}
pub(crate) fn with_severity(
config: &PolicyConfig,
policy: PolicyId,
severity: Severity,
) -> PolicyConfig {
let mut changed: PolicyConfig = config.clone();
for setting in &mut changed.settings {
if setting.id == policy {
setting.severity = severity;
}
}
return changed;
}