...
This commit is contained in:
parent
4be9445702
commit
fe7a676cac
207
buildah_debug_implementation_plan.md
Normal file
207
buildah_debug_implementation_plan.md
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
# Buildah Debug Implementation Plan
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
1. The `Builder` struct already has a `debug` field and methods to get and set it (`debug()` and `set_debug()`).
|
||||||
|
2. There's a thread-local `DEBUG` variable with functions to get and set it.
|
||||||
|
3. The `execute_buildah_command` function checks the thread-local debug flag and outputs some debug information.
|
||||||
|
4. There's an unused `execute_buildah_command_with_debug` function that takes a `Builder` reference.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
1. Use only the Builder's debug flag, not the thread-local debug flag.
|
||||||
|
2. When debug is true, output stdout/stderr regardless of whether the command succeeds or fails.
|
||||||
|
3. If debug is false but there's an error, still output all information.
|
||||||
|
|
||||||
|
## Implementation Plan
|
||||||
|
|
||||||
|
### 1. Keep the Existing Thread-Local DEBUG Variable
|
||||||
|
|
||||||
|
We'll keep the existing thread-local DEBUG variable that's already in the code:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// Thread-local storage for debug flag
|
||||||
|
thread_local! {
|
||||||
|
static DEBUG: std::cell::RefCell<bool> = std::cell::RefCell::new(false);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Modify the Builder Methods to Set/Clear the Thread-Local Debug Flag
|
||||||
|
|
||||||
|
We'll modify each Builder method to set the thread-local debug flag from the Builder's debug flag before calling `execute_buildah_command` and restore it afterward:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub fn run(&self, command: &str) -> Result<CommandResult, BuildahError> {
|
||||||
|
if let Some(container_id) = &self.container_id {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["run", container_id, "sh", "-c", command]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
Err(BuildahError::Other("No container ID available".to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Keep the Existing execute_buildah_command Function
|
||||||
|
|
||||||
|
The existing `execute_buildah_command` function already checks the thread-local debug flag, so we don't need to modify it:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub fn execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Get the debug flag from thread-local storage
|
||||||
|
let debug = thread_local_debug();
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
println!("Executing buildah command: buildah {}", args.join(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... rest of the function ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Update the execute_buildah_command Function to Output stdout/stderr
|
||||||
|
|
||||||
|
We need to modify the `execute_buildah_command` function to output stdout/stderr when debug is true, regardless of success/failure:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub fn execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Get the debug flag from thread-local storage
|
||||||
|
let debug = thread_local_debug();
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
println!("Executing buildah command: buildah {}", args.join(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = Command::new("buildah")
|
||||||
|
.args(args)
|
||||||
|
.output();
|
||||||
|
|
||||||
|
match output {
|
||||||
|
Ok(output) => {
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
|
||||||
|
|
||||||
|
let result = CommandResult {
|
||||||
|
stdout,
|
||||||
|
stderr,
|
||||||
|
success: output.status.success(),
|
||||||
|
code: output.status.code().unwrap_or(-1),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Always output stdout/stderr when debug is true
|
||||||
|
if debug {
|
||||||
|
if !result.stdout.is_empty() {
|
||||||
|
println!("Command stdout: {}", result.stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !result.stderr.is_empty() {
|
||||||
|
println!("Command stderr: {}", result.stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.success {
|
||||||
|
println!("Command succeeded with code {}", result.code);
|
||||||
|
} else {
|
||||||
|
println!("Command failed with code {}", result.code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.success {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
// If command failed and debug is false, output stderr
|
||||||
|
if !debug {
|
||||||
|
println!("Command failed with code {}: {}", result.code, result.stderr.trim());
|
||||||
|
}
|
||||||
|
Err(BuildahError::CommandFailed(format!("Command failed with code {}: {}",
|
||||||
|
result.code, result.stderr.trim())))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
// Always output error information
|
||||||
|
println!("Command execution failed: {}", e);
|
||||||
|
Err(BuildahError::CommandExecutionFailed(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Handle Static Methods
|
||||||
|
|
||||||
|
For static methods, we'll just call `execute_buildah_command` directly, which will use the thread-local debug flag:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub fn images() -> Result<Vec<Image>, BuildahError> {
|
||||||
|
let result = execute_buildah_command(&["images", "--json"])?;
|
||||||
|
// Rest of the method...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If we want to support debugging in static methods, we could add an optional debug parameter:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub fn images(debug: bool) -> Result<Vec<Image>, BuildahError> {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag
|
||||||
|
set_thread_local_debug(debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["images", "--json"]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
// Process the result
|
||||||
|
match result {
|
||||||
|
Ok(cmd_result) => {
|
||||||
|
// Parse JSON and return images...
|
||||||
|
},
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backward compatibility method
|
||||||
|
pub fn images() -> Result<Vec<Image>, BuildahError> {
|
||||||
|
Self::images(false)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Update Rhai Bindings
|
||||||
|
|
||||||
|
We still need to update the Rhai bindings to expose the debug functionality:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// Add a debug getter and setter
|
||||||
|
engine.register_get("debug", |builder: &mut Builder| builder.debug());
|
||||||
|
engine.register_set("debug", |builder: &mut Builder, debug: bool| { builder.set_debug(debug); });
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Remove Unused Code
|
||||||
|
|
||||||
|
We can remove the unused `execute_buildah_command_with_debug` function.
|
||||||
|
|
||||||
|
## Implementation Flow
|
||||||
|
|
||||||
|
1. Modify the `execute_buildah_command` function to output stdout/stderr when debug is true
|
||||||
|
2. Update all Builder methods to set/restore the thread-local debug flag
|
||||||
|
3. Update static methods to optionally accept a debug parameter
|
||||||
|
4. Update Rhai bindings to expose the debug functionality
|
||||||
|
5. Remove unused code
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
|
||||||
|
1. Minimal changes to the existing codebase
|
||||||
|
2. No changes to function signatures
|
||||||
|
3. Backward compatibility with existing code
|
||||||
|
4. Improved debugging capabilities
|
@ -56,6 +56,8 @@ fn register_bah_types(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
|||||||
engine.register_get("container_id", get_builder_container_id);
|
engine.register_get("container_id", get_builder_container_id);
|
||||||
engine.register_get("name", get_builder_name);
|
engine.register_get("name", get_builder_name);
|
||||||
engine.register_get("image", get_builder_image);
|
engine.register_get("image", get_builder_image);
|
||||||
|
engine.register_get("debug", get_builder_debug);
|
||||||
|
engine.register_set("debug", set_builder_debug);
|
||||||
|
|
||||||
// Register Image type and methods (same as before)
|
// Register Image type and methods (same as before)
|
||||||
engine.register_type_with_name::<Image>("BuildahImage");
|
engine.register_type_with_name::<Image>("BuildahImage");
|
||||||
@ -217,6 +219,16 @@ pub fn get_builder_image(builder: &mut Builder) -> String {
|
|||||||
builder.image().to_string()
|
builder.image().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the debug flag from a Builder
|
||||||
|
pub fn get_builder_debug(builder: &mut Builder) -> bool {
|
||||||
|
builder.debug()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the debug flag on a Builder
|
||||||
|
pub fn set_builder_debug(builder: &mut Builder, debug: bool) {
|
||||||
|
builder.set_debug(debug);
|
||||||
|
}
|
||||||
|
|
||||||
// Reset function for Builder
|
// Reset function for Builder
|
||||||
pub fn builder_reset(builder: &mut Builder) -> Result<(), Box<EvalAltResult>> {
|
pub fn builder_reset(builder: &mut Builder) -> Result<(), Box<EvalAltResult>> {
|
||||||
bah_error_to_rhai_error(builder.reset())
|
bah_error_to_rhai_error(builder.reset())
|
||||||
|
@ -9,6 +9,7 @@ mod process;
|
|||||||
mod buildah;
|
mod buildah;
|
||||||
mod nerdctl;
|
mod nerdctl;
|
||||||
mod git;
|
mod git;
|
||||||
|
mod text;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
@ -56,6 +57,16 @@ pub use nerdctl::{
|
|||||||
pub use git::register_git_module;
|
pub use git::register_git_module;
|
||||||
pub use crate::git::{GitTree, GitRepo};
|
pub use crate::git::{GitTree, GitRepo};
|
||||||
|
|
||||||
|
// Re-export text module
|
||||||
|
pub use text::register_text_module;
|
||||||
|
// Re-export text functions directly from text module
|
||||||
|
pub use crate::text::{
|
||||||
|
// Fix functions
|
||||||
|
name_fix, path_fix,
|
||||||
|
// Dedent functions
|
||||||
|
dedent, prefix
|
||||||
|
};
|
||||||
|
|
||||||
// Rename copy functions to avoid conflicts
|
// Rename copy functions to avoid conflicts
|
||||||
pub use os::copy as os_copy;
|
pub use os::copy as os_copy;
|
||||||
|
|
||||||
@ -89,11 +100,14 @@ pub fn register(engine: &mut Engine) -> Result<(), Box<rhai::EvalAltResult>> {
|
|||||||
|
|
||||||
// Register Nerdctl module functions
|
// Register Nerdctl module functions
|
||||||
nerdctl::register_nerdctl_module(engine)?;
|
nerdctl::register_nerdctl_module(engine)?;
|
||||||
|
|
||||||
// Register Git module functions
|
// Register Git module functions
|
||||||
git::register_git_module(engine)?;
|
git::register_git_module(engine)?;
|
||||||
|
|
||||||
|
// Register Text module functions
|
||||||
|
text::register_text_module(engine)?;
|
||||||
|
|
||||||
// Future modules can be registered here
|
// Future modules can be registered here
|
||||||
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
229
src/rhai/text.rs
Normal file
229
src/rhai/text.rs
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
//! Rhai wrappers for Text module functions
|
||||||
|
//!
|
||||||
|
//! This module provides Rhai wrappers for the functions in the Text module.
|
||||||
|
|
||||||
|
use rhai::{Engine, EvalAltResult, Array, Dynamic, Map, Position};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use crate::text::{
|
||||||
|
TextReplacer, TextReplacerBuilder,
|
||||||
|
TemplateBuilder,
|
||||||
|
dedent, prefix,
|
||||||
|
name_fix, path_fix
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Register Text module functions with the Rhai engine
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `engine` - The Rhai engine to register the functions with
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
|
||||||
|
pub fn register_text_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
||||||
|
// Register types
|
||||||
|
register_text_types(engine)?;
|
||||||
|
|
||||||
|
// Register TextReplacer functions
|
||||||
|
engine.register_fn("text_replacer_new", text_replacer_new);
|
||||||
|
|
||||||
|
// Register TextReplacer instance methods
|
||||||
|
engine.register_fn("pattern", builder_pattern);
|
||||||
|
engine.register_fn("replacement", builder_replacement);
|
||||||
|
engine.register_fn("regex", builder_regex);
|
||||||
|
engine.register_fn("case_insensitive", builder_case_insensitive);
|
||||||
|
engine.register_fn("and", builder_and);
|
||||||
|
engine.register_fn("build", builder_build);
|
||||||
|
engine.register_fn("replace", replacer_replace);
|
||||||
|
engine.register_fn("replace_file", replacer_replace_file);
|
||||||
|
engine.register_fn("replace_file_in_place", replacer_replace_file_in_place);
|
||||||
|
engine.register_fn("replace_file_to", replacer_replace_file_to);
|
||||||
|
|
||||||
|
// Register TemplateBuilder functions
|
||||||
|
engine.register_fn("template_builder_open", template_builder_open);
|
||||||
|
|
||||||
|
// Register TemplateBuilder instance methods
|
||||||
|
engine.register_fn("add_var", template_add_var_string);
|
||||||
|
engine.register_fn("add_var", template_add_var_int);
|
||||||
|
engine.register_fn("add_var", template_add_var_float);
|
||||||
|
engine.register_fn("add_var", template_add_var_bool);
|
||||||
|
engine.register_fn("add_var", template_add_var_array);
|
||||||
|
engine.register_fn("add_vars", template_add_vars);
|
||||||
|
engine.register_fn("render", template_render);
|
||||||
|
engine.register_fn("render_to_file", template_render_to_file);
|
||||||
|
|
||||||
|
// Register Fix functions
|
||||||
|
engine.register_fn("name_fix", crate::text::name_fix);
|
||||||
|
engine.register_fn("path_fix", crate::text::path_fix);
|
||||||
|
|
||||||
|
// Register Dedent functions
|
||||||
|
engine.register_fn("dedent", crate::text::dedent);
|
||||||
|
engine.register_fn("prefix", crate::text::prefix);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register Text module types with the Rhai engine
|
||||||
|
fn register_text_types(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
||||||
|
// Register TextReplacerBuilder type
|
||||||
|
engine.register_type_with_name::<TextReplacerBuilder>("TextReplacerBuilder");
|
||||||
|
|
||||||
|
// Register TextReplacer type
|
||||||
|
engine.register_type_with_name::<TextReplacer>("TextReplacer");
|
||||||
|
|
||||||
|
// Register TemplateBuilder type
|
||||||
|
engine.register_type_with_name::<TemplateBuilder>("TemplateBuilder");
|
||||||
|
|
||||||
|
// Register getters for TextReplacer properties (if any)
|
||||||
|
|
||||||
|
// Register getters for TemplateBuilder properties (if any)
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions for error conversion
|
||||||
|
fn io_error_to_rhai_error<T>(result: std::io::Result<T>) -> Result<T, Box<EvalAltResult>> {
|
||||||
|
result.map_err(|e| {
|
||||||
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
format!("IO error: {}", e).into(),
|
||||||
|
Position::NONE
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tera_error_to_rhai_error<T>(result: Result<T, tera::Error>) -> Result<T, Box<EvalAltResult>> {
|
||||||
|
result.map_err(|e| {
|
||||||
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
format!("Template error: {}", e).into(),
|
||||||
|
Position::NONE
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_error_to_rhai_error<T>(result: Result<T, String>) -> Result<T, Box<EvalAltResult>> {
|
||||||
|
result.map_err(|e| {
|
||||||
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
e.into(),
|
||||||
|
Position::NONE
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextReplacer implementation
|
||||||
|
|
||||||
|
/// Creates a new TextReplacerBuilder
|
||||||
|
pub fn text_replacer_new() -> TextReplacerBuilder {
|
||||||
|
TextReplacerBuilder::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the pattern to search for
|
||||||
|
pub fn builder_pattern(builder: TextReplacerBuilder, pat: &str) -> TextReplacerBuilder {
|
||||||
|
builder.pattern(pat)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the replacement text
|
||||||
|
pub fn builder_replacement(builder: TextReplacerBuilder, rep: &str) -> TextReplacerBuilder {
|
||||||
|
builder.replacement(rep)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets whether to use regex
|
||||||
|
pub fn builder_regex(builder: TextReplacerBuilder, yes: bool) -> TextReplacerBuilder {
|
||||||
|
builder.regex(yes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets whether the replacement should be case-insensitive
|
||||||
|
pub fn builder_case_insensitive(builder: TextReplacerBuilder, yes: bool) -> TextReplacerBuilder {
|
||||||
|
builder.case_insensitive(yes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds another replacement operation to the chain and resets the builder for a new operation
|
||||||
|
pub fn builder_and(builder: TextReplacerBuilder) -> TextReplacerBuilder {
|
||||||
|
builder.and()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds the TextReplacer with all configured replacement operations
|
||||||
|
pub fn builder_build(builder: TextReplacerBuilder) -> Result<TextReplacer, Box<EvalAltResult>> {
|
||||||
|
string_error_to_rhai_error(builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies all configured replacement operations to the input text
|
||||||
|
pub fn replacer_replace(replacer: &mut TextReplacer, input: &str) -> String {
|
||||||
|
replacer.replace(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads a file, applies all replacements, and returns the result as a string
|
||||||
|
pub fn replacer_replace_file(replacer: &mut TextReplacer, path: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
|
io_error_to_rhai_error(replacer.replace_file(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads a file, applies all replacements, and writes the result back to the file
|
||||||
|
pub fn replacer_replace_file_in_place(replacer: &mut TextReplacer, path: &str) -> Result<(), Box<EvalAltResult>> {
|
||||||
|
io_error_to_rhai_error(replacer.replace_file_in_place(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads a file, applies all replacements, and writes the result to a new file
|
||||||
|
pub fn replacer_replace_file_to(replacer: &mut TextReplacer, input_path: &str, output_path: &str) -> Result<(), Box<EvalAltResult>> {
|
||||||
|
io_error_to_rhai_error(replacer.replace_file_to(input_path, output_path))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateBuilder implementation
|
||||||
|
|
||||||
|
/// Creates a new TemplateBuilder with the specified template path
|
||||||
|
pub fn template_builder_open(template_path: &str) -> Result<TemplateBuilder, Box<EvalAltResult>> {
|
||||||
|
io_error_to_rhai_error(TemplateBuilder::open(template_path))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a string variable to the template context
|
||||||
|
pub fn template_add_var_string(builder: TemplateBuilder, name: &str, value: &str) -> TemplateBuilder {
|
||||||
|
builder.add_var(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds an integer variable to the template context
|
||||||
|
pub fn template_add_var_int(builder: TemplateBuilder, name: &str, value: i64) -> TemplateBuilder {
|
||||||
|
builder.add_var(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a float variable to the template context
|
||||||
|
pub fn template_add_var_float(builder: TemplateBuilder, name: &str, value: f64) -> TemplateBuilder {
|
||||||
|
builder.add_var(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a boolean variable to the template context
|
||||||
|
pub fn template_add_var_bool(builder: TemplateBuilder, name: &str, value: bool) -> TemplateBuilder {
|
||||||
|
builder.add_var(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds an array variable to the template context
|
||||||
|
pub fn template_add_var_array(builder: TemplateBuilder, name: &str, value: Array) -> TemplateBuilder {
|
||||||
|
// Convert Rhai Array to Vec<String>
|
||||||
|
let vec: Vec<String> = value.iter()
|
||||||
|
.filter_map(|v| v.clone().into_string().ok())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
builder.add_var(name, vec)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds multiple variables to the template context from a Map
|
||||||
|
pub fn template_add_vars(builder: TemplateBuilder, vars: Map) -> TemplateBuilder {
|
||||||
|
// Convert Rhai Map to Rust HashMap
|
||||||
|
let mut hash_map = HashMap::new();
|
||||||
|
|
||||||
|
for (key, value) in vars.iter() {
|
||||||
|
if let Ok(val_str) = value.clone().into_string() {
|
||||||
|
hash_map.insert(key.to_string(), val_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the variables
|
||||||
|
builder.add_vars(hash_map)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Renders the template with the current context
|
||||||
|
pub fn template_render(builder: &mut TemplateBuilder) -> Result<String, Box<EvalAltResult>> {
|
||||||
|
tera_error_to_rhai_error(builder.render())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Renders the template and writes the result to a file
|
||||||
|
pub fn template_render_to_file(builder: &mut TemplateBuilder, output_path: &str) -> Result<(), Box<EvalAltResult>> {
|
||||||
|
io_error_to_rhai_error(builder.render_to_file(output_path))
|
||||||
|
}
|
133
src/rhai_text_implementation_plan.md
Normal file
133
src/rhai_text_implementation_plan.md
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
# Implementation Plan: Rhai Wrappers for Text Tools
|
||||||
|
|
||||||
|
## 1. Overview
|
||||||
|
|
||||||
|
We'll create a new module `rhai/text.rs` that will provide Rhai wrappers for all functionality in the text module, including:
|
||||||
|
- TextReplacer (from replace.rs)
|
||||||
|
- TemplateBuilder (from template.rs)
|
||||||
|
- name_fix and path_fix functions (from fix.rs)
|
||||||
|
- dedent and prefix functions (from dedent.rs)
|
||||||
|
|
||||||
|
The implementation will follow the builder pattern for the TextReplacer and TemplateBuilder classes, similar to their Rust implementations, and will use the same error handling pattern as the existing Rhai modules.
|
||||||
|
|
||||||
|
## 2. Module Structure
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A[rhai/mod.rs] --> B[rhai/text.rs]
|
||||||
|
B --> C[TextReplacer Wrappers]
|
||||||
|
B --> D[TemplateBuilder Wrappers]
|
||||||
|
B --> E[Fix Function Wrappers]
|
||||||
|
B --> F[Dedent Function Wrappers]
|
||||||
|
B --> G[Error Handling]
|
||||||
|
B --> H[Registration Functions]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Implementation Details
|
||||||
|
|
||||||
|
### 3.1. Module Setup and Registration
|
||||||
|
|
||||||
|
1. Create a new file `rhai/text.rs`
|
||||||
|
2. Add the module to `rhai/mod.rs`
|
||||||
|
3. Implement a `register_text_module` function to register all text-related functions with the Rhai engine
|
||||||
|
4. Update the main `register` function in `rhai/mod.rs` to call `register_text_module`
|
||||||
|
|
||||||
|
### 3.2. TextReplacer Implementation
|
||||||
|
|
||||||
|
1. Register the TextReplacer type with the Rhai engine
|
||||||
|
2. Implement the following functions:
|
||||||
|
- `text_replacer_new()` - Creates a new TextReplacerBuilder
|
||||||
|
- `pattern(builder, pat)` - Sets the pattern to search for and automatically adds any previous pattern/replacement pair to the chain
|
||||||
|
- `replacement(builder, rep)` - Sets the replacement text
|
||||||
|
- `regex(builder, yes)` - Sets whether to use regex
|
||||||
|
- `case_insensitive(builder, yes)` - Sets whether the replacement should be case-insensitive
|
||||||
|
- `build(builder)` - Builds the TextReplacer with all configured replacement operations
|
||||||
|
- `replace(replacer, input)` - Applies all configured replacement operations to the input text
|
||||||
|
- `replace_file(replacer, path)` - Reads a file, applies all replacements, and returns the result as a string
|
||||||
|
- `replace_file_in_place(replacer, path)` - Reads a file, applies all replacements, and writes the result back to the file
|
||||||
|
- `replace_file_to(replacer, input_path, output_path)` - Reads a file, applies all replacements, and writes the result to a new file
|
||||||
|
|
||||||
|
### 3.3. TemplateBuilder Implementation
|
||||||
|
|
||||||
|
1. Register the TemplateBuilder type with the Rhai engine
|
||||||
|
2. Implement the following functions:
|
||||||
|
- `template_builder_open(template_path)` - Creates a new TemplateBuilder with the specified template path
|
||||||
|
- `add_var(builder, name, value)` - Adds a variable to the template context
|
||||||
|
- `add_vars(builder, vars_map)` - Adds multiple variables to the template context from a Map
|
||||||
|
- `render(builder)` - Renders the template with the current context
|
||||||
|
- `render_to_file(builder, output_path)` - Renders the template and writes the result to a file
|
||||||
|
|
||||||
|
### 3.4. Fix Functions Implementation
|
||||||
|
|
||||||
|
1. Implement wrappers for the following functions:
|
||||||
|
- `name_fix(text)` - Sanitizes a name by replacing special characters with underscores
|
||||||
|
- `path_fix(text)` - Applies name_fix to the filename part of a path
|
||||||
|
|
||||||
|
### 3.5. Dedent Functions Implementation
|
||||||
|
|
||||||
|
1. Implement wrappers for the following functions:
|
||||||
|
- `dedent(text)` - Removes common leading whitespace from a multiline string
|
||||||
|
- `prefix(text, prefix)` - Adds a prefix to each line of a multiline string
|
||||||
|
|
||||||
|
### 3.6. Error Handling
|
||||||
|
|
||||||
|
1. Implement helper functions to convert Rust errors to Rhai errors:
|
||||||
|
- `io_error_to_rhai_error` - Converts io::Error to EvalAltResult
|
||||||
|
- `tera_error_to_rhai_error` - Converts tera::Error to EvalAltResult
|
||||||
|
- `string_error_to_rhai_error` - Converts String error to EvalAltResult
|
||||||
|
|
||||||
|
## 4. Example Usage in Rhai Scripts
|
||||||
|
|
||||||
|
### TextReplacer Example
|
||||||
|
```rhai
|
||||||
|
// Create a TextReplacer with multiple replacements
|
||||||
|
let replacer = text_replacer_new()
|
||||||
|
.pattern("foo").replacement("bar").regex(true)
|
||||||
|
.pattern("hello").replacement("world")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Use the replacer
|
||||||
|
let result = replacer.replace("foo hello foo");
|
||||||
|
println(result); // Outputs: "bar world bar"
|
||||||
|
|
||||||
|
// Replace in a file
|
||||||
|
let file_result = replacer.replace_file("input.txt");
|
||||||
|
println(file_result);
|
||||||
|
|
||||||
|
// Replace and write to a new file
|
||||||
|
replacer.replace_file_to("input.txt", "output.txt");
|
||||||
|
```
|
||||||
|
|
||||||
|
### TemplateBuilder Example
|
||||||
|
```rhai
|
||||||
|
// Create a TemplateBuilder
|
||||||
|
let template = template_builder_open("template.txt")
|
||||||
|
.add_var("name", "John")
|
||||||
|
.add_var("age", 30)
|
||||||
|
.add_var("items", ["apple", "banana", "cherry"]);
|
||||||
|
|
||||||
|
// Render the template
|
||||||
|
let result = template.render();
|
||||||
|
println(result);
|
||||||
|
|
||||||
|
// Render to a file
|
||||||
|
template.render_to_file("output.html");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fix and Dedent Examples
|
||||||
|
```rhai
|
||||||
|
// Use name_fix and path_fix
|
||||||
|
let fixed_name = name_fix("Hello World!");
|
||||||
|
println(fixed_name); // Outputs: "hello_world"
|
||||||
|
|
||||||
|
let fixed_path = path_fix("/path/to/Hello World!");
|
||||||
|
println(fixed_path); // Outputs: "/path/to/hello_world"
|
||||||
|
|
||||||
|
// Use dedent and prefix
|
||||||
|
let indented_text = " line 1\n line 2\n line 3";
|
||||||
|
let dedented = dedent(indented_text);
|
||||||
|
println(dedented); // Outputs: "line 1\nline 2\n line 3"
|
||||||
|
|
||||||
|
let text = "line 1\nline 2\nline 3";
|
||||||
|
let prefixed = prefix(text, " ");
|
||||||
|
println(prefixed); // Outputs: " line 1\n line 2\n line 3"
|
39
src/rhaiexamples/buildah_debug.rhai
Normal file
39
src/rhaiexamples/buildah_debug.rhai
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// buildah_debug.rhai
|
||||||
|
// Demonstrates using the debug flag on the buildah Builder
|
||||||
|
|
||||||
|
println("Starting buildah debug example...");
|
||||||
|
|
||||||
|
// Define image and container names
|
||||||
|
let base_image = "ubuntu:22.04";
|
||||||
|
let container_name = "debug-test-container";
|
||||||
|
|
||||||
|
println(`Creating container '${container_name}' from base image '${base_image}'...`);
|
||||||
|
|
||||||
|
// Create a new buildah container using the builder pattern
|
||||||
|
let builder = bah_new(container_name, base_image);
|
||||||
|
|
||||||
|
// Enable debug mode
|
||||||
|
println("Enabling debug mode...");
|
||||||
|
builder.debug = true;
|
||||||
|
|
||||||
|
// Run a simple command to see debug output
|
||||||
|
println("Running a command with debug enabled...");
|
||||||
|
let result = builder.run("echo 'Hello from debug mode'");
|
||||||
|
|
||||||
|
// Disable debug mode
|
||||||
|
println("Disabling debug mode...");
|
||||||
|
builder.debug = false;
|
||||||
|
|
||||||
|
// Run another command without debug
|
||||||
|
println("Running a command with debug disabled...");
|
||||||
|
let result2 = builder.run("echo 'Hello without debug'");
|
||||||
|
|
||||||
|
// Enable debug mode again
|
||||||
|
println("Enabling debug mode again...");
|
||||||
|
builder.debug = true;
|
||||||
|
|
||||||
|
// Remove the container with debug enabled
|
||||||
|
println("Removing the container with debug enabled...");
|
||||||
|
builder.remove();
|
||||||
|
|
||||||
|
println("Debug example completed!");
|
162
src/rhaiexamples/text_tools.rhai
Normal file
162
src/rhaiexamples/text_tools.rhai
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
// text_tools.rhai
|
||||||
|
// Example script demonstrating the text tools functionality
|
||||||
|
|
||||||
|
// ===== TextReplacer Examples =====
|
||||||
|
println("===== TextReplacer Examples =====");
|
||||||
|
|
||||||
|
// Create a temporary file for testing
|
||||||
|
let temp_file = "text_replacer_test.txt";
|
||||||
|
write_file(temp_file, "This is a foo bar example with FOO and foo occurrences.\nAnother line with foo and bar.");
|
||||||
|
|
||||||
|
// Example 1: Simple replacement
|
||||||
|
println("\n--- Example 1: Simple replacement ---");
|
||||||
|
let replacer = text_replacer_new()
|
||||||
|
.pattern("foo")
|
||||||
|
.replacement("REPLACED")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let result = replacer.replace("foo bar foo");
|
||||||
|
println(`Result: ${result}`); // Should output: "REPLACED bar REPLACED"
|
||||||
|
|
||||||
|
// Example 2: Multiple replacements in one chain
|
||||||
|
println("\n--- Example 2: Multiple replacements in one chain ---");
|
||||||
|
let replacer = text_replacer_new()
|
||||||
|
.pattern("foo").replacement("AAA")
|
||||||
|
.pattern("bar").replacement("BBB")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let result = replacer.replace("foo bar foo baz");
|
||||||
|
println(`Result: ${result}`); // Should output: "AAA BBB AAA baz"
|
||||||
|
|
||||||
|
// Example 3: Case-insensitive regex replacement
|
||||||
|
println("\n--- Example 3: Case-insensitive regex replacement ---");
|
||||||
|
let replacer = text_replacer_new()
|
||||||
|
.pattern("foo")
|
||||||
|
.replacement("case-insensitive")
|
||||||
|
.regex(true)
|
||||||
|
.case_insensitive(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let result = replacer.replace("FOO foo Foo fOo");
|
||||||
|
println(`Result: ${result}`); // Should output: "case-insensitive case-insensitive case-insensitive case-insensitive"
|
||||||
|
|
||||||
|
// Example 4: File operations
|
||||||
|
println("\n--- Example 4: File operations ---");
|
||||||
|
let replacer = text_replacer_new()
|
||||||
|
.pattern("foo").replacement("EXAMPLE")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Replace and get result as string
|
||||||
|
let file_result = replacer.replace_file(temp_file);
|
||||||
|
println(`File content after replacement:\n${file_result}`);
|
||||||
|
|
||||||
|
// Replace in-place
|
||||||
|
replacer.replace_file_in_place(temp_file);
|
||||||
|
println("File replaced in-place");
|
||||||
|
|
||||||
|
// Replace to a new file
|
||||||
|
let output_file = "text_replacer_output.txt";
|
||||||
|
replacer.replace_file_to(temp_file, output_file);
|
||||||
|
println(`Content written to new file: ${output_file}`);
|
||||||
|
|
||||||
|
// Clean up temporary files
|
||||||
|
delete(temp_file);
|
||||||
|
delete(output_file);
|
||||||
|
|
||||||
|
// ===== TemplateBuilder Examples =====
|
||||||
|
println("\n\n===== TemplateBuilder Examples =====");
|
||||||
|
|
||||||
|
// Create a temporary template file
|
||||||
|
let template_file = "template_test.txt";
|
||||||
|
write_file(template_file, "Hello, {{ name }}! Welcome to {{ place }}.\n{% if show_greeting %}Glad to have you here!{% endif %}\nYour items:\n{% for item in items %} - {{ item }}{% if not loop.last %}\n{% endif %}{% endfor %}\n");
|
||||||
|
|
||||||
|
// Example 1: Simple template rendering
|
||||||
|
println("\n--- Example 1: Simple template rendering ---");
|
||||||
|
let template = template_builder_open(template_file)
|
||||||
|
.add_var("name", "John")
|
||||||
|
.add_var("place", "Rhai")
|
||||||
|
.add_var("show_greeting", true)
|
||||||
|
.add_var("items", ["apple", "banana", "cherry"]);
|
||||||
|
|
||||||
|
let result = template.render();
|
||||||
|
println(`Rendered template:\n${result}`);
|
||||||
|
|
||||||
|
// Example 2: Using a map for variables
|
||||||
|
println("\n--- Example 2: Using a map for variables ---");
|
||||||
|
let vars = #{
|
||||||
|
name: "Alice",
|
||||||
|
place: "Template World"
|
||||||
|
};
|
||||||
|
|
||||||
|
let template = template_builder_open(template_file)
|
||||||
|
.add_vars(vars)
|
||||||
|
.add_var("show_greeting", false)
|
||||||
|
.add_var("items", ["laptop", "phone", "tablet"]);
|
||||||
|
|
||||||
|
let result = template.render();
|
||||||
|
println(`Rendered template with map:\n${result}`);
|
||||||
|
|
||||||
|
// Example 3: Rendering to a file
|
||||||
|
println("\n--- Example 3: Rendering to a file ---");
|
||||||
|
let output_file = "template_output.txt";
|
||||||
|
|
||||||
|
let template = template_builder_open(template_file)
|
||||||
|
.add_var("name", "Bob")
|
||||||
|
.add_var("place", "File Output")
|
||||||
|
.add_var("show_greeting", true)
|
||||||
|
.add_var("items", ["document", "spreadsheet", "presentation"]);
|
||||||
|
|
||||||
|
template.render_to_file(output_file);
|
||||||
|
println(`Template rendered to file: ${output_file}`);
|
||||||
|
println(`Content of the rendered file:\n${read_file(output_file)}`);
|
||||||
|
|
||||||
|
// Clean up temporary files
|
||||||
|
delete(template_file);
|
||||||
|
delete(output_file);
|
||||||
|
|
||||||
|
// ===== Fix Functions Examples =====
|
||||||
|
println("\n\n===== Fix Functions Examples =====");
|
||||||
|
|
||||||
|
// Example 1: name_fix
|
||||||
|
println("\n--- Example 1: name_fix ---");
|
||||||
|
let fixed_name = name_fix("Hello World!");
|
||||||
|
println(`Original: "Hello World!"`);
|
||||||
|
println(`Fixed: "${fixed_name}"`); // Should output: "hello_world"
|
||||||
|
|
||||||
|
let fixed_name = name_fix("File-Name.txt");
|
||||||
|
println(`Original: "File-Name.txt"`);
|
||||||
|
println(`Fixed: "${fixed_name}"`); // Should output: "file_name.txt"
|
||||||
|
|
||||||
|
let fixed_name = name_fix("Résumé.doc");
|
||||||
|
println(`Original: "Résumé.doc"`);
|
||||||
|
println(`Fixed: "${fixed_name}"`); // Should output: "rsum.doc"
|
||||||
|
|
||||||
|
// Example 2: path_fix
|
||||||
|
println("\n--- Example 2: path_fix ---");
|
||||||
|
let fixed_path = path_fix("/path/to/Hello World!");
|
||||||
|
println(`Original: "/path/to/Hello World!"`);
|
||||||
|
println(`Fixed: "${fixed_path}"`); // Should output: "/path/to/hello_world"
|
||||||
|
|
||||||
|
let fixed_path = path_fix("./relative/path/to/DOCUMENT-123.pdf");
|
||||||
|
println(`Original: "./relative/path/to/DOCUMENT-123.pdf"`);
|
||||||
|
println(`Fixed: "${fixed_path}"`); // Should output: "./relative/path/to/document_123.pdf"
|
||||||
|
|
||||||
|
// ===== Dedent Functions Examples =====
|
||||||
|
println("\n\n===== Dedent Functions Examples =====");
|
||||||
|
|
||||||
|
// Example 1: dedent
|
||||||
|
println("\n--- Example 1: dedent ---");
|
||||||
|
let indented_text = " line 1\n line 2\n line 3";
|
||||||
|
println(`Original:\n${indented_text}`);
|
||||||
|
let dedented = dedent(indented_text);
|
||||||
|
println(`Dedented:\n${dedented}`); // Should output: "line 1\nline 2\n line 3"
|
||||||
|
|
||||||
|
// Example 2: prefix
|
||||||
|
println("\n--- Example 2: prefix ---");
|
||||||
|
let text = "line 1\nline 2\nline 3";
|
||||||
|
println(`Original:\n${text}`);
|
||||||
|
let prefixed = prefix(text, " ");
|
||||||
|
println(`Prefixed:\n${prefixed}`); // Should output: " line 1\n line 2\n line 3"
|
||||||
|
|
||||||
|
// Return success message
|
||||||
|
"Text tools example completed successfully!"
|
@ -31,6 +31,7 @@ impl ReplacementOperation {
|
|||||||
|
|
||||||
/// Text replacer that can perform multiple replacement operations
|
/// Text replacer that can perform multiple replacement operations
|
||||||
/// in a single pass over the input text.
|
/// in a single pass over the input text.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct TextReplacer {
|
pub struct TextReplacer {
|
||||||
operations: Vec<ReplacementOperation>,
|
operations: Vec<ReplacementOperation>,
|
||||||
}
|
}
|
||||||
@ -82,7 +83,7 @@ impl TextReplacer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builder for the TextReplacer.
|
/// Builder for the TextReplacer.
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
pub struct TextReplacerBuilder {
|
pub struct TextReplacerBuilder {
|
||||||
operations: Vec<ReplacementOperation>,
|
operations: Vec<ReplacementOperation>,
|
||||||
pattern: Option<String>,
|
pattern: Option<String>,
|
||||||
|
@ -5,6 +5,7 @@ use std::path::Path;
|
|||||||
use tera::{Context, Tera};
|
use tera::{Context, Tera};
|
||||||
|
|
||||||
/// A builder for creating and rendering templates using the Tera template engine.
|
/// A builder for creating and rendering templates using the Tera template engine.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct TemplateBuilder {
|
pub struct TemplateBuilder {
|
||||||
template_path: String,
|
template_path: String,
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -254,7 +255,7 @@ mod tests {
|
|||||||
fn test_template_with_hashmap_vars() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_template_with_hashmap_vars() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Create a temporary template file
|
// Create a temporary template file
|
||||||
let mut temp_file = NamedTempFile::new()?;
|
let mut temp_file = NamedTempFile::new()?;
|
||||||
writeln!(temp_file, "{{ greeting }}, {{ name }}!")?;
|
writeln!(temp_file, "{{{{ greeting }}}}, {{{{ name }}}}!")?;
|
||||||
temp_file.flush()?;
|
temp_file.flush()?;
|
||||||
|
|
||||||
// Create a HashMap of variables
|
// Create a HashMap of variables
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::process::CommandResult;
|
use crate::process::CommandResult;
|
||||||
use crate::virt::buildah::{execute_buildah_command, BuildahError, Image};
|
use crate::virt::buildah::{execute_buildah_command, BuildahError, Image, thread_local_debug, set_thread_local_debug};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
/// Builder struct for buildah operations
|
/// Builder struct for buildah operations
|
||||||
@ -116,7 +116,19 @@ impl Builder {
|
|||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn run(&self, command: &str) -> Result<CommandResult, BuildahError> {
|
pub fn run(&self, command: &str) -> Result<CommandResult, BuildahError> {
|
||||||
if let Some(container_id) = &self.container_id {
|
if let Some(container_id) = &self.container_id {
|
||||||
execute_buildah_command(&["run", container_id, "sh", "-c", command])
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["run", container_id, "sh", "-c", command]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(BuildahError::Other("No container ID available".to_string()))
|
Err(BuildahError::Other("No container ID available".to_string()))
|
||||||
}
|
}
|
||||||
@ -134,7 +146,19 @@ impl Builder {
|
|||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn run_with_isolation(&self, command: &str, isolation: &str) -> Result<CommandResult, BuildahError> {
|
pub fn run_with_isolation(&self, command: &str, isolation: &str) -> Result<CommandResult, BuildahError> {
|
||||||
if let Some(container_id) = &self.container_id {
|
if let Some(container_id) = &self.container_id {
|
||||||
execute_buildah_command(&["run", "--isolation", isolation, container_id, "sh", "-c", command])
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["run", "--isolation", isolation, container_id, "sh", "-c", command]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(BuildahError::Other("No container ID available".to_string()))
|
Err(BuildahError::Other("No container ID available".to_string()))
|
||||||
}
|
}
|
||||||
@ -152,7 +176,19 @@ impl Builder {
|
|||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn copy(&self, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
|
pub fn copy(&self, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
|
||||||
if let Some(container_id) = &self.container_id {
|
if let Some(container_id) = &self.container_id {
|
||||||
execute_buildah_command(&["copy", container_id, source, dest])
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["copy", container_id, source, dest]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(BuildahError::Other("No container ID available".to_string()))
|
Err(BuildahError::Other("No container ID available".to_string()))
|
||||||
}
|
}
|
||||||
@ -170,7 +206,19 @@ impl Builder {
|
|||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn add(&self, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
|
pub fn add(&self, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
|
||||||
if let Some(container_id) = &self.container_id {
|
if let Some(container_id) = &self.container_id {
|
||||||
execute_buildah_command(&["add", container_id, source, dest])
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["add", container_id, source, dest]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(BuildahError::Other("No container ID available".to_string()))
|
Err(BuildahError::Other("No container ID available".to_string()))
|
||||||
}
|
}
|
||||||
@ -187,7 +235,19 @@ impl Builder {
|
|||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn commit(&self, image_name: &str) -> Result<CommandResult, BuildahError> {
|
pub fn commit(&self, image_name: &str) -> Result<CommandResult, BuildahError> {
|
||||||
if let Some(container_id) = &self.container_id {
|
if let Some(container_id) = &self.container_id {
|
||||||
execute_buildah_command(&["commit", container_id, image_name])
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["commit", container_id, image_name]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(BuildahError::Other("No container ID available".to_string()))
|
Err(BuildahError::Other("No container ID available".to_string()))
|
||||||
}
|
}
|
||||||
@ -200,7 +260,19 @@ impl Builder {
|
|||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn remove(&self) -> Result<CommandResult, BuildahError> {
|
pub fn remove(&self) -> Result<CommandResult, BuildahError> {
|
||||||
if let Some(container_id) = &self.container_id {
|
if let Some(container_id) = &self.container_id {
|
||||||
execute_buildah_command(&["rm", container_id])
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["rm", container_id]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(BuildahError::Other("No container ID available".to_string()))
|
Err(BuildahError::Other("No container ID available".to_string()))
|
||||||
}
|
}
|
||||||
@ -213,9 +285,18 @@ impl Builder {
|
|||||||
/// * `Result<(), BuildahError>` - Success or error
|
/// * `Result<(), BuildahError>` - Success or error
|
||||||
pub fn reset(&mut self) -> Result<(), BuildahError> {
|
pub fn reset(&mut self) -> Result<(), BuildahError> {
|
||||||
if let Some(container_id) = &self.container_id {
|
if let Some(container_id) = &self.container_id {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
// Try to remove the container
|
// Try to remove the container
|
||||||
let result = execute_buildah_command(&["rm", container_id]);
|
let result = execute_buildah_command(&["rm", container_id]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
// Clear the container_id regardless of whether the removal succeeded
|
// Clear the container_id regardless of whether the removal succeeded
|
||||||
self.container_id = None;
|
self.container_id = None;
|
||||||
|
|
||||||
@ -256,7 +337,19 @@ impl Builder {
|
|||||||
// Convert Vec<String> to Vec<&str> for execute_buildah_command
|
// Convert Vec<String> to Vec<&str> for execute_buildah_command
|
||||||
let args: Vec<&str> = args_owned.iter().map(|s| s.as_str()).collect();
|
let args: Vec<&str> = args_owned.iter().map(|s| s.as_str()).collect();
|
||||||
|
|
||||||
execute_buildah_command(&args)
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag from the Builder's debug flag
|
||||||
|
set_thread_local_debug(self.debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&args);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(BuildahError::Other("No container ID available".to_string()))
|
Err(BuildahError::Other("No container ID available".to_string()))
|
||||||
}
|
}
|
||||||
@ -268,6 +361,7 @@ impl Builder {
|
|||||||
///
|
///
|
||||||
/// * `Result<Vec<Image>, BuildahError>` - List of images or error
|
/// * `Result<Vec<Image>, BuildahError>` - List of images or error
|
||||||
pub fn images() -> Result<Vec<Image>, BuildahError> {
|
pub fn images() -> Result<Vec<Image>, BuildahError> {
|
||||||
|
// Use default debug value (false) for static method
|
||||||
let result = execute_buildah_command(&["images", "--json"])?;
|
let result = execute_buildah_command(&["images", "--json"])?;
|
||||||
|
|
||||||
// Try to parse the JSON output
|
// Try to parse the JSON output
|
||||||
@ -339,9 +433,36 @@ impl Builder {
|
|||||||
///
|
///
|
||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn image_remove(image: &str) -> Result<CommandResult, BuildahError> {
|
pub fn image_remove(image: &str) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Use default debug value (false) for static method
|
||||||
execute_buildah_command(&["rmi", image])
|
execute_buildah_command(&["rmi", image])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove an image with debug output
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `image` - Image ID or name
|
||||||
|
/// * `debug` - Whether to enable debug output
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
|
pub fn image_remove_with_debug(image: &str, debug: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag
|
||||||
|
set_thread_local_debug(debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["rmi", image]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Pull an image from a registry
|
/// Pull an image from a registry
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
@ -353,6 +474,7 @@ impl Builder {
|
|||||||
///
|
///
|
||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn image_pull(image: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
|
pub fn image_pull(image: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Use default debug value (false) for static method
|
||||||
let mut args = vec!["pull"];
|
let mut args = vec!["pull"];
|
||||||
|
|
||||||
if !tls_verify {
|
if !tls_verify {
|
||||||
@ -364,6 +486,41 @@ impl Builder {
|
|||||||
execute_buildah_command(&args)
|
execute_buildah_command(&args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pull an image from a registry with debug output
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `image` - Image name
|
||||||
|
/// * `tls_verify` - Whether to verify TLS
|
||||||
|
/// * `debug` - Whether to enable debug output
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
|
pub fn image_pull_with_debug(image: &str, tls_verify: bool, debug: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag
|
||||||
|
set_thread_local_debug(debug);
|
||||||
|
|
||||||
|
let mut args = vec!["pull"];
|
||||||
|
|
||||||
|
if !tls_verify {
|
||||||
|
args.push("--tls-verify=false");
|
||||||
|
}
|
||||||
|
|
||||||
|
args.push(image);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&args);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Push an image to a registry
|
/// Push an image to a registry
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
@ -376,6 +533,7 @@ impl Builder {
|
|||||||
///
|
///
|
||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn image_push(image: &str, destination: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
|
pub fn image_push(image: &str, destination: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Use default debug value (false) for static method
|
||||||
let mut args = vec!["push"];
|
let mut args = vec!["push"];
|
||||||
|
|
||||||
if !tls_verify {
|
if !tls_verify {
|
||||||
@ -388,6 +546,43 @@ impl Builder {
|
|||||||
execute_buildah_command(&args)
|
execute_buildah_command(&args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Push an image to a registry with debug output
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `image` - Image name
|
||||||
|
/// * `destination` - Destination registry
|
||||||
|
/// * `tls_verify` - Whether to verify TLS
|
||||||
|
/// * `debug` - Whether to enable debug output
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
|
pub fn image_push_with_debug(image: &str, destination: &str, tls_verify: bool, debug: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag
|
||||||
|
set_thread_local_debug(debug);
|
||||||
|
|
||||||
|
let mut args = vec!["push"];
|
||||||
|
|
||||||
|
if !tls_verify {
|
||||||
|
args.push("--tls-verify=false");
|
||||||
|
}
|
||||||
|
|
||||||
|
args.push(image);
|
||||||
|
args.push(destination);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&args);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Tag an image
|
/// Tag an image
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
@ -399,9 +594,37 @@ impl Builder {
|
|||||||
///
|
///
|
||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn image_tag(image: &str, new_name: &str) -> Result<CommandResult, BuildahError> {
|
pub fn image_tag(image: &str, new_name: &str) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Use default debug value (false) for static method
|
||||||
execute_buildah_command(&["tag", image, new_name])
|
execute_buildah_command(&["tag", image, new_name])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tag an image with debug output
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `image` - Image ID or name
|
||||||
|
/// * `new_name` - New tag for the image
|
||||||
|
/// * `debug` - Whether to enable debug output
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
|
pub fn image_tag_with_debug(image: &str, new_name: &str, debug: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag
|
||||||
|
set_thread_local_debug(debug);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&["tag", image, new_name]);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Commit a container to an image with advanced options
|
/// Commit a container to an image with advanced options
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
@ -416,6 +639,7 @@ impl Builder {
|
|||||||
///
|
///
|
||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn image_commit(container: &str, image_name: &str, format: Option<&str>, squash: bool, rm: bool) -> Result<CommandResult, BuildahError> {
|
pub fn image_commit(container: &str, image_name: &str, format: Option<&str>, squash: bool, rm: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Use default debug value (false) for static method
|
||||||
let mut args = vec!["commit"];
|
let mut args = vec!["commit"];
|
||||||
|
|
||||||
if let Some(format_str) = format {
|
if let Some(format_str) = format {
|
||||||
@ -437,6 +661,54 @@ impl Builder {
|
|||||||
execute_buildah_command(&args)
|
execute_buildah_command(&args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Commit a container to an image with advanced options and debug output
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `container` - Container ID or name
|
||||||
|
/// * `image_name` - Name for the new image
|
||||||
|
/// * `format` - Optional format (oci or docker)
|
||||||
|
/// * `squash` - Whether to squash layers
|
||||||
|
/// * `rm` - Whether to remove the container after commit
|
||||||
|
/// * `debug` - Whether to enable debug output
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
|
pub fn image_commit_with_debug(container: &str, image_name: &str, format: Option<&str>, squash: bool, rm: bool, debug: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag
|
||||||
|
set_thread_local_debug(debug);
|
||||||
|
|
||||||
|
let mut args = vec!["commit"];
|
||||||
|
|
||||||
|
if let Some(format_str) = format {
|
||||||
|
args.push("--format");
|
||||||
|
args.push(format_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if squash {
|
||||||
|
args.push("--squash");
|
||||||
|
}
|
||||||
|
|
||||||
|
if rm {
|
||||||
|
args.push("--rm");
|
||||||
|
}
|
||||||
|
|
||||||
|
args.push(container);
|
||||||
|
args.push(image_name);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&args);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Build an image from a Containerfile/Dockerfile
|
/// Build an image from a Containerfile/Dockerfile
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
@ -450,6 +722,7 @@ impl Builder {
|
|||||||
///
|
///
|
||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn build(tag: Option<&str>, context_dir: &str, file: &str, isolation: Option<&str>) -> Result<CommandResult, BuildahError> {
|
pub fn build(tag: Option<&str>, context_dir: &str, file: &str, isolation: Option<&str>) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Use default debug value (false) for static method
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
args.push("build");
|
args.push("build");
|
||||||
|
|
||||||
@ -470,4 +743,51 @@ impl Builder {
|
|||||||
|
|
||||||
execute_buildah_command(&args)
|
execute_buildah_command(&args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build an image from a Containerfile/Dockerfile with debug output
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `tag` - Optional tag for the image
|
||||||
|
/// * `context_dir` - Directory containing the Containerfile/Dockerfile
|
||||||
|
/// * `file` - Path to the Containerfile/Dockerfile
|
||||||
|
/// * `isolation` - Optional isolation method
|
||||||
|
/// * `debug` - Whether to enable debug output
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
|
pub fn build_with_debug(tag: Option<&str>, context_dir: &str, file: &str, isolation: Option<&str>, debug: bool) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Save the current debug flag
|
||||||
|
let previous_debug = thread_local_debug();
|
||||||
|
|
||||||
|
// Set the thread-local debug flag
|
||||||
|
set_thread_local_debug(debug);
|
||||||
|
|
||||||
|
let mut args = Vec::new();
|
||||||
|
args.push("build");
|
||||||
|
|
||||||
|
if let Some(tag_value) = tag {
|
||||||
|
args.push("-t");
|
||||||
|
args.push(tag_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(isolation_value) = isolation {
|
||||||
|
args.push("--isolation");
|
||||||
|
args.push(isolation_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.push("-f");
|
||||||
|
args.push(file);
|
||||||
|
|
||||||
|
args.push(context_dir);
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
let result = execute_buildah_command(&args);
|
||||||
|
|
||||||
|
// Restore the previous debug flag
|
||||||
|
set_thread_local_debug(previous_debug);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ use super::{BuildahError, Builder};
|
|||||||
///
|
///
|
||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
pub fn execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahError> {
|
pub fn execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahError> {
|
||||||
// Get the current thread-local Builder instance if available
|
// Get the debug flag from thread-local storage
|
||||||
let debug = thread_local_debug();
|
let debug = thread_local_debug();
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
@ -37,6 +37,7 @@ pub fn execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahEr
|
|||||||
code: output.status.code().unwrap_or(-1),
|
code: output.status.code().unwrap_or(-1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Always output stdout/stderr when debug is true
|
||||||
if debug {
|
if debug {
|
||||||
if !result.stdout.is_empty() {
|
if !result.stdout.is_empty() {
|
||||||
println!("Command stdout: {}", result.stdout);
|
println!("Command stdout: {}", result.stdout);
|
||||||
@ -45,26 +46,28 @@ pub fn execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahEr
|
|||||||
if !result.stderr.is_empty() {
|
if !result.stderr.is_empty() {
|
||||||
println!("Command stderr: {}", result.stderr);
|
println!("Command stderr: {}", result.stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if result.success {
|
||||||
|
println!("Command succeeded with code {}", result.code);
|
||||||
|
} else {
|
||||||
|
println!("Command failed with code {}", result.code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.success {
|
if result.success {
|
||||||
if debug {
|
|
||||||
println!("Command succeeded with code {}", result.code);
|
|
||||||
}
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
} else {
|
} else {
|
||||||
let error_msg = format!("Command failed with code {}: {}",
|
// If command failed and debug is false, output stderr
|
||||||
result.code, result.stderr.trim());
|
if !debug {
|
||||||
if debug {
|
println!("Command failed with code {}: {}", result.code, result.stderr.trim());
|
||||||
println!("Command failed: {}", error_msg);
|
|
||||||
}
|
}
|
||||||
Err(BuildahError::CommandFailed(error_msg))
|
Err(BuildahError::CommandFailed(format!("Command failed with code {}: {}",
|
||||||
|
result.code, result.stderr.trim())))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if debug {
|
// Always output error information
|
||||||
println!("Command execution failed: {}", e);
|
println!("Command execution failed: {}", e);
|
||||||
}
|
|
||||||
Err(BuildahError::CommandExecutionFailed(e))
|
Err(BuildahError::CommandExecutionFailed(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,41 +92,4 @@ pub fn thread_local_debug() -> bool {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute a buildah command with debug output
|
// This function is no longer needed as the debug functionality is now integrated into execute_buildah_command
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `args` - The command arguments
|
|
||||||
/// * `builder` - Reference to a Builder instance for debug output
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
///
|
|
||||||
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
|
||||||
pub fn execute_buildah_command_with_debug(args: &[&str], builder: &Builder) -> Result<CommandResult, BuildahError> {
|
|
||||||
if builder.debug() {
|
|
||||||
println!("Executing buildah command: buildah {}", args.join(" "));
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = execute_buildah_command(args);
|
|
||||||
|
|
||||||
if builder.debug() {
|
|
||||||
match &result {
|
|
||||||
Ok(cmd_result) => {
|
|
||||||
if !cmd_result.stdout.is_empty() {
|
|
||||||
println!("Command stdout: {}", cmd_result.stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !cmd_result.stderr.is_empty() {
|
|
||||||
println!("Command stderr: {}", cmd_result.stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Command succeeded with code {}", cmd_result.code);
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
println!("Command failed: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user