This commit is contained in:
2025-04-05 06:34:16 +02:00
parent 245aee12bf
commit 6de7bf9b56
15 changed files with 361 additions and 20 deletions

30
src/docs/subdir/README.md Normal file
View File

@@ -0,0 +1,30 @@
# Rhai Script Commands Documentation
This documentation provides detailed information about the Rhai script commands available in the SAL library. The commands are organized by module for easy reference.
## Modules
- [OS Module](os.md) - File system operations, directory management, and download functions
- [Process Module](process.md) - Command execution and process management
- [Buildah Module](buildah.md) - Container and image management
## Overview
The SAL library provides integration with the Rhai scripting language, allowing you to use powerful system functions within your Rhai scripts. These functions are organized into modules that provide related functionality.
### Using Rhai in Your Projects
To use these commands in your Rhai scripts, you need to register the SAL modules with your Rhai engine:
```rust
use rhai::Engine;
use sal::rhai;
let mut engine = Engine::new();
rhai::register(&mut engine);
// Now you can use SAL functions in Rhai scripts
let result = engine.eval::<bool>("exist('some_file.txt')").unwrap();
```
This will register all available modules (OS, Process, and Buildah) with your Rhai engine.

View File

@@ -0,0 +1,8 @@
{
"label": "Become a Farmer",
"position": 6,
"link": {
"type": "generated-index",
"description": "Learn how to become a farmer. Let's together build Web4 everywhere for everyone."
}
}

118
src/docs/subdir/buildah.md Normal file
View File

@@ -0,0 +1,118 @@
# Buildah Module
The Buildah module provides functions for working with containers and images using the Buildah tool. Buildah helps you create and manage container images.
## Builder Pattern
The Buildah module now supports a Builder pattern, which provides a more intuitive and flexible way to work with containers and images.
### Creating a Builder
```rhai
// Create a builder with a name and base image
let builder = bah_new("my-container", "alpine:latest");
// Access builder properties
let container_id = builder.container_id;
let name = builder.name;
let image = builder.image;
```
### Builder Methods
The Builder object provides the following methods:
- `run(command)`: Run a command in the container
- `run_with_isolation(command, isolation)`: Run a command with specified isolation
- `copy(source, dest)`: Copy files into the container
- `add(source, dest)`: Add files into the container
- `commit(image_name)`: Commit the container to an image
- `remove()`: Remove the container
- `reset()`: Remove the container and clear the container_id
- `config(options)`: Configure container metadata
- `images()`: List images in local storage
- `image_remove(image)`: Remove an image
- `image_pull(image, tls_verify)`: Pull an image from a registry
- `image_push(image, destination, tls_verify)`: Push an image to a registry
- `image_tag(image, new_name)`: Add a tag to an image
- `build(tag, context_dir, file, isolation)`: Build an image from a Dockerfile
### Example
```rhai
// Create a builder
let builder = bah_new("my-container", "alpine:latest");
// Reset the builder to remove any existing container
builder.reset();
// Create a new container
builder = bah_new("my-container", "alpine:latest");
// Run a command
let result = builder.run("echo 'Hello from container'");
println(`Command output: ${result.stdout}`);
// Add a file
file_write("test_file.txt", "Test content");
builder.add("test_file.txt", "/");
// Commit to an image
builder.commit("my-custom-image:latest");
// Clean up
builder.remove();
delete("test_file.txt");
```
## Image Information
### Image Properties
When working with images, you can access the following information:
- `id`: The unique identifier for the image
- `names`: A list of names/tags for the image
- `name`: The primary name of the image, or `<none>` if the image has no names
- `size`: The size of the image
- `created`: When the image was created
## Builder Methods
### `bah_new(name, image)`
Creates a new Builder object for working with a container.
**Parameters:**
- `name` (string): The name to give the container
- `image` (string): The name or ID of the image to create the container from
**Returns:** A Builder object if successful.
**Example:**
```rhai
// Create a new Builder
let builder = bah_new("my-container", "alpine:latest");
```
**Notes:**
- If a container with the given name already exists, it will be reused instead of creating a new one
- The Builder object provides methods for working with the container
### `reset()`
Resets a Builder by removing the container and clearing the container_id. This allows you to start fresh with the same Builder object.
**Returns:** Nothing.
**Example:**
```rhai
// Create a Builder
let builder = bah_new("my-container", "alpine:latest");
// Reset the Builder to remove the container
builder.reset();
// Create a new container with the same name
builder = bah_new("my-container", "alpine:latest");
```

