You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.9 KiB
4.9 KiB
Context
Pacman, Arch Linux's package manager, lacks declarative package management and doesn't support partial upgrades. Users managing system packages from scripts or configuration files need a way to ensure their system state matches a declared package list, with all packages at their latest available versions.
Goals / Non-Goals
Goals:
- Provide a declarative interface for pacman package management through command-line interface
- Support flexible input sources (stdin and multiple state files) with additive merging
- Automatically resolve transitive dependencies (users specify only direct packages)
- Enforce full package upgrades (no partial upgrades) to prevent version mismatches
- Generate machine-readable output suitable for automated scripting
- Enable AI-driven implementation for new Go developers
Non-Goals:
- Package dependency resolution or smart upgrade scheduling
- Transaction rollback capabilities
- Pretty terminal output or interactive prompts
- Support for partial upgrades or selective package versions
- State persistence (tool only syncs, doesn't save state)
Decisions
Language: Go
- Rationale: User wants modern CLI tool with native package management capabilities
- Go provides strong standard library, easy command-line parsing, and excellent for system-level operations
- User unfamiliar with Go - implementation will be AI-driven with detailed documentation
Input Parsing Approach
- Parse whitespace, tabs, newlines for package names
- Support multiple --state files: all additive including with stdin
- Validate package names against pacman available packages (optional validation)
- Empty state detection: print error to stderr and exit with code 1 (abort)
State Merging Logic
- All inputs are additive: combine all packages from stdin and all state files
- No conflict resolution: missing packages are added, duplicates accumulate
- Order-independent: inputs don't override each other
Pacman Interaction
- Use os/exec.Command to run pacman with -Sy (sync databases) and -S flag
- Run pacman -Syu with all target packages to ensure full upgrade
- Capture stderr/stdout for error reporting and machine output
- Detect pacman exit codes and translate to tool exit codes
Error Handling Strategy
- Parse pacman error messages from stderr output
- Distinguish between package-not-found (warning) vs. execution failures (errors)
- Return appropriate exit codes: 0 for success, non-zero for errors
- Include error details in output for scripting purposes
AUR Integration
- For packages not found in pacman repositories, check if available in AUR
- Use makepkg directly to build and install AUR packages (no AUR helpers)
- Clone AUR git repo to temp directory
- Run
makepkg -siin temp directory for installation - Capture stdout/stderr for output and error handling
- Report error to stderr if package not found in pacman or AUR
Dependency Resolution
- Use pacman's dependency resolution by passing all declared packages to
pacman -Syu - Pacman automatically resolves and includes transitive dependencies
- For AUR packages, makepkg handles dependency resolution during build
- No custom dependency resolution logic required - delegate to pacman/makepkg
Explicit Marking & Orphan Cleanup
- Before syncing, get list of all currently installed packages
- Mark declared state packages as explicitly installed via
pacman -D --explicit <pkg> - All other installed packages remain as non-explicit (dependencies)
- After sync completes, run
pacman -Rns $(pacman -Qdtq)to remove orphaned packages - Pacman -Rns $(pacman -Qdtq) only removes packages that are not explicitly installed and not required
- Capture and report number of packages removed during cleanup
Package Version Management
- Always force full system upgrade via
pacman -Syu <packages> - Pacman handles version selection automatically, ensuring latest versions
- No semantic version comparison or pinning logic required
Risks / Trade-offs
Known Risks:
- [User unfamiliarity with Go] → Mitigation: Provide complete implementation with detailed comments; user can review and run without understanding deeply
- [Pacman error message parsing complexity] → Mitigation: Use broad error pattern matching; include error output as-is for debugging
- [Empty state triggers abort] → Mitigation: Print error to stderr and exit with code 1 instead of proceeding with empty state
- [Additive merging could accumulate duplicates] → Mitigation: Accept as design choice; pacman handles duplicates gracefully
- [Dependency conflicts could occur] → Mitigation: Let pacman handle standard conflicts; tool won't implement complex dependency resolution
Trade-offs:
- No conflict resolution: simpler merging but may include packages the system rejects
- Additive vs replacement: safer but less predictable for users expecting replacements
- No user prompts: fully automated for scripting but could be risky without warnings