88 lines
2.7 KiB
Go
88 lines
2.7 KiB
Go
// Package blender handles Blender binary management and execution.
|
|
package blender
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"jiggablend/internal/runner/api"
|
|
"jiggablend/internal/runner/workspace"
|
|
)
|
|
|
|
// Manager handles Blender binary downloads and management.
|
|
type Manager struct {
|
|
manager *api.ManagerClient
|
|
workspaceDir string
|
|
}
|
|
|
|
// NewManager creates a new Blender manager.
|
|
func NewManager(managerClient *api.ManagerClient, workspaceDir string) *Manager {
|
|
return &Manager{
|
|
manager: managerClient,
|
|
workspaceDir: workspaceDir,
|
|
}
|
|
}
|
|
|
|
// GetBinaryPath returns the path to the Blender binary for a specific version.
|
|
// Downloads from manager and extracts if not already present.
|
|
func (m *Manager) GetBinaryPath(version string) (string, error) {
|
|
blenderDir := filepath.Join(m.workspaceDir, "blender-versions")
|
|
if err := os.MkdirAll(blenderDir, 0755); err != nil {
|
|
return "", fmt.Errorf("failed to create blender directory: %w", err)
|
|
}
|
|
|
|
// Check if already installed - look for version folder first
|
|
versionDir := filepath.Join(blenderDir, version)
|
|
binaryPath := filepath.Join(versionDir, "blender")
|
|
|
|
// Check if version folder exists and contains the binary
|
|
if versionInfo, err := os.Stat(versionDir); err == nil && versionInfo.IsDir() {
|
|
// Version folder exists, check if binary is present
|
|
if binaryInfo, err := os.Stat(binaryPath); err == nil {
|
|
// Verify it's actually a file (not a directory)
|
|
if !binaryInfo.IsDir() {
|
|
log.Printf("Found existing Blender %s installation at %s", version, binaryPath)
|
|
return binaryPath, nil
|
|
}
|
|
}
|
|
// Version folder exists but binary is missing - might be incomplete installation
|
|
log.Printf("Version folder %s exists but binary not found, will re-download", versionDir)
|
|
}
|
|
|
|
// Download from manager
|
|
log.Printf("Downloading Blender %s from manager", version)
|
|
|
|
reader, err := m.manager.DownloadBlender(version)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer reader.Close()
|
|
|
|
// Manager serves pre-decompressed .tar files - extract directly
|
|
log.Printf("Extracting Blender %s...", version)
|
|
if err := workspace.ExtractTarStripPrefix(reader, versionDir); err != nil {
|
|
return "", fmt.Errorf("failed to extract blender: %w", err)
|
|
}
|
|
|
|
// Verify binary exists
|
|
if _, err := os.Stat(binaryPath); err != nil {
|
|
return "", fmt.Errorf("blender binary not found after extraction")
|
|
}
|
|
|
|
log.Printf("Blender %s installed at %s", version, binaryPath)
|
|
return binaryPath, nil
|
|
}
|
|
|
|
// GetBinaryForJob returns the Blender binary path for a job.
|
|
// Uses the version from metadata or falls back to system blender.
|
|
func (m *Manager) GetBinaryForJob(version string) (string, error) {
|
|
if version == "" {
|
|
return "blender", nil // System blender
|
|
}
|
|
|
|
return m.GetBinaryPath(version)
|
|
}
|
|
|