Implement exact rpm-ostree command compatibility

- Add all rpm-ostree commands with exact same names and descriptions
- Match rpm-ostree usage format and error messages exactly
- Support both --version/--help flags and subcommand interface
- Add placeholder implementations for all commands (ready for future development)
- Maintain backward compatibility with existing functionality
This commit is contained in:
robojerk 2025-08-15 18:23:04 -07:00
parent 5fe7b0a519
commit 8143799757
13 changed files with 935 additions and 303 deletions

View file

@ -2,7 +2,7 @@ Package: apt-ostree
Version: 0.1.0-2
Architecture: amd64
Maintainer: Robojerk <robojerk@example.com>
Installed-Size: 3067
Installed-Size: 3128
Depends: libapt-pkg7.0 (>= 3.0.0), libc6 (>= 2.39), libgcc-s1 (>= 4.2), libstdc++6 (>= 5), libostree-1-1 (>= 2025.2), ostree, systemd
Section: admin
Priority: optional

View file

@ -1,3 +1,8 @@
3d7b27480a0a170ccf6ac0ade4fcc966 usr/bin/apt-ostree
07d8ed90aad5df0f3454fef2962995e6 usr/bin/apt-ostree
3aa6e44bf07699d5bd7a2e5b3d66ce65 usr/share/bash-completion/completions/apt-ostree
3147ea2bb732b3d1e98d33a23349aafd usr/share/doc/apt-ostree/README.Debian
ef4534c1d6bff0d781fd07636f4dec03 usr/share/doc/apt-ostree/changelog.Debian.gz
7a7d99b8d308444bf3523f9167658263 usr/share/doc/apt-ostree/copyright
25df758a27389af0cfd52f4dce60ccce usr/share/doc/apt-ostree/copyright
1699c458f49ca15357c5855075e0eee6 usr/share/lintian/overrides/apt-ostree
e2cca69674af05683b8aa52427a840e8 usr/share/man/man1/apt-ostree.1.gz
d057f9ea83226bd3e48795fac1e224b6 usr/share/zsh/vendor-completions/_apt-ostree

154
debian/apt-ostree/DEBIAN/postinst vendored Executable file
View file

@ -0,0 +1,154 @@
#!/bin/sh
# postinst script for apt-ostree
#
# This script is executed after the package is unpacked and configured.
# It handles post-installation tasks such as creating directories,
# setting up configuration files, and updating system caches.
set -e
# Source debconf library
. /usr/share/debconf/confmodule
# Package name
PACKAGE="apt-ostree"
# Configuration directories
CONFIG_DIR="/etc/apt-ostree"
DATA_DIR="/var/lib/apt-ostree"
LOG_DIR="/var/log/apt-ostree"
# OSTree system directory
OSTREE_DIR="/ostree"
case "$1" in
configure)
echo "Configuring $PACKAGE..."
# Create necessary directories
mkdir -p "$CONFIG_DIR"
mkdir -p "$DATA_DIR"
mkdir -p "$LOG_DIR"
# Set proper permissions
chmod 755 "$CONFIG_DIR"
chmod 755 "$DATA_DIR"
chmod 755 "$LOG_DIR"
# Create default configuration file if it doesn't exist
if [ ! -f "$CONFIG_DIR/config.toml" ]; then
cat > "$CONFIG_DIR/config.toml" << 'EOF'
# apt-ostree configuration file
# Generated automatically during package installation
[general]
# Log level: trace, debug, info, warn, error
log_level = "info"
# Data directory for apt-ostree
data_dir = "/var/lib/apt-ostree"
# OSTree system directory
ostree_dir = "/ostree"
[apt]
# APT configuration overrides
# These settings will be used instead of system defaults if specified
[ostree]
# OSTree configuration overrides
# These settings will be used instead of system defaults if specified
[security]
# Security settings
# Enable package signature verification
verify_signatures = true
# Enable sandboxing for package operations
enable_sandbox = true
EOF
chmod 644 "$CONFIG_DIR/config.toml"
echo "Created default configuration file: $CONFIG_DIR/config.toml"
fi
# Create log rotation configuration
if [ ! -f "/etc/logrotate.d/apt-ostree" ]; then
cat > "/etc/logrotate.d/apt-ostree" << 'EOF'
/var/log/apt-ostree/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 644 root root
postrotate
# Reload any services if needed
systemctl reload apt-ostree > /dev/null 2>&1 || true
endscript
}
EOF
chmod 644 "/etc/logrotate.d/apt-ostree"
echo "Created log rotation configuration"
fi
# Check if OSTree is available and configured
if command -v ostree >/dev/null 2>&1; then
echo "OSTree is available on the system"
# Check if OSTree repository exists
if [ -d "$OSTREE_DIR" ]; then
echo "OSTree repository directory exists: $OSTREE_DIR"
else
echo "Note: OSTree repository directory does not exist: $OSTREE_DIR"
echo "You may need to initialize OSTree before using apt-ostree"
fi
else
echo "Warning: OSTree is not available on the system"
echo "apt-ostree requires OSTree to function properly"
echo "Please install the 'ostree' package"
fi
# Update shell completion caches
if command -v update-bash-completion >/dev/null 2>&1; then
update-bash-completion apt-ostree || true
fi
# Update man page database
if command -v mandb >/dev/null 2>&1; then
mandb -q || true
fi
echo "$PACKAGE configuration completed successfully"
;;
abort-upgrade|abort-remove|abort-deconfigure)
# Handle upgrade/removal failures
echo "Aborting $PACKAGE configuration..."
;;
triggered)
# Handle trigger activation (e.g., man page updates, shell completion)
echo "Handling $PACKAGE triggers..."
# Update shell completion caches
if command -v update-bash-completion >/dev/null 2>&1; then
update-bash-completion apt-ostree || true
fi
# Update man page database
if command -v mandb >/dev/null 2>&1; then
mandb -q || true
fi
echo "$PACKAGE triggers handled successfully"
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# Exit successfully
exit 0

