sal/src/docs/subdir/git.md
2025-04-05 06:34:16 +02:00

5.5 KiB

Git Module for Rhai

This module provides Rhai wrappers for the Git functionality in SAL.

Note: The constructor for GitTree has been renamed from new() to gittree_new() to avoid confusion with other constructors. This makes the interface more explicit and less likely to cause naming conflicts.

Object-Oriented Design

The Git module follows an object-oriented design with two main classes:

  1. GitTree - Represents a collection of git repositories under a base path

    • Created with gittree_new(base_path)
    • Methods for listing, finding, and getting repositories
  2. GitRepo - Represents a single git repository

    • Obtained from GitTree's get() method
    • Methods for common git operations: pull, reset, push, commit

This design allows for a more intuitive and flexible interface, with method chaining for complex operations.

Creating a GitTree

The GitTree object is the main entry point for git operations. It represents a collection of git repositories under a base path.

// Create a new GitTree with a base path
let git_tree = gittree_new("/root/code");
print(`Created GitTree with base path: /home/user/code`);

Finding Repositories

List All Repositories

// List all git repositories under the base path
let repos = git_tree.list();
print(`Found ${repos.len()} repositories`);

// Print the repositories
for repo in repos {
    print(`  - ${repo}`);
}

Find Repositories Matching a Pattern

// Find repositories matching a pattern
// Use a wildcard (*) suffix to find multiple matches
let matching_repos = git_tree.find("my-project*");
print("Matching repositories:");
for repo in matching_repos {
    print(`  - ${repo}`);
}

// Find a specific repository (must match exactly one)
let specific_repo = git_tree.find("unique-project")[0];
print(`Found specific repository: ${specific_repo}`);

Working with Repositories

Get Repository Objects

// Get GitRepo objects for repositories matching a pattern
let repos = git_tree.get("my-project*");
print(`Found ${repos.len()} repositories`);

// Get a specific repository
let repo = git_tree.get("unique-project")[0];
print(`Working with repository: ${repo.path()}`);

Clone a Repository

// Clone a repository by URL
// This will clone the repository to the base path of the GitTree
let repos = git_tree.get("https://github.com/username/repo.git");
let repo = repos[0];
print(`Repository cloned to: ${repo.path()}`);

Check for Changes

// Check if a repository has uncommitted changes
let repo = git_tree.get("my-project")[0];
if repo.has_changes() {
    print("Repository has uncommitted changes");
} else {
    print("Repository is clean");
}

Repository Operations

Pull Changes

// Pull the latest changes from the remote
// This will fail if there are uncommitted changes
let repo = git_tree.get("my-project")[0];
let result = repo.pull();
print("Repository updated successfully");

Reset Local Changes

// Reset any local changes in the repository
let repo = git_tree.get("my-project")[0];
let result = repo.reset();
print("Repository reset successfully");

Commit Changes

// Commit changes in the repository
let repo = git_tree.get("my-project")[0];
let result = repo.commit("Fix bug in login form");
print("Changes committed successfully");

Push Changes

// Push changes to the remote
let repo = git_tree.get("my-project")[0];
let result = repo.push();
print("Changes pushed successfully");

Method Chaining

The GitRepo methods can be chained together for more complex operations:

// Commit changes and push them to the remote
let repo = git_tree.get("my-project")[0];
let result = repo.commit("Add new feature").push();
print("Changes committed and pushed successfully");

// Reset local changes, pull the latest changes, and commit new changes
let repo = git_tree.get("my-project")[0];
let result = repo.reset().pull().commit("Update dependencies");
print("Repository updated successfully");

Complete Example

// Create a new GitTree
let home_dir = env("HOME");
let git_tree = gittree_new(`${home_dir}/code`);

// Clone a repository
let repos = git_tree.get("https://github.com/username/example-repo.git");
let repo = repos[0];
print(`Cloned repository to: ${repo.path()}`);

// Make some changes (using OS module functions)
let file_path = `${repo.path()}/README.md`;
let content = "# Example Repository\n\nThis is an example repository.";
write_file(file_path, content);

// Commit and push the changes
let result = repo.commit("Update README.md").push();
print("Changes committed and pushed successfully");

// List all repositories
let all_repos = git_tree.list();
print("All repositories:");
for repo_path in all_repos {
    print(`  - ${repo_path}`);
}

Error Handling

All methods in the Git module return a Result type, which means they can either succeed or fail with an error. If an error occurs, it will be propagated to the Rhai script as a runtime error.

For example, if you try to clone a repository that doesn't exist:

// Try to clone a non-existent repository
try {
    let git_tree = gittree_new("/root/code");
    let repos = git_tree.get("https://github.com/nonexistent/repo.git");
    print("This will not be executed if the repository doesn't exist");
} catch(err) {
    print(`Error: ${err}`);  // Will print the error message from git
}

Common errors include:

  • Invalid URL
  • Repository not found
  • Authentication failure
  • Network issues
  • Local changes exist when trying to pull