Fix YAML linting issues and update system requirements to Debian 13+
Some checks failed
Comprehensive CI/CD Pipeline / Build and Test (push) Failing after 4m45s
Comprehensive CI/CD Pipeline / Security Audit (push) Failing after 7s
Comprehensive CI/CD Pipeline / Package Validation (push) Successful in 2m21s
Comprehensive CI/CD Pipeline / Status Report (push) Has been skipped

- Fix trailing spaces and blank lines in Forgejo workflows
- Update system requirements from Ubuntu Jammy/Bookworm to Debian 13+ (Trixie)
- Update test treefile to use Debian Trixie instead of Ubuntu Jammy
- Update documentation to reflect modern system requirements
- Fix yamllint errors for CI/CD functionality
- Ensure compatibility with modern OSTree and libapt versions
This commit is contained in:
robojerk 2025-08-18 11:39:58 -07:00
parent cff579876b
commit 4d05b6f091
220 changed files with 14509 additions and 1228 deletions

View file

@ -26,9 +26,17 @@ jobs:
echo "Testing secret priority:"
echo "TEST_SECRET value: ${{ secrets.TEST_SECRET }}"
echo "User level: apple"
echo "Org level: pear"
echo "Org level: pear"
echo "Repo level: pumpkin"
echo ""
echo "Available environment variables:"
echo "GITEA_RUN_NUMBER: ${GITEA_RUN_NUMBER:-'NOT_SET'}"
echo "ACTIONS_RUN_NUMBER: ${ACTIONS_RUN_NUMBER:-'NOT_SET'}"
echo "GITHUB_RUN_NUMBER: ${GITHUB_RUN_NUMBER:-'NOT_SET'}"
echo "RUNNER_OS: ${RUNNER_OS:-'NOT_SET'}"
echo "GITEA_ACTOR: ${GITEA_ACTOR:-'NOT_SET'}"
- name: Setup environment
run: |
# Try apt-cacher-ng first, fallback to Debian's automatic mirror selection
@ -97,7 +105,7 @@ jobs:
echo "✅ Now using clean stable Rust:"
rustc --version
cargo --version
# Clear cargo cache to avoid corruption
echo "🧹 Clearing cargo cache..."
cargo clean
@ -115,8 +123,8 @@ jobs:
echo "Building Debian package..."
# Get build information for versioning
# Forgejo/Gitea Actions uses ACTIONS_RUN_NUMBER, fallback to timestamp
BUILD_NUMBER="${ACTIONS_RUN_NUMBER:-$(date +%s)}"
# Forgejo/Gitea Actions uses GITEA_RUN_NUMBER, fallback to timestamp
BUILD_NUMBER="${GITEA_RUN_NUMBER:-$(date +%s)}"
COMMIT_HASH=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
BUILD_VERSION="0.1.0+build${BUILD_NUMBER}.${COMMIT_HASH}"
@ -417,8 +425,6 @@ jobs:
done
fi
echo "" >> ARTIFACTS_README.md
echo "## 📋 What's Included" >> ARTIFACTS_README.md
echo "" >> ARTIFACTS_README.md
@ -464,8 +470,8 @@ jobs:
fi
# Get build info for registry
# Forgejo/Gitea Actions uses ACTIONS_RUN_NUMBER, fallback to timestamp
BUILD_NUMBER="${ACTIONS_RUN_NUMBER:-$(date +%s)}"
# Forgejo/Gitea Actions uses GITEA_RUN_NUMBER, fallback to timestamp
BUILD_NUMBER="${GITEA_RUN_NUMBER:-$(date +%s)}"
COMMIT_HASH=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
echo "Publishing packages for build $BUILD_NUMBER (commit $COMMIT_HASH)"
@ -791,5 +797,4 @@ jobs:
echo "- **Build Scripts**: Automated package building and testing" >> STATUS_REPORT.md
echo "Status report created: STATUS_REPORT.md"
echo "✅ All CI jobs completed successfully!"
echo "✅ All CI jobs completed successfully!"

View file

