// 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 }