apt-layer/refactor.md

184 lines
No EOL
6.8 KiB
Markdown

# 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:** `getopt` or `argp` for argument parsing
- **Subcommands:** `create`, `list`, `info`, `export`
- **System calls:** Use `fork`/`exec` (not `system()`) 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-pkg` integration 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-pkg` integration 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:** `syslog` or custom implementation
- **OSTree integration:** `libostree` (avoid shelling out)
### Critical for Phase 2
- **`libapt-pkg`:** **ESSENTIAL** for client-side layering - not just an enhancement
- **`libdpkg`:** Alternative package management interface
- **Container integration:** Shell out to `podman`/`docker` initially
---
## 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
1. **Scaffold CLI:** Parse arguments, print help/version
2. **Implement shell-out logic:** Use `fork`/`exec` for external tool calls
3. **Add config/recipe parsing:** Use library for YAML/JSON
4. **Implement core logic:** Layer creation, listing, info
5. **Replace shell-outs with native code:** Use libraries where possible
6. **Testing:** Write tests for each feature
### Phase 2: End-User Layering (Future)
1. **Integrate `libapt-pkg`:** **CRITICAL** - implement dependency resolution and package operations
2. **Design transactional data structures:** Layer history, rollback info
3. **Implement live system integration:** OSTree admin operations with atomic commits
4. **Add user interaction:** Prompts, confirmations, progress
5. **Implement rollback system:** History tracking and recovery
6. **Add TUI (optional):** Curses-based interface
---
## 8. **Command Structure**
### Build-Time Commands (Phase 1)
```bash
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)
```bash
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-pkg` for 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-get` for 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 `libostree` for direct repo manipulation
- **Use `libapt-pkg` for 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-pkg` integration 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:**
1. Create basic CLI skeleton
2. Implement build-time layer creation
3. Add recipe support
4. **Research and prototype `libapt-pkg` integration**
5. 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