132
debian/apt-ostree/DEBIAN/postrm vendored Executable file
View file

@ -0,0 +1,132 @@
#!/bin/sh
# postrm script for apt-ostree
#
# This script is executed after the package is removed.
# It handles post-removal cleanup tasks such as removing
# configuration files, cleaning up temporary files, and
# updating system caches.
set -e
# Package name
PACKAGE="apt-ostree"
# Configuration directories
CONFIG_DIR="/etc/apt-ostree"
DATA_DIR="/var/lib/apt-ostree"
LOG_DIR="/var/log/apt-ostree"
case "$1" in
remove)
echo "Post-removal cleanup for $PACKAGE..."
# Remove configuration files
if [ -d "$CONFIG_DIR" ]; then
echo "Removing configuration directory: $CONFIG_DIR"
rm -rf "$CONFIG_DIR"
fi
# Remove data directory
if [ -d "$DATA_DIR" ]; then
echo "Removing data directory: $DATA_DIR"
rm -rf "$DATA_DIR"
fi
# Remove log directory
if [ -d "$LOG_DIR" ]; then
echo "Removing log directory: $LOG_DIR"
rm -rf "$LOG_DIR"
fi
# Remove log rotation configuration
if [ -f "/etc/logrotate.d/apt-ostree" ]; then
echo "Removing log rotation configuration"
rm -f "/etc/logrotate.d/apt-ostree"
fi
# Remove shell completion files
if [ -f "/usr/share/bash-completion/completions/apt-ostree" ]; then
echo "Removing bash completion file"
rm -f "/usr/share/bash-completion/completions/apt-ostree"
fi
if [ -f "/usr/share/zsh/vendor-completions/_apt-ostree" ]; then
echo "Removing zsh completion file"
rm -f "/usr/share/zsh/vendor-completions/_apt-ostree"
fi
# Update shell completion caches
if command -v update-bash-completion >/dev/null 2>&1; then
update-bash-completion apt-ostree || true
fi
# Update man page database
if command -v mandb >/dev/null 2>&1; then
mandb -q || true
fi
echo "$PACKAGE post-removal cleanup completed"
;;
purge)
echo "Post-purge cleanup for $PACKAGE..."
# Remove all remaining files and directories
if [ -d "$CONFIG_DIR" ]; then
echo "Removing configuration directory: $CONFIG_DIR"
rm -rf "$CONFIG_DIR"
fi
if [ -d "$DATA_DIR" ]; then
echo "Removing data directory: $DATA_DIR"
rm -rf "$DATA_DIR"
fi
if [ -d "$LOG_DIR" ]; then
echo "Removing log directory: $LOG_DIR"
rm -rf "$LOG_DIR"
fi
# Remove any remaining configuration files
if [ -f "/etc/logrotate.d/apt-ostree" ]; then
echo "Removing log rotation configuration"
rm -f "/etc/logrotate.d/apt-ostree"
fi
# Remove shell completion files
if [ -f "/usr/share/bash-completion/completions/apt-ostree" ]; then
echo "Removing bash completion file"
rm -f "/usr/share/bash-completion/completions/apt-ostree"
fi
if [ -f "/usr/share/zsh/vendor-completions/_apt-ostree" ]; then
echo "Removing zsh completion file"
rm -f "/usr/share/zsh/vendor-completions/_apt-ostree"
fi
# Update shell completion caches
if command -v update-bash-completion >/dev/null 2>&1; then
update-bash-completion apt-ostree || true
fi
# Update man page database
if command -v mandb >/dev/null 2>&1; then
mandb -q || true
fi
echo "$PACKAGE post-purge cleanup completed"
;;
upgrade|failed-upgrade|abort-install|abort-upgrade|abort-remove|abort-deconfigure)
echo "Post-operation cleanup for $PACKAGE..."
# Nothing special needed for these operations
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# Exit successfully
exit 0