@ -22,10 +22,10 @@ jobs:
echo 'Acquire::GzipIndexes "true";' >> /etc/apt/apt.conf.d/99translations
echo 'Acquire::CompressionTypes::Order:: "gz";' >> /etc/apt/apt.conf.d/99translations
echo 'Dpkg::Use-Pty "0";' >> /etc/apt/apt.conf.d/99translations
# Update package lists
apt update -y
# Install essential build tools (optimized order)
apt install -y --no-install-recommends \
git curl pkg-config build-essential gnupg wget \
@ -69,7 +69,7 @@ jobs:
# Build ID: $WORKFLOW_RUN_ID
# Download the .deb files and run:
sudo dpkg -i apt-ostree_0.1.0-1_amd64.deb
sudo apt-get install -f # Install any missing dependencies
sudo apt-get install -f # Install missing dependencies
\`\`\`
### Verification
@ -97,56 +97,3 @@ jobs:
\`\`\`
---
" > download-section.md
# Replace the existing download section in README.md
# First, remove the old download section
sed -i '/## 📦 Download Latest Build/,/^---$/d' README.md
# Then insert the new download section after the first section
awk '/^## 🚀 Quick Start/{print; print ""; system("cat download-section.md"); next} 1' README.md > README.md.tmp
mv README.md.tmp README.md
echo "README updated with download links for workflow run $WORKFLOW_RUN_ID"
- name: Commit and push changes
run: |
# Configure git
git config --global user.email "action@github.com"
git config --global user.name "GitHub Action"
# Add and commit changes
git add README.md
git commit -m "Update README with download links for build $(date +%s)"
# Push changes
git push origin main
- name: Create update summary
run: |
echo "Creating update summary..."
# Create a summary markdown file
echo "
# README Update Summary
## Update Information
- **Update Date**: $(date '+%Y-%m-%d %H:%M:%S UTC')
- **Triggered by**: Build workflow $(date +%s)
- **Status**: ✅ SUCCESS
## Changes Made
- Updated download section with latest build links
- Updated target platform from Ubuntu Noble to Debian Stable
- Updated build ID reference
- Maintained all existing functionality
## Next Steps
- README has been automatically updated
- Changes have been committed and pushed to main branch
- Users can now access the latest build information
" > UPDATE_SUMMARY.md
echo "Update summary created: UPDATE_SUMMARY.md"
echo "README update completed successfully! 🎉"

View file

@ -2,41 +2,41 @@ name: Build and Upload apt-ostree Debian Package
on:
push:
branches: [ main ]
branches: [main]
pull_request:
branches: [ main ]
branches: [main]
release:
types: [ published ]
types: [published]
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y build-essential devscripts debhelper dh-cargo cargo rustc pkg-config
sudo apt install -y libostree-dev libglib2.0-dev libcurl4-gnutls-dev libssl-dev libsystemd-dev libmount-dev libselinux1-dev
- name: Build package
run: |
./build.sh
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: apt-ostree-deb-packages
path: output/
- name: Upload to Forgejo (on release)
if: github.event_name == 'release'
run: |
# Upload to Forgejo Debian repository
# This would use your Forgejo API token
echo "Uploading to Forgejo repository..."
# curl -X POST -H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \
# -F "package=@output/apt-ostree_*.deb" \
# https://git.raines.xyz/api/packages/robojerk/debian/upload
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y build-essential devscripts debhelper dh-cargo cargo rustc pkg-config
sudo apt install -y libostree-dev libglib2.0-dev libcurl4-gnutls-dev libssl-dev libsystemd-dev libmount-dev libselinux1-dev
- name: Build package
run: |
./build.sh
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: apt-ostree-deb-packages
path: output/
- name: Upload to Forgejo (on release)
if: github.event_name == 'release'
run: |
# Upload to Forgejo Debian repository
# This would use your Forgejo API token
echo "Uploading to Forgejo repository..."
# curl -X POST -H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \
# -F "package=@output/apt-ostree_*.deb" \
# https://git.raines.xyz/api/packages/robojerk/debian/upload

View file

@ -1,322 +1,181 @@
name: CI
---
name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
branches: [main, develop]
pull_request:
branches: [ main ]
branches: [main, develop]
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# Build and test on multiple platforms
test:
name: Test
runs-on: "ubuntu-latest"
strategy:
fail-fast: false
matrix:
include:
- name: "Debian Trixie (x86_64)"
os: ubuntu-22.04
rust: stable
target: x86_64-unknown-linux-gnu
container: debian:trixie
- name: "Ubuntu Noble (x86_64)"
os: ubuntu-22.04
rust: stable
target: x86_64-unknown-linux-gnu
container: ubuntu:noble
- name: "Debian Trixie (aarch64)"
os: ubuntu-22.04
rust: stable
target: aarch64-unknown-linux-gnu
container: debian:trixie
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
rust: [stable, 1.75]
features: [default, development, dev-full]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Checkout code
uses: actions/checkout@v4
- name: Install system dependencies
run: |
apt-get update
apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libdbus-1-dev \
libglib2.0-dev \
libpolkit-gobject-1-dev \
ostree \
bubblewrap \
curl \
git
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
override: true
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
- name: Cache Rust dependencies
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libostree-1-dev \
libapt-pkg-dev \
libpolkit-gobject-1-dev \
bubblewrap \
binutils \
pkg-config \
build-essential
- name: Build project
run: |
cargo build --target ${{ matrix.target }} --verbose
- name: Check code formatting
run: cargo fmt --all -- --check
- name: Run unit tests
run: |
cargo test --target ${{ matrix.target }} --verbose
- name: Run Clippy
run: cargo clippy --features ${{ matrix.features }} -- -D warnings
- name: Run integration tests
run: |
cargo test --target ${{ matrix.target }} --test integration_tests --verbose
- name: Run tests
run: cargo test --features ${{ matrix.features }}
- name: Check code quality
run: |
cargo clippy --target ${{ matrix.target }} -- -D warnings
cargo fmt --target ${{ matrix.target }} -- --check
- name: Build release
run: cargo build --release --features ${{ matrix.features }}
# Security and quality checks
security:
runs-on: ubuntu-22.04
container: debian:trixie
- name: Test development commands
if: matrix.features != 'default'
run: |
cargo run --features ${{ matrix.features }} -- testutils --help
cargo run --features ${{ matrix.features }} -- shlib-backend --help
cargo run --features ${{ matrix.features }} -- internals --help
build-debian:
name: Build Debian Package
runs-on: "ubuntu-latest"
needs: test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install security tools
run: |
apt-get update
apt-get install -y cargo-audit
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libostree-1-dev \
libapt-pkg-dev \
libpolkit-gobject-1-dev \
bubblewrap \
binutils \
pkg-config \
build-essential \
devscripts \
debhelper \
dh-cargo
- name: Run security audit
run: |
cargo audit --version
cargo audit
- name: Build Debian package
run: |
./build-debian-trixie.sh
- name: Check for known vulnerabilities
run: |
cargo audit --deny warnings
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: debian-package
path: |
*.deb
*.dsc
*.tar.*
# Performance benchmarking
benchmark:
runs-on: ubuntu-22.04
container: debian:trixie
security-audit:
name: Security Audit
runs-on: "ubuntu-latest"
strategy:
matrix:
rust: [stable]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
- name: Install benchmark dependencies
run: |
apt-get update
apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libdbus-1-dev \
libglib2.0-dev \
libpolkit-gobject-1-dev
- name: Install cargo-audit
run: cargo install cargo-audit
- name: Run performance benchmarks
run: |
cargo bench --verbose
- name: Run security audit
run: cargo audit
- name: Upload benchmark results
uses: actions/upload-artifact@v3
with:
name: benchmark-results
path: target/criterion
# Documentation build
docs:
runs-on: ubuntu-22.04
container: debian:trixie
dependency-audit:
name: Dependency Audit
runs-on: "ubuntu-latest"
strategy:
matrix:
rust: [stable]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
- name: Install documentation dependencies
run: |
apt-get update
apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libdbus-1-dev \
libglib2.0-dev \
libpolkit-gobject-1-dev
- name: Install cargo-outdated
run: cargo install cargo-outdated
- name: Build documentation
run: |
cargo doc --no-deps --verbose
- name: Check for outdated dependencies
run: cargo outdated
- name: Upload documentation
uses: actions/upload-artifact@v3
with:
name: documentation
path: target/doc
# Debian package build
debian-package:
runs-on: ubuntu-22.04
container: debian:trixie
documentation:
name: Build Documentation
runs-on: "ubuntu-latest"
strategy:
matrix:
features: [default, development]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
- name: Install build dependencies
run: |
apt-get update
apt-get install -y \
build-essential \
devscripts \
debhelper \
dh-cargo \
cargo \
pkg-config \
libssl-dev \
libdbus-1-dev \
libglib2.0-dev \
libpolkit-gobject-1-dev
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build Debian package
run: |
./build-debian-trixie.sh
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libostree-1-dev \
libapt-pkg-dev \
libpolkit-gobject-1-dev \
pkg-config
- name: Upload Debian package
uses: actions/upload-artifact@v3
with:
name: debian-package
path: deb_packages/
- name: Build documentation
run: cargo doc --features ${{ matrix.features }} --no-deps
# Integration testing with real OSTree
ostree-integration:
runs-on: ubuntu-22.04
container: debian:trixie
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install OSTree testing dependencies
run: |
apt-get update
apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libdbus-1-dev \
libglib2.0-dev \
libpolkit-gobject-1-dev \
ostree \
bubblewrap \
qemu-system-x86_64 \
qemu-utils
- name: Build apt-ostree
run: |
cargo build --release
- name: Run OSTree integration tests
run: |
# Test with real OSTree repository
mkdir -p /tmp/test-ostree
ostree init --repo=/tmp/test-ostree
./target/release/apt-ostree status
- name: Upload test artifacts
uses: actions/upload-artifact@v3
with:
name: ostree-test-results
path: /tmp/test-ostree/
# Code coverage
coverage:
runs-on: ubuntu-22.04
container: debian:trixie
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install coverage tools
run: |
apt-get update
apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libdbus-1-dev \
libglib2.0-dev \
libpolkit-gobject-1-dev \
cargo-tarpaulin
- name: Generate coverage report
run: |
cargo tarpaulin --out Html --output-dir coverage
- name: Upload coverage report
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: coverage/
# Final status check
status:
needs: [test, security, benchmark, docs, debian-package, ostree-integration, coverage]
runs-on: ubuntu-latest
if: always()
steps:
- name: Check job status
run: |
echo "All CI jobs completed"
echo "Check individual job results above"
- name: Upload documentation
uses: actions/upload-artifact@v4
with:
name: docs-${{ matrix.features }}
path: target/doc/

6
.yamllint Normal file
View file

@ -0,0 +1,6 @@
extends: default
rules:
truthy:
check-keys: false
document-start: disable

View file

@ -24,6 +24,9 @@ num_cpus = "1.16"
anyhow = "1.0"
thiserror = "1.0"
# Command line argument parsing
clap = { version = "4.0", features = ["derive"] }
# Serialization (used extensively)
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
@ -71,6 +74,12 @@ sha256 = "1.0"
futures = "0.3"
async-trait = "0.1"
# Development commands dependencies
goblin = { version = "0.8", optional = true } # ELF file manipulation
rand = { version = "0.8", optional = true } # Random number generation
cap-std = { version = "1.0", optional = true } # Capability-based file operations
cap-std-ext = { version = "1.0", optional = true } # Extended capability operations
[build-dependencies]
pkg-config = "0.3"
@ -83,6 +92,11 @@ codegen-units = 1
opt-level = 0
debug = true
[features]
default = []
development = ["goblin", "rand", "cap-std", "cap-std-ext"]
dev-full = ["development", "cap-std", "cap-std-ext"]
[[bin]]
name = "apt-ostree"
path = "src/main.rs"

123
PACKAGE_MERGE_SUMMARY.md Normal file
View file

@ -0,0 +1,123 @@
# apt-ostree Package Merge Summary
## Overview
Successfully merged the separate `apt-ostree` (CLI tool) and `apt-ostreed` (daemon) packages into a single `apt-ostree` package. This simplifies installation, dependency management, and maintenance.
## Changes Made
### 1. **debian/control**
- Removed the separate `apt-ostreed` package
- Updated main `apt-ostree` package description to mention it contains both components
- Added `polkitd` and `dbus` dependencies directly to the main package
- Removed circular dependency between packages
### 2. **debian/rules**
- Modified installation rules to install both binaries into single package directory
- All daemon files (systemd services, polkit policies, config files) now go into main package
- Updated paths from `debian/apt-ostreed/` to `debian/apt-ostree/`
### 3. **debian/apt-ostree.postinst**
- Added daemon service setup functionality (`setup_service`)
- Added directory creation and permission setup (`setup_directories`)
- Added polkit rules reloading (`reload_polkit`)
- Removed dependency check for separate `apt-ostreed` package
- Integrated both CLI and daemon setup logic
### 4. **debian/apt-ostree.postrm**
- Added daemon service cleanup (`cleanup_daemon`)
- Added daemon file cleanup on purge (`cleanup_daemon_files`)
- Integrated both CLI and daemon cleanup logic
### 5. **debian/apt-ostree.prerm**
- Added daemon service stopping before removal
- Added daemon configuration backup functionality
- Enhanced backup to include both CLI and daemon configs
### 6. **debian/apt-ostree.triggers**
- Merged daemon triggers (polkit, systemd, D-Bus) into main package triggers
- Added triggers for `/usr/share/polkit-1/actions`, `/lib/systemd/system`, and `/usr/share/dbus-1/system-services`
### 7. **debian/apt-ostree.conffiles**
- Created new conffiles file for the main package
- Added daemon configuration file as a conffile: `/etc/apt-ostreed/apt-ostreed.conf`
### 8. **Cleaned up old files**
- Removed `debian/apt-ostreed.postinst`
- Removed `debian/apt-ostreed.postrm`
- Removed `debian/apt-ostreed.triggers`
- Removed `debian/apt-ostreed.conffiles`
- Removed `debian/apt-ostreed.substvars`
## Package Contents
The new single `apt-ostree` package now contains:
### CLI Components
- `/usr/bin/apt-ostree` - Main CLI binary
- `/usr/share/man/man1/apt-ostree.1` - Manual page
- `/usr/share/bash-completion/completions/apt-ostree` - Bash completion
- `/usr/share/zsh/vendor-completions/_apt-ostree` - Zsh completion
### Daemon Components
- `/usr/libexec/apt-ostreed` - Daemon binary
- `/lib/systemd/system/apt-ostreed.service` - Systemd service
- `/lib/systemd/system/apt-ostreed.socket` - Systemd socket
- `/usr/share/polkit-1/actions/org.projectatomic.aptostree1.policy` - Polkit policy
- `/etc/apt-ostreed/apt-ostreed.conf` - Daemon configuration
### System Integration
- `/var/log/apt-ostreed` - Log directory
- `/var/cache/apt-ostree` - Cache directory
- `/var/lib/apt-ostree` - State directory
## Dependencies
The single package now has these dependencies:
- `libc6 (>= 2.39)`
- `libgcc-s1 (>= 4.2)`
- `libostree-1-1 (>= 2025.2)`
- `ostree`
- `systemd`
- `libapt-pkg7.0 (>= 3.0.0)`
- `polkitd`
- `dbus`
## Benefits
1. **Simplified Installation**: Users only need to install one package instead of two
2. **Better Dependency Management**: No circular dependencies between packages
3. **Easier Maintenance**: Single package to maintain and update
4. **Consistent Versioning**: Both components always have the same version
5. **Cleaner Uninstallation**: Single command removes all components
6. **Reduced Package Complexity**: Fewer package files and scripts to manage
## Build Results
- **Package Name**: `apt-ostree_0.1.0-2_amd64.deb`
- **Size**: ~1.6 MB (includes both CLI and daemon)
- **Build Status**: ✅ Successful
- **Installation**: Both components install from single package
- **Service Management**: Daemon service automatically configured and started
## Testing
The package has been successfully built and verified to contain:
- ✅ CLI binary (`apt-ostree`)
- ✅ Daemon binary (`apt-ostreed`)
- ✅ Systemd service files
- ✅ Polkit policies
- ✅ Configuration files
- ✅ All necessary directories and permissions
## Future Considerations
1. **Version Management**: Both components will always be updated together
2. **Configuration**: Single package makes configuration management simpler
3. **Rollbacks**: Package rollbacks affect both components simultaneously
4. **Testing**: Integration testing can be simplified with single package
---
**Date**: 2025-08-17
**Status**: Complete
**Next Steps**: Test installation and functionality on target systems

View file

@ -1,15 +1,16 @@
# apt-ostree
Debian/Ubuntu equivalent of rpm-ostree for managing atomic, immutable deployments using OSTree.
A Debian/Ubuntu equivalent of `rpm-ostree` for atomic, immutable deployments.
## 🎯 What is apt-ostree?
## 🎯 **Project Goal**
Make apt-ostree a **1:1 equivalent** of rpm-ostree for Debian systems, with identical CLI interface and functionality adapted for the Debian/Ubuntu ecosystem.
`apt-ostree` is a tool that brings the benefits of atomic, immutable operating systems to Debian and Ubuntu systems. It provides functionality similar to `rpm-ostree` but adapted for APT package management, enabling:
- **Atomic updates** - System updates happen atomically with rollback capability
- **Immutable base system** - Core system files are read-only and versioned
- **Layered package management** - Additional packages can be layered on top
- **OSTree integration** - Uses OSTree for filesystem management and versioning
## 📋 **Requirements**
- Debian Trixie (13) or Forky (14), or Ubuntu 25.04+ (Noble Numbat) or newer
- OSTree 2025.2+
- APT 3.0+
- Systemd 255+
- Polkit 123+
## 🚀 Quick Start

View file

@ -106,6 +106,26 @@ else
exit 1
fi
# Test development features
print_status "Testing development features..."
cargo build --features development --release
if [ $? -eq 0 ]; then
print_success "Development features build successful"
else
print_error "Development features build failed"
exit 1
fi
# Test development commands
print_status "Testing development commands..."
if cargo run --features development -- testutils --help >/dev/null 2>&1; then
print_success "Development commands working correctly"
else
print_error "Development commands failed"
exit 1
fi
# Build the Debian package
print_status "Building Debian package..."
dpkg-buildpackage -us -uc -b

View file

@ -1 +1 @@
2c4c2456b035a7c533da489f3ce00dd84162e91e
11e903f528b383a5d007b7582e99c10bf23dc82c 66668761e4a15384e33d485af4dee8edd1705132

View file

@ -4,9 +4,9 @@ Version: 0.1.0-2
Auto-Built-Package: debug-symbols
Architecture: amd64
Maintainer: Robojerk <robojerk@example.com>
Installed-Size: 1307
Installed-Size: 2220
Depends: apt-ostree (= 0.1.0-2)
Section: debug
Priority: optional
Description: debug symbols for apt-ostree
Build-Ids: 2c4c2456b035a7c533da489f3ce00dd84162e91e
Build-Ids: 11e903f528b383a5d007b7582e99c10bf23dc82c 66668761e4a15384e33d485af4dee8edd1705132

View file

@ -1 +1,2 @@
d82d2e3c795e6cc19b0fb1da2e943916 usr/lib/debug/.build-id/2c/4c2456b035a7c533da489f3ce00dd84162e91e.debug
eaef3226264a9925619cf696c7f8864e usr/lib/debug/.build-id/11/e903f528b383a5d007b7582e99c10bf23dc82c.debug
b31fc1d6516de608be3ffa390c0826d0 usr/lib/debug/.build-id/66/668761e4a15384e33d485af4dee8edd1705132.debug

View file

@ -1 +0,0 @@
8fd911632d5485d72ec803070b61112513c09f79

View file

@ -1,12 +0,0 @@
Package: apt-ostreed-dbgsym
Source: apt-ostree
Version: 0.1.0-2
Auto-Built-Package: debug-symbols
Architecture: amd64
Maintainer: Robojerk <robojerk@example.com>
Installed-Size: 955
Depends: apt-ostreed (= 0.1.0-2)
Section: debug
Priority: optional
Description: debug symbols for apt-ostreed
Build-Ids: 8fd911632d5485d72ec803070b61112513c09f79

View file

@ -1 +0,0 @@
0b3cb69fa2559edb520e7078d8deece1 usr/lib/debug/.build-id/8f/d911632d5485d72ec803070b61112513c09f79.debug

View file

@ -1,16 +0,0 @@
apt-ostree (0.1.0-2) trixie; urgency=medium
* Updated for Debian Trixie/Forky compatibility
* Updated rust-apt dependency to 0.9.0 for libapt-pkg7.0 support
* Added explicit libapt-pkg7.0 dependency
* Fixed library compatibility issues
-- Robojerk <robojerk@example.com> Tue, 13 Aug 2025 18:40:00 +0000
apt-ostree (0.1.0-1) trixie; urgency=medium
* Initial release
* Basic apt-ostree functionality
* Debian packaging support
-- Robojerk <robojerk@example.com> Tue, 13 Aug 2025 18:35:00 +0000

View file

@ -28,15 +28,81 @@ setup_completions() {
fi
}
# Function to check if systemd is available
check_systemd() {
if ! command -v systemctl >/dev/null 2>&1; then
log "Warning: systemd not available, skipping service setup"
return 1
fi
return 0
}
# Function to enable and start the service
setup_service() {
if ! check_systemd; then
return 0
fi
log "Setting up apt-ostreed service..."
# Reload systemd daemon
systemctl daemon-reload
# Enable the service
if systemctl enable apt-ostreed.service; then
log "apt-ostreed service enabled"
else
log "Warning: Failed to enable apt-ostreed service"
fi
# Start the service if not running
if ! systemctl is-active --quiet apt-ostreed.service; then
if systemctl start apt-ostreed.service; then
log "apt-ostreed service started"
else
log "Warning: Failed to start apt-ostreed service"
fi
else
log "apt-ostreed service already running"
fi
}
# Function to setup directories and permissions
setup_directories() {
log "Setting up directories and permissions..."
# Create necessary directories with proper permissions
mkdir -p /var/log/apt-ostreed
mkdir -p /var/cache/apt-ostree
mkdir -p /var/lib/apt-ostree
mkdir -p /var/lib/apt-ostree/repo
# Set proper ownership (root:root)
chown root:root /var/log/apt-ostreed
chown root:root /var/cache/apt-ostree
chown root:root /var/lib/apt-ostree
chown root:root /var/lib/apt-ostree/repo
# Set proper permissions
chmod 755 /var/log/apt-ostreed
chmod 755 /var/cache/apt-ostree
chmod 755 /var/lib/apt-ostree
chmod 755 /var/lib/apt-ostree/repo
}
# Function to reload polkit rules
reload_polkit() {
if command -v pkaction >/dev/null 2>&1; then
log "Reloading polkit rules..."
# This will trigger polkit to reload its rules
pkaction --version >/dev/null 2>&1 || true
fi
}
# Function to check dependencies
check_dependencies() {
log "Checking dependencies..."
# Check if apt-ostreed is installed and running
if ! dpkg -l apt-ostreed >/dev/null 2>&1; then
log "Warning: apt-ostreed package not found. Some features may not work."
fi
# Check if ostree is available
if ! command -v ostree >/dev/null 2>&1; then
log "Warning: ostree command not found. Please install ostree package."
@ -53,6 +119,9 @@ case "$1" in
configure)
log "Configuring apt-ostree package..."
setup_completions
setup_directories
setup_service
reload_polkit
check_dependencies
log "Configuration completed successfully"
;;

View file

@ -47,15 +47,73 @@ cleanup_man_pages() {
fi
}
# Function to cleanup daemon service
cleanup_daemon() {
log "Cleaning up apt-ostreed daemon..."
# Check if systemd is available
if ! command -v systemctl >/dev/null 2>&1; then
log "Warning: systemd not available, skipping service cleanup"
return 0
fi
# Stop the service if running
if systemctl is-active --quiet apt-ostreed.service; then
log "Stopping apt-ostreed service..."
systemctl stop apt-ostreed.service || true
fi
# Disable the service
if systemctl is-enabled --quiet apt-ostreed.service; then
log "Disabling apt-ostreed service..."
systemctl disable apt-ostreed.service || true
fi
# Reload systemd daemon
systemctl daemon-reload || true
}
# Function to cleanup daemon files
cleanup_daemon_files() {
log "Cleaning up daemon files..."
# Remove systemd service files
if [ -f /lib/systemd/system/apt-ostreed.service ]; then
rm -f /lib/systemd/system/apt-ostreed.service
fi
if [ -f /lib/systemd/system/apt-ostreed.socket ]; then
rm -f /lib/systemd/system/apt-ostreed.socket
fi
# Remove polkit policy
if [ -f /usr/share/polkit-1/actions/org.projectatomic.aptostree1.policy ]; then
rm -f /usr/share/polkit-1/actions/org.projectatomic.aptostree1.policy
fi
# Remove configuration files
if [ -d /etc/apt-ostreed ]; then
rm -rf /etc/apt-ostreed
fi
# Remove binary
if [ -f /usr/libexec/apt-ostreed ]; then
rm -f /usr/libexec/apt-ostreed
fi
}
# Main execution
case "$1" in
remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
cleanup_completions
cleanup_man_pages
cleanup_daemon
;;
purge)
cleanup_completions
cleanup_man_pages
cleanup_daemon
cleanup_daemon_files
;;
*)
log "Unknown action: $1"

12
debian/apt-ostree.postrm.debhelper vendored Normal file
View file

@ -0,0 +1,12 @@
# Automatically added by dh_installsystemd/13.24.2
if [ "$1" = remove ] && [ -d /run/systemd/system ] ; then
systemctl --system daemon-reload >/dev/null || true
fi
# End automatically added section
# Automatically added by dh_installsystemd/13.24.2
if [ "$1" = "purge" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper purge 'apt-ostreed.service' 'apt-ostreed.socket' >/dev/null || true
fi
fi
# End automatically added section

View file

@ -12,6 +12,7 @@ PACKAGE="apt-ostree"
# Configuration directories
CONFIG_DIR="/etc/apt-ostree"
DAEMON_CONFIG_DIR="/etc/apt-ostreed"
DATA_DIR="/var/lib/apt-ostree"
LOG_DIR="/var/log/apt-ostree"
@ -48,6 +49,14 @@ case "$1" in
fi
fi
# Stop the apt-ostreed daemon service if running
if command -v systemctl >/dev/null 2>&1; then
if systemctl is-active --quiet apt-ostreed.service; then
echo "Stopping apt-ostreed service..."
systemctl stop apt-ostreed.service || true
fi
fi
# Stop any running apt-ostree processes
if pgrep -f "apt-ostree" >/dev/null 2>&1; then
echo "Stopping running apt-ostree processes..."
@ -65,6 +74,11 @@ case "$1" in
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
if [ -d "$DAEMON_CONFIG_DIR" ]; then
mkdir -p "/tmp/apt-ostree-backup-$(date +%Y%m%d-%H%M%S)"
cp -r "$DAEMON_CONFIG_DIR" "/tmp/apt-ostree-backup-$(date +%Y%m%d-%H%M%S)/" || true
echo "Daemon configuration backed up to /tmp/apt-ostree-backup-*"
fi
fi
echo "$PACKAGE pre-removal completed"

View file

@ -7,3 +7,12 @@ interest-noawait /usr/share/zsh/vendor-completions
# Trigger when man pages are updated
interest-noawait /usr/share/man
# Trigger when polkit rules are updated
interest-noawait /usr/share/polkit-1/actions
# Trigger when systemd units are updated
interest-noawait /lib/systemd/system
# Trigger when D-Bus configuration is updated
interest-noawait /usr/share/dbus-1/system-services

2
debian/apt-ostree/DEBIAN/conffiles vendored Normal file
View file

@ -0,0 +1,2 @@
/etc/apt-ostreed/apt-ostreed.conf
/etc/apt-ostreed/apt-ostreed.conf

View file

@ -2,8 +2,8 @@ Package: apt-ostree
Version: 0.1.0-2
Architecture: amd64
Maintainer: Robojerk <robojerk@example.com>
Installed-Size: 3655
Depends: libc6 (>= 2.39), libgcc-s1 (>= 4.2), libostree-1-1 (>= 2025.2), ostree, systemd, libapt-pkg7.0 (>= 3.0.0), apt-ostreed (= 0.1.0-2)
Installed-Size: 6525
Depends: libc6 (>= 2.39), libgcc-s1 (>= 4.2), libostree-1-1 (>= 2025.2), ostree, systemd, libapt-pkg7.0 (>= 3.0.0), polkitd, dbus
Section: admin
Priority: optional
Homepage: https://github.com/robojerk/apt-ostree
@ -15,4 +15,9 @@ Description: Debian/Ubuntu equivalent of rpm-ostree
APT package management, enabling atomic updates and rollbacks
on Debian-based systems.
.
This package contains the command-line interface and user tools.
This package contains both the command-line interface and the
system daemon (apt-ostreed) that provides DBus interface for
system management operations.
.
The daemon runs with elevated privileges and provides secure
access to system management functions through D-Bus.

View file

@ -1,8 +1,12 @@
fdb041b5a80001bc08f3f94bcb3daf37 usr/bin/apt-ostree
a485e242b07f321593e7711f9f7b43d7 lib/systemd/system/apt-ostreed.service
bd58c49830864047894e04d986d850db lib/systemd/system/apt-ostreed.socket
4fefc30bb5f348ff65663f7677cd69d8 usr/bin/apt-ostree
4a710566895db1003adccd614e0c8aca usr/libexec/apt-ostreed
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
25df758a27389af0cfd52f4dce60ccce usr/share/doc/apt-ostree/copyright
1699c458f49ca15357c5855075e0eee6 usr/share/lintian/overrides/apt-ostree
e2cca69674af05683b8aa52427a840e8 usr/share/man/man1/apt-ostree.1.gz
863ffbba8bf3105e2cb0c34c90bf5cbe usr/share/polkit-1/actions/org.projectatomic.aptostree1.policy
d057f9ea83226bd3e48795fac1e224b6 usr/share/zsh/vendor-completions/_apt-ostree

View file

@ -28,15 +28,81 @@ setup_completions() {
fi
}
# Function to check if systemd is available
check_systemd() {
if ! command -v systemctl >/dev/null 2>&1; then
log "Warning: systemd not available, skipping service setup"
return 1
fi
return 0
}
# Function to enable and start the service
setup_service() {
if ! check_systemd; then
return 0
fi
log "Setting up apt-ostreed service..."
# Reload systemd daemon
systemctl daemon-reload
# Enable the service
if systemctl enable apt-ostreed.service; then
log "apt-ostreed service enabled"
else
log "Warning: Failed to enable apt-ostreed service"
fi
# Start the service if not running
if ! systemctl is-active --quiet apt-ostreed.service; then
if systemctl start apt-ostreed.service; then
log "apt-ostreed service started"
else
log "Warning: Failed to start apt-ostreed service"
fi
else
log "apt-ostreed service already running"
fi
}
# Function to setup directories and permissions
setup_directories() {
log "Setting up directories and permissions..."
# Create necessary directories with proper permissions
mkdir -p /var/log/apt-ostreed
mkdir -p /var/cache/apt-ostree
mkdir -p /var/lib/apt-ostree
mkdir -p /var/lib/apt-ostree/repo
# Set proper ownership (root:root)
chown root:root /var/log/apt-ostreed
chown root:root /var/cache/apt-ostree
chown root:root /var/lib/apt-ostree
chown root:root /var/lib/apt-ostree/repo
# Set proper permissions
chmod 755 /var/log/apt-ostreed
chmod 755 /var/cache/apt-ostree
chmod 755 /var/lib/apt-ostree
chmod 755 /var/lib/apt-ostree/repo
}
# Function to reload polkit rules
reload_polkit() {
if command -v pkaction >/dev/null 2>&1; then
log "Reloading polkit rules..."
# This will trigger polkit to reload its rules
pkaction --version >/dev/null 2>&1 || true
fi
}
# Function to check dependencies
check_dependencies() {
log "Checking dependencies..."
# Check if apt-ostreed is installed and running
if ! dpkg -l apt-ostreed >/dev/null 2>&1; then
log "Warning: apt-ostreed package not found. Some features may not work."
fi
# Check if ostree is available
if ! command -v ostree >/dev/null 2>&1; then
log "Warning: ostree command not found. Please install ostree package."
@ -53,6 +119,9 @@ case "$1" in
configure)
log "Configuring apt-ostree package..."
setup_completions
setup_directories
setup_service
reload_polkit
check_dependencies
log "Configuration completed successfully"
;;

View file

@ -47,15 +47,73 @@ cleanup_man_pages() {
fi
}
# Function to cleanup daemon service
cleanup_daemon() {
log "Cleaning up apt-ostreed daemon..."
# Check if systemd is available
if ! command -v systemctl >/dev/null 2>&1; then
log "Warning: systemd not available, skipping service cleanup"
return 0
fi
# Stop the service if running
if systemctl is-active --quiet apt-ostreed.service; then
log "Stopping apt-ostreed service..."
systemctl stop apt-ostreed.service || true
fi
# Disable the service
if systemctl is-enabled --quiet apt-ostreed.service; then
log "Disabling apt-ostreed service..."
systemctl disable apt-ostreed.service || true
fi
# Reload systemd daemon
systemctl daemon-reload || true
}
# Function to cleanup daemon files
cleanup_daemon_files() {
log "Cleaning up daemon files..."
# Remove systemd service files
if [ -f /lib/systemd/system/apt-ostreed.service ]; then
rm -f /lib/systemd/system/apt-ostreed.service
fi
if [ -f /lib/systemd/system/apt-ostreed.socket ]; then
rm -f /lib/systemd/system/apt-ostreed.socket
fi
# Remove polkit policy
if [ -f /usr/share/polkit-1/actions/org.projectatomic.aptostree1.policy ]; then
rm -f /usr/share/polkit-1/actions/org.projectatomic.aptostree1.policy
fi
# Remove configuration files
if [ -d /etc/apt-ostreed ]; then
rm -rf /etc/apt-ostreed
fi
# Remove binary
if [ -f /usr/libexec/apt-ostreed ]; then
rm -f /usr/libexec/apt-ostreed
fi
}
# Main execution
case "$1" in
remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
cleanup_completions
cleanup_man_pages
cleanup_daemon
;;
purge)
cleanup_completions
cleanup_man_pages
cleanup_daemon
cleanup_daemon_files
;;
*)
log "Unknown action: $1"

View file

@ -12,6 +12,7 @@ PACKAGE="apt-ostree"
# Configuration directories
CONFIG_DIR="/etc/apt-ostree"
DAEMON_CONFIG_DIR="/etc/apt-ostreed"
DATA_DIR="/var/lib/apt-ostree"
LOG_DIR="/var/log/apt-ostree"
@ -48,6 +49,14 @@ case "$1" in
fi
fi
# Stop the apt-ostreed daemon service if running
if command -v systemctl >/dev/null 2>&1; then
if systemctl is-active --quiet apt-ostreed.service; then
echo "Stopping apt-ostreed service..."
systemctl stop apt-ostreed.service || true
fi
fi
# Stop any running apt-ostree processes
if pgrep -f "apt-ostree" >/dev/null 2>&1; then
echo "Stopping running apt-ostree processes..."
@ -65,6 +74,11 @@ case "$1" in
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
if [ -d "$DAEMON_CONFIG_DIR" ]; then
mkdir -p "/tmp/apt-ostree-backup-$(date +%Y%m%d-%H%M%S)"
cp -r "$DAEMON_CONFIG_DIR" "/tmp/apt-ostree-backup-$(date +%Y%m%d-%H%M%S)/" || true
echo "Daemon configuration backed up to /tmp/apt-ostree-backup-*"
fi
fi
echo "$PACKAGE pre-removal completed"

View file

@ -7,3 +7,12 @@ interest-noawait /usr/share/zsh/vendor-completions
# Trigger when man pages are updated
interest-noawait /usr/share/man
# Trigger when polkit rules are updated
interest-noawait /usr/share/polkit-1/actions
# Trigger when systemd units are updated
interest-noawait /lib/systemd/system
# Trigger when D-Bus configuration is updated
interest-noawait /usr/share/dbus-1/system-services

View file

@ -0,0 +1,44 @@
# apt-ostreed Configuration File
# This file configures the apt-ostree daemon behavior
[Daemon]
# OSTree repository path
RepoPath=/var/lib/apt-ostree/repo
# APT configuration
AptCacheDir=/var/cache/apt-ostree
AptStateDir=/var/lib/apt-ostree/apt
# Transaction management
TransactionTimeout=300
MaxConcurrentTransactions=1
# Automatic update settings
AutomaticEnabled=false
AutomaticSecurityOnly=true
AutomaticReboot=false
# Logging configuration
LogLevel=info
LogFile=/var/log/apt-ostreed.log
# D-Bus configuration
DbusName=org.aptostree.dev
DbusPath=/org/aptostree/dev
# Security settings
RequireAuthentication=true
AllowUnprivilegedRead=true
# Debian/Ubuntu specific settings
Distribution=ubuntu
Release=24.04
Architecture=x86_64
# Package management
DefaultRepositories=main,universe,multiverse,restricted
SecurityRepositories=security
# OSTree settings
OstreeMode=bare
OstreeRef=ubuntu/24.04/x86_64

View file

@ -0,0 +1,30 @@
[Unit]
Description=apt-ostree System Management Daemon
Documentation=man:apt-ostree(1)
ConditionPathExists=/ostree
RequiresMountsFor=/boot
[Service]
# See similar code in apt-ostree-countme.service
User=apt-ostree
DynamicUser=yes
# Our primary API is DBus
Type=dbus
BusName=org.projectatomic.aptostree1
# To use the read-only sysroot bits
MountFlags=slave
# We have no business accessing /var/roothome or /var/home
ProtectHome=true
NotifyAccess=main
# Significantly bump this timeout from the default because
# we do a lot of stuff on daemon startup.
TimeoutStartSec=5m
# We start this main process with full privileges; it may spawn unprivileged processes
# with the apt-ostree user.
ExecStart=+apt-ostree start-daemon
ExecReload=apt-ostree reload
# disable/enable downloading filelists
Environment="DOWNLOAD_FILELISTS=false"
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,12 @@
[Unit]
Description=apt-ostree System Management Daemon Socket
Documentation=man:apt-ostree(1)
[Socket]
ListenStream=/run/apt-ostreed.sock
SocketMode=0660
SocketUser=apt-ostree
SocketGroup=apt-ostree
[Install]
WantedBy=sockets.target

Binary file not shown.

BIN
debian/apt-ostree/usr/libexec/apt-ostreed vendored Executable file

Binary file not shown.

View file

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
<vendor>Project Atomic</vendor>
<vendor_url>https://www.projectatomic.io/</vendor_url>
<icon_name>package-x-generic</icon_name>
<action id="org.projectatomic.aptostree1.install-uninstall-packages">
<description>Install and remove packages</description>
<message>Authentication is required to install and remove software</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.install-local-packages">
<description>Install local packages</description>
<message>Authentication is required to install software</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.override">
<description>Override packages</description>
<message>Authentication is required to override base OS software</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.deploy">
<description>Update base OS</description>
<message>Authentication is required to update software</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.upgrade">
<description>Update base OS</description>
<message>Authentication is required to update software</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.rebase">
<description>Switch to a different base OS</description>
<message>Authentication is required to switch to a different base OS</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.rollback">
<description>Rollback OS updates</description>
<message>Authentication is required to roll back software updates</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.bootconfig">
<description>Change boot configuration</description>
<message>Authentication is required to change boot configuration</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.reload-daemon">
<description>Reload the daemon state</description>
<message>Authentication is required to reload the daemon</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.cleanup">
<description>Clean up system state</description>
<message>Authentication is required to clean up system state</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.initramfs">
<description>Manage initramfs</description>
<message>Authentication is required to manage initramfs</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.projectatomic.aptostree1.kargs">
<description>Manage kernel arguments</description>
<message>Authentication is required to manage kernel arguments</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>

View file

@ -1,104 +0,0 @@
#!/bin/sh
set -e
# Source debconf library
. /usr/share/debconf/confmodule
# Define package name
PACKAGE="apt-ostreed"
# Function to log messages
log() {
echo "$PACKAGE: $1" >&2
}
# Function to check if systemd is available
check_systemd() {
if ! command -v systemctl >/dev/null 2>&1; then
log "Warning: systemd not available, skipping service setup"
return 1
fi
return 0
}
# Function to enable and start the service
setup_service() {
if ! check_systemd; then
return 0
fi
log "Setting up apt-ostreed service..."
# Reload systemd daemon
systemctl daemon-reload
# Enable the service
if systemctl enable apt-ostreed.service; then
log "apt-ostreed service enabled"
else
log "Warning: Failed to enable apt-ostreed service"
fi
# Start the service if not running
if ! systemctl is-active --quiet apt-ostreed.service; then
if systemctl start apt-ostreed.service; then
log "apt-ostreed service started"
else
log "Warning: Failed to start apt-ostreed service"
fi
else
log "apt-ostreed service already running"
fi
}
# Function to setup directories and permissions
setup_directories() {
log "Setting up directories and permissions..."
# Create necessary directories with proper permissions
mkdir -p /var/log/apt-ostreed
mkdir -p /var/cache/apt-ostree
mkdir -p /var/lib/apt-ostree
mkdir -p /var/lib/apt-ostree/repo
# Set proper ownership (root:root)
chown root:root /var/log/apt-ostreed
chown root:root /var/cache/apt-ostree
chown root:root /var/lib/apt-ostree
chown root:root /var/lib/apt-ostree/repo
# Set proper permissions
chmod 755 /var/log/apt-ostreed
chmod 755 /var/cache/apt-ostree
chmod 755 /var/lib/apt-ostree
chmod 755 /var/lib/apt-ostree/repo
}
# Function to reload polkit rules
reload_polkit() {
if command -v pkaction >/dev/null 2>&1; then
log "Reloading polkit rules..."
# This will trigger polkit to reload its rules
pkaction --version >/dev/null 2>&1 || true
fi
}
# Main execution
case "$1" in
configure)
log "Configuring apt-ostreed package..."
setup_directories
setup_service
reload_polkit
log "Configuration completed successfully"
;;
abort-upgrade|abort-remove|abort-deconfigure)
# Do nothing on abort
;;
*)
log "Unknown action: $1"
exit 1
;;
esac
exit 0

View file

@ -1,86 +0,0 @@
#!/bin/sh
set -e
# Source debconf library
. /usr/share/debconf/confmodule
# Define package name
PACKAGE="apt-ostreed"
# Function to log messages
log() {
echo "$PACKAGE: $1" >&2
}
# Function to check if systemd is available
check_systemd() {
if ! command -v systemctl >/dev/null 2>&1; then
return 1
fi
return 0
}
# Function to stop and disable the service
cleanup_service() {
if ! check_systemd; then
return 0
fi
log "Cleaning up apt-ostreed service..."
# Stop the service if running
if systemctl is-active --quiet apt-ostreed.service; then
if systemctl stop apt-ostreed.service; then
log "apt-ostreed service stopped"
else
log "Warning: Failed to stop apt-ostreed service"
fi
fi
# Disable the service
if systemctl is-enabled --quiet apt-ostreed.service; then
if systemctl disable apt-ostreed.service; then
log "apt-ostreed service disabled"
else
log "Warning: Failed to disable apt-ostreed service"
fi
fi
# Reload systemd daemon
systemctl daemon-reload
}
# Function to cleanup directories (only on purge)
cleanup_directories() {
if [ "$1" = "purge" ]; then
log "Purging apt-ostreed directories..."
# Remove log files (but keep directory structure)
rm -f /var/log/apt-ostreed/*
# Remove cache files (but keep directory structure)
rm -rf /var/cache/apt-ostree/*
# Remove state files (but keep directory structure)
rm -rf /var/lib/apt-ostree/*
log "Directory cleanup completed"
fi
}
# Main execution
case "$1" in
remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
cleanup_service
;;
purge)
cleanup_service
cleanup_directories "$1"
;;
*)
log "Unknown action: $1"
exit 1
;;
esac
exit 0

View file

@ -1,3 +0,0 @@
shlibs:Depends=libc6 (>= 2.39), libgcc-s1 (>= 4.2)
misc:Depends=
misc:Pre-Depends=

View file

@ -1,11 +0,0 @@
# apt-ostreed package triggers
# This file defines triggers that are activated when certain events occur
# Trigger when polkit rules are updated
interest-noawait /usr/share/polkit-1/actions
# Trigger when systemd units are updated
interest-noawait /lib/systemd/system
# Trigger when D-Bus configuration is updated
interest-noawait /usr/share/dbus-1/system-services

Binary file not shown.

View file

@ -0,0 +1 @@
{"v":1}

View file

@ -0,0 +1,6 @@
{
"git": {
"sha1": "342af76b486335e5a955c7314fc96cd104e7a17b"
},
"path_in_vcs": ""
}

View file

@ -0,0 +1,2 @@
github: seanmonstar
patreon: seanmonstar

View file

@ -0,0 +1,160 @@
name: CI
on:
pull_request:
push:
branches:
- master
env:
RUST_BACKTRACE: 1
CARGO_TERM_COLOR: always
jobs:
ci-pass:
name: CI is green
runs-on: ubuntu-latest
needs:
- msrv
- test-linux
- test-macos
- test-windows
- build-cross
- test-cgroups
steps:
- run: exit 0
msrv:
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- 1.13
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
rustup default ${{ matrix.rust }}
cargo update
cargo update -p libc --precise 0.2.26
cargo test --verbose
test-linux:
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- beta
- nightly
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
rustup default ${{ matrix.rust }}
rustup target add ${{ matrix.target }}
cargo test --verbose --target ${{ matrix.target }}
test-macos:
runs-on: macos-latest
strategy:
matrix:
rust:
- stable
- beta
- nightly
target:
- x86_64-apple-darwin
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
rustup default ${{ matrix.rust }}
rustup target add ${{ matrix.target }}
cargo test --verbose --target ${{ matrix.target }}
test-windows:
runs-on: windows-latest
strategy:
matrix:
rust:
- stable
- beta
- nightly
target:
- x86_64-pc-windows-gnu
- x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
rustup default ${{ matrix.rust }}
rustup target add ${{ matrix.target }}
cargo test --verbose --target ${{ matrix.target }}
build-cross:
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
target:
- aarch64-unknown-linux-gnu
- i686-pc-windows-gnu
- i686-pc-windows-msvc
- i686-unknown-linux-gnu
- aarch64-apple-darwin
- aarch64-pc-windows-msvc
- aarch64-unknown-linux-musl
- arm-unknown-linux-gnueabi
- arm-unknown-linux-gnueabihf
- armv7-unknown-linux-gnueabihf
- powerpc-unknown-linux-gnu
- powerpc64-unknown-linux-gnu
- powerpc64le-unknown-linux-gnu
- riscv64gc-unknown-linux-gnu
- s390x-unknown-linux-gnu
- x86_64-unknown-freebsd
- x86_64-unknown-illumos
- x86_64-unknown-netbsd
- i686-linux-android
- x86_64-linux-android
- arm-linux-androideabi
- aarch64-linux-android
- x86_64-apple-ios
- aarch64-apple-ios
- aarch64-apple-ios-sim
- aarch64-apple-darwin
steps:
- uses: actions/checkout@v3
- name: Run build
run: |
rustup default ${{ matrix.rust }}
rustup target add ${{ matrix.target }}
cargo build --verbose --target ${{ matrix.target }}
test-cgroups:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Test Cgroup
run: |
docker build -f ci/cgroups/Dockerfile -t num-cpus-cgroups .
# Test without cgroups
docker run -e NUM_CPUS_TEST_GET=4 num-cpus-cgroups
# Only 1 CPU
docker run --cpus="1" -e NUM_CPUS_TEST_GET=1 num-cpus-cgroups
# 1.5 CPUs
docker run --cpus="1.5" -e NUM_CPUS_TEST_GET=2 num-cpus-cgroups

View file

@ -0,0 +1,2 @@
target
Cargo.lock

View file

@ -0,0 +1,167 @@
## v1.17.0
### Fixes
- update hermit-abi to 0.5.0
- remove special support for nacl
## v1.16.0
### Features
- add support for AIX operating system
### Fixes
- update hermit-abi to 0.3.0
## v1.15.0
### Fixes
- update hermit-abi
## v1.14.0
### Features
- add support for cgroups v2
- Skip reading files in Miri
## v1.13.1
### Fixes
- fix parsing zero or multiple optional fields in cgroup mountinfo.
## v1.13.0
### Features
- add Linux cgroups support when calling `get()`.
## v1.12.0
#### Fixes
- fix `get` on OpenBSD to ignore offline CPUs
- implement `get_physical` on OpenBSD
## v1.11.1
#### Fixes
- Use `mem::zeroed` instead of `mem::uninitialized`.
## v1.11.0
#### Features
- add `hermit` target OS support
- removes `bitrig` support
#### Fixes
- fix `get_physical` count with AMD hyperthreading.
## v1.10.1
#### Fixes
- improve `haiku` CPU detection
## v1.10.0
#### Features
- add `illumos` target OS support
- add default fallback if target is unknown to `1`
## v1.9.0
#### Features
- add `sgx` target env support
## v1.8.0
#### Features
- add `wasm-unknown-unknown` target support
## v1.7.0
#### Features
- add `get_physical` support for macOS
#### Fixes
- use `_SC_NPROCESSORS_CONF` on Unix targets
### v1.6.2
#### Fixes
- revert 1.6.1 for now
### v1.6.1
#### Fixes
- fixes sometimes incorrect num on Android/ARM Linux (#45)
## v1.6.0
#### Features
- `get_physical` gains Windows support
### v1.5.1
#### Fixes
- fix `get` to return 1 if `sysconf(_SC_NPROCESSORS_ONLN)` failed
## v1.5.0
#### Features
- `get()` now checks `sched_affinity` on Linux
## v1.4.0
#### Features
- add `haiku` target support
## v1.3.0
#### Features
- add `redox` target support
### v1.2.1
#### Fixes
- fixes `get_physical` count (454ff1b)
## v1.2.0
#### Features
- add `emscripten` target support
- add `fuchsia` target support
## v1.1.0
#### Features
- added `get_physical` function to return number of physical CPUs found
# v1.0.0
#### Features
- `get` function returns number of CPUs (physical and virtual) of current platform

View file

@ -0,0 +1,16 @@
# Contributing
## License
Licensed under either of
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.

View file

@ -0,0 +1,46 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
name = "num_cpus"
version = "1.17.0"
authors = ["Sean McArthur <sean@seanmonstar.com>"]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Get the number of CPUs on a machine."
documentation = "https://docs.rs/num_cpus"
readme = "README.md"
keywords = [
"cpu",
"cpus",
"cores",
]
categories = ["hardware-support"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/seanmonstar/num_cpus"
[lib]
name = "num_cpus"
path = "src/lib.rs"
[[example]]
name = "values"
path = "examples/values.rs"
[target."cfg(not(windows))".dependencies.libc]
version = "0.2.26"
[target.'cfg(target_os = "hermit")'.dependencies.hermit-abi]
version = "0.5.0"

View file

@ -0,0 +1,18 @@
[package]
name = "num_cpus"
version = "1.17.0"
description = "Get the number of CPUs on a machine."
authors = ["Sean McArthur <sean@seanmonstar.com>"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/seanmonstar/num_cpus"
documentation = "https://docs.rs/num_cpus"
keywords = ["cpu", "cpus", "cores"]
categories = ["hardware-support"]
readme = "README.md"
[target.'cfg(not(windows))'.dependencies]
libc = "0.2.26"
[target.'cfg(target_os = "hermit")'.dependencies]
hermit-abi = "0.5.0"

View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,20 @@
Copyright (c) 2015-2025 Sean McArthur
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:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
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.

View file

@ -0,0 +1,27 @@
# num_cpus
[![crates.io](https://img.shields.io/crates/v/num_cpus.svg)](https://crates.io/crates/num_cpus)
[![CI Status](https://github.com/seanmonstar/num_cpus/actions/workflows/ci.yml/badge.svg)](https://github.com/seanmonstar/num_cpus/actions)
- [Documentation](https://docs.rs/num_cpus)
- [CHANGELOG](CHANGELOG.md)
Count the number of CPUs on the current machine.
## Usage
Add to Cargo.toml:
```toml
[dependencies]
num_cpus = "1.0"
```
In your `main.rs` or `lib.rs`:
```rust
extern crate num_cpus;
// count logical cores this process could try to use
let num = num_cpus::get();
```

View file

@ -0,0 +1,9 @@
FROM rust:latest
WORKDIR /usr/num_cpus
COPY . .
RUN cargo build
CMD [ "cargo", "test", "--lib" ]

View file

@ -0,0 +1,6 @@
extern crate num_cpus;
fn main() {
println!("Logical CPUs: {}", num_cpus::get());
println!("Physical CPUs: {}", num_cpus::get_physical());
}

View file

@ -0,0 +1,3 @@
12:perf_event:/
11:cpu,cpuacct:/
3:devices:/user.slice

View file

@ -0,0 +1,8 @@
1 0 8:1 / / rw,noatime shared:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=reordered
2 1 0:1 / /dev rw,relatime shared:2 - devtmpfs udev rw,size=10240k,nr_inodes=16487629,mode=755
3 1 0:2 / /proc rw,nosuid,nodev,noexec,relatime shared:3 - proc proc rw
4 1 0:3 / /sys rw,nosuid,nodev,noexec,relatime shared:4 - sysfs sysfs rw
5 4 0:4 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:5 - tmpfs tmpfs ro,mode=755
6 5 0:5 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:6 - cgroup cgroup rw,cpuset
7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup rw,cpu,cpuacct
8 5 0:7 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:8 - cgroup cgroup rw,memory

View file

@ -0,0 +1,8 @@
1 0 8:1 / / rw,noatime shared:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=reordered
2 1 0:1 / /dev rw,relatime shared:2 - devtmpfs udev rw,size=10240k,nr_inodes=16487629,mode=755
3 1 0:2 / /proc rw,nosuid,nodev,noexec,relatime shared:3 - proc proc rw
4 1 0:3 / /sys rw,nosuid,nodev,noexec,relatime shared:4 - sysfs sysfs rw
5 4 0:4 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:5 - tmpfs tmpfs ro,mode=755
6 5 0:5 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:6 - cgroup cgroup rw,cpuset
7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 shared:8 shared:9 - cgroup cgroup rw,cpu,cpuacct
8 5 0:7 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:8 - cgroup cgroup rw,memory

View file

@ -0,0 +1,8 @@
1 0 8:1 / / rw,noatime shared:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=reordered
2 1 0:1 / /dev rw,relatime shared:2 - devtmpfs udev rw,size=10240k,nr_inodes=16487629,mode=755
3 1 0:2 / /proc rw,nosuid,nodev,noexec,relatime shared:3 - proc proc rw
4 1 0:3 / /sys rw,nosuid,nodev,noexec,relatime shared:4 - sysfs sysfs rw
5 4 0:4 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:5 - tmpfs tmpfs ro,mode=755
6 5 0:5 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:6 - cgroup cgroup rw,cpuset
7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpu,cpuacct
8 5 0:7 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:8 - cgroup cgroup rw,memory

View file

@ -0,0 +1,3 @@
12::/
11:cpu,cpuacct:/
3::/user.slice

View file

@ -0,0 +1,5 @@
1 0 8:1 / / rw,noatime shared:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=reordered
2 1 0:1 / /dev rw,relatime shared:2 - devtmpfs udev rw,size=10240k,nr_inodes=16487629,mode=755
3 1 0:2 / /proc rw,nosuid,nodev,noexec,relatime shared:3 - proc proc rw
4 1 0:3 / /sys rw,nosuid,nodev,noexec,relatime shared:4 - sysfs sysfs rw
5 4 0:4 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 cgroup2 rw,nsdelegate,memory_recursiveprot

View file

@ -0,0 +1,483 @@
//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! Sometimes the CPU will exaggerate the number of CPUs it contains, because it can use
//! [processor tricks] to deliver increased performance when there are more threads. This
//! crate provides methods to get both the logical and physical numbers of cores.
//!
//! This information can be used as a guide to how many tasks can be run in parallel.
//! There are many properties of the system architecture that will affect parallelism,
//! for example memory access speeds (for all the caches and RAM) and the physical
//! architecture of the processor, so the number of CPUs should be used as a rough guide
//! only.
//!
//!
//! ## Examples
//!
//! Fetch the number of logical CPUs.
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
//!
//! See [`rayon::Threadpool`] for an example of where the number of CPUs could be
//! used when setting up parallel jobs (Where the threadpool example uses a fixed
//! number 8, it could use the number of CPUs).
//!
//! [processor tricks]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
//! [`rayon::ThreadPool`]: https://docs.rs/rayon/1.*/rayon/struct.ThreadPool.html
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]
#[cfg(not(windows))]
extern crate libc;
#[cfg(target_os = "hermit")]
extern crate hermit_abi;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
use linux::{get_num_cpus, get_num_physical_cpus};
/// Returns the number of available CPUs of the current system.
///
/// This function will get the number of logical cores. Sometimes this is different from the number
/// of physical cores (See [Simultaneous multithreading on Wikipedia][smt]).
///
/// This will always return at least `1`.
///
/// # Examples
///
/// ```
/// let cpus = num_cpus::get();
/// if cpus > 1 {
/// println!("We are on a multicore system with {} CPUs", cpus);
/// } else {
/// println!("We are on a single core system");
/// }
/// ```
///
/// # Note
///
/// This will check [sched affinity] on Linux, showing a lower number of CPUs if the current
/// thread does not have access to all the computer's CPUs.
///
/// This will also check [cgroups], frequently used in containers to constrain CPU usage.
///
/// [smt]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
/// [sched affinity]: http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html
/// [cgroups]: https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
#[inline]
pub fn get() -> usize {
get_num_cpus()
}
/// Returns the number of physical cores of the current system.
///
/// This will always return at least `1`.
///
/// # Note
///
/// Physical count is supported only on Linux, mac OS and Windows platforms.
/// On other platforms, or if the physical count fails on supported platforms,
/// this function returns the same as [`get()`], which is the number of logical
/// CPUS.
///
/// # Examples
///
/// ```
/// let logical_cpus = num_cpus::get();
/// let physical_cpus = num_cpus::get_physical();
/// if logical_cpus > physical_cpus {
/// println!("We have simultaneous multithreading with about {:.2} \
/// logical cores to 1 physical core.",
/// (logical_cpus as f64) / (physical_cpus as f64));
/// } else if logical_cpus == physical_cpus {
/// println!("Either we don't have simultaneous multithreading, or our \
/// system doesn't support getting the number of physical CPUs.");
/// } else {
/// println!("We have less logical CPUs than physical CPUs, maybe we only have access to \
/// some of the CPUs on our system.");
/// }
/// ```
///
/// [`get()`]: fn.get.html
#[inline]
pub fn get_physical() -> usize {
get_num_physical_cpus()
}
#[cfg(not(any(
target_os = "linux",
target_os = "windows",
target_os = "macos",
target_os = "openbsd",
target_os = "aix")))]
#[inline]
fn get_num_physical_cpus() -> usize {
// Not implemented, fall back
get_num_cpus()
}
#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
match get_num_physical_cpus_windows() {
Some(num) => num,
None => get_num_cpus()
}
}
#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
// Inspired by https://msdn.microsoft.com/en-us/library/ms683194
use std::ptr;
use std::mem;
#[allow(non_upper_case_globals)]
const RelationProcessorCore: u32 = 0;
#[repr(C)]
#[allow(non_camel_case_types)]
struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
mask: usize,
relationship: u32,
_unused: [u64; 2]
}
extern "system" {
fn GetLogicalProcessorInformation(
info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
length: &mut u32
) -> u32;
}
// First we need to determine how much space to reserve.
// The required size of the buffer, in bytes.
let mut needed_size = 0;
unsafe {
GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
}
let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;
// Could be 0, or some other bogus size.
if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
return None;
}
let count = needed_size / struct_size;
// Allocate some memory where we will store the processor info.
let mut buf = Vec::with_capacity(count as usize);
let result;
unsafe {
result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
}
// Failed for any reason.
if result == 0 {
return None;
}
let count = needed_size / struct_size;
unsafe {
buf.set_len(count as usize);
}
let phys_proc_count = buf.iter()
// Only interested in processor packages (physical processors.)
.filter(|proc_info| proc_info.relationship == RelationProcessorCore)
.count();
if phys_proc_count == 0 {
None
} else {
Some(phys_proc_count)
}
}
#[cfg(windows)]
fn get_num_cpus() -> usize {
#[repr(C)]
struct SYSTEM_INFO {
wProcessorArchitecture: u16,
wReserved: u16,
dwPageSize: u32,
lpMinimumApplicationAddress: *mut u8,
lpMaximumApplicationAddress: *mut u8,
dwActiveProcessorMask: *mut u8,
dwNumberOfProcessors: u32,
dwProcessorType: u32,
dwAllocationGranularity: u32,
wProcessorLevel: u16,
wProcessorRevision: u16,
}
extern "system" {
fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
}
unsafe {
let mut sysinfo: SYSTEM_INFO = std::mem::zeroed();
GetSystemInfo(&mut sysinfo);
sysinfo.dwNumberOfProcessors as usize
}
}
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly",
target_os = "netbsd"))]
fn get_num_cpus() -> usize {
use std::ptr;
let mut cpus: libc::c_uint = 0;
let mut cpus_size = std::mem::size_of_val(&cpus);
unsafe {
cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
}
if cpus < 1 {
let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
unsafe {
libc::sysctl(mib.as_mut_ptr(),
2,
&mut cpus as *mut _ as *mut _,
&mut cpus_size as *mut _ as *mut _,
ptr::null_mut(),
0);
}
if cpus < 1 {
cpus = 1;
}
}
cpus as usize
}
#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
use std::ptr;
let mut cpus: libc::c_uint = 0;
let mut cpus_size = std::mem::size_of_val(&cpus);
let mut mib = [libc::CTL_HW, libc::HW_NCPUONLINE, 0, 0];
let rc: libc::c_int;
unsafe {
rc = libc::sysctl(mib.as_mut_ptr(),
2,
&mut cpus as *mut _ as *mut _,
&mut cpus_size as *mut _ as *mut _,
ptr::null_mut(),
0);
}
if rc < 0 {
cpus = 1;
}
cpus as usize
}
#[cfg(target_os = "openbsd")]
fn get_num_physical_cpus() -> usize {
use std::ptr;
let mut cpus: libc::c_uint = 0;
let mut cpus_size = std::mem::size_of_val(&cpus);
let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
let rc: libc::c_int;
unsafe {
rc = libc::sysctl(mib.as_mut_ptr(),
2,
&mut cpus as *mut _ as *mut _,
&mut cpus_size as *mut _ as *mut _,
ptr::null_mut(),
0);
}
if rc < 0 {
cpus = 1;
}
cpus as usize
}
#[cfg(target_os = "macos")]
fn get_num_physical_cpus() -> usize {
use std::ffi::CStr;
use std::ptr;
let mut cpus: i32 = 0;
let mut cpus_size = std::mem::size_of_val(&cpus);
let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
.expect("byte literal is missing NUL");
unsafe {
if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
&mut cpus as *mut _ as *mut _,
&mut cpus_size as *mut _ as *mut _,
ptr::null_mut(),
0) {
return get_num_cpus();
}
}
cpus as usize
}
#[cfg(target_os = "aix")]
fn get_num_physical_cpus() -> usize {
match get_smt_threads_aix() {
Some(num) => get_num_cpus() / num,
None => get_num_cpus(),
}
}
#[cfg(target_os = "aix")]
fn get_smt_threads_aix() -> Option<usize> {
let smt = unsafe {
libc::getsystemcfg(libc::SC_SMT_TC)
};
if smt == u64::MAX {
return None;
}
Some(smt as usize)
}
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "aix",
target_os = "solaris",
target_os = "illumos",
target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
// On ARM targets, processors could be turned off to save power.
// Use `_SC_NPROCESSORS_CONF` to get the real number.
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_CONF;
#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_ONLN;
let cpus = unsafe { libc::sysconf(CONF_NAME) };
if cpus < 1 {
1
} else {
cpus as usize
}
}
#[cfg(target_os = "haiku")]
fn get_num_cpus() -> usize {
use std::mem;
#[allow(non_camel_case_types)]
type bigtime_t = i64;
#[allow(non_camel_case_types)]
type status_t = i32;
#[repr(C)]
pub struct system_info {
pub boot_time: bigtime_t,
pub cpu_count: u32,
pub max_pages: u64,
pub used_pages: u64,
pub cached_pages: u64,
pub block_cache_pages: u64,
pub ignored_pages: u64,
pub needed_memory: u64,
pub free_memory: u64,
pub max_swap_pages: u64,
pub free_swap_pages: u64,
pub page_faults: u32,
pub max_sems: u32,
pub used_sems: u32,
pub max_ports: u32,
pub used_ports: u32,
pub max_threads: u32,
pub used_threads: u32,
pub max_teams: u32,
pub used_teams: u32,
pub kernel_name: [::std::os::raw::c_char; 256usize],
pub kernel_build_date: [::std::os::raw::c_char; 32usize],
pub kernel_build_time: [::std::os::raw::c_char; 32usize],
pub kernel_version: i64,
pub abi: u32,
}
extern {
fn get_system_info(info: *mut system_info) -> status_t;
}
let mut info: system_info = unsafe { mem::zeroed() };
let status = unsafe { get_system_info(&mut info as *mut _) };
if status == 0 {
info.cpu_count as usize
} else {
1
}
}
#[cfg(target_os = "hermit")]
fn get_num_cpus() -> usize {
unsafe { hermit_abi::get_processor_count() }
}
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "aix",
target_os = "solaris",
target_os = "illumos",
target_os = "fuchsia",
target_os = "linux",
target_os = "openbsd",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "netbsd",
target_os = "haiku",
target_os = "hermit",
windows,
)))]
fn get_num_cpus() -> usize {
1
}
#[cfg(test)]
mod tests {
fn env_var(name: &'static str) -> Option<usize> {
::std::env::var(name).ok().map(|val| val.parse().unwrap())
}
#[test]
fn test_get() {
let num = super::get();
if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
assert_eq!(num, n);
} else {
assert!(num > 0);
assert!(num < 236_451);
}
}
#[test]
fn test_get_physical() {
let num = super::get_physical();
if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
assert_eq!(num, n);
} else {
assert!(num > 0);
assert!(num < 236_451);
}
}
}

