qvm/internal/config/paths.go

125 lines
3.8 KiB
Go

// Package config handles QVM configuration loading and management.
package config
import (
"os"
"path/filepath"
)
// XDG-compliant directory paths matching bash lib/common.sh exactly
var (
// DataDir is the base directory for QVM data files (base image, runner)
// Defaults to $HOME/.local/share/qvm
DataDir = getXDGPath("XDG_DATA_HOME", ".local/share", "qvm")
// StateDir is the directory for QVM runtime state (overlay, PID, port files)
// Defaults to $HOME/.local/state/qvm
StateDir = getXDGPath("XDG_STATE_HOME", ".local/state", "qvm")
// CacheDir is the directory for shared build caches (cargo, pnpm, sccache)
// Defaults to $HOME/.cache/qvm
CacheDir = getXDGPath("XDG_CACHE_HOME", ".cache", "qvm")
// ConfigDir is the directory for QVM configuration (flake, qvm.toml)
// Defaults to $HOME/.config/qvm
ConfigDir = getXDGPath("XDG_CONFIG_HOME", ".config", "qvm")
)
// Path constants for VM artifacts
var (
// BaseImage is the path to the base VM image (read-only)
BaseImage = filepath.Join(DataDir, "base.qcow2")
// VMRunner is the path to the VM runner script
VMRunner = filepath.Join(DataDir, "run-vm")
// Overlay is the path to the VM overlay image (copy-on-write)
Overlay = filepath.Join(StateDir, "qvm-dev.qcow2")
// PIDFile is the path to the VM process ID file
PIDFile = filepath.Join(StateDir, "vm.pid")
// SSHPortFile is the path to the SSH port file
SSHPortFile = filepath.Join(StateDir, "ssh.port")
// SerialLog is the path to the VM serial console log
SerialLog = filepath.Join(StateDir, "serial.log")
// WorkspacesFile is the path to the workspaces registry JSON
WorkspacesFile = filepath.Join(StateDir, "workspaces.json")
// QMPSocket is the path to the QMP (QEMU Machine Protocol) socket
QMPSocket = filepath.Join(StateDir, "qmp.sock")
// UserFlake is the path to the user's customizable NixOS flake
UserFlake = filepath.Join(ConfigDir, "flake")
// ConfigFile is the path to the QVM TOML configuration file
ConfigFile = filepath.Join(ConfigDir, "qvm.toml")
)
// Cache directories for 9p mounts (shared between host and VM)
var (
// CargoHome is the shared Cargo registry/cache directory
CargoHome = filepath.Join(CacheDir, "cargo-home")
// CargoTarget is the shared Cargo build artifacts directory
CargoTarget = filepath.Join(CacheDir, "cargo-target")
// PnpmStore is the shared pnpm content-addressable store
PnpmStore = filepath.Join(CacheDir, "pnpm-store")
// Sccache is the shared sccache compilation cache
Sccache = filepath.Join(CacheDir, "sccache")
)
// Host config directories to mount in VM (read-write for tools that need it)
var (
// HostOpencodeConfig is the path to the host's opencode configuration
// Defaults to $HOME/.config/opencode
HostOpencodeConfig = getXDGPath("XDG_CONFIG_HOME", ".config", "opencode")
)
// getXDGPath returns an XDG-compliant path with fallback.
// Args:
// - xdgEnv: XDG environment variable to check (e.g., "XDG_DATA_HOME")
// - fallbackPath: relative path from $HOME if xdgEnv is not set (e.g., ".local/share")
// - suffix: additional path suffix to append (e.g., "qvm")
//
// Returns the resolved absolute path.
func getXDGPath(xdgEnv, fallbackPath, suffix string) string {
base := os.Getenv(xdgEnv)
if base == "" {
home := os.Getenv("HOME")
if home == "" {
// Fallback to current directory if HOME is not set
home = "."
}
base = filepath.Join(home, fallbackPath)
}
return filepath.Join(base, suffix)
}
// EnsureDirs creates all required QVM directories if they don't exist.
// Returns error if directory creation fails.
func EnsureDirs() error {
dirs := []string{
DataDir,
StateDir,
CacheDir,
ConfigDir,
CargoHome,
CargoTarget,
PnpmStore,
Sccache,
}
for _, dir := range dirs {
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
}
return nil
}