# Module: Installer Metadata Analysis # Purpose: Analyzes distribution structure, components, versions, and installation requirements # Dependencies: None (standalone utilities) # Extract distribution archive for analysis export def extract_distribution_for_analysis [dist_path: string, installer_config: record] { let temp_dir = ($installer_config.output_dir | path join "tmp" "analysis") mkdir $temp_dir let dist_name = ($dist_path | path basename) if ($dist_name | str ends-with ".tar.gz") or ($dist_name | str ends-with ".tgz") { cd $temp_dir tar -xzf $dist_path } else if ($dist_name | str ends-with ".zip") { cd $temp_dir unzip $dist_path } else { return { status: "error", reason: $"Unsupported archive format: ($dist_name)" } } # Find the extracted directory (usually a single top-level directory) let extracted_contents = (ls $temp_dir) if ($extracted_contents | length) == 1 and (($extracted_contents | get 0.type) == "dir") { return ($extracted_contents | get 0.name) } else { return $temp_dir } } # Analyze distribution components export def analyze_distribution_components [analysis_path: string] { let components = { has_platform: (($analysis_path | path join "platform") | path exists) has_core: (($analysis_path | path join "core") | path exists) has_config: (($analysis_path | path join "config") | path exists) has_docs: (($analysis_path | path join "docs") | path exists) has_services: (($analysis_path | path join "services") | path exists) } # Find executables let executables = if $components.has_platform { ls ($analysis_path | path join "platform") | where type == file | get name } else if $components.has_core and (($analysis_path | path join "core" "bin") | path exists) { ls ($analysis_path | path join "core" "bin") | where type == file | get name } else { [] } # Find configuration files let config_files = if $components.has_config { ls -la ($analysis_path | path join "config") | where name =~ "\\.(toml|yaml|json)$" | get name } else { [] } # Find service definitions let service_files = if $components.has_services { ls -la ($analysis_path | path join "services") | where name =~ "\\.(service|yml|yaml)$" | get name } else { [] } let components = ($components | insert executables $executables | insert config_files $config_files | insert service_files $service_files | insert total_size (get_directory_size $analysis_path)) return $components } # Detect distribution version export def detect_distribution_version [analysis_path: string] { # Try to find version from metadata let metadata_files = [ ($analysis_path | path join "core-metadata.json") ($analysis_path | path join "platform-metadata.json") ($analysis_path | path join "metadata.json") ($analysis_path | path join "VERSION") ] for metadata_file in $metadata_files { if ($metadata_file | path exists) { let version = if ($metadata_file | str ends-with ".json") { let data = (open $metadata_file) $data.version? | default "unknown" } else { open $metadata_file --raw | str trim } if $version != "unknown" { return { version: $version, source: ($metadata_file | path basename) } } } } # Fallback: try to extract from directory name let dir_name = ($analysis_path | path basename) let version_match = ($dir_name | parse --regex ".*-([0-9]+\\.[0-9]+\\.[0-9]+)") if ($version_match | length) > 0 { return { version: ($version_match | get 0.capture0), source: "directory_name" } } return { version: "unknown", source: "none" } } # Analyze installation requirements export def analyze_installation_requirements [analysis_path: string, components: record] { mut requirements = { system_user: "provisioning" system_group: "provisioning" install_dirs: [] config_dirs: [] data_dirs: [] log_dirs: [] service_dependencies: [] port_requirements: [] } # Standard installation directories if $components.has_platform or ($components.executables | length) > 0 { $requirements.install_dirs = ($requirements.install_dirs | append "/usr/local/bin") } if $components.has_core { $requirements.install_dirs = ($requirements.install_dirs | append "/usr/local/lib/provisioning") } if $components.has_config { $requirements.config_dirs = ($requirements.config_dirs | append "/etc/provisioning") } # Data and log directories $requirements.data_dirs = ($requirements.data_dirs | append "/var/lib/provisioning") $requirements.log_dirs = ($requirements.log_dirs | append "/var/log/provisioning") # Service dependencies (would analyze service files to determine) if $components.has_services { $requirements.service_dependencies = ($requirements.service_dependencies | append "network.target") } # Port requirements (would analyze configuration to determine) $requirements.port_requirements = ($requirements.port_requirements | append { port: 8080, description: "Main API" }) return $requirements } # Get directory size helper def get_directory_size [dir: string] { if not ($dir | path exists) { return 0 } glob $"($dir)/**/*" | each {|file| stat $file | get size } | math sum }