View file

@ -0,0 +1,595 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Read};
use std::mem;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Once;
use libc;
macro_rules! debug {
($($args:expr),*) => ({
if false {
//if true {
println!($($args),*);
}
});
}
macro_rules! some {
($e:expr) => {{
match $e {
Some(v) => v,
None => {
debug!("NONE: {:?}", stringify!($e));
return None;
}
}
}};
}
pub fn get_num_cpus() -> usize {
match cgroups_num_cpus() {
Some(n) => n,
None => logical_cpus(),
}
}
fn logical_cpus() -> usize {
let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
if unsafe { libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
let mut count: u32 = 0;
for i in 0..libc::CPU_SETSIZE as usize {
if unsafe { libc::CPU_ISSET(i, &set) } {
count += 1
}
}
count as usize
} else {
let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
if cpus < 1 {
1
} else {
cpus as usize
}
}
}
pub fn get_num_physical_cpus() -> usize {
let file = match File::open("/proc/cpuinfo") {
Ok(val) => val,
Err(_) => return get_num_cpus(),
};
let reader = BufReader::new(file);
let mut map = HashMap::new();
let mut physid: u32 = 0;
let mut cores: usize = 0;
let mut chgcount = 0;
for line in reader.lines().filter_map(|result| result.ok()) {
let mut it = line.split(':');
let (key, value) = match (it.next(), it.next()) {
(Some(key), Some(value)) => (key.trim(), value.trim()),
_ => continue,
};
if key == "physical id" {
match value.parse() {
Ok(val) => physid = val,
Err(_) => break,
};
chgcount += 1;
}
if key == "cpu cores" {
match value.parse() {
Ok(val) => cores = val,
Err(_) => break,
};
chgcount += 1;
}
if chgcount == 2 {
map.insert(physid, cores);
chgcount = 0;
}
}
let count = map.into_iter().fold(0, |acc, (_, cores)| acc + cores);
if count == 0 {
get_num_cpus()
} else {
count
}
}
/// Cached CPUs calculated from cgroups.
///
/// If 0, check logical cpus.
// Allow deprecation warnings, we want to work on older rustc
#[allow(warnings)]
static CGROUPS_CPUS: AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
fn cgroups_num_cpus() -> Option<usize> {
#[allow(warnings)]
static ONCE: Once = ::std::sync::ONCE_INIT;
ONCE.call_once(init_cgroups);
let cpus = CGROUPS_CPUS.load(Ordering::Acquire);
if cpus > 0 {
Some(cpus)
} else {
None
}
}
fn init_cgroups() {
// Should only be called once
debug_assert!(CGROUPS_CPUS.load(Ordering::SeqCst) == 0);
// Fails in Miri by default (cannot open files), and Miri does not have parallelism anyway.
if cfg!(miri) {
return;
}
if let Some(quota) = load_cgroups("/proc/self/cgroup", "/proc/self/mountinfo") {
if quota == 0 {
return;
}
let logical = logical_cpus();
let count = ::std::cmp::min(quota, logical);
CGROUPS_CPUS.store(count, Ordering::SeqCst);
}
}
fn load_cgroups<P1, P2>(cgroup_proc: P1, mountinfo_proc: P2) -> Option<usize>
where
P1: AsRef<Path>,
P2: AsRef<Path>,
{
let subsys = some!(Subsys::load_cpu(cgroup_proc));
let mntinfo = some!(MountInfo::load_cpu(mountinfo_proc, subsys.version));
let cgroup = some!(Cgroup::translate(mntinfo, subsys));
cgroup.cpu_quota()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum CgroupVersion {
V1,
V2,
}
struct Cgroup {
version: CgroupVersion,
base: PathBuf,
}
struct MountInfo {
version: CgroupVersion,
root: String,
mount_point: String,
}
struct Subsys {
version: CgroupVersion,
base: String,
}
impl Cgroup {
fn new(version: CgroupVersion, dir: PathBuf) -> Cgroup {
Cgroup { version: version, base: dir }
}
fn translate(mntinfo: MountInfo, subsys: Subsys) -> Option<Cgroup> {
// Translate the subsystem directory via the host paths.
debug!(
"subsys = {:?}; root = {:?}; mount_point = {:?}",
subsys.base, mntinfo.root, mntinfo.mount_point
);
let rel_from_root = some!(Path::new(&subsys.base).strip_prefix(&mntinfo.root).ok());
debug!("rel_from_root: {:?}", rel_from_root);
// join(mp.MountPoint, relPath)
let mut path = PathBuf::from(mntinfo.mount_point);
path.push(rel_from_root);
Some(Cgroup::new(mntinfo.version, path))
}
fn cpu_quota(&self) -> Option<usize> {
let (quota_us, period_us) = match self.version {
CgroupVersion::V1 => (some!(self.quota_us()), some!(self.period_us())),
CgroupVersion::V2 => some!(self.max()),
};
// protect against dividing by zero
if period_us == 0 {
return None;
}
// Ceil the division, since we want to be able to saturate
// the available CPUs, and flooring would leave a CPU un-utilized.
Some((quota_us as f64 / period_us as f64).ceil() as usize)
}
fn quota_us(&self) -> Option<usize> {
self.param("cpu.cfs_quota_us")
}
fn period_us(&self) -> Option<usize> {
self.param("cpu.cfs_period_us")
}
fn max(&self) -> Option<(usize, usize)> {
let max = some!(self.raw_param("cpu.max"));
let mut max = some!(max.lines().next()).split(' ');
let quota = some!(max.next().and_then(|quota| quota.parse().ok()));
let period = some!(max.next().and_then(|period| period.parse().ok()));
Some((quota, period))
}
fn param(&self, param: &str) -> Option<usize> {
let buf = some!(self.raw_param(param));
buf.trim().parse().ok()
}
fn raw_param(&self, param: &str) -> Option<String> {
let mut file = some!(File::open(self.base.join(param)).ok());
let mut buf = String::new();
some!(file.read_to_string(&mut buf).ok());
Some(buf)
}
}
impl MountInfo {
fn load_cpu<P: AsRef<Path>>(proc_path: P, version: CgroupVersion) -> Option<MountInfo> {
let file = some!(File::open(proc_path).ok());
let file = BufReader::new(file);
file.lines()
.filter_map(|result| result.ok())
.filter_map(MountInfo::parse_line)
.find(|mount_info| mount_info.version == version)
}
fn parse_line(line: String) -> Option<MountInfo> {
let mut fields = line.split(' ');
// 7 5 0:6 </> /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup rw,cpu,cpuacct
let mnt_root = some!(fields.nth(3));
// 7 5 0:6 / </sys/fs/cgroup/cpu,cpuacct> rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup rw,cpu,cpuacct
let mnt_point = some!(fields.next());
// Ignore all fields until the separator(-).
// Note: there could be zero or more optional fields before hyphen.
// See: https://man7.org/linux/man-pages/man5/proc.5.html
// 7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 <-> cgroup cgroup rw,cpu,cpuacct
// Note: we cannot use `?` here because we need to support Rust 1.13.
match fields.find(|&s| s == "-") {
Some(_) => {}
None => return None,
};
// 7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - <cgroup> cgroup rw,cpu,cpuacct
let version = match fields.next() {
Some("cgroup") => CgroupVersion::V1,
Some("cgroup2") => CgroupVersion::V2,
_ => return None,
};
// cgroups2 only has a single mount point
if version == CgroupVersion::V1 {
// 7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup <rw,cpu,cpuacct>
let super_opts = some!(fields.nth(1));
// We only care about the 'cpu' option
if !super_opts.split(',').any(|opt| opt == "cpu") {
return None;
}
}
Some(MountInfo {
version: version,
root: mnt_root.to_owned(),
mount_point: mnt_point.to_owned(),
})
}
}
impl Subsys {
fn load_cpu<P: AsRef<Path>>(proc_path: P) -> Option<Subsys> {
let file = some!(File::open(proc_path).ok());
let file = BufReader::new(file);
file.lines()
.filter_map(|result| result.ok())
.filter_map(Subsys::parse_line)
.fold(None, |previous, line| {
// already-found v1 trumps v2 since it explicitly specifies its controllers
if previous.is_some() && line.version == CgroupVersion::V2 {
return previous;
}
Some(line)
})
}
fn parse_line(line: String) -> Option<Subsys> {
// Example format:
// 11:cpu,cpuacct:/
let mut fields = line.split(':');
let sub_systems = some!(fields.nth(1));
let version = if sub_systems.is_empty() {
CgroupVersion::V2
} else {
CgroupVersion::V1
};
if version == CgroupVersion::V1 && !sub_systems.split(',').any(|sub| sub == "cpu") {
return None;
}
fields.next().map(|path| Subsys {
version: version,
base: path.to_owned(),
})
}
}
#[cfg(test)]
mod tests {
mod v1 {
use super::super::{Cgroup, CgroupVersion, MountInfo, Subsys};
use std::path::{Path, PathBuf};
// `static_in_const` feature is not stable in Rust 1.13.
static FIXTURES_PROC: &'static str = "fixtures/cgroups/proc/cgroups";
static FIXTURES_CGROUPS: &'static str = "fixtures/cgroups/cgroups";
macro_rules! join {
($base:expr, $($path:expr),+) => ({
Path::new($base)
$(.join($path))+
})
}
#[test]
fn test_load_mountinfo() {
// test only one optional fields
let path = join!(FIXTURES_PROC, "mountinfo");
let mnt_info = MountInfo::load_cpu(path, CgroupVersion::V1).unwrap();
assert_eq!(mnt_info.root, "/");
assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
// test zero optional field
let path = join!(FIXTURES_PROC, "mountinfo_zero_opt");
let mnt_info = MountInfo::load_cpu(path, CgroupVersion::V1).unwrap();
assert_eq!(mnt_info.root, "/");
assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
// test multi optional fields
let path = join!(FIXTURES_PROC, "mountinfo_multi_opt");
let mnt_info = MountInfo::load_cpu(path, CgroupVersion::V1).unwrap();
assert_eq!(mnt_info.root, "/");
assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
}
#[test]
fn test_load_subsys() {
let path = join!(FIXTURES_PROC, "cgroup");
let subsys = Subsys::load_cpu(path).unwrap();
assert_eq!(subsys.base, "/");
assert_eq!(subsys.version, CgroupVersion::V1);
}
#[test]
fn test_cgroup_mount() {
let cases = &[
("/", "/sys/fs/cgroup/cpu", "/", Some("/sys/fs/cgroup/cpu")),
(
"/docker/01abcd",
"/sys/fs/cgroup/cpu",
"/docker/01abcd",
Some("/sys/fs/cgroup/cpu"),
),
(
"/docker/01abcd",
"/sys/fs/cgroup/cpu",
"/docker/01abcd/",
Some("/sys/fs/cgroup/cpu"),
),
(
"/docker/01abcd",
"/sys/fs/cgroup/cpu",
"/docker/01abcd/large",
Some("/sys/fs/cgroup/cpu/large"),
),
// fails
("/docker/01abcd", "/sys/fs/cgroup/cpu", "/", None),
("/docker/01abcd", "/sys/fs/cgroup/cpu", "/docker", None),
("/docker/01abcd", "/sys/fs/cgroup/cpu", "/elsewhere", None),
(
"/docker/01abcd",
"/sys/fs/cgroup/cpu",
"/docker/01abcd-other-dir",
None,
),
];
for &(root, mount_point, subsys, expected) in cases.iter() {
let mnt_info = MountInfo {
version: CgroupVersion::V1,
root: root.into(),
mount_point: mount_point.into(),
};
let subsys = Subsys {
version: CgroupVersion::V1,
base: subsys.into(),
};
let actual = Cgroup::translate(mnt_info, subsys).map(|c| c.base);
let expected = expected.map(PathBuf::from);
assert_eq!(actual, expected);
}
}
#[test]
fn test_cgroup_cpu_quota() {
let cgroup = Cgroup::new(CgroupVersion::V1, join!(FIXTURES_CGROUPS, "good"));
assert_eq!(cgroup.cpu_quota(), Some(6));
}
#[test]
fn test_cgroup_cpu_quota_divide_by_zero() {
let cgroup = Cgroup::new(CgroupVersion::V1, join!(FIXTURES_CGROUPS, "zero-period"));
assert!(cgroup.quota_us().is_some());
assert_eq!(cgroup.period_us(), Some(0));
assert_eq!(cgroup.cpu_quota(), None);
}
#[test]
fn test_cgroup_cpu_quota_ceil() {
let cgroup = Cgroup::new(CgroupVersion::V1, join!(FIXTURES_CGROUPS, "ceil"));
assert_eq!(cgroup.cpu_quota(), Some(2));
}
}
mod v2 {
use super::super::{Cgroup, CgroupVersion, MountInfo, Subsys};
use std::path::{Path, PathBuf};
// `static_in_const` feature is not stable in Rust 1.13.
static FIXTURES_PROC: &'static str = "fixtures/cgroups2/proc/cgroups";
static FIXTURES_CGROUPS: &'static str = "fixtures/cgroups2/cgroups";
macro_rules! join {
($base:expr, $($path:expr),+) => ({
Path::new($base)
$(.join($path))+
})
}
#[test]
fn test_load_mountinfo() {
// test only one optional fields
let path = join!(FIXTURES_PROC, "mountinfo");
let mnt_info = MountInfo::load_cpu(path, CgroupVersion::V2).unwrap();
assert_eq!(mnt_info.root, "/");
assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup");
}
#[test]
fn test_load_subsys() {
let path = join!(FIXTURES_PROC, "cgroup");
let subsys = Subsys::load_cpu(path).unwrap();
assert_eq!(subsys.base, "/");
assert_eq!(subsys.version, CgroupVersion::V2);
}
#[test]
fn test_load_subsys_multi() {
let path = join!(FIXTURES_PROC, "cgroup_multi");
let subsys = Subsys::load_cpu(path).unwrap();
assert_eq!(subsys.base, "/");
assert_eq!(subsys.version, CgroupVersion::V1);
}
#[test]
fn test_cgroup_mount() {
let cases = &[
("/", "/sys/fs/cgroup/cpu", "/", Some("/sys/fs/cgroup/cpu")),
(
"/docker/01abcd",
"/sys/fs/cgroup/cpu",
"/docker/01abcd",
Some("/sys/fs/cgroup/cpu"),
),
(
"/docker/01abcd",
"/sys/fs/cgroup/cpu",
"/docker/01abcd/",
Some("/sys/fs/cgroup/cpu"),
),
(
"/docker/01abcd",
"/sys/fs/cgroup/cpu",
"/docker/01abcd/large",
Some("/sys/fs/cgroup/cpu/large"),
),
// fails
("/docker/01abcd", "/sys/fs/cgroup/cpu", "/", None),
("/docker/01abcd", "/sys/fs/cgroup/cpu", "/docker", None),
("/docker/01abcd", "/sys/fs/cgroup/cpu", "/elsewhere", None),
(
"/docker/01abcd",
"/sys/fs/cgroup/cpu",
"/docker/01abcd-other-dir",
None,
),
];
for &(root, mount_point, subsys, expected) in cases.iter() {
let mnt_info = MountInfo {
version: CgroupVersion::V1,
root: root.into(),
mount_point: mount_point.into(),
};
let subsys = Subsys {
version: CgroupVersion::V1,
base: subsys.into(),
};
let actual = Cgroup::translate(mnt_info, subsys).map(|c| c.base);
let expected = expected.map(PathBuf::from);
assert_eq!(actual, expected);
}
}
#[test]
fn test_cgroup_cpu_quota() {
let cgroup = Cgroup::new(CgroupVersion::V2, join!(FIXTURES_CGROUPS, "good"));
assert_eq!(cgroup.cpu_quota(), Some(6));
}
#[test]
fn test_cgroup_cpu_quota_divide_by_zero() {
let cgroup = Cgroup::new(CgroupVersion::V2, join!(FIXTURES_CGROUPS, "zero-period"));
let period = cgroup.max().map(|max| max.1);
assert_eq!(period, Some(0));
assert_eq!(cgroup.cpu_quota(), None);
}
#[test]
fn test_cgroup_cpu_quota_ceil() {
let cgroup = Cgroup::new(CgroupVersion::V2, join!(FIXTURES_CGROUPS, "ceil"));
assert_eq!(cgroup.cpu_quota(), Some(2));
}
}
}

View file

@ -0,0 +1 @@
11d8fb50310107d5

View file

@ -0,0 +1 @@
{"rustc":12013579709055016942,"features":"[]","declared_features":"[]","target":11245016787129052555,"profile":1170353271454073023,"path":221166937573230998,"deps":[[1441306149310335789,"tempfile",false,104680176640599173],[2357570525450087091,"num_cpus",false,1741484011071919562],[2706460456408817945,"futures",false,7041889134759834829],[2995469292676432503,"uuid",false,10423630888482523907],[3214373357989284387,"pkg_config",false,6268810499543585],[3557232484177382041,"users",false,12913976845937866970],[4246705910297504001,"apt_ostree",false,11975357125015508593],[5554567547226369328,"zbus",false,13685254897742169137],[6079318424673677659,"sha256",false,9150457797868239251],[7750786942752304153,"zbus_macros",false,689425091657810568],[8008191657135824715,"thiserror",false,10189534528494504052],[8606274917505247608,"tracing",false,17926986785606357961],[8832391471063924857,"apt_pkg_native",false,12971005487340007837],[9451456094439810778,"regex",false,12870681495325416547],[9614479274285663593,"serde_yaml",false,15675975708689077309],[9689903380558560274,"serde",false,12272528559381112844],[9857275760291862238,"sha2",false,15393755711540167045],[9897246384292347999,"chrono",false,16853950727758094845],[10113091049430744448,"polkit",false,13493700214129822755],[11207653606310558077,"anyhow",false,14975255058775993133],[11594979262886006466,"tracing_appender",false,14542587824834221061],[11887305395906501191,"libc",false,13101130544926807178],[12367916977474903472,"ostree",false,8922899535111175221],[15622660310229662834,"walkdir",false,10776747726922742443],[16230660778393187092,"tracing_subscriber",false,14814496931625741638],[16362055519698394275,"serde_json",false,15665879969596746662],[16611674984963787466,"async_trait",false,4292402164283099764],[17531218394775549125,"tokio",false,8773151196875886161],[17917672826516349275,"lazy_static",false,5385760582413239955]],"local":[{"CheckDepInfo":{"dep_info":"release/.fingerprint/apt-ostree-0e9da19fce0aa794/dep-bin-apt-ostreed","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View file

@ -1 +0,0 @@
{"rustc":12013579709055016942,"features":"[]","declared_features":"[]","target":14407896363136823024,"profile":1170353271454073023,"path":4942398508502643691,"deps":[[1441306149310335789,"tempfile",false,104680176640599173],[2706460456408817945,"futures",false,7041889134759834829],[2995469292676432503,"uuid",false,10423630888482523907],[3214373357989284387,"pkg_config",false,6268810499543585],[3557232484177382041,"users",false,12913976845937866970],[4246705910297504001,"apt_ostree",false,5779799094897355887],[5554567547226369328,"zbus",false,13685254897742169137],[6079318424673677659,"sha256",false,9150457797868239251],[7750786942752304153,"zbus_macros",false,689425091657810568],[8008191657135824715,"thiserror",false,10189534528494504052],[8606274917505247608,"tracing",false,17926986785606357961],[8832391471063924857,"apt_pkg_native",false,12971005487340007837],[9451456094439810778,"regex",false,12870681495325416547],[9614479274285663593,"serde_yaml",false,15675975708689077309],[9689903380558560274,"serde",false,12272528559381112844],[9857275760291862238,"sha2",false,15393755711540167045],[9897246384292347999,"chrono",false,16853950727758094845],[10113091049430744448,"polkit",false,3416882409239097854],[11207653606310558077,"anyhow",false,14975255058775993133],[11594979262886006466,"tracing_appender",false,14542587824834221061],[11887305395906501191,"libc",false,13101130544926807178],[12367916977474903472,"ostree",false,2857630351280481839],[15622660310229662834,"walkdir",false,10776747726922742443],[16230660778393187092,"tracing_subscriber",false,14814496931625741638],[16362055519698394275,"serde_json",false,15665879969596746662],[16611674984963787466,"async_trait",false,4292402164283099764],[17531218394775549125,"tokio",false,8773151196875886161],[17917672826516349275,"lazy_static",false,5385760582413239955]],"local":[{"CheckDepInfo":{"dep_info":"release/.fingerprint/apt-ostree-20621b3c94a3d86c/dep-bin-apt-ostree","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View file

@ -1,12 +0,0 @@
{"$message_type":"diagnostic","message":"unused import: `warn`","code":{"code":"unused_imports","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":20,"byte_end":24,"line_start":1,"line_end":1,"column_start":21,"column_end":25,"is_primary":true,"text":[{"text":"use tracing::{info, warn, error};","highlight_start":21,"highlight_end":25}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_imports)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove the unused import","code":null,"level":"help","spans":[{"file_name":"src/main.rs","byte_start":18,"byte_end":24,"line_start":1,"line_end":1,"column_start":19,"column_end":25,"is_primary":true,"text":[{"text":"use tracing::{info, warn, error};","highlight_start":19,"highlight_end":25}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `warn`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:1:21\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m1\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse tracing::{info, warn, error};\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_imports)]` on by default\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"variable `opt_notify` is assigned to, but never used","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":18003,"byte_end":18013,"line_start":486,"line_end":486,"column_start":13,"column_end":23,"is_primary":true,"text":[{"text":" let mut opt_notify = false;","highlight_start":13,"highlight_end":23}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"consider using `_opt_notify` instead","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"`#[warn(unused_variables)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: variable `opt_notify` is assigned to, but never used\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:486:13\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m486\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let mut opt_notify = false;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: consider using `_opt_notify` instead\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_variables)]` on by default\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"variable `opt_allow_downgrade` is assigned to, but never used","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":18078,"byte_end":18097,"line_start":488,"line_end":488,"column_start":13,"column_end":32,"is_primary":true,"text":[{"text":" let mut opt_allow_downgrade = false;","highlight_start":13,"highlight_end":32}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"consider using `_opt_allow_downgrade` instead","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: variable `opt_allow_downgrade` is assigned to, but never used\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:488:13\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m488\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let mut opt_allow_downgrade = false;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: consider using `_opt_allow_downgrade` instead\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"value assigned to `opt_notify` is never read","code":{"code":"unused_assignments","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":18460,"byte_end":18470,"line_start":499,"line_end":499,"column_start":27,"column_end":37,"is_primary":true,"text":[{"text":" \"--notify\" => opt_notify = true,","highlight_start":27,"highlight_end":37}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"maybe it is overwritten before being read?","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"`#[warn(unused_assignments)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: value assigned to `opt_notify` is never read\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:499:27\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m499\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m \"--notify\" => opt_notify = true,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mhelp\u001b[0m\u001b[0m: maybe it is overwritten before being read?\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_assignments)]` on by default\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"value assigned to `opt_allow_downgrade` is never read","code":{"code":"unused_assignments","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":18581,"byte_end":18600,"line_start":501,"line_end":501,"column_start":36,"column_end":55,"is_primary":true,"text":[{"text":" \"--allow-downgrade\" => opt_allow_downgrade = true,","highlight_start":36,"highlight_end":55}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"maybe it is overwritten before being read?","code":null,"level":"help","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: value assigned to `opt_allow_downgrade` is never read\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:501:36\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m501\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m \"--allow-downgrade\" => opt_allow_downgrade = true,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mhelp\u001b[0m\u001b[0m: maybe it is overwritten before being read?\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"variable `opt_skip_purge` is assigned to, but never used","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":24081,"byte_end":24095,"line_start":648,"line_end":648,"column_start":13,"column_end":27,"is_primary":true,"text":[{"text":" let mut opt_skip_purge = false;","highlight_start":13,"highlight_end":27}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"consider using `_opt_skip_purge` instead","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: variable `opt_skip_purge` is assigned to, but never used\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:648:13\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m648\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let mut opt_skip_purge = false;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: consider using `_opt_skip_purge` instead\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"variable `opt_bypass_driver` is assigned to, but never used","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":24379,"byte_end":24396,"line_start":656,"line_end":656,"column_start":13,"column_end":30,"is_primary":true,"text":[{"text":" let mut opt_bypass_driver = false;","highlight_start":13,"highlight_end":30}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"consider using `_opt_bypass_driver` instead","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: variable `opt_bypass_driver` is assigned to, but never used\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:656:13\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m656\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let mut opt_bypass_driver = false;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: consider using `_opt_bypass_driver` instead\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"value assigned to `opt_skip_purge` is never read","code":{"code":"unused_assignments","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":24717,"byte_end":24731,"line_start":666,"line_end":666,"column_start":31,"column_end":45,"is_primary":true,"text":[{"text":" \"--skip-purge\" => opt_skip_purge = true,","highlight_start":31,"highlight_end":45}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"maybe it is overwritten before being read?","code":null,"level":"help","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: value assigned to `opt_skip_purge` is never read\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:666:31\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m666\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m \"--skip-purge\" => opt_skip_purge = true,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mhelp\u001b[0m\u001b[0m: maybe it is overwritten before being read?\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"value assigned to `opt_bypass_driver` is never read","code":{"code":"unused_assignments","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":25451,"byte_end":25468,"line_start":684,"line_end":684,"column_start":34,"column_end":51,"is_primary":true,"text":[{"text":" \"--bypass-driver\" => opt_bypass_driver = true,","highlight_start":34,"highlight_end":51}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"maybe it is overwritten before being read?","code":null,"level":"help","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: value assigned to `opt_bypass_driver` is never read\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:684:34\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m684\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m \"--bypass-driver\" => opt_bypass_driver = true,\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mhelp\u001b[0m\u001b[0m: maybe it is overwritten before being read?\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"variable does not need to be mutable","code":{"code":"unused_mut","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":31964,"byte_end":31983,"line_start":862,"line_end":862,"column_start":9,"column_end":28,"is_primary":true,"text":[{"text":" let mut package_manager = apt_ostree::lib::apt::AptManager::new();","highlight_start":9,"highlight_end":28}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_mut)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove this `mut`","code":null,"level":"help","spans":[{"file_name":"src/main.rs","byte_start":31964,"byte_end":31968,"line_start":862,"line_end":862,"column_start":9,"column_end":13,"is_primary":true,"text":[{"text":" let mut package_manager = apt_ostree::lib::apt::AptManager::new();","highlight_start":9,"highlight_end":13}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: variable does not need to be mutable\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:862:9\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m862\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let mut package_manager = apt_ostree::lib::apt::AptManager::new();\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m----\u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12mhelp: remove this `mut`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_mut)]` on by default\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"variable does not need to be mutable","code":{"code":"unused_mut","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":85043,"byte_end":85062,"line_start":2369,"line_end":2369,"column_start":9,"column_end":28,"is_primary":true,"text":[{"text":" let mut package_manager = apt_ostree::lib::apt::AptManager::new();","highlight_start":9,"highlight_end":28}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove this `mut`","code":null,"level":"help","spans":[{"file_name":"src/main.rs","byte_start":85043,"byte_end":85047,"line_start":2369,"line_end":2369,"column_start":9,"column_end":13,"is_primary":true,"text":[{"text":" let mut package_manager = apt_ostree::lib::apt::AptManager::new();","highlight_start":9,"highlight_end":13}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: variable does not need to be mutable\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:2369:9\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m2369\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let mut package_manager = apt_ostree::lib::apt::AptManager::new();\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m----\u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12mhelp: remove this `mut`\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"11 warnings emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: 11 warnings emitted\u001b[0m\n\n"}

View file

@ -0,0 +1 @@
7116fe66db0331a6

View file

@ -0,0 +1 @@
{"rustc":12013579709055016942,"features":"[]","declared_features":"[]","target":11088358253213355025,"profile":4701875279837757004,"path":10763286916239946207,"deps":[[1441306149310335789,"tempfile",false,104680176640599173],[2357570525450087091,"num_cpus",false,1741484011071919562],[2706460456408817945,"futures",false,7041889134759834829],[2995469292676432503,"uuid",false,10423630888482523907],[3214373357989284387,"pkg_config",false,6268810499543585],[3557232484177382041,"users",false,12913976845937866970],[5554567547226369328,"zbus",false,13685254897742169137],[6079318424673677659,"sha256",false,9150457797868239251],[7750786942752304153,"zbus_macros",false,689425091657810568],[8008191657135824715,"thiserror",false,10189534528494504052],[8606274917505247608,"tracing",false,17926986785606357961],[8832391471063924857,"apt_pkg_native",false,12971005487340007837],[9451456094439810778,"regex",false,12870681495325416547],[9614479274285663593,"serde_yaml",false,15675975708689077309],[9689903380558560274,"serde",false,12272528559381112844],[9857275760291862238,"sha2",false,15393755711540167045],[9897246384292347999,"chrono",false,16853950727758094845],[10113091049430744448,"polkit",false,13493700214129822755],[11207653606310558077,"anyhow",false,14975255058775993133],[11594979262886006466,"tracing_appender",false,14542587824834221061],[11887305395906501191,"libc",false,13101130544926807178],[12367916977474903472,"ostree",false,8922899535111175221],[15622660310229662834,"walkdir",false,10776747726922742443],[16230660778393187092,"tracing_subscriber",false,14814496931625741638],[16362055519698394275,"serde_json",false,15665879969596746662],[16611674984963787466,"async_trait",false,4292402164283099764],[17531218394775549125,"tokio",false,8773151196875886161],[17917672826516349275,"lazy_static",false,5385760582413239955]],"local":[{"CheckDepInfo":{"dep_info":"release/.fingerprint/apt-ostree-4c3dcd48f1288e7f/dep-lib-apt_ostree","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View file

@ -9,7 +9,7 @@
{"$message_type":"diagnostic","message":"unused import: `DaemonError`","code":{"code":"unused_imports","explanation":null},"level":"warning","spans":[{"file_name":"src/daemon/os.rs","byte_start":74,"byte_end":85,"line_start":3,"line_end":3,"column_start":35,"column_end":46,"is_primary":true,"text":[{"text":"use crate::daemon::{DaemonResult, DaemonError};","highlight_start":35,"highlight_end":46}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove the unused import","code":null,"level":"help","spans":[{"file_name":"src/daemon/os.rs","byte_start":72,"byte_end":85,"line_start":3,"line_end":3,"column_start":33,"column_end":46,"is_primary":true,"text":[{"text":"use crate::daemon::{DaemonResult, DaemonError};","highlight_start":33,"highlight_end":46}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"src/daemon/os.rs","byte_start":59,"byte_end":60,"line_start":3,"line_end":3,"column_start":20,"column_end":21,"is_primary":true,"text":[{"text":"use crate::daemon::{DaemonResult, DaemonError};","highlight_start":20,"highlight_end":21}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"src/daemon/os.rs","byte_start":85,"byte_end":86,"line_start":3,"line_end":3,"column_start":46,"column_end":47,"is_primary":true,"text":[{"text":"use crate::daemon::{DaemonResult, DaemonError};","highlight_start":46,"highlight_end":47}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `DaemonError`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/daemon/os.rs:3:35\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m3\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse crate::daemon::{DaemonResult, DaemonError};\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"unused import: `ClientError`","code":{"code":"unused_imports","explanation":null},"level":"warning","spans":[{"file_name":"src/client/dbus.rs","byte_start":126,"byte_end":137,"line_start":4,"line_end":4,"column_start":49,"column_end":60,"is_primary":true,"text":[{"text":"use crate::client::{ClientConfig, ClientResult, ClientError};","highlight_start":49,"highlight_end":60}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove the unused import","code":null,"level":"help","spans":[{"file_name":"src/client/dbus.rs","byte_start":124,"byte_end":137,"line_start":4,"line_end":4,"column_start":47,"column_end":60,"is_primary":true,"text":[{"text":"use crate::client::{ClientConfig, ClientResult, ClientError};","highlight_start":47,"highlight_end":60}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `ClientError`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/client/dbus.rs:4:49\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m4\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse crate::client::{ClientConfig, ClientResult, ClientError};\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"unused import: `ClientError`","code":{"code":"unused_imports","explanation":null},"level":"warning","spans":[{"file_name":"src/client/transaction.rs","byte_start":87,"byte_end":98,"line_start":3,"line_end":3,"column_start":49,"column_end":60,"is_primary":true,"text":[{"text":"use crate::client::{ClientConfig, ClientResult, ClientError};","highlight_start":49,"highlight_end":60}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove the unused import","code":null,"level":"help","spans":[{"file_name":"src/client/transaction.rs","byte_start":85,"byte_end":98,"line_start":3,"line_end":3,"column_start":47,"column_end":60,"is_primary":true,"text":[{"text":"use crate::client::{ClientConfig, ClientResult, ClientError};","highlight_start":47,"highlight_end":60}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `ClientError`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/client/transaction.rs:3:49\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m3\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse crate::client::{ClientConfig, ClientResult, ClientError};\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"unused import: `AptOstreeError`","code":{"code":"unused_imports","explanation":null},"level":"warning","spans":[{"file_name":"src/test_utils/test_support.rs","byte_start":24,"byte_end":38,"line_start":1,"line_end":1,"column_start":25,"column_end":39,"is_primary":true,"text":[{"text":"use crate::lib::error::{AptOstreeError, AptOstreeResult};","highlight_start":25,"highlight_end":39}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"if this is a test module, consider adding a `#[cfg(test)]` to the containing module","code":null,"level":"help","spans":[{"file_name":"src/lib.rs","byte_start":504,"byte_end":525,"line_start":29,"line_end":29,"column_start":5,"column_end":26,"is_primary":true,"text":[{"text":" pub mod test_support;","highlight_start":5,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove the unused import","code":null,"level":"help","spans":[{"file_name":"src/test_utils/test_support.rs","byte_start":24,"byte_end":40,"line_start":1,"line_end":1,"column_start":25,"column_end":41,"is_primary":true,"text":[{"text":"use crate::lib::error::{AptOstreeError, AptOstreeResult};","highlight_start":25,"highlight_end":41}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"src/test_utils/test_support.rs","byte_start":23,"byte_end":24,"line_start":1,"line_end":1,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":"use crate::lib::error::{AptOstreeError, AptOstreeResult};","highlight_start":24,"highlight_end":25}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"src/test_utils/test_support.rs","byte_start":55,"byte_end":56,"line_start":1,"line_end":1,"column_start":56,"column_end":57,"is_primary":true,"text":[{"text":"use crate::lib::error::{AptOstreeError, AptOstreeResult};","highlight_start":56,"highlight_end":57}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `AptOstreeError`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/test_utils/test_support.rs:1:25\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m1\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse crate::lib::error::{AptOstreeError, AptOstreeResult};\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: if this is a test module, consider adding a `#[cfg(test)]` to the containing module\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/lib.rs:29:5\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m29\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m pub mod test_support;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"unused import: `AptOstreeError`","code":{"code":"unused_imports","explanation":null},"level":"warning","spans":[{"file_name":"src/test_utils/test_support.rs","byte_start":24,"byte_end":38,"line_start":1,"line_end":1,"column_start":25,"column_end":39,"is_primary":true,"text":[{"text":"use crate::lib::error::{AptOstreeError, AptOstreeResult};","highlight_start":25,"highlight_end":39}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"if this is a test module, consider adding a `#[cfg(test)]` to the containing module","code":null,"level":"help","spans":[{"file_name":"src/lib.rs","byte_start":582,"byte_end":603,"line_start":33,"line_end":33,"column_start":5,"column_end":26,"is_primary":true,"text":[{"text":" pub mod test_support;","highlight_start":5,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove the unused import","code":null,"level":"help","spans":[{"file_name":"src/test_utils/test_support.rs","byte_start":24,"byte_end":40,"line_start":1,"line_end":1,"column_start":25,"column_end":41,"is_primary":true,"text":[{"text":"use crate::lib::error::{AptOstreeError, AptOstreeResult};","highlight_start":25,"highlight_end":41}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"src/test_utils/test_support.rs","byte_start":23,"byte_end":24,"line_start":1,"line_end":1,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":"use crate::lib::error::{AptOstreeError, AptOstreeResult};","highlight_start":24,"highlight_end":25}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"src/test_utils/test_support.rs","byte_start":55,"byte_end":56,"line_start":1,"line_end":1,"column_start":56,"column_end":57,"is_primary":true,"text":[{"text":"use crate::lib::error::{AptOstreeError, AptOstreeResult};","highlight_start":56,"highlight_end":57}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `AptOstreeError`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/test_utils/test_support.rs:1:25\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m1\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse crate::lib::error::{AptOstreeError, AptOstreeResult};\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: if this is a test module, consider adding a `#[cfg(test)]` to the containing module\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/lib.rs:33:5\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m33\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m pub mod test_support;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;14m^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"unused variable: `subject`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/lib/security.rs","byte_start":1041,"byte_end":1048,"line_start":34,"line_end":34,"column_start":13,"column_end":20,"is_primary":true,"text":[{"text":" let subject = UnixProcess::new(","highlight_start":13,"highlight_end":20}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_variables)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src/lib/security.rs","byte_start":1041,"byte_end":1048,"line_start":34,"line_end":34,"column_start":13,"column_end":20,"is_primary":true,"text":[{"text":" let subject = UnixProcess::new(","highlight_start":13,"highlight_end":20}],"label":null,"suggested_replacement":"_subject","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused variable: `subject`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/lib/security.rs:34:13\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m34\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let subject = UnixProcess::new(\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33mhelp: if this is intentional, prefix it with an underscore: `_subject`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_variables)]` on by default\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"variable `current_deployment` is assigned to, but never used","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/lib/ostree.rs","byte_start":4369,"byte_end":4387,"line_start":128,"line_end":128,"column_start":17,"column_end":35,"is_primary":true,"text":[{"text":" let mut current_deployment = None;","highlight_start":17,"highlight_end":35}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"consider using `_current_deployment` instead","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: variable `current_deployment` is assigned to, but never used\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/lib/ostree.rs:128:17\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m128\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let mut current_deployment = None;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: consider using `_current_deployment` instead\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"value assigned to `current_deployment` is never read","code":{"code":"unused_assignments","explanation":null},"level":"warning","spans":[{"file_name":"src/lib/ostree.rs","byte_start":4638,"byte_end":4656,"line_start":134,"line_end":134,"column_start":21,"column_end":39,"is_primary":true,"text":[{"text":" current_deployment = Some(deployment.clone());","highlight_start":21,"highlight_end":39}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"maybe it is overwritten before being read?","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"`#[warn(unused_assignments)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: value assigned to `current_deployment` is never read\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/lib/ostree.rs:134:21\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m134\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m current_deployment = Some(deployment.clone());\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mhelp\u001b[0m\u001b[0m: maybe it is overwritten before being read?\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_assignments)]` on by default\u001b[0m\n\n"}

View file

@ -1 +0,0 @@
{"rustc":12013579709055016942,"features":"[]","declared_features":"[]","target":11245016787129052555,"profile":1170353271454073023,"path":221166937573230998,"deps":[[1441306149310335789,"tempfile",false,104680176640599173],[2706460456408817945,"futures",false,7041889134759834829],[2995469292676432503,"uuid",false,10423630888482523907],[3214373357989284387,"pkg_config",false,6268810499543585],[3557232484177382041,"users",false,12913976845937866970],[4246705910297504001,"apt_ostree",false,5779799094897355887],[5554567547226369328,"zbus",false,13685254897742169137],[6079318424673677659,"sha256",false,9150457797868239251],[7750786942752304153,"zbus_macros",false,689425091657810568],[8008191657135824715,"thiserror",false,10189534528494504052],[8606274917505247608,"tracing",false,17926986785606357961],[8832391471063924857,"apt_pkg_native",false,12971005487340007837],[9451456094439810778,"regex",false,12870681495325416547],[9614479274285663593,"serde_yaml",false,15675975708689077309],[9689903380558560274,"serde",false,12272528559381112844],[9857275760291862238,"sha2",false,15393755711540167045],[9897246384292347999,"chrono",false,16853950727758094845],[10113091049430744448,"polkit",false,3416882409239097854],[11207653606310558077,"anyhow",false,14975255058775993133],[11594979262886006466,"tracing_appender",false,14542587824834221061],[11887305395906501191,"libc",false,13101130544926807178],[12367916977474903472,"ostree",false,2857630351280481839],[15622660310229662834,"walkdir",false,10776747726922742443],[16230660778393187092,"tracing_subscriber",false,14814496931625741638],[16362055519698394275,"serde_json",false,15665879969596746662],[16611674984963787466,"async_trait",false,4292402164283099764],[17531218394775549125,"tokio",false,8773151196875886161],[17917672826516349275,"lazy_static",false,5385760582413239955]],"local":[{"CheckDepInfo":{"dep_info":"release/.fingerprint/apt-ostree-b79722f8319c1604/dep-bin-apt-ostreed","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

Some files were not shown because too many files have changed in this diff Show more