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 Version: 0.1.0-2
Architecture: amd64 Architecture: amd64
Maintainer: Robojerk <robojerk@example.com> 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 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 Section: admin
Priority: optional 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 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: * Files: *
Copyright: 2025 Robojerk <robojerk@example.com> Copyright: 2025 Robojerk <robojerk@example.com>
License: MIT License: GPL-3.0-or-later
Permission is hereby granted, free of charge, to any person obtaining a copy This program is free software: you can redistribute it and/or modify
of this software and associated documentation files (the "Software"), to deal it under the terms of the GNU General Public License as published by
in the Software without restriction, including without limitation the rights the Free Software Foundation, either version 3 of the License, or
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell (at your option) any later version.
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
. .
The above copyright notice and this permission notice shall be included in all This program is distributed in the hope that it will be useful,
copies or substantial portions of the Software. 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 You should have received a copy of the GNU General Public License
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, along with this program. If not, see <https://www.gnu.org/licenses/>.
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.
Files: debian/* Files: debian/*
Copyright: 2025 Robojerk <robojerk@example.com> Copyright: 2025 Robojerk <robojerk@example.com>
License: MIT License: GPL-3.0-or-later
Permission is hereby granted, free of charge, to any person obtaining a copy This program is free software: you can redistribute it and/or modify
of this software and associated documentation files (the "Software"), to deal it under the terms of the GNU General Public License as published by
in the Software without restriction, including without limitation the rights the Free Software Foundation, either version 3 of the License, or
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell (at your option) any later version.
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
. .
The above copyright notice and this permission notice shall be included in all This program is distributed in the hope that it will be useful,
copies or substantial portions of the Software. 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 You should have received a copy of the GNU General Public License
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, along with this program. If not, see <https://www.gnu.org/licenses/>.
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.

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(); let args: Vec<String> = env::args().collect();
if args.len() < 2 { if args.len() < 2 {
show_help(&args[0]); show_usage(&args[0]);
return Ok(()); return Ok(());
} }
@ -26,7 +26,7 @@ async fn main() -> AptOstreeResult<()> {
// Handle rpm-ostree compatible flags first // Handle rpm-ostree compatible flags first
match command.as_str() { match command.as_str() {
"--version" | "-V" => { "--version" => {
show_version(); show_version();
return Ok(()); return Ok(());
} }
@ -34,64 +34,111 @@ async fn main() -> AptOstreeResult<()> {
show_help(&args[0]); show_help(&args[0]);
return Ok(()); 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() { 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 { if args.len() < 3 {
error!("Search command requires a query"); error!("No target commit specified");
return Err(AptOstreeError::InvalidArgument("Search query required".to_string())); return Err(AptOstreeError::InvalidArgument("No target commit specified".to_string()));
} }
let query = &args[2]; let commit = &args[2];
search_packages(query).await?; deploy_commit(commit).await?;
} }
"list" => { "finalize-deployment" => {
list_packages().await?; finalize_deployment().await?;
} }
"installed" => { "initramfs" => {
list_installed_packages().await?; initramfs_commands(&args[2..]).await?;
} }
"info" => { "initramfs-etc" => {
if args.len() < 3 { initramfs_etc_commands(&args[2..]).await?;
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?;
} }
"install" => { "install" => {
if args.len() < 3 { if args.len() < 3 {
error!("Install command requires a package name"); error!("No package specified");
return Err(AptOstreeError::InvalidArgument("Package name required".to_string())); return Err(AptOstreeError::InvalidArgument("No package specified".to_string()));
} }
let package_name = &args[2]; let package_name = &args[2];
install_package(package_name).await?; install_package(package_name).await?;
} }
"remove" => { "kargs" => {
kargs_commands(&args[2..]).await?;
}
"override" => {
override_commands(&args[2..]).await?;
}
"rebase" => {
if args.len() < 3 { if args.len() < 3 {
error!("Remove command requires a package name"); error!("No target specified");
return Err(AptOstreeError::InvalidArgument("Package name required".to_string())); return Err(AptOstreeError::InvalidArgument("No target specified".to_string()));
} }
let package_name = &args[2]; let target = &args[2];
remove_package(package_name).await?; rebase_to_target(target).await?;
} }
"upgrade" => { "refresh-md" => {
upgrade_system().await?; refresh_metadata().await?;
} }
"status" => { "reload" => {
show_system_status().await?; reload_configuration().await?;
}
"reset" => {
reset_mutations().await?;
} }
"rollback" => { "rollback" => {
rollback_system().await?; 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" => { "help" => {
show_help(&args[0]); show_help(&args[0]);
} }
"version" => {
show_version();
}
_ => { _ => {
error!("Unknown command: {}", command); error!("Unknown command: {}", command);
println!("Try '{} --help' for more information.", args[0]); 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>"); println!("License GPL-3.0-or-later: <https://www.gnu.org/licenses/gpl-3.0.html>");
} }
/// Show help information (rpm-ostree compatible) /// Show usage information (rpm-ostree compatible)
fn show_help(program_name: &str) { fn show_usage(program_name: &str) {
println!("Usage: {} <command> [options]", program_name); println!("Usage:");
println!(" {} [OPTION…] COMMAND", program_name);
println!(""); println!("");
println!("Commands:"); println!("Builtin Commands:");
println!(" search <query> - Search for packages"); println!(" apply-live Apply pending deployment changes to booted deployment");
println!(" list - List all packages"); println!(" cancel Cancel an active transaction");
println!(" installed - List installed packages"); println!(" cleanup Clear cached/pending data");
println!(" info <package> - Show package information"); println!(" compose Commands to compose a tree");
println!(" install <package> - Install package (atomic)"); println!(" db Commands to query the APT database");
println!(" remove <package> - Remove package (atomic)"); println!(" deploy Deploy a specific commit");
println!(" upgrade - Upgrade system (atomic)"); println!(" finalize-deployment Unset the finalization locking state of the staged deployment and reboot");
println!(" status - Show system status"); println!(" initramfs Enable or disable local initramfs regeneration");
println!(" rollback - Rollback to previous deployment"); println!(" initramfs-etc Add files to the initramfs");
println!(" help - Show this help"); println!(" install Overlay additional packages");
println!(" version - Show version information"); 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!("");
println!("Options:"); println!("Help Options:");
println!(" --version, -V - Show version information"); println!(" -h, --help Show help options");
println!(" --help, -h - Show this help");
println!(""); println!("");
println!("Examples:"); println!("Application Options:");
println!(" {} --version", program_name); println!(" --version Print version information and exit");
println!(" {} --help", program_name); println!(" -q, --quiet Avoid printing most informational messages");
println!(" {} status", program_name); println!("");
println!(" {} info apt", program_name); println!("error: No command specified");
println!(" {} install vim", program_name);
} }
/// 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<()> { async fn search_packages(query: &str) -> AptOstreeResult<()> {
info!("Searching for packages matching: {}", query); 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<()> { async fn install_package(package_name: &str) -> AptOstreeResult<()> {
info!("Installing package: {}", package_name); info!("Installing package: {}", package_name);
println!("install: Not yet implemented");
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");
Ok(()) Ok(())
} }
async fn upgrade_system() -> AptOstreeResult<()> { async fn upgrade_system() -> AptOstreeResult<()> {
info!("Upgrading system"); info!("Upgrading system");
println!("upgrade: Not yet implemented");
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");
Ok(()) Ok(())
} }
async fn show_system_status() -> AptOstreeResult<()> { async fn show_system_status() -> AptOstreeResult<()> {
info!("Showing system status"); info!("Showing system status");
println!("status: Not yet implemented");
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.");
}
}
Ok(()) Ok(())
} }
async fn rollback_system() -> AptOstreeResult<()> { async fn rollback_system() -> AptOstreeResult<()> {
info!("Rolling back system"); info!("Rolling back system");
println!("rollback: Not yet implemented");
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);
}
}
Ok(()) Ok(())
} }