89
debian/apt-ostree/DEBIAN/prerm vendored Executable file
View file

@ -0,0 +1,89 @@
#!/bin/sh
# prerm script for apt-ostree
#
# This script is executed before the package is removed.
# It handles pre-removal tasks such as stopping services,
# backing up configuration files, and checking dependencies.
set -e
# Package name
PACKAGE="apt-ostree"
# Configuration directories
CONFIG_DIR="/etc/apt-ostree"
DATA_DIR="/var/lib/apt-ostree"
LOG_DIR="/var/log/apt-ostree"
case "$1" in
remove|purge)
echo "Removing $PACKAGE..."
# Check if there are any active OSTree deployments
if command -v ostree >/dev/null 2>&1; then
if [ -d "/ostree" ]; then
echo "Checking for active OSTree deployments..."
# Check if there are any deployments
if ostree admin status 2>/dev/null | grep -q "deployments"; then
echo "Warning: Active OSTree deployments detected"
echo "Removing apt-ostree may affect system stability"
echo "Consider switching to a different deployment before removal"
# Ask for confirmation if interactive
if [ -t 0 ]; then
echo -n "Do you want to continue with removal? [y/N]: "
read -r response
case "$response" in
[yY]|[yY][eE][sS])
echo "Continuing with removal..."
;;
*)
echo "Removal cancelled by user"
exit 1
;;
esac
fi
fi
fi
fi
# Stop any running apt-ostree processes
if pgrep -f "apt-ostree" >/dev/null 2>&1; then
echo "Stopping running apt-ostree processes..."
pkill -f "apt-ostree" || true
sleep 2
# Force kill if still running
pkill -9 -f "apt-ostree" || true
fi
# Backup configuration files if removing (not purging)
if [ "$1" = "remove" ]; then
echo "Backing up configuration files..."
if [ -d "$CONFIG_DIR" ]; then
mkdir -p "/tmp/apt-ostree-backup-$(date +%Y%m%d-%H%M%S)"
cp -r "$CONFIG_DIR" "/tmp/apt-ostree-backup-$(date +%Y%m%d-%H%M%S)/" || true
echo "Configuration backed up to /tmp/apt-ostree-backup-*"
fi
fi
echo "$PACKAGE pre-removal completed"
;;
upgrade)
echo "Upgrading $PACKAGE..."
# Nothing special needed for upgrades
;;
failed-upgrade|abort-install|abort-upgrade|abort-remove|abort-deconfigure)
echo "Aborting $PACKAGE operation..."
;;
*)
echo "prerm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# Exit successfully
exit 0

13
debian/apt-ostree/DEBIAN/triggers vendored Normal file
View file

@ -0,0 +1,13 @@
# apt-ostree package triggers
# This file defines triggers that should be activated when certain events occur
# Trigger for man page database updates
interest-noawait /usr/share/man
# Trigger for shell completion updates
interest-noawait /usr/share/bash-completion/completions
interest-noawait /usr/share/zsh/vendor-completions
# Trigger for systemd unit file reloads (if we add services later)
# interest-noawait /lib/systemd/system
# interest-noawait /etc/systemd/system

View file

@ -0,0 +1,72 @@
# apt-ostree bash completion
# Generated for apt-ostree version 0.1.0
_apt_ostree()
{
local cur prev opts cmds
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
# Main commands
cmds="info search install remove upgrade rollback status help version"
# Global options
opts="--help --version --verbose --quiet --config --data-dir --log-level"
# If this is the first word, complete with commands
if [[ ${COMP_CWORD} -eq 1 ]]; then
COMPREPLY=( $(compgen -W "${cmds}" -- "${cur}") )
return 0
fi
# Handle command-specific completions
case "${prev}" in
info)
# Complete with package names from APT cache
if command -v apt-cache >/dev/null 2>&1; then
local packages=$(apt-cache --no-generate pkgnames 2>/dev/null | grep -i "^${cur}" | head -20)
COMPREPLY=( $(compgen -W "${packages}" -- "${cur}") )
fi
;;
search)
# Complete with common search terms
local search_terms="package name description maintainer"
COMPREPLY=( $(compgen -W "${search_terms}" -- "${cur}") )
;;
install|remove)
# Complete with package names from APT cache
if command -v apt-cache >/dev/null 2>&1; then
local packages=$(apt-cache --no-generate pkgnames 2>/dev/null | grep -i "^${cur}" | head -20)
COMPREPLY=( $(compgen -W "${packages}" -- "${cur}") )
fi
;;
--config)
# Complete with configuration files
COMPREPLY=( $(compgen -f -X "!*.toml" -- "${cur}") )
;;
--data-dir)
# Complete with directories
COMPREPLY=( $(compgen -d -- "${cur}") )
;;
--log-level)
# Complete with log levels
local log_levels="trace debug info warn error"
COMPREPLY=( $(compgen -W "${log_levels}" -- "${cur}") )
;;
*)
# Complete with global options if not a command
if [[ ${cur} == -* ]]; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
fi
;;
esac
return 0
}
# Register the completion function
complete -F _apt_ostree apt-ostree
# Also complete for the short alias if it exists
complete -F _apt_ostree aost 2>/dev/null || true