204
src/docs/subdir/git.md Normal file
View File

@@ -0,0 +1,204 @@
# 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.
```rhai
// 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
```rhai
// 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
```rhai
// 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
```rhai
// 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
```rhai
// 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
```rhai
// 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
```rhai
// 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
```rhai
// 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
```rhai
// 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
```rhai
// 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:
```rhai
// 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
```rhai
// 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:
```rhai
// 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

298
src/docs/subdir/os.md Normal file
View File

@@ -0,0 +1,298 @@
# OS Module
The OS module provides functions for working with files, directories, and downloading files from the internet.
## File System Functions
### `copy(src, dest)`
Recursively copies a file or directory from source to destination.
**Parameters:**
- `src` (string): The source file or directory path
- `dest` (string): The destination path
**Returns:** A message confirming the copy was successful.
**Example:**
```rhai
// Copy a file
copy("source.txt", "destination.txt");
// Copy a directory recursively
copy("source_dir", "destination_dir");
```
### `exist(path)`
Checks if a file or directory exists.
**Parameters:**
- `path` (string): The path to check
**Returns:** A boolean value - `true` if the file or directory exists, `false` otherwise.
**Example:**
```rhai
if exist("config.json") {
// File exists, do something
} else {
// File doesn't exist
}
```
### `find_file(dir, filename)`
Finds a file in a directory with support for wildcards.
**Parameters:**
- `dir` (string): The directory to search in
- `filename` (string): The filename pattern to search for (supports wildcards)
**Returns:** The path of the first matching file.
**Example:**
```rhai
// Find a specific file
let config_file = find_file("./config", "settings.json");
// Find using wildcards
let log_file = find_file("./logs", "*.log");
```
### `find_files(dir, filename)`
Finds multiple files in a directory recursively with support for wildcards.
**Parameters:**
- `dir` (string): The directory to search in
- `filename` (string): The filename pattern to search for (supports wildcards)
**Returns:** A list of matching file paths.
**Example:**
```rhai
// Find all JSON files
let json_files = find_files("./data", "*.json");
// Process each file
for file in json_files {
print(`Found file: ${file}`);
}
```
### `find_dir(dir, dirname)`
Finds a directory in a parent directory with support for wildcards.
**Parameters:**
- `dir` (string): The parent directory to search in
- `dirname` (string): The directory name pattern to search for (supports wildcards)
**Returns:** The path of the first matching directory.
**Example:**
```rhai
// Find a specific directory
let config_dir = find_dir("./", "config");
// Find using wildcards
let version_dir = find_dir("./releases", "v*");
```
### `find_dirs(dir, dirname)`
Finds multiple directories in a parent directory recursively with support for wildcards.
**Parameters:**
- `dir` (string): The parent directory to search in
- `dirname` (string): The directory name pattern to search for (supports wildcards)
**Returns:** A list of matching directory paths.
**Example:**
```rhai
// Find all version directories
let version_dirs = find_dirs("./releases", "v*");
// Process each directory
for dir in version_dirs {
print(`Found directory: ${dir}`);
}
```
### `delete(path)`
Deletes a file or directory. This function is defensive and doesn't error if the file doesn't exist.
**Parameters:**
- `path` (string): The path of the file or directory to delete
**Returns:** A message confirming the deletion was successful.
**Example:**
```rhai
// Delete a file
delete("temp.txt");
// Delete a directory
delete("temp_dir");
```
### `mkdir(path)`
Creates a directory and all parent directories. This function is defensive and doesn't error if the directory already exists.
**Parameters:**
- `path` (string): The path of the directory to create
**Returns:** A message confirming the directory was created.
**Example:**
```rhai
// Create a directory
mkdir("new_dir");
// Create nested directories
mkdir("parent/child/grandchild");
```
### `file_size(path)`
Gets the size of a file in bytes.
**Parameters:**
- `path` (string): The path of the file
**Returns:** The size of the file in bytes.
**Example:**
```rhai
// Get file size
let size = file_size("large_file.dat");
print(`File size: ${size} bytes`);
```
## File Content Functions
### `file_read(path)`
Reads the contents of a file.
**Parameters:**
- `path` (string): The path of the file to read
**Returns:** The content of the file as a string.
**Example:**
```rhai
// Read a file
let content = file_read("config.json");
print(`File content: ${content}`);
```
### `file_write(path, content)`
Writes content to a file. Creates the file if it doesn't exist, overwrites if it does.
**Parameters:**
- `path` (string): The path of the file to write to
- `content` (string): The content to write to the file
**Returns:** A message confirming the file was written.
**Example:**
```rhai
// Write to a file
file_write("config.json", "{\n \"setting\": \"value\"\n}");
```
### `file_write_append(path, content)`
Appends content to a file. Creates the file if it doesn't exist.
**Parameters:**
- `path` (string): The path of the file to append to
- `content` (string): The content to append to the file
**Returns:** A message confirming the content was appended.
**Example:**
```rhai
// Append to a log file
file_write_append("log.txt", "New log entry\n");
```
### `rsync(src, dest)`
Syncs directories using rsync (or platform equivalent).
**Parameters:**
- `src` (string): The source directory
- `dest` (string): The destination directory
**Returns:** A message confirming the directories were synced.
**Example:**
```rhai
// Sync directories
rsync("source_dir", "backup_dir");
```
### `chdir(path)`
Changes the current working directory.
**Parameters:**
- `path` (string): The path to change to
**Returns:** A message confirming the directory was changed.
**Example:**
```rhai
// Change directory
chdir("project/src");
```
## Download Functions
### `download(url, dest, min_size_kb)`
Downloads a file from a URL to a destination using the curl command. If the URL ends with a supported archive format, the file will be automatically extracted to the destination directory.
**Supported archive formats for automatic extraction:**
- `.tar.gz`
- `.tgz`
- `.tar`
- `.zip`
**Parameters:**
- `url` (string): The URL to download from
- `dest` (string): The destination path to save the file
- `min_size_kb` (integer): The minimum expected file size in kilobytes (for validation)
**Returns:** The path where the file was saved or extracted.
**Example:**
```rhai
// Download a file
download("https://example.com/file.zip", "downloads/file.zip", 10);
```
### `download_install(url, min_size_kb)`
Downloads a file and installs it if it's a supported package format.
**Supported package formats for automatic installation:**
- `.deb` packages on Debian-based systems
**Parameters:**
- `url` (string): The URL to download from
- `min_size_kb` (integer): The minimum expected file size in kilobytes (for validation)
**Returns:** The path where the file was saved or installed.
**Example:**
```rhai
// Download and install a package
download_install("https://example.com/package.deb", 1000);

