- Specify production-ready implementation details for sal-git package. - Add a detailed code review and quality assurance process section. - Include comprehensive success metrics and validation checklists for production readiness. - Improve security considerations and risk mitigation strategies. - Add stricter code review criteria based on sal-git's conversion. - Update README with security configurations and environment variables.
208 lines
6.6 KiB
Rust
208 lines
6.6 KiB
Rust
//! Rhai wrappers for Git module functions
|
|
//!
|
|
//! This module provides Rhai wrappers for the functions in the Git module.
|
|
|
|
use crate::{GitError, GitRepo, GitTree};
|
|
use rhai::{Array, Dynamic, Engine, EvalAltResult};
|
|
|
|
/// Register Git module functions with the Rhai engine
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `engine` - The Rhai engine to register the functions with
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
|
|
pub fn register_git_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
|
// Register GitTree constructor
|
|
engine.register_type::<GitTree>();
|
|
engine.register_fn("git_tree_new", git_tree_new);
|
|
|
|
// Register GitTree methods
|
|
engine.register_fn("list", git_tree_list);
|
|
engine.register_fn("find", git_tree_find);
|
|
engine.register_fn("get", git_tree_get);
|
|
|
|
// Register GitRepo methods
|
|
engine.register_type::<GitRepo>();
|
|
engine.register_fn("path", git_repo_path);
|
|
engine.register_fn("has_changes", git_repo_has_changes);
|
|
engine.register_fn("pull", git_repo_pull);
|
|
engine.register_fn("reset", git_repo_reset);
|
|
engine.register_fn("commit", git_repo_commit);
|
|
engine.register_fn("push", git_repo_push);
|
|
|
|
// Register git_clone function for testing
|
|
engine.register_fn("git_clone", git_clone);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// Helper functions for error conversion
|
|
fn git_error_to_rhai_error<T>(result: Result<T, GitError>) -> Result<T, Box<EvalAltResult>> {
|
|
result.map_err(|e| {
|
|
Box::new(EvalAltResult::ErrorRuntime(
|
|
format!("Git error: {}", e).into(),
|
|
rhai::Position::NONE,
|
|
))
|
|
})
|
|
}
|
|
|
|
//
|
|
// GitTree Function Wrappers
|
|
//
|
|
|
|
/// Wrapper for GitTree::new
|
|
///
|
|
/// Creates a new GitTree with the specified base path.
|
|
pub fn git_tree_new(base_path: &str) -> Result<GitTree, Box<EvalAltResult>> {
|
|
git_error_to_rhai_error(GitTree::new(base_path))
|
|
}
|
|
|
|
/// Wrapper for GitTree::list
|
|
///
|
|
/// Lists all git repositories under the base path.
|
|
pub fn git_tree_list(git_tree: &mut GitTree) -> Result<Array, Box<EvalAltResult>> {
|
|
let repos = git_error_to_rhai_error(git_tree.list())?;
|
|
|
|
// Convert Vec<String> to Rhai Array
|
|
let mut array = Array::new();
|
|
for repo in repos {
|
|
array.push(Dynamic::from(repo));
|
|
}
|
|
|
|
Ok(array)
|
|
}
|
|
|
|
/// Wrapper for GitTree::find
|
|
///
|
|
/// Finds repositories matching a pattern and returns them as an array of GitRepo objects.
|
|
/// Assumes the underlying GitTree::find Rust method now returns Result<Vec<GitRepo>, GitError>.
|
|
pub fn git_tree_find(git_tree: &mut GitTree, pattern: &str) -> Result<Array, Box<EvalAltResult>> {
|
|
let repos: Vec<GitRepo> = git_error_to_rhai_error(git_tree.find(pattern))?;
|
|
|
|
// Convert Vec<GitRepo> to Rhai Array
|
|
let mut array = Array::new();
|
|
for repo in repos {
|
|
array.push(Dynamic::from(repo));
|
|
}
|
|
|
|
Ok(array)
|
|
}
|
|
|
|
/// Wrapper for GitTree::get
|
|
///
|
|
/// Gets a single GitRepo object based on an exact name or URL.
|
|
/// The underlying Rust GitTree::get method returns Result<Vec<GitRepo>, GitError>.
|
|
/// This wrapper ensures that for Rhai, 'get' returns a single GitRepo or an error
|
|
/// if zero or multiple repositories are found (for local names/patterns),
|
|
/// or if a URL operation fails or unexpectedly yields not exactly one result.
|
|
pub fn git_tree_get(
|
|
git_tree: &mut GitTree,
|
|
name_or_url: &str,
|
|
) -> Result<GitRepo, Box<EvalAltResult>> {
|
|
let mut repos_vec: Vec<GitRepo> = git_error_to_rhai_error(git_tree.get(name_or_url))?;
|
|
|
|
match repos_vec.len() {
|
|
1 => Ok(repos_vec.remove(0)), // Efficient for Vec of size 1, transfers ownership
|
|
0 => Err(Box::new(EvalAltResult::ErrorRuntime(
|
|
format!("Git error: Repository '{}' not found.", name_or_url).into(),
|
|
rhai::Position::NONE,
|
|
))),
|
|
_ => Err(Box::new(EvalAltResult::ErrorRuntime(
|
|
format!(
|
|
"Git error: Multiple repositories ({}) found matching '{}'. Use find() for patterns or provide a more specific name for get().",
|
|
repos_vec.len(),
|
|
name_or_url
|
|
)
|
|
.into(),
|
|
rhai::Position::NONE,
|
|
))),
|
|
}
|
|
}
|
|
|
|
//
|
|
// GitRepo Function Wrappers
|
|
//
|
|
|
|
/// Wrapper for GitRepo::path
|
|
///
|
|
/// Gets the path of the repository.
|
|
pub fn git_repo_path(git_repo: &mut GitRepo) -> String {
|
|
git_repo.path().to_string()
|
|
}
|
|
|
|
/// Wrapper for GitRepo::has_changes
|
|
///
|
|
/// Checks if the repository has uncommitted changes.
|
|
pub fn git_repo_has_changes(git_repo: &mut GitRepo) -> Result<bool, Box<EvalAltResult>> {
|
|
git_error_to_rhai_error(git_repo.has_changes())
|
|
}
|
|
|
|
/// Wrapper for GitRepo::pull
|
|
///
|
|
/// Pulls the latest changes from the remote repository.
|
|
pub fn git_repo_pull(git_repo: &mut GitRepo) -> Result<GitRepo, Box<EvalAltResult>> {
|
|
git_error_to_rhai_error(git_repo.pull())
|
|
}
|
|
|
|
/// Wrapper for GitRepo::reset
|
|
///
|
|
/// Resets any local changes in the repository.
|
|
pub fn git_repo_reset(git_repo: &mut GitRepo) -> Result<GitRepo, Box<EvalAltResult>> {
|
|
git_error_to_rhai_error(git_repo.reset())
|
|
}
|
|
|
|
/// Wrapper for GitRepo::commit
|
|
///
|
|
/// Commits changes in the repository.
|
|
pub fn git_repo_commit(
|
|
git_repo: &mut GitRepo,
|
|
message: &str,
|
|
) -> Result<GitRepo, Box<EvalAltResult>> {
|
|
git_error_to_rhai_error(git_repo.commit(message))
|
|
}
|
|
|
|
/// Wrapper for GitRepo::push
|
|
///
|
|
/// Pushes changes to the remote repository.
|
|
pub fn git_repo_push(git_repo: &mut GitRepo) -> Result<GitRepo, Box<EvalAltResult>> {
|
|
git_error_to_rhai_error(git_repo.push())
|
|
}
|
|
|
|
/// Clone a git repository to a temporary location
|
|
///
|
|
/// This function clones a repository from the given URL to a temporary directory
|
|
/// and returns the GitRepo object for further operations.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `url` - The URL of the git repository to clone
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Ok(GitRepo)` - The cloned repository object
|
|
/// * `Err(Box<EvalAltResult>)` - If the clone operation failed
|
|
pub fn git_clone(url: &str) -> Result<GitRepo, Box<EvalAltResult>> {
|
|
// Get base path from environment or use default temp directory
|
|
let base_path = std::env::var("GIT_DEFAULT_BASE_PATH").unwrap_or_else(|_| {
|
|
std::env::temp_dir()
|
|
.join("sal_git_clones")
|
|
.to_string_lossy()
|
|
.to_string()
|
|
});
|
|
|
|
// Create GitTree and clone the repository
|
|
let git_tree = git_error_to_rhai_error(GitTree::new(&base_path))?;
|
|
let repos = git_error_to_rhai_error(git_tree.get(url))?;
|
|
|
|
// Return the first (and should be only) repository
|
|
repos.into_iter().next().ok_or_else(|| {
|
|
Box::new(EvalAltResult::ErrorRuntime(
|
|
"Git error: No repository was cloned".into(),
|
|
rhai::Position::NONE,
|
|
))
|
|
})
|
|
}
|