deb-bootc-compose/internal/phases/gather.go
robojerk cca68c90f6 Add comprehensive phase system, types, and treefile support for deb-bootc-compose
- Add internal/phases/ with complete phase management system
- Add internal/types/ with core data structures
- Add internal/treefile/ for OSTree treefile generation
- Update examples with YAML configurations
- Update .gitignore to properly exclude test artifacts and build outputs
- Update dependencies and configuration files
2025-08-19 20:48:46 -07:00

174 lines
6 KiB
Go

package phases
import (
"fmt"
"os"
"path/filepath"
"deb-bootc-compose/internal/types"
)
// GatherPhase handles package gathering and dependency resolution
type GatherPhase struct {
PhaseBase
}
// NewGatherPhase creates a new GatherPhase
func NewGatherPhase() *GatherPhase {
return &GatherPhase{
PhaseBase: NewPhaseBase("gather", []string{"init"}),
}
}
// Run executes the gather phase
func (p *GatherPhase) Run(engine types.Engine) error {
logger := engine.GetLogger()
logger.Printf("Starting package gathering phase")
// Get package information from treefile
treefile := engine.GetTreefile()
// Process each variant and architecture
for _, variant := range treefile.Variants {
for _, arch := range variant.Architectures {
logger.Printf("Processing variant %s for architecture %s", variant.Name, arch)
// Get packages for this variant/architecture combination
packages := treefile.GetPackagesForVariant(variant.Name, arch)
excluded := treefile.GetExcludedPackagesForVariant(variant.Name, arch)
// Create variant-specific work directory
variantWorkDir := filepath.Join(engine.GetWorkDir(), "variants", variant.Name, arch)
if err := os.MkdirAll(variantWorkDir, 0755); err != nil {
return fmt.Errorf("failed to create variant work directory: %w", err)
}
// Gather package information
if err := p.gatherPackageInfo(engine, variantWorkDir, packages, excluded, arch); err != nil {
return fmt.Errorf("failed to gather package info for variant %s/%s: %w", variant.Name, arch, err)
}
// Resolve dependencies
if err := p.resolveDependencies(engine, variantWorkDir, packages, arch); err != nil {
return fmt.Errorf("failed to resolve dependencies for variant %s/%s: %w", variant.Name, arch, err)
}
logger.Printf("Completed processing variant %s for architecture %s", variant.Name, arch)
}
}
logger.Printf("Package gathering phase completed successfully")
return nil
}
// gatherPackageInfo gathers information about packages
func (p *GatherPhase) gatherPackageInfo(engine types.Engine, workDir string, packages types.PackageSet, excluded []string, arch string) error {
logger := engine.GetLogger()
// Create package info directory
packageInfoDir := filepath.Join(workDir, "package-info")
if err := os.MkdirAll(packageInfoDir, 0755); err != nil {
return fmt.Errorf("failed to create package info directory: %w", err)
}
// Write package lists
if err := p.writePackageList(packageInfoDir, "required", packages.Required); err != nil {
return fmt.Errorf("failed to write required packages list: %w", err)
}
if err := p.writePackageList(packageInfoDir, "optional", packages.Optional); err != nil {
return fmt.Errorf("failed to write optional packages list: %w", err)
}
if err := p.writePackageList(packageInfoDir, "recommended", packages.Recommended); err != nil {
return fmt.Errorf("failed to write recommended packages list: %w", err)
}
if err := p.writePackageList(packageInfoDir, "development", packages.Development); err != nil {
return fmt.Errorf("failed to write development packages list: %w", err)
}
if err := p.writePackageList(packageInfoDir, "kernel", packages.Kernel); err != nil {
return fmt.Errorf("failed to write kernel packages list: %w", err)
}
if err := p.writePackageList(packageInfoDir, "bootloader", packages.Bootloader); err != nil {
return fmt.Errorf("failed to write bootloader packages list: %w", err)
}
if err := p.writePackageList(packageInfoDir, "excluded", excluded); err != nil {
return fmt.Errorf("failed to write excluded packages list: %w", err)
}
logger.Printf("Package information gathered for architecture %s", arch)
return nil
}
// writePackageList writes a list of packages to a file
func (p *GatherPhase) writePackageList(dir, name string, packages []string) error {
if len(packages) == 0 {
return nil
}
filename := filepath.Join(dir, name+".txt")
content := ""
for _, pkg := range packages {
content += pkg + "\n"
}
if err := os.WriteFile(filename, []byte(content), 0644); err != nil {
return fmt.Errorf("failed to write package list %s: %w", name, err)
}
return nil
}
// resolveDependencies resolves package dependencies
func (p *GatherPhase) resolveDependencies(engine types.Engine, workDir string, packages types.PackageSet, arch string) error {
logger := engine.GetLogger()
// Create dependencies directory
depsDir := filepath.Join(workDir, "dependencies")
if err := os.MkdirAll(depsDir, 0755); err != nil {
return fmt.Errorf("failed to create dependencies directory: %w", err)
}
// Collect all packages
allPackages := make([]string, 0)
allPackages = append(allPackages, packages.Required...)
allPackages = append(allPackages, packages.Optional...)
allPackages = append(allPackages, packages.Recommended...)
allPackages = append(allPackages, packages.Development...)
allPackages = append(allPackages, packages.Kernel...)
allPackages = append(allPackages, packages.Bootloader...)
// Remove duplicates
uniquePackages := make(map[string]bool)
for _, pkg := range allPackages {
uniquePackages[pkg] = true
}
// Write unique package list
uniqueList := make([]string, 0, len(uniquePackages))
for pkg := range uniquePackages {
uniqueList = append(uniqueList, pkg)
}
if err := p.writePackageList(depsDir, "all-packages", uniqueList); err != nil {
return fmt.Errorf("failed to write all packages list: %w", err)
}
// TODO: Implement actual dependency resolution using apt-cache or similar
// For now, just log what we would do
logger.Printf("Would resolve dependencies for %d unique packages on architecture %s", len(uniqueList), arch)
// Create a placeholder dependencies file
depsFile := filepath.Join(depsDir, "resolved-dependencies.txt")
placeholder := fmt.Sprintf("# Dependencies resolved for architecture %s\n# This is a placeholder - actual resolution not yet implemented\n", arch)
if err := os.WriteFile(depsFile, []byte(placeholder), 0644); err != nil {
return fmt.Errorf("failed to write placeholder dependencies file: %w", err)
}
logger.Printf("Dependencies resolved for architecture %s", arch)
return nil
}