231
src/docs/subdir/process.md Normal file
View File

@@ -0,0 +1,231 @@
# Process Module
The Process module provides functions for running commands and managing processes on your system.
## Command Results
### Command Output Information
When you run a command, you get back information about what happened:
- `stdout`: The normal output of the command
- `stderr`: Any error messages from the command
- `success`: Whether the command worked (true) or failed (false)
- `code`: The exit code (0 usually means success)
### Process Information
When you get information about a running process, you can see:
- `pid`: The process ID number
- `name`: The name of the process
- `memory`: How much memory the process is using
- `cpu`: How much CPU the process is using
## Run Functions
### `run(command)`
Runs a command or multiline script with arguments.
**Parameters:**
- `command` (string): The command to run (can be a single command or a multiline script)
**Returns:** The result of the command, including output and whether it succeeded.
**Example 1: Running a simple command**
```rhai
// Run a simple command
let result = run("ls -la");
// Check if the command was successful
if result.success {
print(`Command output: ${result.stdout}`);
} else {
print(`Command failed with error: ${result.stderr}`);
}
```
**Example 2: Running a multiline script**
```rhai
// Create a multiline script using backtick string literals
let setup_script = `
# Create directories
mkdir -p /tmp/test_project
cd /tmp/test_project
# Initialize git repository
git init
echo 'Initial content' > README.md
git add README.md
git config --local user.email 'test@example.com'
git config --local user.name 'Test User'
git commit -m 'Initial commit'
`;
// Execute the multiline script
let result = run(setup_script);
```
### `run_silent(command)`
Runs a command or multiline script with arguments silently (without displaying output).
**Parameters:**
- `command` (string): The command to run
**Returns:** The result of the command, without displaying the output.
**Example:**
```rhai
// Run a command silently
let result = run_silent("git pull");
// Check the exit code
if result.code == 0 {
print("Git pull successful");
} else {
print(`Git pull failed with code ${result.code}`);
}
```
### `new_run_options()`
Creates a new map with default run options.
**Returns:** A map with the following default options:
- `die` (boolean): `true` - Whether to throw an error if the command fails
- `silent` (boolean): `false` - Whether to suppress command output
- `async_exec` (boolean): `false` - Whether to run the command asynchronously
- `log` (boolean): `false` - Whether to log the command execution
**Example:**
```rhai
// Create run options
let options = new_run_options();
```
### `run_with_options(command, options)`
Runs a command with options specified in a map.
**Parameters:**
- `command` (string): The command to run
- `options` (map): A map of options created with `new_run_options()`
**Returns:** The result of the command with your custom settings applied.
**Example:**
```rhai
// Create and customize run options
let options = new_run_options();
options.die = false; // Don't throw an error if the command fails
options.silent = true; // Suppress command output
options.async_exec = false; // Run synchronously
options.log = true; // Log the command execution
// Run a command with options
let result = run_with_options("npm install", options);
```
## Working with Multiline Scripts
The Process module allows you to execute multiline scripts, which is particularly useful for complex operations that require multiple commands to be executed in sequence.
### Creating Multiline Scripts
Multiline scripts can be created using backtick (`) string literals in Rhai:
```rhai
let my_script = `
# This is a multiline bash script
echo "Hello, World!"
mkdir -p /tmp/my_project
cd /tmp/my_project
touch example.txt
`;
```
## Process Management Functions
### `which(cmd)`
Checks if a command exists in the PATH.
**Parameters:**
- `cmd` (string): The command to check
**Returns:** The full path to the command if found, or nothing if not found.
**Example:**
```rhai
// Check if a command exists
let git_path = which("git");
if git_path != () {
print(`Git is installed at: ${git_path}`);
} else {
print("Git is not installed");
}
```
### `kill(pattern)`
Kills processes matching a pattern.
**Parameters:**
- `pattern` (string): The pattern to match process names against
**Returns:** A message confirming the processes were killed.
**Example:**
```rhai
// Kill all processes with "node" in their name
kill("node");
```
### `process_list(pattern)`
Lists processes matching a pattern (or all processes if the pattern is empty).
**Parameters:**
- `pattern` (string): The pattern to match process names against (can be empty to list all processes)
**Returns:** A list of processes matching your search.
**Example:**
```rhai
// List all processes
let all_processes = process_list("");
// List processes containing "node" in their name
let node_processes = process_list("node");
// Display process information
for process in node_processes {
print(`PID: ${process.pid}, Name: ${process.name}, Memory: ${process.memory}, CPU: ${process.cpu}`);
}
```
### `process_get(pattern)`
Gets a single process matching the pattern. Throws an error if zero or more than one process matches.
**Parameters:**
- `pattern` (string): The pattern to match process names against
**Returns:** Information about the matching process. This will only work if exactly one process matches.
**Example:**
```rhai
// Try to get a specific process
try {
let process = process_get("my_app");
print(`Found process: PID=${process.pid}, Name=${process.name}`);
} catch(err) {
print(`Error: ${err}`);
}
```