Add support for partial image creation and improve logging

- Introduced the `ImageType` enum to support both `Full` and `Partial` image types during creation.
- Updated `Image::create_image` to accept `ImageType` as a parameter.
- Enhanced logging with detailed debug statements for catalog building, image queries, and package processing.
- Refactored CLI to include a new `--type` option for specifying image type during image creation.
- Simplified path determination logic in `pkg6` with a new `determine_image_path` helper function.
- Removed unused imports and unnecessary file checks for cleaner code.
This commit is contained in:
Till Wegmueller 2025-08-04 23:01:04 +02:00
parent e27cd35d8d
commit f31d2e11af
No known key found for this signature in database
6 changed files with 198 additions and 54 deletions

View file

@ -119,53 +119,79 @@ impl ImageCatalog {
/// Build the catalog from downloaded catalogs /// Build the catalog from downloaded catalogs
pub fn build_catalog(&self, publishers: &[String]) -> Result<()> { pub fn build_catalog(&self, publishers: &[String]) -> Result<()> {
println!("Building catalog with publishers: {:?}", publishers);
println!("Catalog directory: {:?}", self.catalog_dir);
println!("Catalog database path: {:?}", self.db_path);
if publishers.is_empty() { if publishers.is_empty() {
println!("No publishers provided");
return Err(CatalogError::NoPublishers); return Err(CatalogError::NoPublishers);
} }
// Open the database // Open the database
println!("Opening database at {:?}", self.db_path);
let db = Database::open(&self.db_path) let db = Database::open(&self.db_path)
.map_err(|e| CatalogError::Database(format!("Failed to open database: {}", e)))?; .map_err(|e| CatalogError::Database(format!("Failed to open database: {}", e)))?;
// Begin a writing transaction // Begin a writing transaction
println!("Beginning write transaction");
let tx = db.begin_write() let tx = db.begin_write()
.map_err(|e| CatalogError::Database(format!("Failed to begin transaction: {}", e)))?; .map_err(|e| CatalogError::Database(format!("Failed to begin transaction: {}", e)))?;
// Open the catalog table // Open the catalog table
println!("Opening catalog table");
let mut catalog_table = tx.open_table(CATALOG_TABLE) let mut catalog_table = tx.open_table(CATALOG_TABLE)
.map_err(|e| CatalogError::Database(format!("Failed to open catalog table: {}", e)))?; .map_err(|e| CatalogError::Database(format!("Failed to open catalog table: {}", e)))?;
// Open the obsoleted table // Open the obsoleted table
println!("Opening obsoleted table");
let mut obsoleted_table = tx.open_table(OBSOLETED_TABLE) let mut obsoleted_table = tx.open_table(OBSOLETED_TABLE)
.map_err(|e| CatalogError::Database(format!("Failed to open obsoleted table: {}", e)))?; .map_err(|e| CatalogError::Database(format!("Failed to open obsoleted table: {}", e)))?;
// Process each publisher // Process each publisher
for publisher in publishers { for publisher in publishers {
println!("Processing publisher: {}", publisher);
let publisher_catalog_dir = self.catalog_dir.join(publisher); let publisher_catalog_dir = self.catalog_dir.join(publisher);
println!("Publisher catalog directory: {:?}", publisher_catalog_dir);
// Skip if the publisher catalog directory doesn't exist // Skip if the publisher catalog directory doesn't exist
if !publisher_catalog_dir.exists() { if !publisher_catalog_dir.exists() {
println!("Publisher catalog directory not found: {}", publisher_catalog_dir.display());
warn!("Publisher catalog directory not found: {}", publisher_catalog_dir.display()); warn!("Publisher catalog directory not found: {}", publisher_catalog_dir.display());
continue; continue;
} }
// Create a catalog manager for this publisher // Create a catalog manager for this publisher
println!("Creating catalog manager for publisher: {}", publisher);
let mut catalog_manager = CatalogManager::new(&publisher_catalog_dir, publisher) let mut catalog_manager = CatalogManager::new(&publisher_catalog_dir, publisher)
.map_err(|e| CatalogError::Repository(crate::repository::RepositoryError::Other(format!("Failed to create catalog manager: {}", e))))?; .map_err(|e| CatalogError::Repository(crate::repository::RepositoryError::Other(format!("Failed to create catalog manager: {}", e))))?;
// Get all catalog parts // Get all catalog parts
println!("Getting catalog parts for publisher: {}", publisher);
let parts = catalog_manager.attrs().parts.clone(); let parts = catalog_manager.attrs().parts.clone();
println!("Catalog parts: {:?}", parts.keys().collect::<Vec<_>>());
// Load all catalog parts // Load all catalog parts
for part_name in parts.keys() { for part_name in parts.keys() {
println!("Loading catalog part: {}", part_name);
catalog_manager.load_part(part_name) catalog_manager.load_part(part_name)
.map_err(|e| CatalogError::Repository(crate::repository::RepositoryError::Other(format!("Failed to load catalog part: {}", e))))?; .map_err(|e| CatalogError::Repository(crate::repository::RepositoryError::Other(format!("Failed to load catalog part: {}", e))))?;
} }
// Process each catalog part // Process each catalog part
for (part_name, _) in parts { for (part_name, _) in parts {
println!("Processing catalog part: {}", part_name);
if let Some(part) = catalog_manager.get_part(&part_name) { if let Some(part) = catalog_manager.get_part(&part_name) {
println!("Found catalog part: {}", part_name);
println!("Packages in part: {:?}", part.packages.keys().collect::<Vec<_>>());
if let Some(publisher_packages) = part.packages.get(publisher) {
println!("Packages for publisher {}: {:?}", publisher, publisher_packages.keys().collect::<Vec<_>>());
} else {
println!("No packages found for publisher: {}", publisher);
}
self.process_catalog_part(&mut catalog_table, &mut obsoleted_table, part, publisher)?; self.process_catalog_part(&mut catalog_table, &mut obsoleted_table, part, publisher)?;
} else {
println!("Catalog part not found: {}", part_name);
} }
} }
} }
@ -190,70 +216,109 @@ impl ImageCatalog {
part: &CatalogPart, part: &CatalogPart,
publisher: &str, publisher: &str,
) -> Result<()> { ) -> Result<()> {
println!("Processing catalog part for publisher: {}", publisher);
// Get packages for this publisher // Get packages for this publisher
if let Some(publisher_packages) = part.packages.get(publisher) { if let Some(publisher_packages) = part.packages.get(publisher) {
println!("Found {} package stems for publisher {}", publisher_packages.len(), publisher);
// Process each package stem // Process each package stem
for (stem, versions) in publisher_packages { for (stem, versions) in publisher_packages {
println!("Processing package stem: {}", stem);
println!("Found {} versions for stem {}", versions.len(), stem);
// Process each package version // Process each package version
for version_entry in versions { for version_entry in versions {
println!("Processing version: {}", version_entry.version);
println!("Actions: {:?}", version_entry.actions);
// Create the FMRI // Create the FMRI
let version = if !version_entry.version.is_empty() { let version = if !version_entry.version.is_empty() {
match crate::fmri::Version::parse(&version_entry.version) { match crate::fmri::Version::parse(&version_entry.version) {
Ok(v) => Some(v), Ok(v) => {
println!("Parsed version: {:?}", v);
Some(v)
},
Err(e) => { Err(e) => {
println!("Failed to parse version '{}': {}", version_entry.version, e);
warn!("Failed to parse version '{}': {}", version_entry.version, e); warn!("Failed to parse version '{}': {}", version_entry.version, e);
continue; continue;
} }
} }
} else { } else {
println!("Empty version string");
None None
}; };
let fmri = Fmri::with_publisher(publisher, stem, version); let fmri = Fmri::with_publisher(publisher, stem, version);
println!("Created FMRI: {}", fmri);
// Create the key for the catalog table (stem@version) // Create the key for the catalog table (stem@version)
let catalog_key = format!("{}@{}", stem, version_entry.version); let catalog_key = format!("{}@{}", stem, version_entry.version);
println!("Catalog key: {}", catalog_key);
// Create the key for the obsoleted table (full FMRI including publisher) // Create the key for the obsoleted table (full FMRI including publisher)
let obsoleted_key = fmri.to_string(); let obsoleted_key = fmri.to_string();
println!("Obsoleted key: {}", obsoleted_key);
// Check if we already have this package in the catalog // Check if we already have this package in the catalog
let existing_manifest = if let Ok(bytes) = catalog_table.get(catalog_key.as_str()) { let existing_manifest = if let Ok(bytes) = catalog_table.get(catalog_key.as_str()) {
if let Some(bytes) = bytes { if let Some(bytes) = bytes {
println!("Found existing manifest for {}", catalog_key);
Some(serde_json::from_slice::<Manifest>(bytes.value())?) Some(serde_json::from_slice::<Manifest>(bytes.value())?)
} else { } else {
println!("No existing manifest found for {}", catalog_key);
None None
} }
} else { } else {
println!("Error getting manifest for {}", catalog_key);
None None
}; };
// Create or update the manifest // Create or update the manifest
println!("Creating or updating manifest");
let manifest = self.create_or_update_manifest(existing_manifest, version_entry, stem, publisher)?; let manifest = self.create_or_update_manifest(existing_manifest, version_entry, stem, publisher)?;
// Check if the package is obsolete // Check if the package is obsolete
let is_obsolete = self.is_package_obsolete(&manifest); let is_obsolete = self.is_package_obsolete(&manifest);
println!("Package is obsolete: {}", is_obsolete);
// Serialize the manifest // Serialize the manifest
let manifest_bytes = serde_json::to_vec(&manifest)?; let manifest_bytes = serde_json::to_vec(&manifest)?;
println!("Serialized manifest size: {} bytes", manifest_bytes.len());
// Store the package in the appropriate table // Store the package in the appropriate table
if is_obsolete { if is_obsolete {
println!("Storing obsolete package in obsoleted table");
// Store obsolete packages in the obsoleted table with the full FMRI as key // Store obsolete packages in the obsoleted table with the full FMRI as key
// We don't store any meaningful values in the obsoleted table as per requirements, // We don't store any meaningful values in the obsoleted table as per requirements,
// but we need to provide a valid byte slice // but we need to provide a valid byte slice
let empty_bytes: &[u8] = &[0u8; 0]; let empty_bytes: &[u8] = &[0u8; 0];
obsoleted_table.insert(obsoleted_key.as_str(), empty_bytes) match obsoleted_table.insert(obsoleted_key.as_str(), empty_bytes) {
.map_err(|e| CatalogError::Database(format!("Failed to insert into obsoleted table: {}", e)))?; Ok(_) => println!("Successfully inserted into obsoleted table"),
Err(e) => {
println!("Failed to insert into obsoleted table: {}", e);
return Err(CatalogError::Database(format!("Failed to insert into obsoleted table: {}", e)));
}
}
} else { } else {
println!("Storing non-obsolete package in catalog table");
// Store non-obsolete packages in the catalog table with stem@version as a key // Store non-obsolete packages in the catalog table with stem@version as a key
catalog_table.insert(catalog_key.as_str(), manifest_bytes.as_slice()) match catalog_table.insert(catalog_key.as_str(), manifest_bytes.as_slice()) {
.map_err(|e| CatalogError::Database(format!("Failed to insert into catalog table: {}", e)))?; Ok(_) => println!("Successfully inserted into catalog table"),
Err(e) => {
println!("Failed to insert into catalog table: {}", e);
return Err(CatalogError::Database(format!("Failed to insert into catalog table: {}", e)));
}
}
} }
} }
} }
} else {
println!("No packages found for publisher: {}", publisher);
} }
println!("Finished processing catalog part for publisher: {}", publisher);
Ok(()) Ok(())
} }

View file

@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::actions::{Attr, Manifest}; use crate::actions::{Attr, Manifest};
use crate::fmri::Fmri; use crate::fmri::Fmri;
use redb::ReadableTable; use redb::{Database, ReadableTable};
use std::str::FromStr; use std::str::FromStr;
use tempfile::tempdir; use tempfile::tempdir;
@ -12,7 +12,7 @@ fn test_installed_packages() {
let image_path = temp_dir.path().join("image"); let image_path = temp_dir.path().join("image");
// Create the image // Create the image
let image = Image::create_image(&image_path).unwrap(); let image = Image::create_image(&image_path, ImageType::Full).unwrap();
// Verify that the installed packages database was initialized // Verify that the installed packages database was initialized
assert!(image.installed_db_path().exists()); assert!(image.installed_db_path().exists());

View file

@ -4,7 +4,6 @@ mod tests;
use miette::Diagnostic; use miette::Diagnostic;
use properties::*; use properties::*;
use redb::Database;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::{self, File}; use std::fs::{self, File};
@ -455,9 +454,17 @@ impl Image {
/// ///
/// This method only creates the image structure without adding publishers or downloading catalogs. /// This method only creates the image structure without adding publishers or downloading catalogs.
/// Publisher addition and catalog downloading should be handled separately. /// Publisher addition and catalog downloading should be handled separately.
pub fn create_image<P: AsRef<Path>>(path: P) -> Result<Self> { ///
// Create a new image /// # Arguments
let image = Image::new_full(path.as_ref().to_path_buf()); ///
/// * `path` - The path where the image will be created
/// * `image_type` - The type of image to create (Full or Partial)
pub fn create_image<P: AsRef<Path>>(path: P, image_type: ImageType) -> Result<Self> {
// Create a new image based on the specified type
let image = match image_type {
ImageType::Full => Image::new_full(path.as_ref().to_path_buf()),
ImageType::Partial => Image::new_partial(path.as_ref().to_path_buf()),
};
// Create the directory structure // Create the directory structure
image.create_metadata_dir()?; image.create_metadata_dir()?;

View file

@ -9,7 +9,7 @@ fn test_image_catalog() {
let image_path = temp_dir.path().join("image"); let image_path = temp_dir.path().join("image");
// Create the image // Create the image
let image = Image::create_image(&image_path).unwrap(); let image = Image::create_image(&image_path, ImageType::Full).unwrap();
// Verify that the catalog database was initialized // Verify that the catalog database was initialized
assert!(image.catalog_db_path().exists()); assert!(image.catalog_db_path().exists());
@ -25,14 +25,24 @@ fn test_catalog_methods() {
let image_path = temp_dir.path().join("image"); let image_path = temp_dir.path().join("image");
// Create the image // Create the image
let mut image = Image::create_image(&image_path).unwrap(); let mut image = Image::create_image(&image_path, ImageType::Full).unwrap();
// Print the image type and paths
println!("Image type: {:?}", image.image_type());
println!("Image path: {:?}", image.path());
println!("Metadata dir: {:?}", image.metadata_dir());
println!("Catalog dir: {:?}", image.catalog_dir());
// Add a publisher // Add a publisher
image.add_publisher("test", "http://example.com/repo", vec![], true).unwrap(); image.add_publisher("test", "http://example.com/repo", vec![], true).unwrap();
// Print the publishers
println!("Publishers: {:?}", image.publishers());
// Create the catalog directory structure // Create the catalog directory structure
let catalog_dir = image.catalog_dir(); let catalog_dir = image.catalog_dir();
let publisher_dir = catalog_dir.join("test"); let publisher_dir = catalog_dir.join("test");
println!("Publisher dir: {:?}", publisher_dir);
fs::create_dir_all(&publisher_dir).unwrap(); fs::create_dir_all(&publisher_dir).unwrap();
// Create a simple catalog.attrs file // Create a simple catalog.attrs file
@ -42,6 +52,8 @@ fn test_catalog_methods() {
}, },
"version": 1 "version": 1
}"#; }"#;
println!("Writing catalog.attrs to {:?}", publisher_dir.join("catalog.attrs"));
println!("catalog.attrs content: {}", attrs_content);
fs::write(publisher_dir.join("catalog.attrs"), attrs_content).unwrap(); fs::write(publisher_dir.join("catalog.attrs"), attrs_content).unwrap();
// Create a simple base catalog part // Create a simple base catalog part
@ -71,13 +83,33 @@ fn test_catalog_methods() {
} }
} }
}"#; }"#;
println!("Writing base catalog part to {:?}", publisher_dir.join("base"));
println!("base catalog part content: {}", base_content);
fs::write(publisher_dir.join("base"), base_content).unwrap(); fs::write(publisher_dir.join("base"), base_content).unwrap();
// Verify that the files were written correctly
println!("Checking if catalog.attrs exists: {}", publisher_dir.join("catalog.attrs").exists());
println!("Checking if base catalog part exists: {}", publisher_dir.join("base").exists());
// Build the catalog // Build the catalog
image.build_catalog().unwrap(); println!("Building catalog...");
match image.build_catalog() {
Ok(_) => println!("Catalog built successfully"),
Err(e) => println!("Failed to build catalog: {:?}", e),
}
// Query the catalog // Query the catalog
let packages = image.query_catalog(None).unwrap(); println!("Querying catalog...");
let packages = match image.query_catalog(None) {
Ok(pkgs) => {
println!("Found {} packages", pkgs.len());
pkgs
},
Err(e) => {
println!("Failed to query catalog: {:?}", e);
panic!("Failed to query catalog: {:?}", e);
}
};
// Verify that both non-obsolete and obsolete packages are in the results // Verify that both non-obsolete and obsolete packages are in the results
assert_eq!(packages.len(), 2); assert_eq!(packages.len(), 2);

View file

@ -396,8 +396,7 @@ pub struct CatalogManager {
impl CatalogManager { impl CatalogManager {
/// Create a new catalog manager /// Create a new catalog manager
pub fn new<P: AsRef<Path>>(base_dir: P, publisher: &str) -> Result<Self> { pub fn new<P: AsRef<Path>>(base_dir: P, publisher: &str) -> Result<Self> {
let base_dir = base_dir.as_ref().to_path_buf(); let publisher_catalog_dir = base_dir.as_ref().to_path_buf();
let publisher_catalog_dir = base_dir.join(publisher).join("catalog");
// Create catalog directory if it doesn't exist // Create catalog directory if it doesn't exist
if !publisher_catalog_dir.exists() { if !publisher_catalog_dir.exists() {

View file

@ -2,8 +2,6 @@ mod error;
use error::{Pkg6Error, Result}; use error::{Pkg6Error, Result};
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use libips::fmri::Fmri;
use libips::image::Publisher;
use serde::Serialize; use serde::Serialize;
use std::path::PathBuf; use std::path::PathBuf;
use std::io::Write; use std::io::Write;
@ -39,6 +37,14 @@ struct PublisherOutput {
#[clap(author, version, about, long_about = None)] #[clap(author, version, about, long_about = None)]
#[clap(propagate_version = true)] #[clap(propagate_version = true)]
struct App { struct App {
/// Path to the image to operate on
///
/// If not specified, the default image is determined as follows:
/// - If $HOME/.pkg exists, that directory is used
/// - Otherwise, the root directory (/) is used
#[clap(short = 'R', global = true)]
image_path: Option<PathBuf>,
#[clap(subcommand)] #[clap(subcommand)]
command: Commands, command: Commands,
} }
@ -411,9 +417,39 @@ enum Commands {
/// Publisher origin URL (required if publisher is specified) /// Publisher origin URL (required if publisher is specified)
#[clap(short = 'g', requires = "publisher")] #[clap(short = 'g', requires = "publisher")]
origin: Option<String>, origin: Option<String>,
/// Type of image to create (full or partial, default: full)
#[clap(short = 't', long = "type", default_value = "full")]
image_type: String,
}, },
} }
/// Determines the image path to use based on the provided argument and default rules
///
/// If the image_path argument is provided, that path is used.
/// Otherwise, if $HOME/.pkg exists, that path is used.
/// Otherwise, the root directory (/) is used.
fn determine_image_path(image_path: Option<PathBuf>) -> PathBuf {
if let Some(path) = image_path {
// Use the explicitly provided path
debug!("Using explicitly provided image path: {}", path.display());
path
} else {
// Check if $HOME/.pkg exists
if let Ok(home_dir) = std::env::var("HOME") {
let home_pkg = PathBuf::from(home_dir).join(".pkg");
if home_pkg.exists() {
debug!("Using user home image path: {}", home_pkg.display());
return PathBuf::from(home_pkg);
}
}
// Default to root directory
debug!("Using root directory as image path");
PathBuf::from("/")
}
}
fn main() -> Result<()> { fn main() -> Result<()> {
// Add debug statement at the very beginning // Add debug statement at the very beginning
eprintln!("MAIN: Starting pkg6 command"); eprintln!("MAIN: Starting pkg6 command");
@ -588,15 +624,16 @@ fn main() -> Result<()> {
debug!("Origin: {:?}", origin); debug!("Origin: {:?}", origin);
debug!("Mirror: {:?}", mirror); debug!("Mirror: {:?}", mirror);
// Get the current working directory as the default image path // Determine the image path using the -R argument or default rules
let current_dir = std::env::current_dir()?; let image_path = determine_image_path(cli.image_path.clone());
info!("Using image at: {}", image_path.display());
// Try to load the image from the current directory // Try to load the image from the determined path
let mut image = match libips::image::Image::load(&current_dir) { let mut image = match libips::image::Image::load(&image_path) {
Ok(img) => img, Ok(img) => img,
Err(e) => { Err(e) => {
error!("Failed to load image from current directory: {}", e); error!("Failed to load image from {}: {}", image_path.display(), e);
error!("Make sure you are in an image directory or use pkg6 image-create first"); error!("Make sure the path points to a valid image or use pkg6 image-create first");
return Err(e.into()); return Err(e.into());
} }
}; };
@ -639,15 +676,16 @@ fn main() -> Result<()> {
Commands::UnsetPublisher { publisher } => { Commands::UnsetPublisher { publisher } => {
info!("Unsetting publisher: {}", publisher); info!("Unsetting publisher: {}", publisher);
// Get the current working directory as the default image path // Determine the image path using the -R argument or default rules
let current_dir = std::env::current_dir()?; let image_path = determine_image_path(cli.image_path.clone());
info!("Using image at: {}", image_path.display());
// Try to load the image from the current directory // Try to load the image from the determined path
let mut image = match libips::image::Image::load(&current_dir) { let mut image = match libips::image::Image::load(&image_path) {
Ok(img) => img, Ok(img) => img,
Err(e) => { Err(e) => {
error!("Failed to load image from current directory: {}", e); error!("Failed to load image from {}: {}", image_path.display(), e);
error!("Make sure you are in an image directory or use pkg6 image-create first"); error!("Make sure the path points to a valid image or use pkg6 image-create first");
return Err(e.into()); return Err(e.into());
} }
}; };
@ -670,28 +708,20 @@ fn main() -> Result<()> {
Commands::Publisher { verbose, output_format, publishers } => { Commands::Publisher { verbose, output_format, publishers } => {
info!("Showing publisher information"); info!("Showing publisher information");
// Get the current working directory as the default image path // Determine the image path using the -R argument or default rules
let current_dir = std::env::current_dir()?; let image_path = determine_image_path(cli.image_path.clone());
info!("Using image at: {}", image_path.display());
// Determine the path to the image configuration file // Try to load the image from the determined path
let image_json_path = match libips::image::ImageType::Full { let image = match libips::image::Image::load(&image_path) {
libips::image::ImageType::Full => current_dir.join("var/pkg/pkg6.image.json"), Ok(img) => img,
libips::image::ImageType::Partial => current_dir.join(".pkg/pkg6.image.json"), Err(e) => {
error!("Failed to load image from {}: {}", image_path.display(), e);
error!("Make sure the path points to a valid image or use pkg6 image-create first");
return Err(e.into());
}
}; };
// Check if the image configuration file exists
if !image_json_path.exists() {
error!("Image configuration file not found at {}", image_json_path.display());
error!("Make sure you are in an image directory or use pkg6 image-create first");
return Err(Pkg6Error::from(format!("Image configuration file not found at {}", image_json_path.display())));
}
// Read the image configuration file
let image_json = std::fs::read_to_string(&image_json_path)?;
// Parse the image configuration file
let image: libips::image::Image = serde_json::from_str(&image_json)?;
// Get all publishers // Get all publishers
let all_publishers = image.publishers(); let all_publishers = image.publishers();
@ -725,8 +755,8 @@ fn main() -> Result<()> {
.map(|p| { .map(|p| {
let catalog_dir = if *verbose { let catalog_dir = if *verbose {
let dir = match image.image_type() { let dir = match image.image_type() {
libips::image::ImageType::Full => current_dir.join("var/pkg/catalog"), libips::image::ImageType::Full => image_path.join("var/pkg/catalog"),
libips::image::ImageType::Partial => current_dir.join(".pkg/catalog"), libips::image::ImageType::Partial => image_path.join(".pkg/catalog"),
}; };
Some(dir.join(&p.name).display().to_string()) Some(dir.join(&p.name).display().to_string())
} else { } else {
@ -808,13 +838,24 @@ fn main() -> Result<()> {
info!("Publisher completed successfully"); info!("Publisher completed successfully");
Ok(()) Ok(())
}, },
Commands::ImageCreate { full_path, publisher, origin } => { Commands::ImageCreate { full_path, publisher, origin, image_type } => {
info!("Creating image at: {}", full_path.display()); info!("Creating image at: {}", full_path.display());
debug!("Publisher: {:?}", publisher); debug!("Publisher: {:?}", publisher);
debug!("Origin: {:?}", origin); debug!("Origin: {:?}", origin);
debug!("Image type: {}", image_type);
// Convert the image type string to the ImageType enum
let image_type = match image_type.to_lowercase().as_str() {
"full" => libips::image::ImageType::Full,
"partial" => libips::image::ImageType::Partial,
_ => {
error!("Invalid image type: {}. Using default (full)", image_type);
libips::image::ImageType::Full
}
};
// Create the image (only creates the basic structure) // Create the image (only creates the basic structure)
let mut image = libips::image::Image::create_image(&full_path)?; let mut image = libips::image::Image::create_image(&full_path, image_type)?;
info!("Image created successfully at: {}", full_path.display()); info!("Image created successfully at: {}", full_path.display());
// If publisher and origin are provided, add the publisher and download the catalog // If publisher and origin are provided, add the publisher and download the catalog