git working
This commit is contained in:
parent
21893ce225
commit
104097ee4b
218
docs/git/git.md
Normal file
218
docs/git/git.md
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
# Rhai Git Module Manual
|
||||||
|
|
||||||
|
## Core Concepts
|
||||||
|
|
||||||
|
The Git module in Rhai allows interaction with Git repositories through two main objects:
|
||||||
|
|
||||||
|
- **`GitTree`**: Represents a collection of Git repositories under a specified base directory. Use it to manage, find, and access these repositories.
|
||||||
|
- **`GitRepo`**: Represents a single Git repository. Use it to perform common Git operations like `pull`, `commit`, and `push`.
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
Methods performing Git operations (e.g., `pull`, `GitTree.get` when cloning) return a `Result`. If an operation fails and the error is not handled within the Rhai script, the script execution will halt, and Rhai will report the error. The examples below show direct usage, relying on this default error-halting behavior.
|
||||||
|
|
||||||
|
## `GitTree` Object
|
||||||
|
|
||||||
|
The `GitTree` object is the entry point for working with Git repositories.
|
||||||
|
|
||||||
|
### `git_tree_new(base_path: String) -> GitTree`
|
||||||
|
|
||||||
|
Creates a `GitTree` instance.
|
||||||
|
|
||||||
|
- **Description**: Initializes a `GitTree` to operate within the `base_path`. This directory is where repositories are located or will be cloned. It's created if it doesn't exist.
|
||||||
|
- **Parameters**:
|
||||||
|
- `base_path: String` - Path to the directory for Git repositories.
|
||||||
|
- **Returns**: `GitTree` - A new `GitTree` object. Halts on error (e.g., invalid path).
|
||||||
|
- **Rhai Example**:
|
||||||
|
```rhai
|
||||||
|
let git_tree = git_tree_new("./my_projects");
|
||||||
|
print("GitTree created.");
|
||||||
|
// To access the base path from Rhai, a `base_path()` getter would need to be exposed.
|
||||||
|
// // print(`GitTree base path: ${git_tree.base_path()}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
### `list() -> Array`
|
||||||
|
|
||||||
|
Lists names of all Git repositories in the `GitTree`'s `base_path`.
|
||||||
|
|
||||||
|
- **Description**: Scans `base_path` for immediate subdirectories that are Git repositories and returns their names.
|
||||||
|
- **Returns**: `Array` - An array of strings (repository names). Returns an empty array if no repositories are found. Halts on other errors.
|
||||||
|
- **Rhai Example**:
|
||||||
|
```rhai
|
||||||
|
let git_tree = git_tree_new("./my_projects");
|
||||||
|
let repo_names = git_tree.list();
|
||||||
|
print(`Found ${repo_names.len()} repositories: ${repo_names}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
### `find(pattern: String) -> Array`
|
||||||
|
|
||||||
|
Finds Git repositories matching `pattern` and returns them as `GitRepo` objects.
|
||||||
|
|
||||||
|
- **Description**: Searches `base_path` for Git repository subdirectories whose names match the `pattern` (e.g., `*`, `service-*`).
|
||||||
|
- **Parameters**:
|
||||||
|
- `pattern: String` - A pattern to match repository names.
|
||||||
|
- **Returns**: `Array` - An array of `GitRepo` objects. Returns an empty array if no repositories match. Halts on other errors (e.g. invalid pattern).
|
||||||
|
- **Rhai Example**:
|
||||||
|
```rhai
|
||||||
|
let git_tree = git_tree_new("./my_projects");
|
||||||
|
let api_repos = git_tree.find("api-*");
|
||||||
|
print(`Found ${api_repos.len()} API repositories.`);
|
||||||
|
for repo in api_repos {
|
||||||
|
print(`- Path: ${repo.path()}, Has Changes: ${repo.has_changes()}`);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `get(name_or_url: String) -> GitRepo`
|
||||||
|
|
||||||
|
Retrieves a single `GitRepo` object by its exact local name or by a remote URL.
|
||||||
|
|
||||||
|
- **Description**:
|
||||||
|
- **Local Name**: If `name_or_url` is an exact subdirectory name in `base_path` (e.g., `"myrepo"`), opens that repository.
|
||||||
|
- **Remote URL**: If `name_or_url` is a Git URL (e.g., `"https://github.com/user/repo.git"`), it clones the repository (if not present) into `base_path` or opens it if it already exists.
|
||||||
|
- **Note**: Does not support wildcards for local names. Use `find()` for pattern matching.
|
||||||
|
- **Parameters**:
|
||||||
|
- `name_or_url: String` - The exact local repository name or a full Git URL.
|
||||||
|
- **Returns**: `GitRepo` - A single `GitRepo` object.
|
||||||
|
- **Halts on error if**:
|
||||||
|
- The local `name` is not found or is ambiguous.
|
||||||
|
- The `url` is invalid, or the clone/access operation fails.
|
||||||
|
- The target is not a valid Git repository.
|
||||||
|
- **Rhai Examples**:
|
||||||
|
|
||||||
|
*Get specific local repository by name:*
|
||||||
|
```rhai
|
||||||
|
let git_tree = git_tree_new("./my_projects");
|
||||||
|
// Assumes "my_service_a" is a git repo in "./my_projects/my_service_a"
|
||||||
|
// Script halts if "my_service_a" is not found or not a git repo.
|
||||||
|
let service_a_repo = git_tree.get("my_service_a");
|
||||||
|
print(`Opened repo: ${service_a_repo.path()}`);
|
||||||
|
service_a_repo.pull(); // Example operation
|
||||||
|
```
|
||||||
|
|
||||||
|
*Clone or get repository by URL:*
|
||||||
|
```rhai
|
||||||
|
let git_tree = git_tree_new("./cloned_repos_dest");
|
||||||
|
let url = "https://github.com/rhai-script/rhai.git";
|
||||||
|
// Clones if not present, otherwise opens. Halts on error.
|
||||||
|
let rhai_repo = git_tree.get(url);
|
||||||
|
print(`Rhai repository path: ${rhai_repo.path()}`);
|
||||||
|
print(`Rhai repo has changes: ${rhai_repo.has_changes()}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
## `GitRepo` Object
|
||||||
|
|
||||||
|
Represents a single Git repository. Obtained from `GitTree.get()` or `GitTree.find()`.
|
||||||
|
|
||||||
|
### `path() -> String`
|
||||||
|
|
||||||
|
Returns the full file system path of the repository.
|
||||||
|
|
||||||
|
- **Returns**: `String` - The absolute path to the repository's root directory.
|
||||||
|
- **Rhai Example**:
|
||||||
|
```rhai
|
||||||
|
let git_tree = git_tree_new("./my_projects");
|
||||||
|
// Assumes "my_app" exists and is a Git repository.
|
||||||
|
// get() will halt if "my_app" is not found.
|
||||||
|
let app_repo = git_tree.get("my_app");
|
||||||
|
print(`App repository is at: ${app_repo.path()}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
### `has_changes() -> bool`
|
||||||
|
|
||||||
|
Checks if the repository has any uncommitted local changes.
|
||||||
|
|
||||||
|
- **Description**: Checks for uncommitted modifications in the working directory or staged changes.
|
||||||
|
- **Returns**: `bool` - `true` if uncommitted changes exist, `false` otherwise. Halts on error.
|
||||||
|
- **Rhai Example** (assuming `app_repo` is a `GitRepo` object):
|
||||||
|
```rhai
|
||||||
|
if app_repo.has_changes() {
|
||||||
|
print(`Repository ${app_repo.path()} has uncommitted changes.`);
|
||||||
|
} else {
|
||||||
|
print(`Repository ${app_repo.path()} is clean.`);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `pull() -> GitRepo`
|
||||||
|
|
||||||
|
Pulls latest changes from the remote.
|
||||||
|
|
||||||
|
- **Description**: Fetches changes from the default remote and merges them into the current local branch (`git pull`).
|
||||||
|
- **Returns**: `GitRepo` - The same `GitRepo` object for chaining. Halts on error (e.g., network issues, merge conflicts).
|
||||||
|
- **Rhai Example** (assuming `app_repo` is a `GitRepo` object):
|
||||||
|
```rhai
|
||||||
|
print(`Pulling latest changes for ${app_repo.path()}...`);
|
||||||
|
app_repo.pull(); // Halts on error
|
||||||
|
print("Pull successful.");
|
||||||
|
```
|
||||||
|
|
||||||
|
### `reset() -> GitRepo`
|
||||||
|
|
||||||
|
Resets local changes. **Caution: Discards uncommitted work.**
|
||||||
|
|
||||||
|
- **Description**: Discards local modifications and staged changes, resetting the working directory to match the last commit (`git reset --hard HEAD` or similar).
|
||||||
|
- **Returns**: `GitRepo` - The same `GitRepo` object for chaining. Halts on error.
|
||||||
|
- **Rhai Example** (assuming `app_repo` is a `GitRepo` object):
|
||||||
|
```rhai
|
||||||
|
print(`Resetting local changes in ${app_repo.path()}...`);
|
||||||
|
app_repo.reset(); // Halts on error
|
||||||
|
print("Reset successful.");
|
||||||
|
```
|
||||||
|
|
||||||
|
### `commit(message: String) -> GitRepo`
|
||||||
|
|
||||||
|
Commits staged changes.
|
||||||
|
|
||||||
|
- **Description**: Performs `git commit -m "message"`. Assumes changes are staged. Behavior regarding auto-staging of tracked files depends on the underlying Rust implementation.
|
||||||
|
- **Parameters**:
|
||||||
|
- `message: String` - The commit message.
|
||||||
|
- **Returns**: `GitRepo` - The same `GitRepo` object for chaining. Halts on error (e.g., nothing to commit).
|
||||||
|
- **Rhai Example** (assuming `app_repo` is a `GitRepo` object):
|
||||||
|
```rhai
|
||||||
|
// Ensure there are changes to commit.
|
||||||
|
if app_repo.has_changes() {
|
||||||
|
print(`Committing changes in ${app_repo.path()}...`);
|
||||||
|
app_repo.commit("Automated commit via Rhai script"); // Halts on error
|
||||||
|
print("Commit successful.");
|
||||||
|
} else {
|
||||||
|
print("No changes to commit.");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `push() -> GitRepo`
|
||||||
|
|
||||||
|
Pushes committed changes to the remote.
|
||||||
|
|
||||||
|
- **Description**: Performs `git push` to the default remote and branch.
|
||||||
|
- **Returns**: `GitRepo` - The same `GitRepo` object for chaining. Halts on error (e.g., network issues, push rejected).
|
||||||
|
- **Rhai Example** (assuming `app_repo` is a `GitRepo` object with committed changes):
|
||||||
|
```rhai
|
||||||
|
print(`Pushing changes for ${app_repo.path()}...`);
|
||||||
|
app_repo.push(); // Halts on error
|
||||||
|
print("Push successful.");
|
||||||
|
```
|
||||||
|
|
||||||
|
## Chaining Operations
|
||||||
|
|
||||||
|
`GitRepo` methods like `pull`, `reset`, `commit`, and `push` return the `GitRepo` object, allowing for chained operations. If any operation in the chain fails, script execution halts.
|
||||||
|
|
||||||
|
- **Rhai Example**:
|
||||||
|
```rhai
|
||||||
|
let git_tree = git_tree_new("./my_projects");
|
||||||
|
// Assumes "my_writable_app" exists and you have write access.
|
||||||
|
// get() will halt if not found.
|
||||||
|
let app_repo = git_tree.get("my_writable_app");
|
||||||
|
print(`Performing chained operations on ${app_repo.path()}`);
|
||||||
|
|
||||||
|
// This example demonstrates a common workflow.
|
||||||
|
// Ensure the repo state is suitable (e.g., changes exist for commit/push).
|
||||||
|
app_repo.pull()
|
||||||
|
.commit("Rhai: Chained operations - automated update") // Commits if pull results in changes or local changes existed and were staged.
|
||||||
|
.push();
|
||||||
|
print("Chained pull, commit, and push reported successful.");
|
||||||
|
|
||||||
|
// Alternative:
|
||||||
|
// app_repo.pull();
|
||||||
|
// if app_repo.has_changes() {
|
||||||
|
// app_repo.commit("Updates").push();
|
||||||
|
// }
|
||||||
|
```
|
28
examples/git/git_basic.rhai
Normal file
28
examples/git/git_basic.rhai
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Simplified Git Basic Operations Example
|
||||||
|
|
||||||
|
let git_tree = git_tree_new("/tmp/git"); // Using /tmp/git as base path
|
||||||
|
|
||||||
|
print("--- Git Basic Operations ---");
|
||||||
|
// print(`Base path: ${git_tree.base_path()}`); // base_path() getter would need to be exposed from Rust
|
||||||
|
|
||||||
|
let all_repos = git_tree.list();
|
||||||
|
print(`Listed ${all_repos.len()} repos.`);
|
||||||
|
|
||||||
|
// Find repos starting with "home" (adjust pattern if /tmp/git might contain other "home*" repos)
|
||||||
|
let found_repos = git_tree.find("home*");
|
||||||
|
print(`Found ${found_repos.len()} repos matching "home*".`);
|
||||||
|
for r in found_repos {
|
||||||
|
print(` - Found: ${r.path()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Getting/Cloning 'https://github.com/freeflowuniverse/home'...");
|
||||||
|
let repo = git_tree.get("https://github.com/freeflowuniverse/home");
|
||||||
|
print(`Repo path: ${repo.path()}`);
|
||||||
|
print(`Has changes: ${repo.has_changes()}`);
|
||||||
|
|
||||||
|
print("Performing pull & reset...");
|
||||||
|
repo.pull().reset();
|
||||||
|
print("Pull and reset complete.");
|
||||||
|
print(`Has changes after pull/reset: ${repo.has_changes()}`);
|
||||||
|
|
||||||
|
print("--- Example Finished ---");
|
@ -197,40 +197,41 @@ impl GitTree {
|
|||||||
/// * `Ok(Vec<String>)` - A vector of paths to matching repositories
|
/// * `Ok(Vec<String>)` - A vector of paths to matching repositories
|
||||||
/// * `Err(GitError)` - If no matching repositories are found,
|
/// * `Err(GitError)` - If no matching repositories are found,
|
||||||
/// or if multiple repositories match a non-wildcard pattern
|
/// or if multiple repositories match a non-wildcard pattern
|
||||||
pub fn find(&self, pattern: &str) -> Result<Vec<String>, GitError> {
|
pub fn find(&self, pattern: &str) -> Result<Vec<GitRepo>, GitError> {
|
||||||
// Get all repos
|
let repo_names = self.list()?; // list() already ensures these are git repo names
|
||||||
let repos = self.list()?;
|
|
||||||
|
|
||||||
if repos.is_empty() {
|
if repo_names.is_empty() {
|
||||||
return Err(GitError::NoRepositoriesFound);
|
return Ok(Vec::new()); // If no repos listed, find results in an empty list
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if pattern ends with wildcard
|
let mut matched_repos: Vec<GitRepo> = Vec::new();
|
||||||
if pattern.ends_with('*') {
|
|
||||||
let search_pattern = &pattern[0..pattern.len()-1]; // Remove the *
|
|
||||||
let matching: Vec<String> = repos.iter()
|
|
||||||
.filter(|repo| repo.contains(search_pattern))
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if matching.is_empty() {
|
if pattern == "*" {
|
||||||
return Err(GitError::RepositoryNotFound(pattern.to_string()));
|
for name in repo_names {
|
||||||
|
let full_path = format!("{}/{}", self.base_path, name);
|
||||||
|
matched_repos.push(GitRepo::new(full_path));
|
||||||
|
}
|
||||||
|
} else if pattern.ends_with('*') {
|
||||||
|
let prefix = &pattern[0..pattern.len()-1];
|
||||||
|
for name in repo_names {
|
||||||
|
if name.starts_with(prefix) {
|
||||||
|
let full_path = format!("{}/{}", self.base_path, name);
|
||||||
|
matched_repos.push(GitRepo::new(full_path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(matching)
|
|
||||||
} else {
|
} else {
|
||||||
// No wildcard, need to find exactly one match
|
// Exact match for the name
|
||||||
let matching: Vec<String> = repos.iter()
|
for name in repo_names {
|
||||||
.filter(|repo| repo.contains(pattern))
|
if name == pattern {
|
||||||
.cloned()
|
let full_path = format!("{}/{}", self.base_path, name);
|
||||||
.collect();
|
matched_repos.push(GitRepo::new(full_path));
|
||||||
|
// `find` returns all exact matches. If names aren't unique (unlikely from `list`),
|
||||||
|
// it could return more than one. For an exact name, typically one is expected.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match matching.len() {
|
Ok(matched_repos)
|
||||||
0 => Err(GitError::RepositoryNotFound(pattern.to_string())),
|
|
||||||
1 => Ok(matching),
|
|
||||||
_ => Err(GitError::MultipleRepositoriesFound(pattern.to_string(), matching.len())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets one or more GitRepo objects based on a path pattern or URL.
|
/// Gets one or more GitRepo objects based on a path pattern or URL.
|
||||||
@ -281,14 +282,9 @@ impl GitTree {
|
|||||||
Err(GitError::GitCommandFailed(format!("Git clone error: {}", error)))
|
Err(GitError::GitCommandFailed(format!("Git clone error: {}", error)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// It's a path pattern, find matching repositories
|
// It's a path pattern, find matching repositories using the updated self.find()
|
||||||
let repo_paths = self.find(path_or_url)?;
|
// which now directly returns Result<Vec<GitRepo>, GitError>.
|
||||||
|
let repos = self.find(path_or_url)?;
|
||||||
// Convert paths to GitRepo objects
|
|
||||||
let repos: Vec<GitRepo> = repo_paths.into_iter()
|
|
||||||
.map(GitRepo::new)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(repos)
|
Ok(repos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@ use crate::git::{GitTree, GitRepo, GitError};
|
|||||||
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
|
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
|
||||||
pub fn register_git_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
pub fn register_git_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
||||||
// Register GitTree constructor
|
// Register GitTree constructor
|
||||||
engine.register_fn("gittree_new", git_tree_new);
|
engine.register_type::<GitTree>();
|
||||||
|
engine.register_fn("git_tree_new", git_tree_new);
|
||||||
|
|
||||||
// Register GitTree methods
|
// Register GitTree methods
|
||||||
engine.register_fn("list", git_tree_list);
|
engine.register_fn("list", git_tree_list);
|
||||||
@ -24,6 +25,7 @@ pub fn register_git_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>
|
|||||||
engine.register_fn("get", git_tree_get);
|
engine.register_fn("get", git_tree_get);
|
||||||
|
|
||||||
// Register GitRepo methods
|
// Register GitRepo methods
|
||||||
|
engine.register_type::<GitRepo>();
|
||||||
engine.register_fn("path", git_repo_path);
|
engine.register_fn("path", git_repo_path);
|
||||||
engine.register_fn("has_changes", git_repo_has_changes);
|
engine.register_fn("has_changes", git_repo_has_changes);
|
||||||
engine.register_fn("pull", git_repo_pull);
|
engine.register_fn("pull", git_repo_pull);
|
||||||
@ -72,11 +74,12 @@ pub fn git_tree_list(git_tree: &mut GitTree) -> Result<Array, Box<EvalAltResult>
|
|||||||
|
|
||||||
/// Wrapper for GitTree::find
|
/// Wrapper for GitTree::find
|
||||||
///
|
///
|
||||||
/// Finds repositories matching a pattern or partial path.
|
/// 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>> {
|
pub fn git_tree_find(git_tree: &mut GitTree, pattern: &str) -> Result<Array, Box<EvalAltResult>> {
|
||||||
let repos = git_error_to_rhai_error(git_tree.find(pattern))?;
|
let repos: Vec<GitRepo> = git_error_to_rhai_error(git_tree.find(pattern))?;
|
||||||
|
|
||||||
// Convert Vec<String> to Rhai Array
|
// Convert Vec<GitRepo> to Rhai Array
|
||||||
let mut array = Array::new();
|
let mut array = Array::new();
|
||||||
for repo in repos {
|
for repo in repos {
|
||||||
array.push(Dynamic::from(repo));
|
array.push(Dynamic::from(repo));
|
||||||
@ -87,17 +90,30 @@ pub fn git_tree_find(git_tree: &mut GitTree, pattern: &str) -> Result<Array, Box
|
|||||||
|
|
||||||
/// Wrapper for GitTree::get
|
/// Wrapper for GitTree::get
|
||||||
///
|
///
|
||||||
/// Gets one or more GitRepo objects based on a path pattern or URL.
|
/// Gets a single GitRepo object based on an exact name or URL.
|
||||||
pub fn git_tree_get(git_tree: &mut GitTree, path_or_url: &str) -> Result<Array, Box<EvalAltResult>> {
|
/// The underlying Rust GitTree::get method returns Result<Vec<GitRepo>, GitError>.
|
||||||
let repos = git_error_to_rhai_error(git_tree.get(path_or_url))?;
|
/// 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))?;
|
||||||
|
|
||||||
// Convert Vec<GitRepo> to Rhai Array
|
match repos_vec.len() {
|
||||||
let mut array = Array::new();
|
1 => Ok(repos_vec.remove(0)), // Efficient for Vec of size 1, transfers ownership
|
||||||
for repo in repos {
|
0 => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||||
array.push(Dynamic::from(repo));
|
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,
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(array)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -6,9 +6,7 @@ use rhai::{Engine, EvalAltResult, Array, Map, Position};
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::text::{
|
use crate::text::{
|
||||||
TextReplacer, TextReplacerBuilder,
|
TextReplacer, TextReplacerBuilder,
|
||||||
TemplateBuilder,
|
TemplateBuilder
|
||||||
dedent, prefix,
|
|
||||||
name_fix, path_fix
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Register Text module functions with the Rhai engine
|
/// Register Text module functions with the Rhai engine
|
||||||
|
@ -1,164 +0,0 @@
|
|||||||
// Simplified test script for Git module functions
|
|
||||||
|
|
||||||
// Ensure test directory exists using a bash script
|
|
||||||
fn ensure_test_dir() {
|
|
||||||
print("Ensuring test directory exists at /tmp/code");
|
|
||||||
|
|
||||||
// Create a bash script to set up the test environment
|
|
||||||
let setup_script = `#!/bin/bash -ex
|
|
||||||
rm -rf /tmp/code
|
|
||||||
mkdir -p /tmp/code
|
|
||||||
cd /tmp/code
|
|
||||||
|
|
||||||
mkdir -p myserver.com/myaccount/repogreen
|
|
||||||
mkdir -p myserver.com/myaccount/repored
|
|
||||||
|
|
||||||
cd myserver.com/myaccount/repogreen
|
|
||||||
git init
|
|
||||||
echo 'Initial test file' > test.txt
|
|
||||||
git add test.txt
|
|
||||||
git config --local user.email 'test@example.com'
|
|
||||||
git config --local user.name 'Test User'
|
|
||||||
git commit -m 'Initial commit'
|
|
||||||
|
|
||||||
cd myserver.com/myaccount/repored
|
|
||||||
git init
|
|
||||||
echo 'Initial test file' > test2.txt
|
|
||||||
git add test2.txt
|
|
||||||
git config --local user.email 'test@example.com'
|
|
||||||
git config --local user.name 'Test User'
|
|
||||||
git commit -m 'Initial commit'
|
|
||||||
|
|
||||||
//now we have 2 repos
|
|
||||||
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Run the setup script
|
|
||||||
let result = run(setup_script);
|
|
||||||
if !result.success {
|
|
||||||
print("Failed to set up test directory");
|
|
||||||
print(`Error: ${result.stderr}`);
|
|
||||||
throw "Test setup failed";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test GitTree creation
|
|
||||||
fn test_git_tree_creation() {
|
|
||||||
print("\n=== Testing GitTree creation ===");
|
|
||||||
let git_tree = gittree_new("/tmp/code");
|
|
||||||
print(`Created GitTree with base path: /tmp/code`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test GitTree list method
|
|
||||||
fn test_git_tree_list() {
|
|
||||||
print("\n=== Testing GitTree list method ===");
|
|
||||||
let git_tree = gittree_new("/tmp/code");
|
|
||||||
let repos = git_tree.list();
|
|
||||||
|
|
||||||
print(`Found ${repos.len()} repositories`);
|
|
||||||
|
|
||||||
// Print repositories
|
|
||||||
for repo in repos {
|
|
||||||
print(` - ${repo}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if repos.len() == 0 {
|
|
||||||
print("No repositories found, which is unexpected");
|
|
||||||
throw "No repositories found";
|
|
||||||
}
|
|
||||||
|
|
||||||
if repos.len() != 2 {
|
|
||||||
print("No enough repositories found, needs to be 2");
|
|
||||||
throw "No enough repositories found";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test GitTree find method
|
|
||||||
fn test_git_tree_find() {
|
|
||||||
print("\n=== Testing GitTree find method ===");
|
|
||||||
let git_tree = gittree_new("/tmp/code");
|
|
||||||
|
|
||||||
// Search for repositories with "code" in the name
|
|
||||||
let search_pattern = "myaccount/repo"; //we need to check if we need *, would be better not
|
|
||||||
print(`Searching for repositories matching pattern: ${search_pattern}`);
|
|
||||||
let matching = git_tree.find(search_pattern);
|
|
||||||
|
|
||||||
print(`Found ${matching.len()} matching repositories`);
|
|
||||||
for repo in matching {
|
|
||||||
print(` - ${repo}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if matching.len() == 0 {
|
|
||||||
print("No matching repositories found, which is unexpected");
|
|
||||||
throw "No matching repositories found";
|
|
||||||
}
|
|
||||||
if repos.len() != 2 {
|
|
||||||
print("No enough repositories found, needs to be 2");
|
|
||||||
throw "No enough repositories found";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test GitRepo operations
|
|
||||||
fn test_git_repo_operations() {
|
|
||||||
print("\n=== Testing GitRepo operations ===");
|
|
||||||
let git_tree = gittree_new("/tmp/code");
|
|
||||||
let repos = git_tree.list();
|
|
||||||
|
|
||||||
if repos.len() == 0 {
|
|
||||||
print("No repositories found, which is unexpected");
|
|
||||||
throw "No repositories found";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the first repo
|
|
||||||
let repo_path = repos[0];
|
|
||||||
print(`Testing operations on repository: ${repo_path}`);
|
|
||||||
|
|
||||||
// Get GitRepo object
|
|
||||||
let git_repos = git_tree.get(repo_path);
|
|
||||||
if git_repos.len() == 0 {
|
|
||||||
print("Failed to get GitRepo object");
|
|
||||||
throw "Failed to get GitRepo object";
|
|
||||||
}
|
|
||||||
|
|
||||||
let git_repo = git_repos[0];
|
|
||||||
|
|
||||||
// Test has_changes method
|
|
||||||
print("Testing has_changes method");
|
|
||||||
let has_changes = git_repo.has_changes();
|
|
||||||
print(`Repository has changes: ${has_changes}`);
|
|
||||||
|
|
||||||
// Create a change to test
|
|
||||||
print("Creating a change to test");
|
|
||||||
file_write("/tmp/code/test2.txt", "Another test file");
|
|
||||||
|
|
||||||
// Check if changes are detected
|
|
||||||
let has_changes_after = git_repo.has_changes();
|
|
||||||
print(`Repository has changes after modification: ${has_changes_after}`);
|
|
||||||
|
|
||||||
if !has_changes_after {
|
|
||||||
print("Changes not detected, which is unexpected");
|
|
||||||
throw "Changes not detected";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up the change
|
|
||||||
delete("/tmp/code/test2.txt");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run all tests
|
|
||||||
fn run_all_tests() {
|
|
||||||
print("Starting Git module tests...");
|
|
||||||
|
|
||||||
// Ensure test directory exists
|
|
||||||
ensure_test_dir();
|
|
||||||
|
|
||||||
// Run tests
|
|
||||||
test_git_tree_creation();
|
|
||||||
test_git_tree_list();
|
|
||||||
test_git_tree_find();
|
|
||||||
test_git_repo_operations();
|
|
||||||
|
|
||||||
print("\nAll tests completed successfully!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run all tests
|
|
||||||
run_all_tests();
|
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{self, Read, Seek, SeekFrom};
|
use std::io::{self, Read};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
/// Represents the type of replacement to perform.
|
/// Represents the type of replacement to perform.
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
use crate::virt::nerdctl::execute_nerdctl_command;
|
use crate::virt::nerdctl::execute_nerdctl_command;
|
||||||
use crate::process::CommandResult;
|
use crate::process::CommandResult;
|
||||||
use super::NerdctlError;
|
use super::NerdctlError;
|
||||||
use serde_json::{self};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Represents a container image
|
/// Represents a container image
|
||||||
|
@ -12,4 +12,3 @@ pub use mount::{list_mounts, unmount_all, unmount, get_mount_info};
|
|||||||
pub use pack::{pack_directory, unpack, list_contents, verify};
|
pub use pack::{pack_directory, unpack, list_contents, verify};
|
||||||
|
|
||||||
// Re-export the execute_rfs_command function for use in other modules
|
// Re-export the execute_rfs_command function for use in other modules
|
||||||
pub(crate) use cmd::execute_rfs_command;
|
|
Loading…
Reference in New Issue
Block a user