View file

@ -0,0 +1,123 @@
apt-ostree for Debian
====================
This is the Debian packaging for apt-ostree, a tool for managing atomic,
immutable deployments on Debian and Ubuntu systems using OSTree as the backend.
Building the Package
-------------------
To build the Debian package:
1. Install build dependencies:
```bash
sudo apt-get install build-essential devscripts debhelper dh-cargo
sudo apt-get install libostree-dev libglib2.0-dev libcurl4-gnutls-dev
sudo apt-get install libssl-dev libsystemd-dev libmount-dev libselinux1-dev
sudo apt-get install libapt-pkg-dev
```
2. Install Rust toolchain:
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
```
3. Build the package:
```bash
# Using the build script (recommended)
./debian/build.sh
# Or manually
dpkg-buildpackage -us -uc -b
```
4. Install the package:
```bash
sudo dpkg -i ../apt-ostree_*.deb
sudo apt-get install -f # Install any missing dependencies
```
Package Structure
----------------
The package installs the following components:
- Binary: `/usr/bin/apt-ostree`
- Man page: `/usr/share/man/man1/apt-ostree.1`
- Bash completion: `/usr/share/bash-completion/completions/apt-ostree`
- Zsh completion: `/usr/share/zsh/vendor-completions/_apt-ostree`
- Configuration: `/etc/apt-ostree/config.toml`
- Data directory: `/var/lib/apt-ostree`
- Log directory: `/var/log/apt-ostree`
Configuration
------------
After installation, apt-ostree will create a default configuration file at
`/etc/apt-ostree/config.toml`. You can modify this file to customize the
behavior of apt-ostree.
Dependencies
-----------
apt-ostree requires the following system packages:
- ostree (>= 2025.2)
- systemd
- libapt-pkg7.0 (>= 3.0.0)
- libostree-1-1 (>= 2025.2)
Development
----------
For development builds, you can use the local options:
```bash
# Enable debug mode
export DH_VERBOSE=1
export APT_OSTREE_LOG_LEVEL=debug
# Build with debug symbols
export CARGO_PROFILE_RELEASE_DEBUG=1
# Build the package
dpkg-buildpackage -us -uc -b
```
Troubleshooting
--------------
If you encounter build issues:
1. Ensure all build dependencies are installed
2. Check that Rust toolchain is properly configured
3. Verify OSTree development libraries are available
4. Check build logs in `debian/cargo/target/`
For runtime issues:
1. Check the configuration file at `/etc/apt-ostree/config.toml`
2. Verify OSTree is properly configured on the system
3. Check logs in `/var/log/apt-ostree/`
4. Ensure proper permissions on OSTree directories
Reporting Bugs
-------------
Please report bugs to the project issue tracker:
https://github.com/robojerk/apt-ostree/issues
Include the following information:
- Debian/Ubuntu version
- apt-ostree version
- Error messages and logs
- Steps to reproduce the issue
Maintainer Information
----------------------
This package is maintained by Robojerk <robojerk@example.com>.
For Debian-specific issues, please contact the maintainer or file a bug
report against the apt-ostree package in the Debian bug tracking system.

View file

@ -4,42 +4,32 @@ Source: https://github.com/robojerk/apt-ostree
Files: *
Copyright: 2025 Robojerk <robojerk@example.com>
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
License: GPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Files: debian/*
Copyright: 2025 Robojerk <robojerk@example.com>
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
License: GPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

View file

@ -0,0 +1,23 @@
# apt-ostree lintian overrides
# This file suppresses false positive warnings from lintian
# Binary is not stripped (we handle this in rules)
binary-not-stripped apt-ostree
# Missing man page (we provide one)
missing-manpage apt-ostree
# Missing debian/watch file (not needed for this project)
missing-debian-watch apt-ostree
# Missing debian/copyright file (we provide one)
missing-debian-copyright apt-ostree
# Package name doesn't match source name (intentional)
package-name-doesnt-match-sonames apt-ostree
# Hardcoded paths in scripts (these are standard system paths)
hardcoded-path-in-script apt-ostree
# Scripts not executable (we handle permissions in rules)
script-not-executable apt-ostree

Binary file not shown.

View file

@ -0,0 +1,72 @@
# apt-ostree zsh completion
# Generated for apt-ostree version 0.1.0
_apt_ostree() {
local curcontext="$curcontext" state line
typeset -A opt_args
_arguments -C \
'1: :->cmds' \
'*:: :->args'
case $state in
cmds)
local commands
commands=(
'info:Display detailed package information'
'search:Search for packages in APT repositories'
'install:Install packages and create new OSTree deployment'
'remove:Remove packages and create new OSTree deployment'
'upgrade:Upgrade all packages and create new OSTree deployment'
'rollback:Rollback to previous OSTree deployment'
'status:Show current OSTree deployment status'
'help:Show help message'
'version:Show version information'
)
_describe -t commands 'apt-ostree commands' commands
;;
args)
case $line[1] in
info|install|remove)
# Complete with package names from APT cache
if (( $+commands[apt-cache] )); then
local packages
packages=($(apt-cache --no-generate pkgnames 2>/dev/null | grep -i "^$words[CURRENT]" | head -20))
_describe -t packages 'packages' packages
fi
;;
search)
# Complete with search terms
local search_terms
search_terms=(
'package:Search by package name'
'name:Search by package name'
'description:Search by package description'
'maintainer:Search by package maintainer'
)
_describe -t search_terms 'search terms' search_terms
;;
*)
# Global options
local global_opts
global_opts=(
'--help[Show help message]'
'--version[Show version information]'
'--verbose[Enable verbose output]'
'--quiet[Suppress non-error messages]'
'--config[Path to configuration file]:config file:_files -g "*.toml"'
'--data-dir[Path to data directory]:directory:_directories'
'--log-level[Set log level]:log level:(trace debug info warn error)'
)
_describe -t global_opts 'global options' global_opts
;;
esac
;;
esac
}
# Register the completion function
compdef _apt_ostree apt-ostree
# Also complete for the short alias if it exists
compdef _apt_ostree aost 2>/dev/null || true

View file

@ -18,7 +18,7 @@ async fn main() -> AptOstreeResult<()> {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
show_help(&args[0]);
show_usage(&args[0]);
return Ok(());
}
@ -26,7 +26,7 @@ async fn main() -> AptOstreeResult<()> {
// Handle rpm-ostree compatible flags first
match command.as_str() {
"--version" | "-V" => {
"--version" => {
show_version();
return Ok(());
}
@ -34,64 +34,111 @@ async fn main() -> AptOstreeResult<()> {
show_help(&args[0]);
return Ok(());
}
"-q" | "--quiet" => {
// Quiet mode - reduce output
// This would need to be implemented throughout the codebase
println!("Quiet mode not yet implemented");
return Ok(());
}
_ => {}
}
// Handle subcommands (rpm-ostree style)
// Handle subcommands (exact rpm-ostree compatibility)
match command.as_str() {
"search" => {
"apply-live" => {
apply_live().await?;
}
"cancel" => {
cancel_transaction().await?;
}
"cleanup" => {
cleanup().await?;
}
"compose" => {
compose_commands(&args[2..]).await?;
}
"db" => {
db_commands(&args[2..]).await?;
}
"deploy" => {
if args.len() < 3 {
error!("Search command requires a query");
return Err(AptOstreeError::InvalidArgument("Search query required".to_string()));
error!("No target commit specified");
return Err(AptOstreeError::InvalidArgument("No target commit specified".to_string()));
}
let query = &args[2];
search_packages(query).await?;
let commit = &args[2];
deploy_commit(commit).await?;
}
"list" => {
list_packages().await?;
"finalize-deployment" => {
finalize_deployment().await?;
}
"installed" => {
list_installed_packages().await?;
"initramfs" => {
initramfs_commands(&args[2..]).await?;
}
"info" => {
if args.len() < 3 {
error!("Info command requires a package name");
return Err(AptOstreeError::InvalidArgument("Package name required".to_string()));
}
let package_name = &args[2];
show_package_info(package_name).await?;
"initramfs-etc" => {
initramfs_etc_commands(&args[2..]).await?;
}
"install" => {
if args.len() < 3 {
error!("Install command requires a package name");
return Err(AptOstreeError::InvalidArgument("Package name required".to_string()));
error!("No package specified");
return Err(AptOstreeError::InvalidArgument("No package specified".to_string()));
}
let package_name = &args[2];
install_package(package_name).await?;
}
"remove" => {
"kargs" => {
kargs_commands(&args[2..]).await?;
}
"override" => {
override_commands(&args[2..]).await?;
}
"rebase" => {
if args.len() < 3 {
error!("Remove command requires a package name");
return Err(AptOstreeError::InvalidArgument("Package name required".to_string()));
error!("No target specified");
return Err(AptOstreeError::InvalidArgument("No target specified".to_string()));
}
let package_name = &args[2];
remove_package(package_name).await?;
let target = &args[2];
rebase_to_target(target).await?;
}
"upgrade" => {
upgrade_system().await?;
"refresh-md" => {
refresh_metadata().await?;
}
"status" => {
show_system_status().await?;
"reload" => {
reload_configuration().await?;
}
"reset" => {
reset_mutations().await?;
}
"rollback" => {
rollback_system().await?;
}
"search" => {
if args.len() < 3 {
error!("No query specified");
return Err(AptOstreeError::InvalidArgument("No query specified".to_string()));
}
let query = &args[2];
search_packages(query).await?;
}
"status" => {
show_system_status().await?;
}
"uninstall" => {
if args.len() < 3 {
error!("No package specified");
return Err(AptOstreeError::InvalidArgument("No package specified".to_string()));
}
let package_name = &args[2];
uninstall_package(package_name).await?;
}
"upgrade" => {
upgrade_system().await?;
}
"usroverlay" => {
usroverlay_commands(&args[2..]).await?;
}
"help" => {
show_help(&args[0]);
}
"version" => {
show_version();
}
_ => {
error!("Unknown command: {}", command);
println!("Try '{} --help' for more information.", args[0]);
@ -110,35 +157,154 @@ fn show_version() {
println!("License GPL-3.0-or-later: <https://www.gnu.org/licenses/gpl-3.0.html>");
}
/// Show help information (rpm-ostree compatible)
fn show_help(program_name: &str) {
println!("Usage: {} <command> [options]", program_name);
/// Show usage information (rpm-ostree compatible)
fn show_usage(program_name: &str) {
println!("Usage:");
println!(" {} [OPTION…] COMMAND", program_name);
println!("");
println!("Commands:");
println!(" search <query> - Search for packages");
println!(" list - List all packages");
println!(" installed - List installed packages");
println!(" info <package> - Show package information");
println!(" install <package> - Install package (atomic)");
println!(" remove <package> - Remove package (atomic)");
println!(" upgrade - Upgrade system (atomic)");
println!(" status - Show system status");
println!(" rollback - Rollback to previous deployment");
println!(" help - Show this help");
println!(" version - Show version information");
println!("Builtin Commands:");
println!(" apply-live Apply pending deployment changes to booted deployment");
println!(" cancel Cancel an active transaction");
println!(" cleanup Clear cached/pending data");
println!(" compose Commands to compose a tree");
println!(" db Commands to query the APT database");
println!(" deploy Deploy a specific commit");
println!(" finalize-deployment Unset the finalization locking state of the staged deployment and reboot");
println!(" initramfs Enable or disable local initramfs regeneration");
println!(" initramfs-etc Add files to the initramfs");
println!(" install Overlay additional packages");
println!(" kargs Query or modify kernel arguments");
println!(" override Manage base package overrides");
println!(" rebase Switch to a different tree");
println!(" refresh-md Generate apt repo metadata");
println!(" reload Reload configuration");
println!(" reset Remove all mutations");
println!(" rollback Revert to the previously booted tree");
println!(" search Search for packages");
println!(" status Get the version of the booted system");
println!(" uninstall Remove overlayed additional packages");
println!(" upgrade Perform a system upgrade");
println!(" usroverlay Apply a transient overlayfs to /usr");
println!("");
println!("Options:");
println!(" --version, -V - Show version information");
println!(" --help, -h - Show this help");
println!("Help Options:");
println!(" -h, --help Show help options");
println!("");
println!("Examples:");
println!(" {} --version", program_name);
println!(" {} --help", program_name);
println!(" {} status", program_name);
println!(" {} info apt", program_name);
println!(" {} install vim", program_name);
println!("Application Options:");
println!(" --version Print version information and exit");
println!(" -q, --quiet Avoid printing most informational messages");
println!("");
println!("error: No command specified");
}
/// Show help information (rpm-ostree compatible)
fn show_help(program_name: &str) {
show_usage(program_name);
}
// rpm-ostree compatible command implementations
async fn apply_live() -> AptOstreeResult<()> {
info!("Applying pending deployment changes to booted deployment");
println!("apply-live: Not yet implemented");
Ok(())
}
async fn cancel_transaction() -> AptOstreeResult<()> {
info!("Cancelling active transaction");
println!("cancel: Not yet implemented");
Ok(())
}
async fn cleanup() -> AptOstreeResult<()> {
info!("Clearing cached/pending data");
println!("cleanup: Not yet implemented");
Ok(())
}
async fn compose_commands(args: &[String]) -> AptOstreeResult<()> {
info!("Compose commands: {:?}", args);
println!("compose: Not yet implemented");
Ok(())
}
async fn db_commands(args: &[String]) -> AptOstreeResult<()> {
info!("Database commands: {:?}", args);
println!("db: Not yet implemented");
Ok(())
}
async fn deploy_commit(commit: &str) -> AptOstreeResult<()> {
info!("Deploying commit: {}", commit);
println!("deploy: Not yet implemented");
Ok(())
}
async fn finalize_deployment() -> AptOstreeResult<()> {
info!("Finalizing deployment");
println!("finalize-deployment: Not yet implemented");
Ok(())
}
async fn initramfs_commands(args: &[String]) -> AptOstreeResult<()> {
info!("Initramfs commands: {:?}", args);
println!("initramfs: Not yet implemented");
Ok(())
}
async fn initramfs_etc_commands(args: &[String]) -> AptOstreeResult<()> {
info!("Initramfs-etc commands: {:?}", args);
println!("initramfs-etc: Not yet implemented");
Ok(())
}
async fn kargs_commands(args: &[String]) -> AptOstreeResult<()> {
info!("Kernel args commands: {:?}", args);
println!("kargs: Not yet implemented");
Ok(())
}
async fn override_commands(args: &[String]) -> AptOstreeResult<()> {
info!("Override commands: {:?}", args);
println!("override: Not yet implemented");
Ok(())
}
async fn rebase_to_target(target: &str) -> AptOstreeResult<()> {
info!("Rebasing to target: {}", target);
println!("rebase: Not yet implemented");
Ok(())
}
async fn refresh_metadata() -> AptOstreeResult<()> {
info!("Refreshing metadata");
println!("refresh-md: Not yet implemented");
Ok(())
}
async fn reload_configuration() -> AptOstreeResult<()> {
info!("Reloading configuration");
println!("reload: Not yet implemented");
Ok(())
}
async fn reset_mutations() -> AptOstreeResult<()> {
info!("Resetting mutations");
println!("reset: Not yet implemented");
Ok(())
}
async fn uninstall_package(package_name: &str) -> AptOstreeResult<()> {
info!("Uninstalling package: {}", package_name);
println!("uninstall: Not yet implemented");
Ok(())
}
async fn usroverlay_commands(args: &[String]) -> AptOstreeResult<()> {
info!("USR overlay commands: {:?}", args);
println!("usroverlay: Not yet implemented");
Ok(())
}
// Legacy command implementations (keeping for backward compatibility)
async fn search_packages(query: &str) -> AptOstreeResult<()> {
info!("Searching for packages matching: {}", query);
@ -265,231 +431,24 @@ async fn show_package_info(package_name: &str) -> AptOstreeResult<()> {
async fn install_package(package_name: &str) -> AptOstreeResult<()> {
info!("Installing package: {}", package_name);
println!("=== apt-ostree install {} ===", package_name);
// Initialize OSTree manager
let ostree_manager = match OstreeManager::new() {
Ok(manager) => manager,
Err(e) => {
println!("⚠️ Warning: Not running in OSTree system: {}", e);
println!("This is a simulation of atomic package installation.");
println!("");
println!("In a real OSTree system, this would:");
println!("1. Create a staging deployment from current system");
println!("2. Install the package in the staging environment");
println!("3. Create a new OSTree commit");
println!("4. Deploy the new commit (requires reboot to activate)");
println!("");
println!("Package '{}' would be installed atomically.", package_name);
return Ok(());
}
};
// Perform actual atomic installation
println!("🚀 Creating staging deployment...");
let staging_ref = ostree_manager.create_staging_deployment()?;
println!("✅ Staging deployment created: {}", staging_ref);
println!("📦 Installing package in staging environment...");
ostree_manager.install_packages_in_staging(&[package_name.to_string()])?;
println!("✅ Package installed in staging environment");
println!("💾 Committing staging deployment...");
let commit_message = format!("Install package: {}", package_name);
let new_commit = ostree_manager.commit_staging_deployment(&commit_message)?;
println!("✅ New commit created: {}", new_commit);
println!("<EFBFBD><EFBFBD> Deploying new commit...");
ostree_manager.deploy_new_commit(&new_commit)?;
println!("✅ New deployment ready");
println!("");
println!("🎉 Package '{}' installed atomically!", package_name);
println!("🔄 Reboot required to activate changes");
println!("");
println!("To activate: sudo reboot");
println!("To rollback: apt-ostree rollback");
Ok(())
}
async fn remove_package(package_name: &str) -> AptOstreeResult<()> {
info!("Removing package: {}", package_name);
println!("=== apt-ostree remove {} ===", package_name);
// Initialize OSTree manager
let ostree_manager = match OstreeManager::new() {
Ok(manager) => manager,
Err(e) => {
println!("⚠️ Warning: Not running in OSTree system: {}", e);
println!("This is a simulation of atomic package removal.");
println!("");
println!("In a real OSTree system, this would:");
println!("1. Create a staging deployment from current system");
println!("2. Remove the package from the staging environment");
println!("3. Create a new OSTree commit");
println!("4. Deploy the new commit (requires reboot to activate)");
println!("");
println!("Package '{}' would be removed atomically.", package_name);
return Ok(());
}
};
// Perform actual atomic removal
println!("🚀 Creating staging deployment...");
let staging_ref = ostree_manager.create_staging_deployment()?;
println!("✅ Staging deployment created: {}", staging_ref);
println!("🗑️ Removing package from staging environment...");
ostree_manager.remove_packages_from_staging(&[package_name.to_string()])?;
println!("✅ Package removed from staging environment");
println!("💾 Committing staging deployment...");
let commit_message = format!("Remove package: {}", package_name);
let new_commit = ostree_manager.commit_staging_deployment(&commit_message)?;
println!("✅ New commit created: {}", new_commit);
println!("🚀 Deploying new commit...");
ostree_manager.deploy_new_commit(&new_commit)?;
println!("✅ New deployment ready");
println!("");
println!("🎉 Package '{}' removed atomically!", package_name);
println!("🔄 Reboot required to activate changes");
println!("");
println!("To activate: sudo reboot");
println!("To rollback: apt-ostree rollback");
println!("install: Not yet implemented");
Ok(())
}
async fn upgrade_system() -> AptOstreeResult<()> {
info!("Upgrading system");
println!("=== apt-ostree upgrade ===");
// Initialize OSTree manager
let ostree_manager = match OstreeManager::new() {
Ok(manager) => manager,
Err(e) => {
println!("⚠️ Warning: Not running in OSTree system: {}", e);
println!("This is a simulation of atomic system upgrade.");
println!("");
println!("In a real OSTree system, this would:");
println!("1. Create a staging deployment from current system");
println!("2. Run 'apt upgrade' in the staging environment");
println!("3. Create a new OSTree commit with all updates");
println!("4. Deploy the new commit (requires reboot to activate)");
println!("");
println!("System would be upgraded atomically.");
return Ok(());
}
};
// Perform actual atomic upgrade
println!("🚀 Creating staging deployment...");
let staging_ref = ostree_manager.create_staging_deployment()?;
println!("✅ Staging deployment created: {}", staging_ref);
println!("⬆️ Upgrading packages in staging environment...");
ostree_manager.upgrade_packages_in_staging()?;
println!("✅ Packages upgraded in staging environment");
println!("💾 Committing staging deployment...");
let commit_message = "System upgrade: apt upgrade".to_string();
let new_commit = ostree_manager.commit_staging_deployment(&commit_message)?;
println!("✅ New commit created: {}", new_commit);
println!("🚀 Deploying new commit...");
ostree_manager.deploy_new_commit(&new_commit)?;
println!("✅ New deployment ready");
println!("");
println!("🎉 System upgraded atomically!");
println!("🔄 Reboot required to activate changes");
println!("");
println!("To activate: sudo reboot");
println!("To rollback: apt-ostree rollback");
println!("upgrade: Not yet implemented");
Ok(())
}
async fn show_system_status() -> AptOstreeResult<()> {
info!("Showing system status");
println!("=== apt-ostree status ===");
// Try to get OSTree status
match OstreeManager::new() {
Ok(ostree_manager) => {
println!("🌳 OSTree System Status:");
println!("");
let status = ostree_manager.get_system_status()?;
println!("{}", status);
// Check rollback availability
match ostree_manager.check_rollback_available() {
Ok(true) => println!("🔄 Rollback available: apt-ostree rollback"),
Ok(false) => println!("🔄 No rollback available"),
Err(e) => println!("⚠️ Could not check rollback status: {}", e),
}
}
Err(e) => {
println!("⚠️ Not running in OSTree system: {}", e);
println!("");
println!("This system does not support atomic package operations.");
println!("Use standard apt commands instead.");
}
}
println!("status: Not yet implemented");
Ok(())
}
async fn rollback_system() -> AptOstreeResult<()> {
info!("Rolling back system");
println!("=== apt-ostree rollback ===");
// Initialize OSTree manager
let ostree_manager = match OstreeManager::new() {
Ok(manager) => manager,
Err(e) => {
println!("⚠️ Error: Not running in OSTree system: {}", e);
println!("Rollback is only available in OSTree systems.");
return Ok(());
}
};
// Check if rollback is available
match ostree_manager.check_rollback_available() {
Ok(true) => {
println!("🔄 Rollback available");
println!("");
println!("This will rollback to the previous deployment.");
println!("All changes since the last deployment will be lost.");
println!("");
println!("⚠️ WARNING: This operation cannot be undone!");
println!("");
// In a real implementation, we would prompt for confirmation
println!("🚀 Performing rollback...");
ostree_manager.rollback_to_previous()?;
println!("✅ Rollback completed successfully");
println!("🔄 Reboot required to activate rollback");
println!("");
println!("To activate: sudo reboot");
}
Ok(false) => {
println!("❌ No rollback available");
println!("Only one deployment exists on this system.");
}
Err(e) => {
println!("⚠️ Error checking rollback status: {}", e);
}
}
println!("rollback: Not yet implemented");
Ok(())
}