zsvo/pkg/recipe/recipe.go
itexpert228 e351ee62d1
кал
2026-03-09 22:40:05 +03:00

110 lines
2.9 KiB
Go

package recipe
import (
"fmt"
"io"
"os"
"path/filepath"
"github.com/BurntSushi/toml"
)
// Recipe represents a package recipe
type Recipe struct {
Name string `toml:"name"`
Version string `toml:"version"`
Description string `toml:"description,omitempty"`
Source Source `toml:"source"`
Build Build `toml:"build"`
Package Package `toml:"package"`
Dependencies []string `toml:"dependencies,omitempty"`
Options map[string]bool `toml:"options,omitempty"`
}
// Source represents source information
type Source struct {
URL string `toml:"url"`
Sha256 string `toml:"sha256"`
Patches []string `toml:"patches,omitempty"`
}
// Build represents build configuration
type Build struct {
Commands []string `toml:"commands"`
Env []string `toml:"env,omitempty"`
}
// Package represents package configuration
type Package struct {
Commands []string `toml:"commands"`
}
// ParseRecipe parses a recipe from a TOML file
func ParseRecipe(path string) (*Recipe, error) {
// Validate input path
if path == "" {
return nil, fmt.Errorf("recipe path cannot be empty")
}
// Clean and normalize path
path = filepath.Clean(path)
file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("failed to open recipe file %s: %w", path, err)
}
defer file.Close()
return ParseRecipeFromReader(file)
}
// ParseRecipeFromReader parses a recipe from an io.Reader
func ParseRecipeFromReader(r io.Reader) (*Recipe, error) {
var recipe Recipe
if _, err := toml.NewDecoder(r).Decode(&recipe); err != nil {
return nil, fmt.Errorf("failed to parse recipe: %w", err)
}
if recipe.Name == "" {
return nil, fmt.Errorf("recipe must have a name")
}
if recipe.Version == "" {
return nil, fmt.Errorf("recipe must have a version")
}
if recipe.Source.URL == "" {
return nil, fmt.Errorf("recipe must have a source URL")
}
if recipe.Source.Sha256 == "" {
return nil, fmt.Errorf("recipe must have a source SHA256 checksum")
}
if len(recipe.Build.Commands) == 0 {
return nil, fmt.Errorf("recipe must have build commands")
}
return &recipe, nil
}
// GetPackageName returns the package name in format name-version
func (r *Recipe) GetPackageName() string {
return fmt.Sprintf("%s-%s", r.Name, r.Version)
}
// GetPackageFileName returns the package file name
func (r *Recipe) GetPackageFileName() string {
return fmt.Sprintf("%s.pkg.tar.zst", r.GetPackageName())
}
// GetPackageDir returns the package directory path
func (r *Recipe) GetPackageDir(baseDir string) string {
return filepath.Join(baseDir, "packages", r.GetPackageName())
}
// GetSourceDir returns the source directory path
func (r *Recipe) GetSourceDir(baseDir string) string {
return filepath.Join(baseDir, "sources", r.GetPackageName())
}
// GetStagingDir returns the staging directory path
func (r *Recipe) GetStagingDir(baseDir string) string {
return filepath.Join(baseDir, "staging", r.GetPackageName())
}