219 lines
9.0 KiB
Markdown
219 lines
9.0 KiB
Markdown
# 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();
|
|
// }
|
|
```
|