6.8 KiB
6.8 KiB
apt-layer C Refactor Plan
If you want to turn apt-layer.sh into a C binary, here's a practical, staged approach:
1. Clarify the Scope
- Current: Build-time tool for adding packages during image creation (not live/transactional)
- Future: End-user transactional package layering (like
rpm-ostree install) - Platforms: Linux only initially, Debian/Ubuntu-specific due to apt integration
- Note: Deep apt integration makes portability to other package managers a major rewrite
2. Current Shell Script Analysis
- OSTree repo management: Creating commits, managing branches
- Package installation: Using apt/apt-get in chroot/container
- Container integration: Podman/Docker for isolated builds
- Recipe parsing: YAML/JSON layer definitions
- Logging and error handling: Progress reporting and failure recovery
Break down into:
- Shell glue (calling external tools)
- Logic (parsing, validation, error handling)
- User interaction (progress reporting, prompts)
3. Design the C Program
Phase 1: Build-Time Tool (MVP)
- CLI interface:
getoptorargpfor argument parsing - Subcommands:
create,list,info,export - System calls: Use
fork/exec(notsystem()) for better control and security - Logging: Simple file logging or syslog
- Config/Recipes: YAML/JSON parser library
Phase 2: End-User Layering (Future)
- Transactional commands:
install,remove,rollback,status - Live system integration: OSTree admin/deploy operations with atomic commits
- User session handling: Prompts, reboots, error recovery
- History management: Layer tracking and rollback support
- Critical: Deep
libapt-pkgintegration for reliable package management
4. Incremental Porting Strategy
- MVP: C program that wraps shell logic (calls
ostree,apt, etc.) - Refactor: Gradually replace shell-outs with native C code
- Testing: Ensure C binary produces same results as shell script
- Transition: Keep shell script as fallback during development
- Phase 2 Prerequisite:
libapt-pkgintegration before attempting live layering
5. Libraries to Consider
Essential Libraries
- Argument parsing:
argp,getopt_long - YAML/JSON parsing:
libyaml,jansson - Process management:
fork,execvp,popen - Logging:
syslogor custom implementation - OSTree integration:
libostree(avoid shelling out)
Critical for Phase 2
libapt-pkg: ESSENTIAL for client-side layering - not just an enhancementlibdpkg: Alternative package management interface- Container integration: Shell out to
podman/dockerinitially
6. Project Structure
apt-layer/
├── src/
│ ├── main.c # Entry point, CLI parsing
│ ├── cli.c / cli.h # Command line interface
│ ├── layer.c / layer.h # Layer creation logic
│ ├── ostree.c / ostree.h # OSTree operations
│ ├── apt.c / apt.h # Package management (shell-out initially)
│ ├── apt_pkg.c / apt_pkg.h # libapt-pkg integration (Phase 2)
│ ├── config.c / config.h # Configuration/recipe parsing
│ ├── log.c / log.h # Logging system
│ ├── container.c / container.h # Container integration
│ └── transaction.c / transaction.h # Transactional operations (Phase 2)
├── include/
├── tests/
├── Makefile
├── README.md
└── LICENSE
7. Development Steps
Phase 1: Build-Time Tool
- Scaffold CLI: Parse arguments, print help/version
- Implement shell-out logic: Use
fork/execfor external tool calls - Add config/recipe parsing: Use library for YAML/JSON
- Implement core logic: Layer creation, listing, info
- Replace shell-outs with native code: Use libraries where possible
- Testing: Write tests for each feature
Phase 2: End-User Layering (Future)
- Integrate
libapt-pkg: CRITICAL - implement dependency resolution and package operations - Design transactional data structures: Layer history, rollback info
- Implement live system integration: OSTree admin operations with atomic commits
- Add user interaction: Prompts, confirmations, progress
- Implement rollback system: History tracking and recovery
- Add TUI (optional): Curses-based interface
8. Command Structure
Build-Time Commands (Phase 1)
apt-layer create <base-branch> <new-branch> [packages...]
apt-layer list [branch-pattern]
apt-layer info <branch>
apt-layer export <branch> <image-name>
apt-layer --recipe <file>
End-User Commands (Phase 2)
apt-layer install <packages...>
apt-layer remove <packages...>
apt-layer rollback [commit]
apt-layer status
apt-layer history
9. Critical Technical Challenges
Phase 2 Complexity
- Atomic Operations: Ensuring package installation and OSTree commit happen atomically
- Dependency Resolution: Using
libapt-pkgfor reliable dependency handling - State Management: Tracking package state across OSTree commits
- Failure Recovery: Handling failed installations without breaking the system
- Performance: Making client-side operations fast enough for interactive use
libapt-pkg Integration
- Not Optional: Shelling out to
apt-getfor client-side layering will be brittle and slow - Complexity: Direct integration with apt's internals is challenging but necessary
- Benefits: Reliable dependency resolution, state management, and immutability guarantees
10. Long-Term Enhancements
- Use
libostreefor direct repo manipulation - Use
libapt-pkgfor package management (Phase 2 requirement) - Add TUI with
ncurses - Add parallelism and better error handling
- Support for remote repositories
- Layer signing and verification
11. Transitional Strategy
- Keep shell script as fallback for unimplemented features
- Gradually phase out shell script as C code matures
- Maintain compatibility with existing build systems
- Test both build-time and user-time scenarios
- Phase 2 milestone: Must have
libapt-pkgintegration before attempting live layering
Summary:
Start with build-time tool in C, then incrementally add end-user layering features. The integration with libapt-pkg is critical for Phase 2 success - it's not just an enhancement but a fundamental requirement for achieving true rpm-ostree-like behavior.
Next Steps:
- Create basic CLI skeleton
- Implement build-time layer creation
- Add recipe support
- Research and prototype
libapt-pkgintegration - Prepare for transactional layering
Success Criteria:
- Phase 1: C binary that replicates current shell script functionality
- Phase 2: Reliable client-side package layering with atomic operations and rollback support