0.0.3-alpha.3
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/knowledge-git-lib/src/backend.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
//! Physical source configuration, generated-state layout and controlled Git process runner.
|
||||
|
||||
@@ -51,6 +51,16 @@ impl crate::GitBackendConfig {
|
||||
pub fn snapshots_path(&self) -> std::path::PathBuf {
|
||||
return self.state_root.join("snapshots");
|
||||
}
|
||||
|
||||
/// Return the directory reserved for temporary isolated write worktrees.
|
||||
pub fn write_worktrees_path(&self) -> std::path::PathBuf {
|
||||
return self.state_root.join("write-worktrees");
|
||||
}
|
||||
|
||||
/// Return the controlled empty global Git configuration path.
|
||||
pub fn empty_global_config_path(&self) -> std::path::PathBuf {
|
||||
return self.state_root.join("empty-global.gitconfig");
|
||||
}
|
||||
}
|
||||
|
||||
/// Coarse physical source kind used by the backend.
|
||||
@@ -155,7 +165,9 @@ impl crate::GitMirror {
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct GitCommandSpec {
|
||||
arguments: Vec<std::ffi::OsString>,
|
||||
environment: Vec<(std::ffi::OsString, std::ffi::OsString)>,
|
||||
executable: std::path::PathBuf,
|
||||
global_config_path: std::path::PathBuf,
|
||||
hooks_path: std::path::PathBuf,
|
||||
operation: crate::GitOperation,
|
||||
}
|
||||
@@ -183,9 +195,20 @@ impl GitCommandRunner for SystemGitRunner {
|
||||
command.env_remove("GIT_INDEX_FILE");
|
||||
command.env_remove("GIT_OBJECT_DIRECTORY");
|
||||
command.env_remove("GIT_WORK_TREE");
|
||||
command.env_remove("GIT_AUTHOR_NAME");
|
||||
command.env_remove("GIT_AUTHOR_EMAIL");
|
||||
command.env_remove("GIT_COMMITTER_NAME");
|
||||
command.env_remove("GIT_COMMITTER_EMAIL");
|
||||
command.env_remove("GIT_CONFIG_GLOBAL");
|
||||
command.env_remove("GIT_CONFIG_NOSYSTEM");
|
||||
command.env("GIT_CONFIG_GLOBAL", &specification.global_config_path);
|
||||
command.env("GIT_CONFIG_NOSYSTEM", "1");
|
||||
command.env("GIT_CONFIG_COUNT", "1");
|
||||
command.env("GIT_CONFIG_KEY_0", "core.hooksPath");
|
||||
command.env("GIT_CONFIG_VALUE_0", &specification.hooks_path);
|
||||
for (name, value) in &specification.environment {
|
||||
command.env(name, value);
|
||||
}
|
||||
let output_result = command.output();
|
||||
let output = match output_result {
|
||||
Ok(value) => value,
|
||||
@@ -246,7 +269,7 @@ impl crate::GitBackend {
|
||||
source_id: &knowledge_domain_lib::SourceId,
|
||||
revision: &knowledge_git_api::GitRevision,
|
||||
) -> Result<std::path::PathBuf, crate::GitBackendError> {
|
||||
if !is_safe_revision(revision.as_str()) {
|
||||
if !crate::is_safe_revision(revision.as_str()) {
|
||||
return Err(crate::GitBackendError::InvalidRevision);
|
||||
}
|
||||
let source_key = crate::GitSourceKey::from_source_id(source_id);
|
||||
@@ -301,7 +324,7 @@ impl crate::GitBackend {
|
||||
}
|
||||
}
|
||||
|
||||
fn configured_source(&self, source_id: &knowledge_domain_lib::SourceId) -> Result<&crate::GitSourceConfig, crate::GitBackendError> {
|
||||
pub(crate) fn configured_source(&self, source_id: &knowledge_domain_lib::SourceId) -> Result<&crate::GitSourceConfig, crate::GitBackendError> {
|
||||
for source in &self.sources {
|
||||
if source.source_id() == source_id {
|
||||
return Ok(source);
|
||||
@@ -310,16 +333,44 @@ impl crate::GitBackend {
|
||||
return Err(crate::GitBackendError::SourceNotConfigured);
|
||||
}
|
||||
|
||||
fn prepare_state_directories(&self) -> Result<(), crate::GitBackendError> {
|
||||
for path in [self.config.hooks_path(), self.config.repositories_path(), self.config.snapshots_path()] {
|
||||
pub(crate) fn prepare_state_directories(&self) -> Result<(), crate::GitBackendError> {
|
||||
for path in [self.config.hooks_path(), self.config.repositories_path(), self.config.snapshots_path(), self.config.write_worktrees_path()] {
|
||||
let create_result = std::fs::create_dir_all(path);
|
||||
if create_result.is_err() {
|
||||
return Err(crate::GitBackendError::StatePreparationFailed);
|
||||
}
|
||||
}
|
||||
let config_path = self.config.empty_global_config_path();
|
||||
if !config_path.exists() {
|
||||
let write_result = std::fs::write(config_path, b"");
|
||||
if write_result.is_err() {
|
||||
return Err(crate::GitBackendError::StatePreparationFailed);
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub(crate) fn run_controlled_git(
|
||||
&self,
|
||||
operation: crate::GitOperation,
|
||||
arguments: Vec<std::ffi::OsString>,
|
||||
environment: Vec<(std::ffi::OsString, std::ffi::OsString)>,
|
||||
) -> Result<Vec<u8>, crate::GitBackendError> {
|
||||
let specification = GitCommandSpec {
|
||||
arguments,
|
||||
environment,
|
||||
executable: self.config.git_executable().to_path_buf(),
|
||||
global_config_path: self.config.empty_global_config_path(),
|
||||
hooks_path: self.config.hooks_path(),
|
||||
operation,
|
||||
};
|
||||
let result = self.runner.run(&specification);
|
||||
match result {
|
||||
Ok(output) => return Ok(output.stdout),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_mirror(&self, source: &crate::GitSourceConfig, repository_path: &std::path::Path) -> Result<(), crate::GitBackendError> {
|
||||
let mut arguments = vec![std::ffi::OsString::from("clone"), std::ffi::OsString::from("--mirror")];
|
||||
if source.source_kind == crate::GitSourceKind::Local {
|
||||
@@ -330,7 +381,9 @@ impl crate::GitBackend {
|
||||
arguments.push(repository_path.as_os_str().to_os_string());
|
||||
let specification = GitCommandSpec {
|
||||
arguments,
|
||||
environment: Vec::new(),
|
||||
executable: self.config.git_executable().to_path_buf(),
|
||||
global_config_path: self.config.empty_global_config_path(),
|
||||
hooks_path: self.config.hooks_path(),
|
||||
operation: crate::GitOperation::CloneMirror,
|
||||
};
|
||||
@@ -349,7 +402,9 @@ impl crate::GitBackend {
|
||||
std::ffi::OsString::from("rev-parse"),
|
||||
std::ffi::OsString::from("--is-bare-repository"),
|
||||
],
|
||||
environment: Vec::new(),
|
||||
executable: self.config.git_executable().to_path_buf(),
|
||||
global_config_path: self.config.empty_global_config_path(),
|
||||
hooks_path: self.config.hooks_path(),
|
||||
operation: crate::GitOperation::InspectMirror,
|
||||
};
|
||||
@@ -390,7 +445,9 @@ impl crate::GitBackend {
|
||||
std::ffi::OsString::from("update"),
|
||||
std::ffi::OsString::from("--prune"),
|
||||
],
|
||||
environment: Vec::new(),
|
||||
executable: self.config.git_executable().to_path_buf(),
|
||||
global_config_path: self.config.empty_global_config_path(),
|
||||
hooks_path: self.config.hooks_path(),
|
||||
operation: crate::GitOperation::RefreshMirror,
|
||||
};
|
||||
@@ -427,7 +484,9 @@ impl crate::GitBackend {
|
||||
std::ffi::OsString::from("--end-of-options"),
|
||||
std::ffi::OsString::from(revision_expression),
|
||||
],
|
||||
environment: Vec::new(),
|
||||
executable: self.config.git_executable().to_path_buf(),
|
||||
global_config_path: self.config.empty_global_config_path(),
|
||||
hooks_path: self.config.hooks_path(),
|
||||
operation: crate::GitOperation::ResolveRevision,
|
||||
};
|
||||
@@ -443,7 +502,7 @@ impl crate::GitBackend {
|
||||
return Err(crate::GitBackendError::UnexpectedGitOutput { operation: crate::GitOperation::ResolveRevision });
|
||||
},
|
||||
};
|
||||
if !is_safe_revision(stdout) {
|
||||
if !crate::is_safe_revision(stdout) {
|
||||
return Err(crate::GitBackendError::UnexpectedGitOutput { operation: crate::GitOperation::ResolveRevision });
|
||||
}
|
||||
return Ok(knowledge_git_api::GitRevision::new(stdout));
|
||||
@@ -459,7 +518,7 @@ impl crate::GitBackend {
|
||||
Ok(_) => (),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
if !is_safe_revision(revision.as_str()) {
|
||||
if !crate::is_safe_revision(revision.as_str()) {
|
||||
return Err(crate::GitBackendError::InvalidRevision);
|
||||
}
|
||||
let mirror_result = self.inspect_mirror(source_id);
|
||||
@@ -499,7 +558,9 @@ impl crate::GitBackend {
|
||||
snapshot_path.as_os_str().to_os_string(),
|
||||
std::ffi::OsString::from(revision.as_str()),
|
||||
],
|
||||
environment: Vec::new(),
|
||||
executable: self.config.git_executable().to_path_buf(),
|
||||
global_config_path: self.config.empty_global_config_path(),
|
||||
hooks_path: self.config.hooks_path(),
|
||||
operation: crate::GitOperation::CreateSnapshot,
|
||||
};
|
||||
@@ -527,7 +588,9 @@ impl crate::GitBackend {
|
||||
std::ffi::OsString::from("--verify"),
|
||||
std::ffi::OsString::from("HEAD"),
|
||||
],
|
||||
environment: Vec::new(),
|
||||
executable: self.config.git_executable().to_path_buf(),
|
||||
global_config_path: self.config.empty_global_config_path(),
|
||||
hooks_path: self.config.hooks_path(),
|
||||
operation: crate::GitOperation::InspectSnapshot,
|
||||
};
|
||||
@@ -552,7 +615,9 @@ impl crate::GitBackend {
|
||||
std::ffi::OsString::from("--porcelain=v1"),
|
||||
std::ffi::OsString::from("--untracked-files=all"),
|
||||
],
|
||||
environment: Vec::new(),
|
||||
executable: self.config.git_executable().to_path_buf(),
|
||||
global_config_path: self.config.empty_global_config_path(),
|
||||
hooks_path: self.config.hooks_path(),
|
||||
operation: crate::GitOperation::InspectSnapshot,
|
||||
};
|
||||
@@ -592,7 +657,7 @@ impl knowledge_git_api::GitRepository for crate::GitBackend {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_safe_revision(value: &str) -> bool {
|
||||
pub(crate) fn is_safe_revision(value: &str) -> bool {
|
||||
if value.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user