This commit is contained in:
7
docs/docs/intro.md
Normal file
7
docs/docs/intro.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: "intro"
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# HeroScript
|
||||
|
105
docs/docs/rhai/buildah_module_tests.md
Normal file
105
docs/docs/rhai/buildah_module_tests.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Buildah Module Tests
|
||||
|
||||
This document describes the test scripts for the Buildah module in the SAL library. These tests verify the functionality of the Buildah module's container and image operations.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into three main scripts:
|
||||
|
||||
1. **Builder Pattern** (`01_builder_pattern.rhai`): Tests for the Builder pattern, including creating containers, running commands, and working with container content.
|
||||
2. **Image Operations** (`02_image_operations.rhai`): Tests for image-related operations like pulling, tagging, listing, and removing images.
|
||||
3. **Container Operations** (`03_container_operations.rhai`): Tests for container-related operations like configuration, isolation, and content management.
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/buildah/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/buildah/01_builder_pattern.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### Builder Pattern Test
|
||||
|
||||
The Builder Pattern test (`01_builder_pattern.rhai`) verifies the following functions:
|
||||
|
||||
- `bah_new`: Creating a new Builder with a container from a specified image
|
||||
- Builder properties: `container_id`, `name`, `image`, `debug_mode`
|
||||
- `run`: Running commands in the container
|
||||
- `write_content`: Writing content to files in the container
|
||||
- `read_content`: Reading content from files in the container
|
||||
- `set_entrypoint`: Setting the container's entrypoint
|
||||
- `set_cmd`: Setting the container's command
|
||||
- `add`: Adding files to the container
|
||||
- `copy`: Copying files to the container
|
||||
- `commit`: Committing the container to an image
|
||||
- `remove`: Removing the container
|
||||
- `images`: Listing images
|
||||
- `image_remove`: Removing images
|
||||
|
||||
### Image Operations Test
|
||||
|
||||
The Image Operations test (`02_image_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `image_pull`: Pulling images from registries
|
||||
- `image_tag`: Tagging images
|
||||
- `images`: Listing images
|
||||
- `build`: Building images from Dockerfiles
|
||||
- `image_remove`: Removing images
|
||||
|
||||
The test creates a temporary directory with a Dockerfile for testing the build functionality.
|
||||
|
||||
### Container Operations Test
|
||||
|
||||
The Container Operations test (`03_container_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `reset`: Resetting a Builder by removing its container
|
||||
- `config`: Configuring container properties
|
||||
- `run_with_isolation`: Running commands with isolation
|
||||
- Content operations: Creating and executing scripts in the container
|
||||
- `commit` with options: Committing a container with additional configuration
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Checks if Buildah is available before running tests
|
||||
2. Skips tests if Buildah is not available
|
||||
3. Contains simplified versions of each test
|
||||
4. Runs each test in a try/catch block to handle errors
|
||||
5. Catches and reports any errors
|
||||
6. Provides a summary of passed, failed, and skipped tests
|
||||
|
||||
## Buildah Requirements
|
||||
|
||||
These tests require the Buildah tool to be installed and available in the system's PATH. The tests will check for Buildah's availability and skip the tests if it's not found, rather than failing.
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/buildah` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the Buildah module:
|
||||
|
||||
1. Always check if Buildah is available before running tests
|
||||
2. Use unique names for containers and images to avoid conflicts
|
||||
3. Clean up any containers, images, or files created during testing
|
||||
4. Use assertions to verify expected behavior
|
||||
5. Print clear messages about what's being tested
|
||||
6. Handle errors gracefully
|
||||
7. Make tests independent of each other
|
||||
8. Keep tests focused on specific functionality
|
71
docs/docs/rhai/ci_workflow.md
Normal file
71
docs/docs/rhai/ci_workflow.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Continuous Integration for Rhai Tests
|
||||
|
||||
This document describes the continuous integration (CI) workflow for running Rhai tests in the SAL library.
|
||||
|
||||
## GitHub Actions Workflow
|
||||
|
||||
The SAL project includes a GitHub Actions workflow that automatically runs all Rhai tests whenever changes are made to relevant files. This ensures that the Rhai integration continues to work correctly as the codebase evolves.
|
||||
|
||||
### Workflow File
|
||||
|
||||
The workflow is defined in `.github/workflows/rhai-tests.yml`.
|
||||
|
||||
### Trigger Events
|
||||
|
||||
The workflow runs automatically when:
|
||||
|
||||
1. Changes are pushed to the `main` or `master` branch that affect:
|
||||
- Rhai test scripts (`src/rhai_tests/**`)
|
||||
- Rhai module code (`src/rhai/**`)
|
||||
- Git module code (`src/git/**`)
|
||||
- OS module code (`src/os/**`)
|
||||
- The test runner script (`run_rhai_tests.sh`)
|
||||
- The workflow file itself (`.github/workflows/rhai-tests.yml`)
|
||||
|
||||
2. A pull request is opened or updated that affects the same files.
|
||||
|
||||
3. The workflow is manually triggered using the GitHub Actions interface.
|
||||
|
||||
### Workflow Steps
|
||||
|
||||
The workflow performs the following steps:
|
||||
|
||||
1. **Checkout Code**: Checks out the repository code.
|
||||
2. **Set up Rust**: Installs the Rust toolchain.
|
||||
3. **Cache Dependencies**: Caches Rust dependencies to speed up builds.
|
||||
4. **Build herodo**: Builds the `herodo` binary used to run Rhai scripts.
|
||||
5. **Install Dependencies**: Installs system dependencies like Git and curl.
|
||||
6. **Run Rhai Tests**: Runs the `run_rhai_tests.sh` script to execute all Rhai tests.
|
||||
7. **Check for Failures**: Verifies that all tests passed.
|
||||
|
||||
### Test Results
|
||||
|
||||
The workflow will fail if any Rhai test fails. This prevents changes that break the Rhai integration from being merged.
|
||||
|
||||
## Local Testing
|
||||
|
||||
Before pushing changes, you can run the same tests locally using the `run_rhai_tests.sh` script:
|
||||
|
||||
```bash
|
||||
./run_rhai_tests.sh
|
||||
```
|
||||
|
||||
This will produce the same test results as the CI workflow, allowing you to catch and fix issues before pushing your changes.
|
||||
|
||||
## Logs
|
||||
|
||||
The test runner script creates a log file (`run_rhai_tests.log`) that contains the output of all tests. This log is used by the CI workflow to check for test failures.
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
When adding new tests, make sure they are included in the appropriate module's test runner script (`run_all_tests.rhai`). The CI workflow will automatically run the new tests.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If the CI workflow fails, check the GitHub Actions logs for details. Common issues include:
|
||||
|
||||
1. **Missing Dependencies**: Ensure all required dependencies are installed.
|
||||
2. **Test Failures**: Fix any failing tests.
|
||||
3. **Build Errors**: Fix any errors in the Rust code.
|
||||
|
||||
If you need to modify the workflow, edit the `.github/workflows/rhai-tests.yml` file.
|
81
docs/docs/rhai/git_module_tests.md
Normal file
81
docs/docs/rhai/git_module_tests.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Git Module Tests
|
||||
|
||||
This document describes the test scripts for the Git module in the SAL library. These tests verify the functionality of the Git module's repository management and Git operations.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into two main scripts:
|
||||
|
||||
1. **Basic Git Operations** (`01_git_basic.rhai`): Tests basic Git functionality like creating a GitTree, listing repositories, finding repositories, and cloning repositories.
|
||||
2. **Git Repository Operations** (`02_git_operations.rhai`): Tests Git operations like pull, reset, commit, and push.
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/git/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/git/01_git_basic.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### Basic Git Operations Test
|
||||
|
||||
The basic Git operations test (`01_git_basic.rhai`) verifies the following functions:
|
||||
|
||||
- `git_tree_new`: Creating a GitTree
|
||||
- `list`: Listing repositories in a GitTree
|
||||
- `find`: Finding repositories matching a pattern
|
||||
- `get`: Getting or cloning a repository
|
||||
- `path`: Getting the path of a repository
|
||||
- `has_changes`: Checking if a repository has changes
|
||||
|
||||
The test creates a temporary directory, performs operations on it, and then cleans up after itself.
|
||||
|
||||
### Git Repository Operations Test
|
||||
|
||||
The Git repository operations test (`02_git_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `pull`: Pulling changes from a remote repository
|
||||
- `reset`: Resetting local changes
|
||||
- `commit`: Committing changes (method existence only)
|
||||
- `push`: Pushing changes to a remote repository (method existence only)
|
||||
|
||||
Note: The test does not actually commit or push changes to avoid modifying remote repositories. It only verifies that the methods exist and can be called.
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Contains simplified versions of each test
|
||||
2. Runs each test in a try/catch block to handle errors
|
||||
3. Catches and reports any errors
|
||||
4. Provides a summary of passed and failed tests
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/git` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the Git module:
|
||||
|
||||
1. Always clean up temporary files and directories
|
||||
2. Use assertions to verify expected behavior
|
||||
3. Print clear messages about what's being tested
|
||||
4. Handle errors gracefully
|
||||
5. Make tests independent of each other
|
||||
6. Avoid tests that modify remote repositories
|
||||
7. Keep tests focused on specific functionality
|
85
docs/docs/rhai/index.md
Normal file
85
docs/docs/rhai/index.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Rhai Scripting in SAL
|
||||
|
||||
This documentation covers the Rhai scripting integration in the SAL (System Abstraction Layer) library.
|
||||
|
||||
## Overview
|
||||
|
||||
SAL provides integration with the [Rhai scripting language](https://rhai.rs/), allowing you to use SAL's functionality in scripts. This enables automation of system tasks, testing, and more complex operations without having to write Rust code.
|
||||
|
||||
## Modules
|
||||
|
||||
SAL exposes the following modules to Rhai scripts:
|
||||
|
||||
- [OS Module](os_module_tests.md): File system operations, downloads, and package management
|
||||
- Process Module: Process management and command execution
|
||||
- Git Module: Git repository operations
|
||||
- Text Module: Text processing utilities
|
||||
- Buildah Module: Container image building
|
||||
- Nerdctl Module: Container runtime operations
|
||||
- RFS Module: Remote file system operations
|
||||
- Redis Client Module: Redis database connection and operations
|
||||
- PostgreSQL Client Module: PostgreSQL database connection and operations
|
||||
|
||||
## Running Rhai Scripts
|
||||
|
||||
You can run Rhai scripts using the `herodo` binary:
|
||||
|
||||
```bash
|
||||
herodo --path path/to/script.rhai
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
SAL includes test scripts for verifying the functionality of its Rhai integration. These tests are located in the `src/rhai_tests` directory and are organized by module.
|
||||
|
||||
- [OS Module Tests](os_module_tests.md): Tests for file system, download, and package management operations
|
||||
- [Git Module Tests](git_module_tests.md): Tests for Git repository management and operations
|
||||
- [Process Module Tests](process_module_tests.md): Tests for command execution and process management
|
||||
- [Redis Client Module Tests](redisclient_module_tests.md): Tests for Redis connection and operations
|
||||
- [PostgreSQL Client Module Tests](postgresclient_module_tests.md): Tests for PostgreSQL connection and operations
|
||||
- [Text Module Tests](text_module_tests.md): Tests for text manipulation, normalization, replacement, and template rendering
|
||||
- [Buildah Module Tests](buildah_module_tests.md): Tests for container and image operations
|
||||
- [Nerdctl Module Tests](nerdctl_module_tests.md): Tests for container and image operations using nerdctl
|
||||
- [RFS Module Tests](rfs_module_tests.md): Tests for remote filesystem operations and filesystem layers
|
||||
- [Running Tests](running_tests.md): Instructions for running all Rhai tests
|
||||
- [CI Workflow](ci_workflow.md): Continuous integration workflow for Rhai tests
|
||||
|
||||
## Examples
|
||||
|
||||
For examples of how to use SAL's Rhai integration, see the `examples` directory in the project root. These examples demonstrate various features and use cases.
|
||||
|
||||
## Writing Your Own Scripts
|
||||
|
||||
When writing Rhai scripts that use SAL:
|
||||
|
||||
1. Import the necessary modules (they're automatically registered)
|
||||
2. Use the functions provided by each module
|
||||
3. Handle errors appropriately
|
||||
4. Clean up resources when done
|
||||
|
||||
Example:
|
||||
|
||||
```rhai
|
||||
// Simple example of using the OS module
|
||||
let test_dir = "my_test_dir";
|
||||
mkdir(test_dir);
|
||||
|
||||
if exist(test_dir) {
|
||||
print(`Directory ${test_dir} created successfully`);
|
||||
|
||||
// Create a file
|
||||
let test_file = test_dir + "/test.txt";
|
||||
file_write(test_file, "Hello, world!");
|
||||
|
||||
// Read the file
|
||||
let content = file_read(test_file);
|
||||
print(`File content: ${content}`);
|
||||
|
||||
// Clean up
|
||||
delete(test_dir);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
For detailed information about the functions available in each module, refer to the module-specific documentation.
|
116
docs/docs/rhai/nerdctl_module_tests.md
Normal file
116
docs/docs/rhai/nerdctl_module_tests.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Nerdctl Module Tests
|
||||
|
||||
This document describes the test scripts for the Nerdctl module in the SAL library. These tests verify the functionality of the Nerdctl module's container and image operations.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into three main scripts:
|
||||
|
||||
1. **Container Operations** (`01_container_operations.rhai`): Tests for basic container operations like creating, running, executing commands, and removing containers.
|
||||
2. **Image Operations** (`02_image_operations.rhai`): Tests for image-related operations like pulling, tagging, listing, building, and removing images.
|
||||
3. **Container Builder Pattern** (`03_container_builder.rhai`): Tests for the Container Builder pattern, which provides a fluent interface for configuring and running containers.
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/nerdctl/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/nerdctl/01_container_operations.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### Container Operations Test
|
||||
|
||||
The Container Operations test (`01_container_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `nerdctl_container_new`: Creating a new Container
|
||||
- Container properties: `name`, `container_id`, `image`, `detach`
|
||||
- `with_image`: Setting the container image
|
||||
- `with_detach`: Setting detach mode
|
||||
- `with_env` and `with_envs`: Setting environment variables
|
||||
- `with_port` and `with_ports`: Setting port mappings
|
||||
- `with_volume`: Setting volume mounts
|
||||
- `with_cpu_limit` and `with_memory_limit`: Setting resource limits
|
||||
- `run`: Running the container
|
||||
- `exec`: Executing commands in the container
|
||||
- `logs`: Getting container logs
|
||||
- `stop`: Stopping the container
|
||||
- `remove`: Removing the container
|
||||
|
||||
### Image Operations Test
|
||||
|
||||
The Image Operations test (`02_image_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `nerdctl_image_pull`: Pulling images from registries
|
||||
- `nerdctl_images`: Listing images
|
||||
- `nerdctl_image_tag`: Tagging images
|
||||
- `nerdctl_image_build`: Building images from Dockerfiles
|
||||
- `nerdctl_run_with_name`: Running containers from images
|
||||
- `nerdctl_stop` and `nerdctl_remove`: Stopping and removing containers
|
||||
- `nerdctl_image_remove`: Removing images
|
||||
|
||||
The test creates a temporary directory with a Dockerfile for testing the build functionality.
|
||||
|
||||
### Container Builder Pattern Test
|
||||
|
||||
The Container Builder Pattern test (`03_container_builder.rhai`) verifies the following functions:
|
||||
|
||||
- `nerdctl_container_from_image`: Creating a container from an image
|
||||
- `reset`: Resetting container configuration
|
||||
- `with_detach`: Setting detach mode
|
||||
- `with_ports`: Setting multiple port mappings
|
||||
- `with_volumes`: Setting multiple volume mounts
|
||||
- `with_envs`: Setting multiple environment variables
|
||||
- `with_network`: Setting network
|
||||
- `with_cpu_limit` and `with_memory_limit`: Setting resource limits
|
||||
- `run`: Running the container
|
||||
- `exec`: Executing commands in the container
|
||||
- `stop`: Stopping the container
|
||||
- `remove`: Removing the container
|
||||
|
||||
The test also verifies that environment variables and volume mounts work correctly by writing and reading files between the container and the host.
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Checks if nerdctl is available before running tests
|
||||
2. Skips tests if nerdctl is not available
|
||||
3. Contains simplified versions of each test
|
||||
4. Runs each test in a try/catch block to handle errors
|
||||
5. Catches and reports any errors
|
||||
6. Provides a summary of passed, failed, and skipped tests
|
||||
|
||||
## Nerdctl Requirements
|
||||
|
||||
These tests require the nerdctl tool to be installed and available in the system's PATH. The tests will check for nerdctl's availability and skip the tests if it's not found, rather than failing.
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/nerdctl` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the Nerdctl module:
|
||||
|
||||
1. Always check if nerdctl is available before running tests
|
||||
2. Use unique names for containers and images to avoid conflicts
|
||||
3. Clean up any containers, images, or files created during testing
|
||||
4. Use assertions to verify expected behavior
|
||||
5. Print clear messages about what's being tested
|
||||
6. Handle errors gracefully
|
||||
7. Make tests independent of each other
|
||||
8. Keep tests focused on specific functionality
|
105
docs/docs/rhai/os_module_tests.md
Normal file
105
docs/docs/rhai/os_module_tests.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# OS Module Tests
|
||||
|
||||
This document describes the test scripts for the OS module in the SAL library. These tests verify the functionality of the OS module's file system operations, download capabilities, and package management features.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into three main scripts:
|
||||
|
||||
1. **File Operations** (`01_file_operations.rhai`): Tests file system operations like creating, reading, writing, and manipulating files and directories.
|
||||
2. **Download Operations** (`02_download_operations.rhai`): Tests downloading files from the internet and related operations.
|
||||
3. **Package Operations** (`03_package_operations.rhai`): Tests package management functionality.
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency on the `run_script` function.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
# Assume that you have the herodo binary/built into your system
|
||||
herodo --path src/rhai_tests/os/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
# Assume that you have the herodo binary/built into your system
|
||||
herodo --path src/rhai_tests/os/01_file_operations.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### File Operations Test
|
||||
|
||||
The file operations test (`01_file_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `mkdir`: Creating directories
|
||||
- `file_write`: Writing content to files
|
||||
- `file_read`: Reading content from files
|
||||
- `file_size`: Getting file size
|
||||
- `file_write_append`: Appending content to files
|
||||
- `copy`: Copying files
|
||||
- `mv`: Moving files
|
||||
- `find_file`: Finding a single file matching a pattern
|
||||
- `find_files`: Finding multiple files matching a pattern
|
||||
- `find_dir`: Finding a single directory matching a pattern
|
||||
- `find_dirs`: Finding multiple directories matching a pattern
|
||||
- `chdir`: Changing the current working directory
|
||||
- `rsync`: Synchronizing directories
|
||||
- `delete`: Deleting files and directories
|
||||
- `exist`: Checking if files or directories exist
|
||||
|
||||
The test creates a temporary directory structure, performs operations on it, and then cleans up after itself.
|
||||
|
||||
### Download Operations Test
|
||||
|
||||
The download operations test (`02_download_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `which`: Checking if a command exists in the system PATH
|
||||
- `cmd_ensure_exists`: Ensuring commands exist
|
||||
- `download_file`: Downloading a file from a URL
|
||||
- `chmod_exec`: Making a file executable
|
||||
|
||||
The test downloads a small file from GitHub, verifies its content, and then cleans up.
|
||||
|
||||
### Package Operations Test
|
||||
|
||||
The package operations test (`03_package_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `package_platform`: Getting the current platform
|
||||
- `package_set_debug`: Setting debug mode for package operations
|
||||
- `package_is_installed`: Checking if a package is installed
|
||||
- `package_search`: Searching for packages
|
||||
- `package_list`: Listing installed packages
|
||||
|
||||
Note: The test does not verify `package_install`, `package_remove`, `package_update`, or `package_upgrade` as these require root privileges and could modify the system state.
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Contains simplified versions of each test
|
||||
2. Runs each test in a try/catch block to handle errors
|
||||
3. Catches and reports any errors
|
||||
4. Provides a summary of passed and failed tests
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/os` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the OS module:
|
||||
|
||||
1. Always clean up temporary files and directories
|
||||
2. Use assertions to verify expected behavior
|
||||
3. Print clear messages about what's being tested
|
||||
4. Handle errors gracefully
|
||||
5. Make tests independent of each other
|
||||
6. Avoid tests that require root privileges when possible
|
||||
7. Keep tests focused on specific functionality
|
188
docs/docs/rhai/postgresclient_module_tests.md
Normal file
188
docs/docs/rhai/postgresclient_module_tests.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# PostgreSQL Client Module Tests
|
||||
|
||||
The PostgreSQL client module provides functions for connecting to and interacting with PostgreSQL databases. These tests verify the functionality of the module.
|
||||
|
||||
## PostgreSQL Client Features
|
||||
|
||||
The PostgreSQL client module provides the following features:
|
||||
|
||||
1. **Basic PostgreSQL Operations**: Execute queries, fetch results, etc.
|
||||
2. **Connection Management**: Automatic connection handling and reconnection
|
||||
3. **Builder Pattern for Configuration**: Flexible configuration with authentication support
|
||||
4. **PostgreSQL Installer**: Install and configure PostgreSQL using nerdctl
|
||||
5. **Database Management**: Create databases and execute SQL scripts
|
||||
|
||||
## Prerequisites
|
||||
|
||||
For basic PostgreSQL operations:
|
||||
- PostgreSQL server must be running and accessible
|
||||
- Environment variables should be set for connection details:
|
||||
- `POSTGRES_HOST`: PostgreSQL server host (default: localhost)
|
||||
- `POSTGRES_PORT`: PostgreSQL server port (default: 5432)
|
||||
- `POSTGRES_USER`: PostgreSQL username (default: postgres)
|
||||
- `POSTGRES_PASSWORD`: PostgreSQL password
|
||||
- `POSTGRES_DB`: PostgreSQL database name (default: postgres)
|
||||
|
||||
For PostgreSQL installer:
|
||||
- nerdctl must be installed and working
|
||||
- Docker images must be accessible
|
||||
- Sufficient permissions to create and manage containers
|
||||
|
||||
## Test Files
|
||||
|
||||
### 01_postgres_connection.rhai
|
||||
|
||||
Tests basic PostgreSQL connection and operations:
|
||||
|
||||
- Connecting to PostgreSQL
|
||||
- Pinging the server
|
||||
- Creating a table
|
||||
- Inserting data
|
||||
- Querying data
|
||||
- Dropping a table
|
||||
- Resetting the connection
|
||||
|
||||
### 02_postgres_installer.rhai
|
||||
|
||||
Tests PostgreSQL installer functionality:
|
||||
|
||||
- Installing PostgreSQL using nerdctl
|
||||
- Creating a database
|
||||
- Executing SQL scripts
|
||||
- Checking if PostgreSQL is running
|
||||
|
||||
### run_all_tests.rhai
|
||||
|
||||
Runs all PostgreSQL client module tests and provides a summary of the results.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
You can run the tests using the `herodo` command:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/postgresclient/run_all_tests.rhai
|
||||
```
|
||||
|
||||
Or run individual tests:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/postgresclient/01_postgres_connection.rhai
|
||||
```
|
||||
|
||||
## Available Functions
|
||||
|
||||
### Connection Functions
|
||||
|
||||
- `pg_connect()`: Connect to PostgreSQL using environment variables
|
||||
- `pg_ping()`: Ping the PostgreSQL server to check if it's available
|
||||
- `pg_reset()`: Reset the PostgreSQL client connection
|
||||
|
||||
### Query Functions
|
||||
|
||||
- `pg_execute(query)`: Execute a query and return the number of affected rows
|
||||
- `pg_query(query)`: Execute a query and return the results as an array of maps
|
||||
- `pg_query_one(query)`: Execute a query and return a single row as a map
|
||||
|
||||
### Installer Functions
|
||||
|
||||
- `pg_install(container_name, version, port, username, password)`: Install PostgreSQL using nerdctl
|
||||
- `pg_create_database(container_name, db_name)`: Create a new database in PostgreSQL
|
||||
- `pg_execute_sql(container_name, db_name, sql)`: Execute a SQL script in PostgreSQL
|
||||
- `pg_is_running(container_name)`: Check if PostgreSQL is running
|
||||
|
||||
## Authentication Support
|
||||
|
||||
The PostgreSQL client module will support authentication using the builder pattern in a future update.
|
||||
|
||||
The backend implementation is ready, but the Rhai bindings are still in development.
|
||||
|
||||
When implemented, the builder pattern will support the following configuration options:
|
||||
|
||||
- Host: Set the PostgreSQL host
|
||||
- Port: Set the PostgreSQL port
|
||||
- User: Set the PostgreSQL username
|
||||
- Password: Set the PostgreSQL password
|
||||
- Database: Set the PostgreSQL database name
|
||||
- Application name: Set the application name
|
||||
- Connection timeout: Set the connection timeout in seconds
|
||||
- SSL mode: Set the SSL mode
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Basic PostgreSQL Operations
|
||||
|
||||
```rust
|
||||
// Connect to PostgreSQL
|
||||
if (pg_connect()) {
|
||||
print("Connected to PostgreSQL!");
|
||||
|
||||
// Create a table
|
||||
let create_table_query = "CREATE TABLE IF NOT EXISTS test_table (id SERIAL PRIMARY KEY, name TEXT)";
|
||||
pg_execute(create_table_query);
|
||||
|
||||
// Insert data
|
||||
let insert_query = "INSERT INTO test_table (name) VALUES ('test')";
|
||||
pg_execute(insert_query);
|
||||
|
||||
// Query data
|
||||
let select_query = "SELECT * FROM test_table";
|
||||
let results = pg_query(select_query);
|
||||
|
||||
// Process results
|
||||
for (result in results) {
|
||||
print(`ID: ${result.id}, Name: ${result.name}`);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
let drop_query = "DROP TABLE test_table";
|
||||
pg_execute(drop_query);
|
||||
}
|
||||
```
|
||||
|
||||
### PostgreSQL Installer
|
||||
|
||||
```rust
|
||||
// Install PostgreSQL
|
||||
let container_name = "my-postgres";
|
||||
let postgres_version = "15";
|
||||
let postgres_port = 5432;
|
||||
let postgres_user = "myuser";
|
||||
let postgres_password = "mypassword";
|
||||
|
||||
if (pg_install(container_name, postgres_version, postgres_port, postgres_user, postgres_password)) {
|
||||
print("PostgreSQL installed successfully!");
|
||||
|
||||
// Create a database
|
||||
let db_name = "mydb";
|
||||
if (pg_create_database(container_name, db_name)) {
|
||||
print(`Database '${db_name}' created successfully!`);
|
||||
|
||||
// Execute a SQL script
|
||||
let create_table_sql = `
|
||||
CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT UNIQUE NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
let result = pg_execute_sql(container_name, db_name, create_table_sql);
|
||||
print("Table created successfully!");
|
||||
|
||||
// Insert data
|
||||
let insert_sql = "#
|
||||
INSERT INTO users (name, email) VALUES
|
||||
('John Doe', 'john@example.com'),
|
||||
('Jane Smith', 'jane@example.com');
|
||||
#";
|
||||
|
||||
result = pg_execute_sql(container_name, db_name, insert_sql);
|
||||
print("Data inserted successfully!");
|
||||
|
||||
// Query data
|
||||
let query_sql = "SELECT * FROM users;";
|
||||
result = pg_execute_sql(container_name, db_name, query_sql);
|
||||
print(`Query result: ${result}`);
|
||||
}
|
||||
}
|
||||
```
|
79
docs/docs/rhai/process_module_tests.md
Normal file
79
docs/docs/rhai/process_module_tests.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Process Module Tests
|
||||
|
||||
This document describes the test scripts for the Process module in the SAL library. These tests verify the functionality of the Process module's command execution and process management features.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into two main scripts:
|
||||
|
||||
1. **Command Execution** (`01_command_execution.rhai`): Tests command execution functions like `run()` and `which()`.
|
||||
2. **Process Management** (`02_process_management.rhai`): Tests process management functions like `process_list()` and `process_get()`.
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/process/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/process/01_command_execution.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### Command Execution Test
|
||||
|
||||
The command execution test (`01_command_execution.rhai`) verifies the following functions:
|
||||
|
||||
- `run()`: Running shell commands
|
||||
- `run().do()`: Executing commands and capturing output
|
||||
- `run().silent()`: Running commands without displaying output
|
||||
- `run().ignore_error()`: Running commands that might fail without throwing errors
|
||||
- `which()`: Finding the path of an executable
|
||||
|
||||
The test runs various commands and verifies their output and exit status.
|
||||
|
||||
### Process Management Test
|
||||
|
||||
The process management test (`02_process_management.rhai`) verifies the following functions:
|
||||
|
||||
- `process_list()`: Listing running processes
|
||||
- `process_get()`: Getting information about a specific process
|
||||
- Process properties: Accessing process information like PID, name, CPU usage, and memory usage
|
||||
|
||||
The test lists running processes and verifies that their properties are accessible.
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Contains simplified versions of each test
|
||||
2. Runs each test in a try/catch block to handle errors
|
||||
3. Catches and reports any errors
|
||||
4. Provides a summary of passed and failed tests
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/process` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the Process module:
|
||||
|
||||
1. Use assertions to verify expected behavior
|
||||
2. Print clear messages about what's being tested
|
||||
3. Handle errors gracefully
|
||||
4. Make tests independent of each other
|
||||
5. Avoid tests that could disrupt the system (e.g., killing important processes)
|
||||
6. Keep tests focused on specific functionality
|
||||
7. Clean up any resources created during testing
|
125
docs/docs/rhai/redisclient_module_tests.md
Normal file
125
docs/docs/rhai/redisclient_module_tests.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Redis Client Module Tests
|
||||
|
||||
This document describes the test scripts for the Redis client module in the SAL library. These tests verify the functionality of the Redis client module's connection management and Redis operations.
|
||||
|
||||
## Redis Client Features
|
||||
|
||||
The Redis client module provides the following features:
|
||||
|
||||
1. **Basic Redis Operations**: SET, GET, DEL, etc.
|
||||
2. **Hash Operations**: HSET, HGET, HGETALL, HDEL
|
||||
3. **List Operations**: RPUSH, LPUSH, LLEN, LRANGE
|
||||
4. **Connection Management**: Automatic connection handling and reconnection
|
||||
5. **Builder Pattern for Configuration**: Flexible configuration with authentication support
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into two main scripts:
|
||||
|
||||
1. **Redis Connection** (`01_redis_connection.rhai`): Tests basic Redis connection and simple operations like PING, SET, GET, and DEL.
|
||||
2. **Redis Operations** (`02_redis_operations.rhai`): Tests more advanced Redis operations like hash operations (HSET, HGET, HGETALL, HDEL) and list operations (RPUSH, LLEN, LRANGE).
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/redisclient/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/redisclient/01_redis_connection.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### Redis Connection Test
|
||||
|
||||
The Redis connection test (`01_redis_connection.rhai`) verifies the following functions:
|
||||
|
||||
- `redis_ping`: Checking if the Redis server is available
|
||||
- `redis_set`: Setting a key-value pair
|
||||
- `redis_get`: Getting a value by key
|
||||
- `redis_del`: Deleting a key
|
||||
|
||||
The test creates a temporary key, performs operations on it, and then cleans up after itself.
|
||||
|
||||
### Redis Operations Test
|
||||
|
||||
The Redis operations test (`02_redis_operations.rhai`) verifies the following functions:
|
||||
|
||||
- Hash operations:
|
||||
- `redis_hset`: Setting a field in a hash
|
||||
- `redis_hget`: Getting a field from a hash
|
||||
- `redis_hgetall`: Getting all fields and values from a hash
|
||||
- `redis_hdel`: Deleting a field from a hash
|
||||
|
||||
- List operations:
|
||||
- `redis_rpush`: Adding elements to a list
|
||||
- `redis_llen`: Getting the length of a list
|
||||
- `redis_lrange`: Getting a range of elements from a list
|
||||
|
||||
The test creates temporary keys with a unique prefix, performs operations on them, and then cleans up after itself.
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Checks if Redis is available before running tests
|
||||
2. Skips tests if Redis is not available
|
||||
3. Contains simplified versions of each test
|
||||
4. Runs each test in a try/catch block to handle errors
|
||||
5. Catches and reports any errors
|
||||
6. Provides a summary of passed, failed, and skipped tests
|
||||
|
||||
## Redis Server Requirements
|
||||
|
||||
These tests require a Redis server to be running and accessible. The tests will attempt to connect to Redis using the following strategy:
|
||||
|
||||
1. First, try to connect via Unix socket at `$HOME/hero/var/myredis.sock`
|
||||
2. If that fails, try to connect via TCP to `127.0.0.1` on the default Redis port (6379)
|
||||
|
||||
If no Redis server is available, the tests will be skipped rather than failing.
|
||||
|
||||
## Authentication Support
|
||||
|
||||
The Redis client module will support authentication using the builder pattern in a future update.
|
||||
|
||||
The backend implementation is ready, but the Rhai bindings are still in development.
|
||||
|
||||
When implemented, the builder pattern will support the following configuration options:
|
||||
|
||||
- Host: Set the Redis host
|
||||
- Port: Set the Redis port
|
||||
- Database: Set the Redis database number
|
||||
- Username: Set the Redis username (Redis 6.0+)
|
||||
- Password: Set the Redis password
|
||||
- TLS: Enable/disable TLS
|
||||
- Unix socket: Enable/disable Unix socket
|
||||
- Socket path: Set the Unix socket path
|
||||
- Connection timeout: Set the connection timeout in seconds
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/redisclient` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the Redis client module:
|
||||
|
||||
1. Always check if Redis is available before running tests
|
||||
2. Use a unique prefix for test keys to avoid conflicts
|
||||
3. Clean up any keys created during testing
|
||||
4. Use assertions to verify expected behavior
|
||||
5. Print clear messages about what's being tested
|
||||
6. Handle errors gracefully
|
||||
7. Make tests independent of each other
|
||||
8. Keep tests focused on specific functionality
|
113
docs/docs/rhai/rfs_module_tests.md
Normal file
113
docs/docs/rhai/rfs_module_tests.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# RFS Module Tests
|
||||
|
||||
This document describes the test scripts for the RFS (Remote File System) module in the SAL library. These tests verify the functionality of the RFS module's mount operations and filesystem layer management.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into two main scripts:
|
||||
|
||||
1. **Mount Operations** (`01_mount_operations.rhai`): Tests for mounting, listing, and unmounting filesystems.
|
||||
2. **Filesystem Layer Operations** (`02_filesystem_layer_operations.rhai`): Tests for packing, unpacking, listing, and verifying filesystem layers.
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/rfs/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/rfs/01_mount_operations.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### Mount Operations Test
|
||||
|
||||
The Mount Operations test (`01_mount_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `rfs_mount`: Mounting a filesystem
|
||||
- Tests mounting a local directory with options
|
||||
- Verifies mount properties (ID, source, target, type)
|
||||
|
||||
- `rfs_list_mounts`: Listing mounted filesystems
|
||||
- Tests listing all mounts
|
||||
- Verifies that the mounted filesystem is in the list
|
||||
|
||||
- `rfs_get_mount_info`: Getting information about a mounted filesystem
|
||||
- Tests getting information about a specific mount
|
||||
- Verifies that the mount information is correct
|
||||
|
||||
- `rfs_unmount`: Unmounting a specific filesystem
|
||||
- Tests unmounting a specific mount
|
||||
- Verifies that the mount is no longer available
|
||||
|
||||
- `rfs_unmount_all`: Unmounting all filesystems
|
||||
- Tests unmounting all mounts
|
||||
- Verifies that no mounts remain after the operation
|
||||
|
||||
The test also verifies that files in the mounted filesystem are accessible and have the correct content.
|
||||
|
||||
### Filesystem Layer Operations Test
|
||||
|
||||
The Filesystem Layer Operations test (`02_filesystem_layer_operations.rhai`) verifies the following functions:
|
||||
|
||||
- `rfs_pack`: Packing a directory into a filesystem layer
|
||||
- Tests packing a directory with files and subdirectories
|
||||
- Verifies that the output file is created
|
||||
|
||||
- `rfs_list_contents`: Listing the contents of a filesystem layer
|
||||
- Tests listing the contents of a packed filesystem layer
|
||||
- Verifies that the list includes all expected files
|
||||
|
||||
- `rfs_verify`: Verifying a filesystem layer
|
||||
- Tests verifying a packed filesystem layer
|
||||
- Verifies that the layer is valid
|
||||
|
||||
- `rfs_unpack`: Unpacking a filesystem layer
|
||||
- Tests unpacking a filesystem layer to a directory
|
||||
- Verifies that all files are unpacked correctly with the right content
|
||||
|
||||
The test creates a directory structure with files, packs it into a filesystem layer, and then unpacks it to verify the integrity of the process.
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Checks if RFS is available before running tests
|
||||
2. Skips tests if RFS is not available
|
||||
3. Contains simplified versions of each test
|
||||
4. Runs each test in a try/catch block to handle errors
|
||||
5. Catches and reports any errors
|
||||
6. Provides a summary of passed, failed, and skipped tests
|
||||
|
||||
## RFS Requirements
|
||||
|
||||
These tests require the RFS tool to be installed and available in the system's PATH. The tests will check for RFS's availability and skip the tests if it's not found, rather than failing.
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/rfs` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the RFS module:
|
||||
|
||||
1. Always check if RFS is available before running tests
|
||||
2. Clean up any mounts before and after testing
|
||||
3. Use unique names for test directories and files to avoid conflicts
|
||||
4. Clean up any files or directories created during testing
|
||||
5. Use assertions to verify expected behavior
|
||||
6. Print clear messages about what's being tested
|
||||
7. Handle errors gracefully
|
||||
8. Make tests independent of each other
|
||||
9. Keep tests focused on specific functionality
|
76
docs/docs/rhai/running_tests.md
Normal file
76
docs/docs/rhai/running_tests.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Running Rhai Tests
|
||||
|
||||
This document describes how to run the Rhai tests for the SAL library.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The Rhai tests are organized by module in the `src/rhai_tests` directory:
|
||||
|
||||
- `src/rhai_tests/os/`: Tests for the OS module
|
||||
- `src/rhai_tests/git/`: Tests for the Git module
|
||||
|
||||
Each module directory contains:
|
||||
- Individual test scripts (e.g., `01_file_operations.rhai`)
|
||||
- A test runner script (`run_all_tests.rhai`) that runs all tests for that module
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Running All Tests
|
||||
|
||||
To run all Rhai tests across all modules, use the provided shell script:
|
||||
|
||||
```bash
|
||||
./run_rhai_tests.sh
|
||||
```
|
||||
|
||||
This script:
|
||||
1. Finds all test runner scripts in the `src/rhai_tests` directory
|
||||
2. Runs each test runner
|
||||
3. Reports the results for each module
|
||||
4. Provides a summary of all test results
|
||||
|
||||
The script will exit with code 0 if all tests pass, or code 1 if any tests fail.
|
||||
|
||||
### Running Tests for a Specific Module
|
||||
|
||||
To run tests for a specific module, use the `herodo` command with the module's test runner:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/os/run_all_tests.rhai
|
||||
```
|
||||
|
||||
### Running Individual Tests
|
||||
|
||||
To run a specific test, use the `herodo` command with the test script:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/os/01_file_operations.rhai
|
||||
```
|
||||
|
||||
## Test Output
|
||||
|
||||
The test output includes:
|
||||
- Information about what's being tested
|
||||
- Success or failure messages for each test
|
||||
- A summary of test results
|
||||
|
||||
Successful tests are indicated with a checkmark (✓), while failed tests show an error message.
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
When adding new tests:
|
||||
|
||||
1. Create a new test script in the appropriate module directory
|
||||
2. Update the module's test runner script to include the new test
|
||||
3. Update the module's documentation to describe the new test
|
||||
|
||||
The `run_rhai_tests.sh` script will automatically find and run the new tests as long as they're included in a module's test runner script.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If tests fail, check the following:
|
||||
|
||||
1. Make sure the `herodo` binary is in your PATH
|
||||
2. Verify that the test scripts have the correct permissions
|
||||
3. Check for any dependencies required by the tests (e.g., `git` for Git module tests)
|
||||
4. Look for specific error messages in the test output
|
129
docs/docs/rhai/text_module_tests.md
Normal file
129
docs/docs/rhai/text_module_tests.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Text Module Tests
|
||||
|
||||
This document describes the test scripts for the Text module in the SAL library. These tests verify the functionality of the Text module's text manipulation, normalization, replacement, and template rendering capabilities.
|
||||
|
||||
## Test Structure
|
||||
|
||||
The tests are organized into four main scripts:
|
||||
|
||||
1. **Text Indentation** (`01_text_indentation.rhai`): Tests for the `dedent` and `prefix` functions.
|
||||
2. **Filename and Path Normalization** (`02_name_path_fix.rhai`): Tests for the `name_fix` and `path_fix` functions.
|
||||
3. **Text Replacement** (`03_text_replacer.rhai`): Tests for the `TextReplacer` class and its methods.
|
||||
4. **Template Rendering** (`04_template_builder.rhai`): Tests for the `TemplateBuilder` class and its methods.
|
||||
|
||||
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run all tests, execute the following command from the project root:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/text/run_all_tests.rhai
|
||||
```
|
||||
|
||||
To run individual test scripts:
|
||||
|
||||
```bash
|
||||
herodo --path src/rhai_tests/text/01_text_indentation.rhai
|
||||
```
|
||||
|
||||
## Test Details
|
||||
|
||||
### Text Indentation Test
|
||||
|
||||
The text indentation test (`01_text_indentation.rhai`) verifies the following functions:
|
||||
|
||||
- `dedent`: Removes common leading whitespace from multiline strings
|
||||
- Tests basic indentation removal
|
||||
- Tests mixed indentation handling
|
||||
- Tests preservation of empty lines
|
||||
- Tests handling of text without indentation
|
||||
- Tests single line indentation removal
|
||||
|
||||
- `prefix`: Adds a specified prefix to each line of a multiline string
|
||||
- Tests basic prefix addition
|
||||
- Tests empty prefix handling
|
||||
- Tests prefix addition to empty lines
|
||||
- Tests prefix addition to single line
|
||||
- Tests non-space prefix addition
|
||||
|
||||
- Combination of `dedent` and `prefix` functions
|
||||
|
||||
### Filename and Path Normalization Test
|
||||
|
||||
The filename and path normalization test (`02_name_path_fix.rhai`) verifies the following functions:
|
||||
|
||||
- `name_fix`: Normalizes filenames
|
||||
- Tests basic name fixing (spaces to underscores, lowercase conversion)
|
||||
- Tests special character handling
|
||||
- Tests multiple special character handling
|
||||
- Tests non-ASCII character removal
|
||||
- Tests uppercase conversion
|
||||
|
||||
- `path_fix`: Applies `name_fix` to the filename portion of a path
|
||||
- Tests paths ending with `/` (directories)
|
||||
- Tests single filename handling
|
||||
- Tests path with filename handling
|
||||
- Tests relative path handling
|
||||
- Tests path with special characters in filename
|
||||
|
||||
### Text Replacement Test
|
||||
|
||||
The text replacement test (`03_text_replacer.rhai`) verifies the following functions:
|
||||
|
||||
- `TextReplacer` with simple replacements
|
||||
- Tests basic replacement
|
||||
- Tests multiple replacements
|
||||
|
||||
- `TextReplacer` with regex replacements
|
||||
- Tests basic regex replacement
|
||||
- Tests case-insensitive regex replacement
|
||||
|
||||
- `TextReplacer` with file operations
|
||||
- Tests `replace_file` (read file, apply replacements, return result)
|
||||
- Tests `replace_file_to` (read file, apply replacements, write to new file)
|
||||
- Tests `replace_file_in_place` (read file, apply replacements, write back to same file)
|
||||
|
||||
### Template Rendering Test
|
||||
|
||||
The template rendering test (`04_template_builder.rhai`) verifies the following functions:
|
||||
|
||||
- `TemplateBuilder` with file template
|
||||
- Tests basic template with string variable
|
||||
- Tests template with multiple variables of different types
|
||||
- Tests template with array variable
|
||||
- Tests template with map variable
|
||||
|
||||
- `TemplateBuilder` with file operations
|
||||
- Tests template from file
|
||||
- Tests `render_to_file` (render template, write to file)
|
||||
|
||||
Note: The `template_builder_open` function expects a file path, not a string template. The test creates template files on disk for testing.
|
||||
|
||||
## Test Runner
|
||||
|
||||
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||
|
||||
1. Contains simplified versions of each test
|
||||
2. Runs each test in a try/catch block to handle errors
|
||||
3. Catches and reports any errors
|
||||
4. Provides a summary of passed and failed tests
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
To add a new test:
|
||||
|
||||
1. Create a new Rhai script in the `src/rhai_tests/text` directory
|
||||
2. Add a new test section to the `run_all_tests.rhai` script
|
||||
3. Update this documentation to include information about the new test
|
||||
|
||||
## Best Practices for Writing Tests
|
||||
|
||||
When writing tests for the Text module:
|
||||
|
||||
1. Use the `assert_true` and `assert_eq` functions to verify expected behavior
|
||||
2. Print clear messages about what's being tested
|
||||
3. Clean up any temporary files or directories created during testing
|
||||
4. Handle errors gracefully
|
||||
5. Make tests independent of each other
|
||||
6. Keep tests focused on specific functionality
|
8
docs/docs/sal/_category_.json
Normal file
8
docs/docs/sal/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "SAL",
|
||||
"position": 6,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Tools to work with operating system."
|
||||
}
|
||||
}
|
239
docs/docs/sal/buildah.md
Normal file
239
docs/docs/sal/buildah.md
Normal file
@@ -0,0 +1,239 @@
|
||||
---
|
||||
title: "build containers"
|
||||
sidebar_position: 20
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Container Builder
|
||||
|
||||
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
|
||||
|
||||
```js
|
||||
// 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
|
||||
- `set_entrypoint(entrypoint)`: Set the entrypoint for the container
|
||||
- `set_cmd(cmd)`: Set the default command for the container
|
||||
- `debug_mode`: Get or set the debug flag (true/false)
|
||||
- `write_content(content, dest_path)`: Write content to a file in the container
|
||||
- `read_content(source_path)`: Read content from a file in the container
|
||||
- `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
|
||||
- `build(tag, context_dir, file, isolation)`: Build an image from a Dockerfile
|
||||
|
||||
### Example
|
||||
|
||||
```js
|
||||
// Create a builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Enable debug mode to see command output
|
||||
builder.debug_mode = true;
|
||||
|
||||
// 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}`);
|
||||
|
||||
// Write content directly to a file in the container
|
||||
let script_content = `#!/bin/sh
|
||||
echo "Hello from startup script"
|
||||
`;
|
||||
builder.write_content(script_content, "/start.sh");
|
||||
builder.run("chmod +x /start.sh");
|
||||
|
||||
// Set the entrypoint for the container
|
||||
builder.set_entrypoint("/start.sh");
|
||||
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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");
|
||||
```
|
||||
|
||||
### `debug_mode`
|
||||
|
||||
Get or set the debug flag for the Builder. When debug mode is enabled, all buildah commands will output their stdout/stderr, making it easier to debug issues.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Enable debug mode
|
||||
builder.debug_mode = true;
|
||||
|
||||
// Run a command with debug output
|
||||
builder.run("echo 'Hello with debug'");
|
||||
|
||||
// Disable debug mode
|
||||
builder.debug_mode = false;
|
||||
```
|
||||
|
||||
### `set_entrypoint(entrypoint)`
|
||||
|
||||
Sets the entrypoint for the container. The entrypoint is the command that will be executed when the container starts.
|
||||
|
||||
**Parameters:**
|
||||
- `entrypoint` (string): The entrypoint command
|
||||
|
||||
**Returns:** Command result if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Set the entrypoint
|
||||
builder.set_entrypoint("/start.sh");
|
||||
```
|
||||
|
||||
### `set_cmd(cmd)`
|
||||
|
||||
Sets the default command for the container. This is used as arguments to the entrypoint.
|
||||
|
||||
**Parameters:**
|
||||
- `cmd` (string): The default command
|
||||
|
||||
**Returns:** Command result if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Set the default command
|
||||
builder.set_cmd("--verbose");
|
||||
```
|
||||
|
||||
### `write_content(content, dest_path)`
|
||||
|
||||
Writes content to a file in the container.
|
||||
|
||||
**Parameters:**
|
||||
- `content` (string): The content to write
|
||||
- `dest_path` (string): The destination path in the container
|
||||
|
||||
**Returns:** Command result if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Write content to a file
|
||||
let content = "Hello, world!";
|
||||
builder.write_content(content, "/hello.txt");
|
||||
```
|
||||
|
||||
### `read_content(source_path)`
|
||||
|
||||
Reads content from a file in the container.
|
||||
|
||||
**Parameters:**
|
||||
- `source_path` (string): The source path in the container
|
||||
|
||||
**Returns:** The file content as a string if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Write content to a file
|
||||
builder.write_content("Hello, world!", "/hello.txt");
|
||||
|
||||
// Read content from the file
|
||||
let content = builder.read_content("/hello.txt");
|
||||
println(content); // Outputs: Hello, world!
|
||||
```
|
210
docs/docs/sal/git.md
Normal file
210
docs/docs/sal/git.md
Normal file
@@ -0,0 +1,210 @@
|
||||
---
|
||||
title: "git"
|
||||
sidebar_position: 5
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Git
|
||||
|
||||
This module provides HeroScript 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.
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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:
|
||||
|
||||
```js
|
||||
// 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
|
||||
|
||||
```js
|
||||
// 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 HeroScript script as a runtime error.
|
||||
|
||||
For example, if you try to clone a repository that doesn't exist:
|
||||
|
||||
```js
|
||||
// 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
|
215
docs/docs/sal/git/git.md
Normal file
215
docs/docs/sal/git/git.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# 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`
|
||||
|
||||
```rhai
|
||||
print(`Pushing changes for ${app_repo.path()}...`);
|
||||
app_repo.push(); // Halts on error
|
||||
print("Push successful.");
|
||||
```
|
||||
|
||||
## Chaining Operations
|
||||
|
||||
```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();
|
||||
// }
|
||||
```
|
10
docs/docs/sal/intro.md
Normal file
10
docs/docs/sal/intro.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "intro"
|
||||
sidebar_position: 1
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
## HeroScript Script Commands Documentation
|
||||
|
||||
|
||||
The SAL library provides integration with the HeroScript scripting language, allowing you to use powerful system functions within your HeroScript scripts. These functions are organized into modules that provide related functionality.
|
239
docs/docs/sal/nerdctl.md
Normal file
239
docs/docs/sal/nerdctl.md
Normal file
@@ -0,0 +1,239 @@
|
||||
---
|
||||
title: "run containers"
|
||||
sidebar_position: 21
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Container Manager
|
||||
|
||||
The Container Manager module provides a comprehensive API for working with containers using nerdctl. It offers a modern builder pattern approach for container management.
|
||||
|
||||
## Container Builder Pattern
|
||||
|
||||
The Container Builder Pattern allows for fluent, chainable configuration of containers. This pattern makes container creation more readable and maintainable by allowing you to build complex container configurations step by step.
|
||||
|
||||
### Creating a Container
|
||||
|
||||
Start by creating a new container instance:
|
||||
|
||||
```rhai
|
||||
// Create an empty container with just a name
|
||||
let container = nerdctl_container_new("my-container");
|
||||
|
||||
// Or create a container from an image
|
||||
let container = nerdctl_container_from_image("my-container", "nginx:latest");
|
||||
```
|
||||
|
||||
### Configuring the Container
|
||||
|
||||
Once you have a container instance, you can configure it using the various builder methods:
|
||||
|
||||
```rhai
|
||||
// Configure the container with various options
|
||||
let container = nerdctl_container_from_image("web-server", "nginx:latest")
|
||||
.with_port("8080:80") // Map port 8080 to container port 80
|
||||
.with_volume("/host/path:/container/path") // Mount a volume
|
||||
.with_env("NGINX_HOST", "localhost") // Set an environment variable
|
||||
.with_network("bridge") // Set the network
|
||||
.with_detach(true); // Run in detached mode
|
||||
```
|
||||
|
||||
### Resetting Container Configuration
|
||||
|
||||
If you need to reset the container configuration to its default state while keeping the name and image:
|
||||
|
||||
```rhai
|
||||
// Reset the container configuration
|
||||
let container = nerdctl_container_from_image("web-server", "nginx:latest")
|
||||
.reset() // Reset all configuration to defaults
|
||||
.with_port("8080:80") // Start configuring again
|
||||
.with_detach(true);
|
||||
```
|
||||
|
||||
### Building and Starting the Container
|
||||
|
||||
After configuring the container, you can build and start it:
|
||||
|
||||
```rhai
|
||||
// Build the container (creates it but doesn't start it)
|
||||
let built_container = container.build();
|
||||
|
||||
// Start the container
|
||||
let start_result = built_container.start();
|
||||
|
||||
// Check if the container started successfully
|
||||
if (start_result.success) {
|
||||
println("Container started successfully!");
|
||||
} else {
|
||||
println(`Failed to start container: ${start_result.stderr}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Container Lifecycle Operations
|
||||
|
||||
Once your container is running, you can perform various operations:
|
||||
|
||||
```rhai
|
||||
// Execute a command in the container
|
||||
let exec_result = container.exec("ls -la");
|
||||
|
||||
// Get container logs
|
||||
let logs = container.logs();
|
||||
|
||||
// Stop the container
|
||||
let stop_result = container.stop();
|
||||
|
||||
// Remove the container
|
||||
let remove_result = container.remove();
|
||||
```
|
||||
|
||||
## Available Builder Methods
|
||||
|
||||
The Container Builder Pattern provides the following methods for configuring containers:
|
||||
|
||||
| Method | Description | Example |
|
||||
| -------------------------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| `reset()` | Reset configuration to defaults | `.reset()` |
|
||||
| `with_port(port)` | Add a port mapping | `.with_port("8080:80")` |
|
||||
| `with_ports(ports_array)` | Add multiple port mappings | `.with_ports(["8080:80", "443:443"])` |
|
||||
| `with_volume(volume)` | Add a volume mount | `.with_volume("/host/path:/container/path")` |
|
||||
| `with_volumes(volumes_array)` | Add multiple volume mounts | `.with_volumes(["/host/path1:/container/path1", "/host/path2:/container/path2"])` |
|
||||
| `with_env(key, value)` | Add an environment variable | `.with_env("NGINX_HOST", "localhost")` |
|
||||
| `with_envs(env_map)` | Add multiple environment variables | `.with_envs(#{"KEY1": "value1", "KEY2": "value2"})` |
|
||||
| `with_network(network)` | Set the network | `.with_network("bridge")` |
|
||||
| `with_network_alias(alias)` | Add a network alias | `.with_network_alias("web-server")` |
|
||||
| `with_network_aliases(aliases_array)` | Add multiple network aliases | `.with_network_aliases(["web-server", "http-service"])` |
|
||||
| `with_cpu_limit(cpus)` | Set CPU limit | `.with_cpu_limit("1.0")` |
|
||||
| `with_cpu_shares(shares)` | Set CPU shares | `.with_cpu_shares("1024")` |
|
||||
| `with_memory_limit(memory)` | Set memory limit | `.with_memory_limit("512m")` |
|
||||
| `with_memory_swap_limit(memory_swap)` | Set memory swap limit | `.with_memory_swap_limit("1g")` |
|
||||
| `with_restart_policy(policy)` | Set restart policy | `.with_restart_policy("unless-stopped")` |
|
||||
| `with_health_check(cmd)` | Set health check command | `.with_health_check("curl -f http://localhost/ | | exit 1")` |
|
||||
| `with_health_check_options(cmd, interval, timeout, retries, start_period)` | Set health check with options | `.with_health_check_options("curl -f http://localhost/ | | exit 1", "5s", "3s", 3, "10s")` |
|
||||
| `with_snapshotter(snapshotter)` | Set snapshotter | `.with_snapshotter("native")` |
|
||||
| `with_detach(detach)` | Set detach mode | `.with_detach(true)` |
|
||||
|
||||
## Complete Example: Web Server
|
||||
|
||||
Here's a complete example that demonstrates setting up an Nginx web server using the Container Builder Pattern:
|
||||
|
||||
```rhai
|
||||
// Create a temporary directory for our files
|
||||
let work_dir = "/tmp/nerdctl";
|
||||
mkdir(work_dir);
|
||||
chdir(work_dir);
|
||||
|
||||
// Create a custom index.html file
|
||||
let html_content = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Rhai Nerdctl Demo</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 40px;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
}
|
||||
h1 {
|
||||
color: #0066cc;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Rhai Nerdctl!</h1>
|
||||
<p>This page is served by an Nginx container created using the Rhai nerdctl wrapper.</p>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
// Write the HTML file
|
||||
let html_file = `${work_dir}/index.html`;
|
||||
file_write(html_file, html_content);
|
||||
|
||||
// Set up environment variables
|
||||
let env_map = #{};
|
||||
env_map["NGINX_HOST"] = "localhost";
|
||||
env_map["NGINX_PORT"] = "80";
|
||||
env_map["NGINX_WORKER_PROCESSES"] = "auto";
|
||||
|
||||
// Create and configure the container
|
||||
let container_name = "rhai-nginx-demo";
|
||||
|
||||
// First, try to remove any existing container with the same name
|
||||
nerdctl_remove(container_name);
|
||||
|
||||
// Create a container with a rich set of options using the builder pattern
|
||||
let container = nerdctl_container_from_image(container_name, "nginx:latest")
|
||||
.reset() // Reset to default configuration
|
||||
.with_detach(true)
|
||||
.with_ports(["8080:80"]) // Add multiple ports at once
|
||||
.with_volumes([`${work_dir}:/usr/share/nginx/html`]) // Mount our work dir
|
||||
.with_envs(env_map) // Add multiple environment variables at once
|
||||
.with_network("bridge")
|
||||
.with_network_aliases(["web-server", "nginx-demo"]) // Add multiple network aliases
|
||||
.with_cpu_limit("1.0")
|
||||
.with_memory_limit("512m");
|
||||
|
||||
// Build and start the container
|
||||
let built_container = container.build();
|
||||
let start_result = built_container.start();
|
||||
|
||||
println("The web server is running at http://localhost:8080");
|
||||
```
|
||||
|
||||
## Using Local Images Created with Buildah
|
||||
|
||||
When working with images created by Buildah, you may need to take additional steps to ensure nerdctl can find and use these images. This is because Buildah and nerdctl may use different storage backends by default.
|
||||
|
||||
### Tagging with localhost Prefix
|
||||
|
||||
One approach is to tag the Buildah-created image with a `localhost/` prefix:
|
||||
|
||||
```rhai
|
||||
// Create and commit a container with Buildah
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
builder.run("echo 'Hello' > /hello.txt");
|
||||
builder.commit("my-custom-image:latest");
|
||||
|
||||
// Tag the image with localhost prefix for nerdctl compatibility
|
||||
let local_image_name = "localhost/my-custom-image:latest";
|
||||
bah_image_tag("my-custom-image:latest", local_image_name);
|
||||
|
||||
// Now use the image with nerdctl
|
||||
let container = nerdctl_container_from_image("my-app", local_image_name)
|
||||
.with_detach(true)
|
||||
.build();
|
||||
```
|
||||
|
||||
### Using a Local Registry
|
||||
|
||||
For more reliable interoperability, you can push the image to a local registry:
|
||||
|
||||
```rhai
|
||||
// Push the Buildah-created image to a local registry
|
||||
bah_image_push("my-custom-image:latest", "localhost:5000/my-custom-image:latest", false);
|
||||
|
||||
// Pull the image with nerdctl
|
||||
nerdctl_image_pull("localhost:5000/my-custom-image:latest");
|
||||
|
||||
// Use the image
|
||||
let container = nerdctl_container_from_image("my-app", "localhost:5000/my-custom-image:latest")
|
||||
.with_detach(true)
|
||||
.build();
|
||||
```
|
||||
|
||||
## Image Management Functions
|
||||
|
||||
The module also provides functions for managing container images:
|
||||
|
||||
| Function | Description | Example |
|
||||
| --------------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------- |
|
||||
| `nerdctl_images()` | List images in local storage | `nerdctl_images()` |
|
||||
| `nerdctl_image_remove(image)` | Remove an image | `nerdctl_image_remove("nginx:latest")` |
|
||||
| `nerdctl_image_push(image, destination)` | Push an image to a registry | `nerdctl_image_push("my-image:latest", "registry.example.com/my-image:latest")` |
|
||||
| `nerdctl_image_tag(image, new_name)` | Add an additional name to a local image | `nerdctl_image_tag("nginx:latest", "my-nginx:latest")` |
|
||||
| `nerdctl_image_pull(image)` | Pull an image from a registry | `nerdctl_image_pull("nginx:latest")` |
|
||||
| `nerdctl_image_commit(container, image_name)` | Commit a container to an image | `nerdctl_image_commit("web-server", "my-nginx:latest")` |
|
||||
| `nerdctl_image_build(tag, context_path)` | Build an image using a Dockerfile | `nerdctl_image_build("my-image:latest", "./")` |
|
359
docs/docs/sal/os.md
Normal file
359
docs/docs/sal/os.md
Normal file
@@ -0,0 +1,359 @@
|
||||
---
|
||||
title: "os"
|
||||
sidebar_position: 2
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# OS Tools
|
||||
|
||||
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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// Delete a file
|
||||
delete("temp.txt");
|
||||
|
||||
// Delete a directory
|
||||
delete("temp_dir");
|
||||
```
|
||||
|
||||
### `mv(src, dest)`
|
||||
|
||||
Moves a file or directory from source to destination.
|
||||
|
||||
**Parameters:**
|
||||
- `src` (string): The source path
|
||||
- `dest` (string): The destination path
|
||||
|
||||
**Returns:** A message confirming the move was successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Move a file
|
||||
mv("file.txt", "new_location/file.txt");
|
||||
|
||||
// Move a directory
|
||||
mv("source_dir", "destination_dir");
|
||||
|
||||
// Rename a file
|
||||
mv("old_name.txt", "new_name.txt");
|
||||
```
|
||||
|
||||
### `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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// Change directory
|
||||
chdir("project/src");
|
||||
```
|
||||
|
||||
## Download Functions
|
||||
|
||||
### `download(url, dest, min_size_kb)`
|
||||
|
||||
Downloads a file from a URL to a destination directory 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 directory where the file will be saved or extracted
|
||||
- `min_size_kb` (integer): The minimum expected file size in kilobytes (for validation)
|
||||
|
||||
**Returns:** The path where the file was saved or extracted.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Download a file to a directory
|
||||
download("https://example.com/file.zip", "downloads/", 10);
|
||||
```
|
||||
|
||||
### `download_file(url, dest, min_size_kb)`
|
||||
|
||||
Downloads a file from a URL to a specific file destination using the curl command. This function is designed for downloading files to a specific path, not for extracting archives.
|
||||
|
||||
**Parameters:**
|
||||
- `url` (string): The URL to download from
|
||||
- `dest` (string): The destination file path where the file will be saved
|
||||
- `min_size_kb` (integer): The minimum expected file size in kilobytes (for validation)
|
||||
|
||||
**Returns:** The path where the file was saved.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Download a file to a specific path
|
||||
download_file("https://example.com/file.txt", "downloads/myfile.txt", 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:**
|
||||
```js
|
||||
// Download and install a package
|
||||
download_install("https://example.com/package.deb", 1000);
|
||||
```
|
||||
|
||||
### `chmod_exec(path)`
|
||||
|
||||
Makes a file executable (equivalent to `chmod +x` in Unix).
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path to the file to make executable
|
||||
|
||||
**Returns:** A message confirming the file was made executable.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Make a file executable
|
||||
chmod_exec("downloads/script.sh");
|
||||
```
|
60
docs/docs/sal/os/download.md
Normal file
60
docs/docs/sal/os/download.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# os.download Module
|
||||
|
||||
### `download(url, dest, min_size_kb)`
|
||||
|
||||
Download a file from URL to destination using the curl command.
|
||||
|
||||
- **Description**: Downloads a file from the given `url`. If `dest` is a directory, the filename is derived from the URL. If `dest` is a file path, it is used directly. Requires the `curl` command to be available. Halts script execution on download or file writing errors, or if the downloaded file size is less than `min_size_kb`. Returns the destination path.
|
||||
- **Returns**: `String` - The path where the file was downloaded.
|
||||
- **Arguments**:
|
||||
- `url`: `String` - The URL of the file to download.
|
||||
- `dest`: `String` - The destination path (directory or file).
|
||||
- `min_size_kb`: `Integer` - The minimum expected size of the downloaded file in kilobytes.
|
||||
|
||||
```rhai
|
||||
let download_url = "https://example.com/archive.zip";
|
||||
let download_dest_dir = "/tmp/downloads";
|
||||
print(`Downloading ${download_url} to ${download_dest_dir}...`);
|
||||
let downloaded_file_path = os::download(download_url, download_dest_dir, 50); // Halts on error
|
||||
print(`Downloaded to: ${downloaded_file_path}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `download_file(url, dest, min_size_kb)`
|
||||
|
||||
Download a file from URL to a specific file destination using the curl command.
|
||||
|
||||
- **Description**: Downloads a file from the given `url` directly to the specified file `dest`. Requires the `curl` command. Halts script execution on download or file writing errors, or if the downloaded file size is less than `min_size_kb`. Returns the destination path.
|
||||
- **Returns**: `String` - The path where the file was downloaded.
|
||||
- **Arguments**:
|
||||
- `url`: `String` - The URL of the file to download.
|
||||
- `dest`: `String` - The full path where the file should be saved.
|
||||
- `min_size_kb`: `Integer` - The minimum expected size of the downloaded file in kilobytes.
|
||||
|
||||
```rhai
|
||||
let data_url = "https://example.com/dataset.tar.gz";
|
||||
let local_path = "/opt/data/dataset.tar.gz";
|
||||
print(`Downloading ${data_url} to ${local_path}...`);
|
||||
os::download_file(data_url, local_path, 1024); // Halts on error
|
||||
print(`Downloaded dataset to: ${local_path}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `download_install(url, min_size_kb)`
|
||||
|
||||
Download a file and install it if it\'s a supported package format.
|
||||
|
||||
- **Description**: Downloads a file from the given `url` to a temporary location and then attempts to install it using the appropriate system package manager if the file format is supported (e.g., `.deb` on Ubuntu, `.pkg` or `.dmg` on MacOS). Requires the `curl` command and the system package manager. Halts script execution on download, installation, or file size errors. Returns a success message.
|
||||
- **Returns**: `String` - A success message upon successful download and installation attempt.
|
||||
- **Arguments**:
|
||||
- `url`: `String` - The URL of the package file to download and install.
|
||||
- `min_size_kb`: `Integer` - The minimum expected size of the downloaded file in kilobytes.
|
||||
|
||||
```rhai
|
||||
let package_url = "https://example.com/mytool.deb";
|
||||
print(`Downloading and installing ${package_url}...`);
|
||||
os::download_install(package_url, 300); // Halts on error
|
||||
print("Installation attempt finished.");
|
||||
```
|
338
docs/docs/sal/os/fs.md
Normal file
338
docs/docs/sal/os/fs.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# os.fs Module
|
||||
|
||||
The `os` module provides functions for interacting with the operating system, including file system operations, command execution checks, downloads, and package management.
|
||||
|
||||
All functions that interact with the file system or external commands will halt the script execution if an error occurs, unless explicitly noted otherwise.
|
||||
|
||||
---
|
||||
|
||||
### `copy(src, dest)`
|
||||
|
||||
Recursively copy a file or directory from source to destination.
|
||||
|
||||
- **Description**: Performs a recursive copy operation. Halts script execution on failure.
|
||||
- **Returns**: `String` - The destination path.
|
||||
- **Arguments**:
|
||||
- `src`: `String` - The path to the source file or directory.
|
||||
- `dest`: `String` - The path to the destination file or directory.
|
||||
|
||||
```rhai
|
||||
print("Copying directory...");
|
||||
let source_dir = "/tmp/source_data";
|
||||
let dest_dir = "/backup/source_data";
|
||||
let copied_path = os::copy(source_dir, dest_dir); // Halts on error
|
||||
print(`Copied ${source_dir} to ${copied_path}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `exist(path)`
|
||||
|
||||
Check if a file or directory exists.
|
||||
|
||||
- **Description**: Checks for the presence of a file or directory at the given path. This function does NOT halt on error if the path is invalid or permissions prevent checking.
|
||||
- **Returns**: `Boolean` - `true` if the path exists, `false` otherwise.
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to check.
|
||||
|
||||
```rhai
|
||||
if os::exist("config.json") {
|
||||
print(`${file_path} exists.`);
|
||||
} else {
|
||||
print(`${file_path} does not exist.`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `find_file(dir, filename)`
|
||||
|
||||
Find a file in a directory (with support for wildcards).
|
||||
|
||||
- **Description**: Searches for a file matching `filename` within the specified `dir`. Supports simple wildcards like `*` and `?`. Halts script execution if the directory cannot be read or if no file is found.
|
||||
- **Returns**: `String` - The path to the first file found that matches the pattern.
|
||||
- **Arguments**:
|
||||
- `dir`: `String` - The directory to search within.
|
||||
- `filename`: `String` - The filename pattern to search for (e.g., `"*.log"`).
|
||||
|
||||
```rhai
|
||||
let log_file = os::find_file("/var/log", "syslog*.log"); // Halts if not found or directory error
|
||||
print(`Found log file: ${log_file}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `find_files(dir, filename)`
|
||||
|
||||
Find multiple files in a directory (recursive, with support for wildcards).
|
||||
|
||||
- **Description**: Recursively searches for all files matching `filename` within the specified `dir` and its subdirectories. Supports simple wildcards. Halts script execution if the directory cannot be read.
|
||||
- **Returns**: `Array` of `String` - An array containing paths to all matching files.
|
||||
- **Arguments**:
|
||||
- `dir`: `String` - The directory to start the recursive search from.
|
||||
- `filename`: `String` - The filename pattern to search for (e.g., `"*.tmp"`).
|
||||
|
||||
```rhai
|
||||
let temp_files = os::find_files("/tmp", "*.swp"); // Halts on directory error
|
||||
print("Found temporary files:");
|
||||
for file in temp_files {
|
||||
print(`- ${file}`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `find_dir(dir, dirname)`
|
||||
|
||||
Find a directory in a parent directory (with support for wildcards).
|
||||
|
||||
- **Description**: Searches for a directory matching `dirname` within the specified `dir`. Supports simple wildcards. Halts script execution if the directory cannot be read or if no directory is found.
|
||||
- **Returns**: `String` - The path to the first directory found that matches the pattern.
|
||||
- **Arguments**:
|
||||
- `dir`: `String` - The directory to search within.
|
||||
- `dirname`: `String` - The directory name pattern to search for (e.g., `"backup_*"`).
|
||||
|
||||
```rhai
|
||||
let latest_backup_dir = os::find_dir("/mnt/backups", "backup_20*"); // Halts if not found or directory error
|
||||
print(`Found backup directory: ${latest_backup_dir}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `find_dirs(dir, dirname)`
|
||||
|
||||
Find multiple directories in a parent directory (recursive, with support for wildcards).
|
||||
|
||||
- **Description**: Recursively searches for all directories matching `dirname` within the specified `dir` and its subdirectories. Supports simple wildcards. Halts script execution if the directory cannot be read.
|
||||
- **Returns**: `Array` of `String` - An array containing paths to all matching directories.
|
||||
- **Arguments**:
|
||||
- `dir`: `String` - The directory to start the recursive search from.
|
||||
- `dirname`: `String` - The directory name pattern to search for (e.g., `"project_*_v?"`).
|
||||
|
||||
```rhai
|
||||
let project_versions = os::find_dirs("/home/user/dev", "project_*_v?"); // Halts on directory error
|
||||
print("Found project version directories:");
|
||||
for dir in project_versions {
|
||||
print(`- ${dir}`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `delete(path)`
|
||||
|
||||
Delete a file or directory (defensive - doesn't error if file doesn't exist).
|
||||
|
||||
- **Description**: Deletes the file or directory at the given path. If the path does not exist, the function does nothing and does not halt. Halts script execution on other errors (e.g., permission denied, directory not empty). Returns the path that was attempted to be deleted.
|
||||
- **Returns**: `String` - The path that was given as input.
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to the file or directory to delete.
|
||||
|
||||
```rhai
|
||||
let temp_path = "/tmp/temporary_item";
|
||||
print(`Attempting to delete: ${temp_path}`);
|
||||
os::delete(temp_path); // Halts on permissions or non-empty directory error
|
||||
print("Deletion attempt finished.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `mkdir(path)`
|
||||
|
||||
Create a directory and all parent directories (defensive - doesn't error if directory exists).
|
||||
|
||||
- **Description**: Creates the directory at the given path, including any necessary parent directories. If the directory already exists, the function does nothing and does not halt. Halts script execution on other errors (e.g., permission denied). Returns the path that was created (or already existed).
|
||||
- **Returns**: `String` - The path that was created or checked.
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to the directory to create.
|
||||
|
||||
```rhai
|
||||
let new_dir = "/data/processed/reports";
|
||||
print(`Ensuring directory exists: ${new_dir}`);
|
||||
os::mkdir(new_dir); // Halts on permission error
|
||||
print("Directory check/creation finished.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `file_size(path)`
|
||||
|
||||
Get the size of a file in bytes.
|
||||
|
||||
- **Description**: Returns the size of the file at the given path. Halts script execution if the file does not exist or cannot be accessed.
|
||||
- **Returns**: `Integer` - The size of the file in bytes (as i64).
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to the file.
|
||||
|
||||
```rhai
|
||||
let file_path = "important_document.pdf";
|
||||
let size = os::file_size(file_path); // Halts if file not found or cannot read
|
||||
print(`File size: ${size} bytes`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `rsync(src, dest)`
|
||||
|
||||
Sync directories using rsync (or platform equivalent).
|
||||
|
||||
- **Description**: Synchronizes the contents of the source directory (`src`) to the destination directory (`dest`) using the system's available rsync-like command. Halts script execution on any error during the sync process. Returns a success message string.
|
||||
- **Returns**: `String` - A success message indicating the operation completed.
|
||||
- **Arguments**:
|
||||
- `src`: `String` - The source directory.
|
||||
- `dest`: `String` - The destination directory.
|
||||
|
||||
```rhai
|
||||
let source = "/local/project_files";
|
||||
let destination = "/remote/backup/project_files";
|
||||
print(`Syncing from ${source} to ${destination}...`);
|
||||
let result_message = os::rsync(source, destination); // Halts on error
|
||||
print(`Sync successful: ${result_message}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `chdir(path)`
|
||||
|
||||
Change the current working directory.
|
||||
|
||||
- **Description**: Changes the current working directory of the script process. Halts script execution if the directory does not exist or cannot be accessed. Returns the new current working directory path.
|
||||
- **Returns**: `String` - The absolute path of the directory the process changed into.
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to change the working directory to.
|
||||
|
||||
```rhai
|
||||
print(`Current directory: ${os::chdir(".")}`); // Use "." to get current path
|
||||
let new_cwd = "/tmp";
|
||||
os::chdir(new_cwd); // Halts if directory not found or access denied
|
||||
print(`Changed directory to: ${os::chdir(".")}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `file_read(path)`
|
||||
|
||||
Read the contents of a file.
|
||||
|
||||
- **Description**: Reads the entire content of the file at the given path into a string. Halts script execution if the file does not exist or cannot be read.
|
||||
- **Returns**: `String` - The content of the file.
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to the file.
|
||||
|
||||
```rhai
|
||||
let config_content = os::file_read("settings.conf"); // Halts if file not found or cannot read
|
||||
print("Config content:");
|
||||
print(config_content);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `file_write(path, content)`
|
||||
|
||||
Write content to a file (creates the file if it doesn\'t exist, overwrites if it does).
|
||||
|
||||
- **Description**: Writes the specified `content` to the file at the given `path`. If the file exists, its content is replaced. If it doesn't exist, it is created. Halts script execution on error (e.g., permission denied, invalid path). Returns the path written to.
|
||||
- **Returns**: `String` - The path of the file written to.
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to the file.
|
||||
- `content`: `String` - The content to write to the file.
|
||||
|
||||
```rhai
|
||||
let output_path = "/tmp/hello.txt";
|
||||
let text_to_write = "Hello from Rhai!";
|
||||
os::file_write(output_path, text_to_write); // Halts on error
|
||||
print(`Wrote to ${output_path}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `file_write_append(path, content)`
|
||||
|
||||
Append content to a file (creates the file if it doesn\'t exist).
|
||||
|
||||
- **Description**: Appends the specified `content` to the end of the file at the given `path`. If the file does not exist, it is created. Halts script execution on error (e.g., permission denied, invalid path). Returns the path written to.
|
||||
- **Returns**: `String` - The path of the file written to.
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to the file.
|
||||
- `content`: `String` - The content to append to the file.
|
||||
|
||||
```rhai
|
||||
let log_path = "application.log";
|
||||
let log_entry = "User login failed.\n";
|
||||
os::file_write_append(log_path, log_entry); // Halts on error
|
||||
print(`Appended to ${log_path}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `mv(src, dest)`
|
||||
|
||||
Move a file or directory from source to destination.
|
||||
|
||||
- **Description**: Moves the file or directory from `src` to `dest`. Halts script execution on error (e.g., permission denied, source not found, destination exists and cannot be overwritten). Returns the destination path.
|
||||
- **Returns**: `String` - The path of the destination.
|
||||
- **Arguments**:
|
||||
- `src`: `String` - The path to the source file or directory.
|
||||
- `dest`: `String` - The path to the destination.
|
||||
|
||||
```rhai
|
||||
let old_path = "/tmp/report.csv";
|
||||
let new_path = "/archive/reports/report_final.csv";
|
||||
os::mv(old_path, new_path); // Halts on error
|
||||
print(`Moved ${old_path} to ${new_path}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `which(command)`
|
||||
|
||||
Check if a command exists in the system PATH.
|
||||
|
||||
- **Description**: Searches the system's PATH environment variable for the executable `command`. This function does NOT halt on error; it returns an empty string if the command is not found.
|
||||
- **Returns**: `String` - The full path to the command executable if found, otherwise an empty string (`""`).
|
||||
- **Arguments**:
|
||||
- `command`: `String` - The name of the command to search for (e.g., `"git"`).
|
||||
|
||||
```rhai
|
||||
let git_path = os::which("git");
|
||||
if git_path != "" {
|
||||
print(`Git executable found at: ${git_path}`);
|
||||
} else {
|
||||
print("Git executable not found in PATH.");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `cmd_ensure_exists(commands)`
|
||||
|
||||
Ensure that one or more commands exist in the system PATH.
|
||||
|
||||
- **Description**: Checks if all command names specified in the `commands` string (space or comma separated) exist in the system's PATH. Halts script execution if any of the commands are not found. Returns a success message if all commands are found.
|
||||
- **Returns**: `String` - A success message.
|
||||
- **Arguments**:
|
||||
- `commands`: `String` - A string containing one or more command names, separated by spaces or commas (e.g., `"curl,tar,unzip"`).
|
||||
|
||||
```rhai
|
||||
print("Ensuring required commands are available...");
|
||||
os::cmd_ensure_exists("git curl docker"); // Halts if any command is missing
|
||||
print("All required commands found.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `chmod_exec(path)`
|
||||
|
||||
Make a file executable (equivalent to chmod +x).
|
||||
|
||||
- **Description**: Sets the executable permission for the file at the given `path` for the owner, group, and others. Halts script execution on error (e.g., file not found, permission denied). Returns the path modified.
|
||||
- **Returns**: `String` - The path of the file whose permissions were modified.
|
||||
- **Arguments**:
|
||||
- `path`: `String` - The path to the file.
|
||||
|
||||
```rhai
|
||||
let script_path = "/usr/local/bin/myscript";
|
||||
print(`Making ${script_path} executable...`);
|
||||
os::chmod_exec(script_path); // Halts on error
|
||||
print("Permissions updated.");
|
||||
```
|
157
docs/docs/sal/os/package.md
Normal file
157
docs/docs/sal/os/package.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# os.package Module
|
||||
|
||||
### `package_install(package)`
|
||||
|
||||
Install a package using the system package manager.
|
||||
|
||||
- **Description**: Installs the specified `package` using the detected system package manager (e.g., `apt` on Ubuntu, `brew` on MacOS). Halts script execution if the package manager command fails. Returns a success message.
|
||||
- **Returns**: `String` - A message indicating successful installation.
|
||||
- **Arguments**:
|
||||
- `package`: `String` - The name of the package to install (e.g., `"nano"`).
|
||||
|
||||
```rhai
|
||||
print("Installing 'nano' package...");
|
||||
os::package_install("nano"); // Halts on package manager error
|
||||
print("'nano' installed successfully.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `package_remove(package)`
|
||||
|
||||
Remove a package using the system package manager.
|
||||
|
||||
- **Description**: Removes the specified `package` using the detected system package manager. Halts script execution if the package manager command fails. Returns a success message.
|
||||
- **Returns**: `String` - A message indicating successful removal.
|
||||
- **Arguments**:
|
||||
- `package`: `String` - The name of the package to remove (e.g., `"htop"`).
|
||||
|
||||
```rhai
|
||||
print("Removing 'htop' package...");
|
||||
os::package_remove("htop"); // Halts on package manager error
|
||||
print("'htop' removed successfully.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `package_update()`
|
||||
|
||||
Update package lists using the system package manager.
|
||||
|
||||
- **Description**: Updates the package lists that the system package manager uses (e.g., `apt update`, `brew update`). Halts script execution if the package manager command fails. Returns a success message.
|
||||
- **Returns**: `String` - A message indicating successful update.
|
||||
- **Arguments**: None.
|
||||
|
||||
```rhai
|
||||
print("Updating package lists...");
|
||||
os::package_update(); // Halts on package manager error
|
||||
print("Package lists updated.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `package_upgrade()`
|
||||
|
||||
Upgrade installed packages using the system package manager.
|
||||
|
||||
- **Description**: Upgrades installed packages using the detected system package manager (e.g., `apt upgrade`, `brew upgrade`). Halts script execution if the package manager command fails. Returns a success message.
|
||||
- **Returns**: `String` - A message indicating successful upgrade.
|
||||
- **Arguments**: None.
|
||||
|
||||
```rhai
|
||||
print("Upgrading installed packages...");
|
||||
os::package_upgrade(); // Halts on package manager error
|
||||
print("Packages upgraded.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `package_list()`
|
||||
|
||||
List installed packages using the system package manager.
|
||||
|
||||
- **Description**: Lists the names of packages installed on the system using the detected package manager. Halts script execution if the package manager command fails.
|
||||
- **Returns**: `Array` of `String` - An array containing the names of installed packages.
|
||||
- **Arguments**: None.
|
||||
|
||||
```rhai
|
||||
print("Listing installed packages...");
|
||||
let installed_packages = os::package_list(); // Halts on package manager error
|
||||
for pkg in installed_packages {
|
||||
print(`- ${pkg}`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `package_search(query)`
|
||||
|
||||
Search for packages using the system package manager.
|
||||
|
||||
- **Description**: Searches for packages matching the given `query` using the detected system package manager. Halts script execution if the package manager command fails.
|
||||
- **Returns**: `Array` of `String` - An array containing the search results (package names and/or descriptions).
|
||||
- **Arguments**:
|
||||
- `query`: `String` - The search term.
|
||||
|
||||
```rhai
|
||||
print("Searching for 'python' packages...");
|
||||
let python_packages = os::package_search("python"); // Halts on package manager error
|
||||
for pkg in python_packages {
|
||||
print(`- ${pkg}`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `package_is_installed(package)`
|
||||
|
||||
Check if a package is installed using the system package manager.
|
||||
|
||||
- **Description**: Checks if the specified `package` is installed using the detected system package manager. Halts script execution if the package manager command itself fails (e.g., command not found), but does NOT halt if the package is simply not found.
|
||||
- **Returns**: `Boolean` - `true` if the package is installed, `false` otherwise.
|
||||
- **Arguments**:
|
||||
- `package`: `String` - The name of the package to check (e.g., `"wget"`).
|
||||
|
||||
```rhai
|
||||
let package_name = "wget";
|
||||
if os::package_is_installed(package_name) { // Halts on package manager command error
|
||||
print(`${package_name} is installed.`);
|
||||
} else {
|
||||
print(`${package_name} is not installed.`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `package_set_debug(debug)`
|
||||
|
||||
Set the debug mode for package management operations.
|
||||
|
||||
- **Description**: Enables or disables debug output for subsequent package management operations. This function does NOT halt on error and always returns the boolean value it was set to.
|
||||
- **Returns**: `Boolean` - The boolean value that the debug flag was set to.
|
||||
- **Arguments**:
|
||||
- `debug`: `Boolean` - Set to `true` to enable debug output, `false` to disable.
|
||||
|
||||
```rhai
|
||||
print("Enabling package debug output.");
|
||||
os::package_set_debug(true);
|
||||
// Subsequent package operations will print debug info
|
||||
|
||||
print("Disabling package debug output.");
|
||||
os::package_set_debug(false);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `package_platform()`
|
||||
|
||||
Get the current platform name for package management.
|
||||
|
||||
- **Description**: Returns the name of the operating system platform as detected by the package manager logic. This function does NOT halt on error; it returns `"Unknown"` if the platform cannot be determined.
|
||||
- **Returns**: `String` - The platform name, one of `"Ubuntu"`, `"MacOS"`, or `"Unknown"`.
|
||||
- **Arguments**: None.
|
||||
|
||||
```rhai
|
||||
let platform = os::package_platform(); // Does not halt on error
|
||||
print(`Detected package platform: ${platform}`);
|
||||
```
|
237
docs/docs/sal/process.md
Normal file
237
docs/docs/sal/process.md
Normal file
@@ -0,0 +1,237 @@
|
||||
---
|
||||
title: "process"
|
||||
sidebar_position: 3
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# 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**
|
||||
```js
|
||||
// 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**
|
||||
```js
|
||||
// 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:**
|
||||
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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 HeroScript:
|
||||
|
||||
```js
|
||||
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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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:**
|
||||
```js
|
||||
// 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}`);
|
||||
}
|
||||
```
|
223
docs/docs/sal/process/process.md
Normal file
223
docs/docs/sal/process/process.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# Process Module
|
||||
|
||||
The `process` module provides functions for running external commands and managing system processes using a builder pattern for command execution.
|
||||
|
||||
For running commands, you start with the `run()` function which returns a `CommandBuilder` object. You can then chain configuration methods like `silent()`, `ignore_error()`, and `log()` before finally calling the `do()` method to execute the command.
|
||||
|
||||
By default, command execution using the builder (`.do()`) will halt the script execution if the command itself fails (returns a non-zero exit code) or if there's an operating system error preventing the command from running. You can change this behavior with `ignore_error()`.
|
||||
|
||||
Other process management functions (`which`, `kill`, `process_list`, `process_get`) have specific error handling behaviors described below.
|
||||
|
||||
---
|
||||
|
||||
### `CommandResult`
|
||||
|
||||
An object returned by command execution functions (`.do()`) containing the result of the command.
|
||||
|
||||
- **Properties**:
|
||||
- `stdout`: `String` - The standard output of the command.
|
||||
- `stderr`: `String` - The standard error of the command.
|
||||
- `success`: `Boolean` - `true` if the command exited with code 0, `false` otherwise.
|
||||
- `code`: `Integer` - The exit code of the command.
|
||||
|
||||
```rhai
|
||||
let result = run("echo hi").do();
|
||||
print(`Success: ${result.success}, Output: ${result.stdout}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `ProcessInfo`
|
||||
|
||||
An object found by process listing/getting functions (`process_list`, `process_get`) containing information about a running process.
|
||||
|
||||
- **Properties**:
|
||||
- `pid`: `Integer` - The process ID.
|
||||
- `name`: `String` - The name of the process executable.
|
||||
- `memory`: `Integer` - The memory usage of the process (unit depends on the operating system, typically KB or bytes).
|
||||
- `cpu`: `Float` - The CPU usage percentage (value and meaning may vary by operating system).
|
||||
|
||||
```rhai
|
||||
let processes = process_list("my_service");
|
||||
if (processes.len() > 0) {
|
||||
let first_proc = processes[0];
|
||||
print(`Process ${first_proc.name} (PID: ${first_proc.pid}) is running.`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `run(command)`
|
||||
|
||||
Start building a command execution.
|
||||
|
||||
- **Description**: Initializes a `CommandBuilder` for the given command string. This is the entry point to configure and run a process.
|
||||
- **Returns**: `CommandBuilder` - A builder object for configuring the command.
|
||||
- **Arguments**:
|
||||
- `command`: `String` - The command string to execute. Can include arguments and be a simple multiline script.
|
||||
|
||||
```rhai
|
||||
let cmd_builder = run("ls -l");
|
||||
// Now you can chain methods like .silent(), .ignore_error(), .log()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `CommandBuilder:silent()`
|
||||
|
||||
Configure the command to run silently.
|
||||
|
||||
- **Description**: Suppresses real-time standard output and standard error from being printed to the script's console during command execution. The output is still captured in the resulting `CommandResult`.
|
||||
- **Returns**: `CommandBuilder` - Returns `self` for chaining.
|
||||
- **Arguments**: None.
|
||||
|
||||
```rhai
|
||||
print("Running silent command...");
|
||||
run("echo This won\'t show directly").silent().do();
|
||||
print("Silent command finished.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `CommandBuilder:ignore_error()`
|
||||
|
||||
Configure the command to ignore non-zero exit codes.
|
||||
|
||||
- **Description**: By default, the `do()` method halts script execution if the command returns a non-zero exit code. Calling `ignore_error()` prevents this. The `CommandResult` will still indicate `success: false` and contain the non-zero `code`, allowing the script to handle the command failure explicitly. OS errors preventing the command from running will still cause a halt.
|
||||
- **Returns**: `CommandBuilder` - Returns `self` for chaining.
|
||||
- **Arguments**: None.
|
||||
|
||||
```rhai
|
||||
print("Running command that will fail but not halt...");
|
||||
let result = run("exit 1").ignore_error().do(); // Will not halt
|
||||
if (!result.success) {
|
||||
print(`Command failed as expected with code: ${result.code}`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `CommandBuilder:log()`
|
||||
|
||||
Configure the command to log the execution details.
|
||||
|
||||
- **Description**: Enables logging of the command string before execution.
|
||||
- **Returns**: `CommandBuilder` - Returns `self` for chaining.
|
||||
- **Arguments**: None.
|
||||
|
||||
```rhai
|
||||
print("Running command with logging...");
|
||||
run("ls /tmp").log().do(); // Will print the "ls /tmp" command before running
|
||||
print("Command finished.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `CommandBuilder:do()`
|
||||
|
||||
Execute the configured command.
|
||||
|
||||
- **Description**: Runs the command with the options set by the builder methods. Waits for the command to complete and returns the `CommandResult`. This method is the final step in the command execution builder chain. Halts based on the `ignore_error()` setting and OS errors.
|
||||
- **Returns**: `CommandResult` - An object containing the output and status of the command.
|
||||
- **Arguments**: None.
|
||||
|
||||
```rhai
|
||||
print("Running command using builder...");
|
||||
let command_result = run("pwd")
|
||||
.log() // Log the command
|
||||
.silent() // Don't print output live
|
||||
.do(); // Execute and get result (halts on error by default)
|
||||
|
||||
print(`Command output: ${command_result.stdout}`);
|
||||
|
||||
// Example with multiple options
|
||||
let fail_result = run("command_that_does_not_exist")
|
||||
.ignore_error() // Don't halt on non-zero exit (though OS error might still halt)
|
||||
.silent() // Don't print error live
|
||||
.do();
|
||||
|
||||
if (!fail_result.success) {
|
||||
print(`Failed command exited with code: ${fail_result.code} and stderr: ${fail_result.stderr}`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `which(cmd)`
|
||||
|
||||
Check if a command exists in the system PATH.
|
||||
|
||||
- **Description**: Searches the system's PATH environment variable for the executable `cmd`. This function does NOT halt if the command is not found; it returns an empty string.
|
||||
- **Returns**: `String` - The full path to the command executable if found, otherwise an empty string (`""`).
|
||||
- **Arguments**:
|
||||
- `cmd`: `String` - The name of the command to search for (e.g., `"node"`).
|
||||
|
||||
```rhai
|
||||
let node_path = which("node"); // Does not halt if node is not found
|
||||
if (node_path != "") {
|
||||
print(`Node executable found at: ${node_path}`);
|
||||
} else {
|
||||
print("Node executable not found in PATH.");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `kill(pattern)`
|
||||
|
||||
Kill processes matching a pattern.
|
||||
|
||||
- **Description**: Terminates running processes whose names match the provided `pattern`. Uses platform-specific commands (like `pkill` or equivalent). Halts script execution on error interacting with the system process list or kill command.
|
||||
- **Returns**: `String` - A success message indicating the kill attempt finished.
|
||||
- **Arguments**:
|
||||
- `pattern`: `String` - A pattern to match against process names (e.g., `"nginx"`).
|
||||
|
||||
```rhai
|
||||
print("Attempting to kill processes matching 'my_service'...");
|
||||
// Use with caution!
|
||||
kill("my_service"); // Halts on OS error during kill attempt
|
||||
print("Kill command sent.");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `process_list(pattern)`
|
||||
|
||||
List processes matching a pattern (or all if pattern is empty).
|
||||
|
||||
- **Description**: Lists information about running processes whose names match the provided `pattern`. If `pattern` is an empty string `""`, lists all processes. Halts script execution on error interacting with the system process list. Returns an empty array if no processes match the pattern.
|
||||
- **Returns**: `Array` of `ProcessInfo` - An array of objects, each containing `pid` (Integer), `name` (String), `memory` (Integer), and `cpu` (Float).
|
||||
- **Arguments**:
|
||||
- `pattern`: `String` - A pattern to match against process names, or `""` for all processes.
|
||||
|
||||
```rhai
|
||||
print("Listing processes matching 'bash'...");
|
||||
let bash_processes = process_list("bash"); // Halts on OS error
|
||||
if (bash_processes.len() > 0) {
|
||||
print("Found bash processes:");
|
||||
for proc in bash_processes {
|
||||
print(`- PID: ${proc.pid}, Name: ${proc.name}, CPU: ${proc.cpu}%, Memory: ${proc.memory}`);
|
||||
}
|
||||
} else {
|
||||
print("No bash processes found.");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `process_get(pattern)`
|
||||
|
||||
Get a single process matching the pattern (error if 0 or more than 1 match).
|
||||
|
||||
- **Description**: Finds exactly one running process whose name matches the provided `pattern`. Halts script execution if zero or more than one process matches the pattern, or on error interacting with the system process list.
|
||||
- **Returns**: `ProcessInfo` - An object containing `pid` (Integer), `name` (String), `memory` (Integer), and `cpu` (Float).
|
||||
- **Arguments**:
|
||||
- `pattern`: `String` - A pattern to match against process names, expected to match exactly one process.
|
||||
|
||||
```rhai
|
||||
let expected_service_name = "my_critical_service";
|
||||
print(`Getting process info for '${expected_service_name}'...`);
|
||||
// This will halt if the service isn't running, or if multiple services have this name
|
||||
let service_proc_info = process_get(expected_service_name);
|
||||
print(`Found process: PID ${service_proc_info.pid}, Name: ${service_proc_info.name}`);
|
||||
```
|
154
docs/docs/sal/rfs.md
Normal file
154
docs/docs/sal/rfs.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# RFS (Remote File System)
|
||||
|
||||
The RFS module provides a Rust wrapper for the RFS tool, which allows mounting remote filesystems locally and managing filesystem layers.
|
||||
|
||||
## Overview
|
||||
|
||||
RFS (Remote File System) is a tool that enables mounting various types of remote filesystems locally, as well as creating and managing filesystem layers. The SAL library provides a Rust wrapper for RFS with a fluent builder API, making it easy to use in your applications.
|
||||
|
||||
## Features
|
||||
|
||||
- Mount remote filesystems locally (SSH, S3, WebDAV, etc.)
|
||||
- List mounted filesystems
|
||||
- Unmount filesystems
|
||||
- Pack directories into filesystem layers
|
||||
- Unpack filesystem layers
|
||||
- List contents of filesystem layers
|
||||
- Verify filesystem layers
|
||||
|
||||
## Usage in Rust
|
||||
|
||||
### Mounting a Filesystem
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::{RfsBuilder, MountType};
|
||||
|
||||
// Create a new RFS builder
|
||||
let mount = RfsBuilder::new("user@example.com:/remote/path", "/local/mount/point", MountType::SSH)
|
||||
.with_option("port", "2222")
|
||||
.with_option("identity_file", "/path/to/key")
|
||||
.with_debug(true)
|
||||
.mount()?;
|
||||
|
||||
println!("Mounted filesystem with ID: {}", mount.id);
|
||||
```
|
||||
|
||||
### Listing Mounts
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::list_mounts;
|
||||
|
||||
// List all mounts
|
||||
let mounts = list_mounts()?;
|
||||
for mount in mounts {
|
||||
println!("Mount ID: {}, Source: {}, Target: {}", mount.id, mount.source, mount.target);
|
||||
}
|
||||
```
|
||||
|
||||
### Unmounting a Filesystem
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::unmount;
|
||||
|
||||
// Unmount a filesystem
|
||||
unmount("/local/mount/point")?;
|
||||
```
|
||||
|
||||
### Packing a Directory
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::{PackBuilder, StoreSpec};
|
||||
|
||||
// Create store specifications
|
||||
let store_spec = StoreSpec::new("file")
|
||||
.with_option("path", "/path/to/store");
|
||||
|
||||
// Pack a directory with builder pattern
|
||||
let result = PackBuilder::new("/path/to/directory", "output.fl")
|
||||
.with_store_spec(store_spec)
|
||||
.with_debug(true)
|
||||
.pack()?;
|
||||
```
|
||||
|
||||
### Unpacking a Filesystem Layer
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::unpack;
|
||||
|
||||
// Unpack a filesystem layer
|
||||
unpack("input.fl", "/path/to/unpack")?;
|
||||
```
|
||||
|
||||
## Usage in Rhai Scripts
|
||||
|
||||
### Mounting a Filesystem
|
||||
|
||||
```rhai
|
||||
// Create a map for mount options
|
||||
let options = #{
|
||||
"port": "22",
|
||||
"identity_file": "/path/to/key",
|
||||
"readonly": "true"
|
||||
};
|
||||
|
||||
// Mount the directory
|
||||
let mount = rfs_mount("user@example.com:/remote/path", "/local/mount/point", "ssh", options);
|
||||
|
||||
print(`Mounted ${mount.source} to ${mount.target} with ID: ${mount.id}`);
|
||||
```
|
||||
|
||||
### Listing Mounts
|
||||
|
||||
```rhai
|
||||
// List all mounts
|
||||
let mounts = rfs_list_mounts();
|
||||
print(`Number of mounts: ${mounts.len()}`);
|
||||
|
||||
for mount in mounts {
|
||||
print(`Mount ID: ${mount.id}, Source: ${mount.source}, Target: ${mount.target}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Unmounting a Filesystem
|
||||
|
||||
```rhai
|
||||
// Unmount the directory
|
||||
rfs_unmount("/local/mount/point");
|
||||
```
|
||||
|
||||
### Packing a Directory
|
||||
|
||||
```rhai
|
||||
// Pack the directory
|
||||
// Store specs format: "file:path=/path/to/store,s3:bucket=my-bucket"
|
||||
rfs_pack("/path/to/directory", "output.fl", "file:path=/path/to/store");
|
||||
```
|
||||
|
||||
### Unpacking a Filesystem Layer
|
||||
|
||||
```rhai
|
||||
// Unpack the filesystem layer
|
||||
rfs_unpack("output.fl", "/path/to/unpack");
|
||||
```
|
||||
|
||||
## Mount Types
|
||||
|
||||
The RFS module supports various mount types:
|
||||
|
||||
- **Local**: Mount a local directory
|
||||
- **SSH**: Mount a remote directory via SSH
|
||||
- **S3**: Mount an S3 bucket
|
||||
- **WebDAV**: Mount a WebDAV server
|
||||
|
||||
## Store Specifications
|
||||
|
||||
When packing a directory into a filesystem layer, you can specify one or more stores to use. Each store has a type and options:
|
||||
|
||||
- **File**: Store files on the local filesystem
|
||||
- Options: `path` (path to the store)
|
||||
- **S3**: Store files in an S3 bucket
|
||||
- Options: `bucket` (bucket name), `region` (AWS region), `access_key`, `secret_key`
|
||||
|
||||
## Examples
|
||||
|
||||
See the [RFS example script](../../rhaiexamples/rfs_example.rhai) for more examples of how to use the RFS module in Rhai scripts.
|
237
docs/docs/sal/text.md
Normal file
237
docs/docs/sal/text.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# Text Manipulation Tools
|
||||
|
||||
The SAL text module provides powerful text manipulation capabilities that can be used from Rhai scripts. These include text replacement (with regex support), template rendering, string normalization, and text formatting utilities.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Text Replacement](#text-replacement)
|
||||
- [Template Rendering](#template-rendering)
|
||||
- [String Normalization](#string-normalization)
|
||||
- [Text Formatting](#text-formatting)
|
||||
|
||||
## Text Replacement
|
||||
|
||||
The text replacement tools allow you to perform simple or complex text replacements, with support for regular expressions, case-insensitive matching, and file operations.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```rhai
|
||||
// Create a new text replacer
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("foo") // Set the pattern to search for
|
||||
.replacement("bar") // Set the replacement text
|
||||
.build(); // Build the replacer
|
||||
|
||||
// Apply the replacer to a string
|
||||
let result = replacer.replace("foo bar foo");
|
||||
// Result: "bar bar bar"
|
||||
```
|
||||
|
||||
### Advanced Features
|
||||
|
||||
#### Regular Expressions
|
||||
|
||||
```rhai
|
||||
// Create a replacer with regex support
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("\\bfoo\\b") // Use regex pattern (word boundary)
|
||||
.replacement("bar")
|
||||
.regex(true) // Enable regex mode
|
||||
.build();
|
||||
|
||||
// Apply the replacer to a string
|
||||
let result = replacer.replace("foo foobar");
|
||||
// Result: "bar foobar" (only replaces whole "foo" words)
|
||||
```
|
||||
|
||||
#### Case-Insensitive Matching
|
||||
|
||||
```rhai
|
||||
// Create a replacer with case-insensitive matching
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("foo")
|
||||
.replacement("bar")
|
||||
.regex(true)
|
||||
.case_insensitive(true) // Enable case-insensitive matching
|
||||
.build();
|
||||
|
||||
// Apply the replacer to a string
|
||||
let result = replacer.replace("FOO foo Foo");
|
||||
// Result: "bar bar bar"
|
||||
```
|
||||
|
||||
#### Multiple Replacements
|
||||
|
||||
```rhai
|
||||
// Chain multiple replacements
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("foo")
|
||||
.replacement("bar")
|
||||
.and() // Add another replacement operation
|
||||
.pattern("baz")
|
||||
.replacement("qux")
|
||||
.build();
|
||||
|
||||
// Apply the replacer to a string
|
||||
let result = replacer.replace("foo baz");
|
||||
// Result: "bar qux"
|
||||
```
|
||||
|
||||
#### File Operations
|
||||
|
||||
```rhai
|
||||
// Create a replacer
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("foo")
|
||||
.replacement("bar")
|
||||
.build();
|
||||
|
||||
// Replace in a file and get the result as a string
|
||||
let result = replacer.replace_file("input.txt");
|
||||
|
||||
// Replace in a file and write back to the same file
|
||||
replacer.replace_file_in_place("input.txt");
|
||||
|
||||
// Replace in a file and write to a new file
|
||||
replacer.replace_file_to("input.txt", "output.txt");
|
||||
```
|
||||
|
||||
## Template Rendering
|
||||
|
||||
The template rendering tools allow you to create and render templates with variables, using the powerful Tera template engine.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```rhai
|
||||
// Create a template builder with a template file
|
||||
let template = template_builder_open("template.txt")
|
||||
.add_var("name", "John") // Add a string variable
|
||||
.add_var("age", 30) // Add a numeric variable
|
||||
.add_var("items", ["a", "b", "c"]); // Add an array variable
|
||||
|
||||
// Render the template
|
||||
let result = template.render();
|
||||
|
||||
// Render to a file
|
||||
template.render_to_file("output.txt");
|
||||
```
|
||||
|
||||
### Template Variables
|
||||
|
||||
You can add variables of various types:
|
||||
|
||||
```rhai
|
||||
let template = template_builder_open("template.txt")
|
||||
.add_var("name", "John") // String
|
||||
.add_var("age", 30) // Integer
|
||||
.add_var("height", 1.85) // Float
|
||||
.add_var("is_active", true) // Boolean
|
||||
.add_var("items", ["a", "b", "c"]); // Array
|
||||
```
|
||||
|
||||
### Using Map for Variables
|
||||
|
||||
```rhai
|
||||
// Create a map of variables
|
||||
let vars = #{
|
||||
name: "Alice",
|
||||
place: "Wonderland"
|
||||
};
|
||||
|
||||
// Add all variables from the map
|
||||
let template = template_builder_open("template.txt")
|
||||
.add_vars(vars);
|
||||
```
|
||||
|
||||
### Template Syntax
|
||||
|
||||
The template engine uses Tera, which supports:
|
||||
|
||||
- Variable interpolation: `{{ variable }}`
|
||||
- Conditionals: `{% if condition %}...{% endif %}`
|
||||
- Loops: `{% for item in items %}...{% endfor %}`
|
||||
- Filters: `{{ variable | filter }}`
|
||||
|
||||
Example template:
|
||||
|
||||
```
|
||||
Hello, {{ name }}!
|
||||
|
||||
{% if show_greeting %}
|
||||
Welcome to {{ place }}.
|
||||
{% endif %}
|
||||
|
||||
Your items:
|
||||
{% for item in items %}
|
||||
- {{ item }}{% if not loop.last %}{% endif %}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
## String Normalization
|
||||
|
||||
The string normalization tools help convert strings to consistent formats for use as file names or paths.
|
||||
|
||||
### name_fix
|
||||
|
||||
Converts a string to a safe, normalized name by:
|
||||
- Converting to lowercase
|
||||
- Replacing spaces and special characters with underscores
|
||||
- Removing non-alphanumeric characters
|
||||
|
||||
```rhai
|
||||
let fixed_name = name_fix("Hello World!");
|
||||
// Result: "hello_world"
|
||||
|
||||
let fixed_name = name_fix("File-Name.txt");
|
||||
// Result: "file_name.txt"
|
||||
```
|
||||
|
||||
### path_fix
|
||||
|
||||
Similar to name_fix, but preserves path separators:
|
||||
|
||||
```rhai
|
||||
let fixed_path = path_fix("/path/to/Hello World!");
|
||||
// Result: "/path/to/hello_world"
|
||||
|
||||
let fixed_path = path_fix("./relative/path/to/DOCUMENT-123.pdf");
|
||||
// Result: "./relative/path/to/document_123.pdf"
|
||||
```
|
||||
|
||||
## Text Formatting
|
||||
|
||||
Tools to help with text formatting and indentation.
|
||||
|
||||
### dedent
|
||||
|
||||
Removes common leading whitespace from multi-line strings:
|
||||
|
||||
```rhai
|
||||
let indented_text = " line 1
|
||||
line 2
|
||||
line 3";
|
||||
|
||||
let dedented = dedent(indented_text);
|
||||
// Result: "line 1
|
||||
// line 2
|
||||
// line 3"
|
||||
```
|
||||
|
||||
### prefix
|
||||
|
||||
Adds a prefix to every line in a multi-line string:
|
||||
|
||||
```rhai
|
||||
let text = "line 1
|
||||
line 2
|
||||
line 3";
|
||||
|
||||
let prefixed = prefix(text, " ");
|
||||
// Result: " line 1
|
||||
// line 2
|
||||
// line 3"
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
See the [text_tools.rhai](https://github.com/ourworld-tf/herocode/blob/main/sal/src/rhaiexamples/text_tools.rhai) example script for more detailed examples of using these text manipulation tools.
|
Reference in New Issue
Block a user