sal/docs/git/git.md
2025-05-08 09:05:44 +03:00

9.0 KiB

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:
    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:
    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:
    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:

    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:

    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:
    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):
    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):
    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):
    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):
    // 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):
    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:
    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();
    // }