Fix branch name conversion bug with regex-based solution

- Replace broken sequential replace() logic with robust regex pattern
- Fix architecture name preservation (x86_64, aarch64, arm64)
- Use regex pattern ^([^_]+)_([^_]+)_(.*)$ for proper parsing
- Add lazy_static for efficient regex compilation
- Resolve compose command branch matching issues
- Test: ubuntu_24.04_x86_64 now correctly converts to ubuntu/24.04/x86_64
This commit is contained in:
robojerk 2025-07-18 20:25:07 +00:00
parent 5777c11f85
commit c39d6c03b5
4 changed files with 55 additions and 15 deletions

View file

@ -60,6 +60,9 @@ jsonpath-rust = "0.1"
# Regular expressions # Regular expressions
regex = "1.0" regex = "1.0"
# Lazy static initialization
lazy_static = "1.4"
# UUID generation # UUID generation
uuid = { version = "1.0", features = ["v4"] } uuid = { version = "1.0", features = ["v4"] }

View file

@ -1,7 +1,6 @@
use std::path::PathBuf;
use tracing::{info, warn}; use tracing::{info, warn};
use crate::error::AptOstreeResult; use crate::error::AptOstreeResult;
use crate::system::AptOstreeSystem; use crate::ostree::OstreeManager;
/// Base image reference (e.g., "ubuntu:24.04") /// Base image reference (e.g., "ubuntu:24.04")
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -32,15 +31,18 @@ pub struct ComposeOptions {
/// Compose manager for handling base image resolution and compose operations /// Compose manager for handling base image resolution and compose operations
pub struct ComposeManager { pub struct ComposeManager {
branch: String, branch: String,
ostree_manager: OstreeManager,
} }
impl ComposeManager { impl ComposeManager {
/// Create a new compose manager /// Create a new compose manager
pub async fn new(branch: &str) -> AptOstreeResult<Self> { pub async fn new(branch: &str) -> AptOstreeResult<Self> {
// For now, don't initialize the full system to avoid OSTree validation // Initialize OSTree manager for real branch operations
// TODO: Add proper system initialization when OSTree integration is complete let ostree_manager = OstreeManager::new("/var/lib/apt-ostree/repo")?;
Ok(Self { Ok(Self {
branch: branch.to_string(), branch: branch.to_string(),
ostree_manager,
}) })
} }
@ -51,7 +53,7 @@ impl ComposeManager {
let base_image = self.parse_base_image_ref(base_ref)?; let base_image = self.parse_base_image_ref(base_ref)?;
let ostree_branch = self.map_to_ostree_branch(&base_image)?; let ostree_branch = self.map_to_ostree_branch(&base_image)?;
// Check if the branch exists locally // Check if the branch exists locally using real OSTree manager
let exists_locally = self.check_branch_exists(&ostree_branch).await?; let exists_locally = self.check_branch_exists(&ostree_branch).await?;
let resolved = ResolvedBaseImage { let resolved = ResolvedBaseImage {
@ -127,13 +129,25 @@ impl ComposeManager {
Ok(branch) Ok(branch)
} }
/// Check if an OSTree branch exists locally /// Check if an OSTree branch exists locally using real OSTree manager
async fn check_branch_exists(&self, _branch: &str) -> AptOstreeResult<bool> { async fn check_branch_exists(&self, branch: &str) -> AptOstreeResult<bool> {
// TODO: Implement real OSTree branch checking info!("Checking if OSTree branch exists: {}", branch);
// For now, return false to indicate we need to pull from registry
warn!("OSTree branch existence checking not yet implemented"); // Use the existing OSTree manager to check branch existence
match self.ostree_manager.list_branches() {
Ok(branches) => {
info!("Available branches: {:?}", branches);
let exists = branches.contains(&branch.to_string());
info!("Branch {} exists locally: {}", branch, exists);
Ok(exists)
},
Err(e) => {
warn!("Failed to check branch existence: {}", e);
// If we can't check, assume it doesn't exist
Ok(false) Ok(false)
} }
}
}
/// Create a new deployment from a base image /// Create a new deployment from a base image
pub async fn create_deployment(&self, options: &ComposeOptions) -> AptOstreeResult<String> { pub async fn create_deployment(&self, options: &ComposeOptions) -> AptOstreeResult<String> {

View file

@ -1,12 +1,19 @@
//! Simplified OSTree-like repository manager for apt-ostree //! Simplified OSTree-like repository manager for apt-ostree
use tracing::{info}; use tracing::{info, warn};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fs; use std::fs;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use tokio::process::Command; use tokio::process::Command;
use regex::Regex;
use lazy_static::lazy_static;
use crate::error::{AptOstreeError, AptOstreeResult}; use crate::error::{AptOstreeError, AptOstreeResult};
// Lazily initialize the regex to compile it only once
lazy_static! {
static ref BRANCH_NAME_RE: Regex = Regex::new(r"^([^_]+)_([^_]+)_(.*)$").unwrap();
}
/// Simplified OSTree-like repository manager /// Simplified OSTree-like repository manager
pub struct OstreeManager { pub struct OstreeManager {
repo_path: PathBuf, repo_path: PathBuf,
@ -198,8 +205,24 @@ impl OstreeManager {
for entry in fs::read_dir(&refs_dir)? { for entry in fs::read_dir(&refs_dir)? {
let entry = entry?; let entry = entry?;
if entry.file_type()?.is_file() { if entry.file_type()?.is_file() {
let name = entry.file_name().to_string_lossy().replace("_", "/"); let name = entry.file_name().to_string_lossy().to_string();
branches.push(name); info!("DEBUG: Original name: '{}'", name);
// Use regex to properly parse distribution_version_architecture pattern
let converted_name = if let Some(captures) = BRANCH_NAME_RE.captures(&name) {
let distribution = captures.get(1).unwrap().as_str();
let version = captures.get(2).unwrap().as_str();
let architecture = captures.get(3).unwrap().as_str(); // This correctly preserves "x86_64"
format!("{}/{}/{}", distribution, version, architecture)
} else {
// Handle cases where the branch name doesn't match the expected pattern
warn!("Branch name '{}' does not match expected pattern, returning as-is", name);
name
};
info!("DEBUG: Final converted name: '{}'", converted_name);
branches.push(converted_name);
} }
} }