diff --git a/debian/apt-ostree/DEBIAN/control b/debian/apt-ostree/DEBIAN/control index de82d97e..d12c0ffc 100644 --- a/debian/apt-ostree/DEBIAN/control +++ b/debian/apt-ostree/DEBIAN/control @@ -2,7 +2,7 @@ Package: apt-ostree Version: 0.1.0-2 Architecture: amd64 Maintainer: Robojerk -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 diff --git a/debian/apt-ostree/DEBIAN/md5sums b/debian/apt-ostree/DEBIAN/md5sums index d9cd6150..0bdf0265 100644 --- a/debian/apt-ostree/DEBIAN/md5sums +++ b/debian/apt-ostree/DEBIAN/md5sums @@ -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 diff --git a/debian/apt-ostree/DEBIAN/postinst b/debian/apt-ostree/DEBIAN/postinst new file mode 100755 index 00000000..e79cfc07 --- /dev/null +++ b/debian/apt-ostree/DEBIAN/postinst @@ -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 diff --git a/debian/apt-ostree/DEBIAN/postrm b/debian/apt-ostree/DEBIAN/postrm new file mode 100755 index 00000000..bccf8aae --- /dev/null +++ b/debian/apt-ostree/DEBIAN/postrm @@ -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 diff --git a/debian/apt-ostree/DEBIAN/prerm b/debian/apt-ostree/DEBIAN/prerm new file mode 100755 index 00000000..ba5b6175 --- /dev/null +++ b/debian/apt-ostree/DEBIAN/prerm @@ -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 diff --git a/debian/apt-ostree/DEBIAN/triggers b/debian/apt-ostree/DEBIAN/triggers new file mode 100644 index 00000000..ccb5310f --- /dev/null +++ b/debian/apt-ostree/DEBIAN/triggers @@ -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 diff --git a/debian/apt-ostree/usr/share/bash-completion/completions/apt-ostree b/debian/apt-ostree/usr/share/bash-completion/completions/apt-ostree new file mode 100644 index 00000000..afeca462 --- /dev/null +++ b/debian/apt-ostree/usr/share/bash-completion/completions/apt-ostree @@ -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 diff --git a/debian/apt-ostree/usr/share/doc/apt-ostree/README.Debian b/debian/apt-ostree/usr/share/doc/apt-ostree/README.Debian new file mode 100644 index 00000000..a818177d --- /dev/null +++ b/debian/apt-ostree/usr/share/doc/apt-ostree/README.Debian @@ -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 . + +For Debian-specific issues, please contact the maintainer or file a bug +report against the apt-ostree package in the Debian bug tracking system. diff --git a/debian/apt-ostree/usr/share/doc/apt-ostree/copyright b/debian/apt-ostree/usr/share/doc/apt-ostree/copyright index 44c0e3ec..ab27f6de 100644 --- a/debian/apt-ostree/usr/share/doc/apt-ostree/copyright +++ b/debian/apt-ostree/usr/share/doc/apt-ostree/copyright @@ -4,42 +4,32 @@ Source: https://github.com/robojerk/apt-ostree Files: * Copyright: 2025 Robojerk -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 . Files: debian/* Copyright: 2025 Robojerk -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. \ No newline at end of file + You should have received a copy of the GNU General Public License + along with this program. If not, see . \ No newline at end of file diff --git a/debian/apt-ostree/usr/share/lintian/overrides/apt-ostree b/debian/apt-ostree/usr/share/lintian/overrides/apt-ostree new file mode 100644 index 00000000..382a9a0c --- /dev/null +++ b/debian/apt-ostree/usr/share/lintian/overrides/apt-ostree @@ -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 diff --git a/debian/apt-ostree/usr/share/man/man1/apt-ostree.1.gz b/debian/apt-ostree/usr/share/man/man1/apt-ostree.1.gz new file mode 100644 index 00000000..7d4dbd3a Binary files /dev/null and b/debian/apt-ostree/usr/share/man/man1/apt-ostree.1.gz differ diff --git a/debian/apt-ostree/usr/share/zsh/vendor-completions/_apt-ostree b/debian/apt-ostree/usr/share/zsh/vendor-completions/_apt-ostree new file mode 100644 index 00000000..e670af65 --- /dev/null +++ b/debian/apt-ostree/usr/share/zsh/vendor-completions/_apt-ostree @@ -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 diff --git a/src/main.rs b/src/main.rs index bec2a315..f3da0a04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ async fn main() -> AptOstreeResult<()> { let args: Vec = 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: "); } -/// Show help information (rpm-ostree compatible) -fn show_help(program_name: &str) { - println!("Usage: {} [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 - Search for packages"); - println!(" list - List all packages"); - println!(" installed - List installed packages"); - println!(" info - Show package information"); - println!(" install - Install package (atomic)"); - println!(" remove - 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!("οΏ½οΏ½ 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(()) }