Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30d3537c0e | ||
|
|
90cb16e3d0 | ||
|
|
5192a0f1dc | ||
|
|
bec7edf1fc | ||
|
|
051784ac0d | ||
|
|
17d715479a | ||
|
|
39a90f5ebe | ||
|
|
80c4bd5065 | ||
|
|
222d800a32 | ||
|
|
b29699fc55 | ||
|
|
fc0e5461eb | ||
|
|
75da4a709c | ||
|
|
02e388122b | ||
|
|
02fe1087de | ||
|
|
34b7943fd1 | ||
|
|
b61886f0f9 | ||
|
|
d9a8ecfd33 | ||
|
|
6c68bfaf64 | ||
|
|
5866a0570f | ||
|
|
28f5754efd | ||
|
|
ea1b286c98 | ||
|
|
22ab77de6d | ||
|
|
410bd61c75 | ||
|
|
07b422915c | ||
|
|
5b9d387ef3 | ||
|
|
5b5dd27834 | ||
|
|
79f65981a5 | ||
|
|
a52c775247 | ||
|
|
549111db3a | ||
|
|
1572974ec4 | ||
|
|
8387468607 | ||
|
|
94979d6b7a | ||
|
|
6652a2aa90 | ||
|
|
f943b220d9 | ||
|
|
0fc7016d68 | ||
|
|
9e9e6c9d55 | ||
|
|
bafa15c8f1 | ||
|
|
f669de8272 | ||
|
|
ff26835406 | ||
|
|
99892359c7 | ||
|
|
8fc25d7fd4 | ||
|
|
942bfaa708 | ||
|
|
a1fd324e82 | ||
|
|
62bf2c6e90 | ||
|
|
9f1e0c8eef | ||
|
|
027de7c865 |
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -18,8 +18,10 @@ assignees: ''
|
||||
option to skip this step?
|
||||
|
||||
## I want to suggest some general feature
|
||||
|
||||
Topgrade should...
|
||||
|
||||
## More information
|
||||
|
||||
<!-- Assuming that someone else implements the feature,
|
||||
please state if you know how to test it from a side branch of Topgrade. -->
|
||||
|
||||
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,6 +1,5 @@
|
||||
## What does this PR do
|
||||
|
||||
|
||||
## Standards checklist
|
||||
|
||||
- [ ] The PR title is descriptive
|
||||
|
||||
@@ -15,8 +15,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
- run: |
|
||||
- uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- run: |
|
||||
CONFIG_PATH=~/.config/topgrade.toml;
|
||||
if [ -f "$CONFIG_PATH" ]; then rm $CONFIG_PATH; fi
|
||||
cargo build;
|
||||
|
||||
2
.github/workflows/check_i18n.yml
vendored
2
.github/workflows/check_i18n.yml
vendored
@@ -15,6 +15,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install checker
|
||||
# Build it with the dev profile as this is faster and the checker still works
|
||||
|
||||
@@ -25,11 +25,13 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run DevSkim scanner
|
||||
uses: microsoft/DevSkim-Action@4b5047945a44163b94642a1cecc0d93a3f428cc6 # v1.0.16
|
||||
|
||||
- name: Upload DevSkim scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v4.31.0
|
||||
uses: github/codeql-action/upload-sarif@v4.31.2
|
||||
with:
|
||||
sarif_file: devskim-results.sarif
|
||||
|
||||
24
.github/workflows/ci.yml
vendored
24
.github/workflows/ci.yml
vendored
@@ -13,6 +13,10 @@ env:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
fmt:
|
||||
name: Rustfmt
|
||||
@@ -20,6 +24,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run cargo fmt
|
||||
env:
|
||||
@@ -34,6 +40,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check if `Step` enum is sorted
|
||||
run: |
|
||||
@@ -122,9 +130,14 @@ jobs:
|
||||
- target: x86_64-pc-windows-msvc
|
||||
target_name: Windows
|
||||
os: windows-latest
|
||||
env:
|
||||
cargo_cmd: ${{ matrix.use_cross == true && 'cross' || 'cargo' }}
|
||||
matrix_target: ${{ matrix.target }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Rust Cache
|
||||
uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
|
||||
@@ -133,17 +146,20 @@ jobs:
|
||||
|
||||
- name: Setup cross
|
||||
if: matrix.use_cross == true
|
||||
run: curl -fL --retry 3 https://github.com/cross-rs/cross/releases/download/v${{ env.CROSS_VER }}/cross-x86_64-unknown-linux-musl.tar.gz | tar vxz -C /usr/local/bin
|
||||
run: |
|
||||
curl -fL --retry 3 "https://github.com/cross-rs/cross/releases/download/v${CROSS_VER}/cross-x86_64-unknown-linux-musl.tar.gz" | tar vxz -C /usr/local/bin
|
||||
|
||||
- name: Run cargo/cross check
|
||||
run: ${{ matrix.use_cross == true && 'cross' || 'cargo' }} check --locked --target ${{ matrix.target }}
|
||||
run: |
|
||||
"${cargo_cmd}" check --locked --target "${matrix_target}"
|
||||
|
||||
- name: Run cargo/cross clippy
|
||||
run: |
|
||||
rustup component add clippy
|
||||
${{ matrix.use_cross == true && 'cross' || 'cargo' }} clippy --locked --target ${{ matrix.target }} --all-features -- -D warnings
|
||||
"${cargo_cmd}" clippy --locked --target "${matrix_target}" --all-features -- -D warnings
|
||||
|
||||
- name: Run cargo test
|
||||
# ONLY run test with cargo
|
||||
if: matrix.use_cross == false
|
||||
run: cargo test --locked --target ${{ matrix.target }}
|
||||
run: |
|
||||
cargo test --locked --target "${matrix_target}"
|
||||
|
||||
55
.github/workflows/create_release_assets.yml
vendored
55
.github/workflows/create_release_assets.yml
vendored
@@ -5,7 +5,8 @@ on:
|
||||
types: [ release-created ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
# Write permissions to call the repository dispatch
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
# Publish release files for CD native environments
|
||||
@@ -25,8 +26,12 @@ jobs:
|
||||
# https://github.com/topgrade-rs/topgrade/issues/1095
|
||||
platform: [ ubuntu-22.04, macos-latest, macos-15-intel, windows-latest ]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
env:
|
||||
tag: ${{ github.event.client_payload.tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install needed components
|
||||
run: |
|
||||
@@ -80,7 +85,7 @@ jobs:
|
||||
run: |
|
||||
cargo install default-target
|
||||
mkdir -p assets
|
||||
FILENAME=topgrade-${{ github.event.client_payload.tag }}-$(default-target)
|
||||
FILENAME=topgrade-${tag}-$(default-target)
|
||||
mv target/release/topgrade assets
|
||||
cd assets
|
||||
tar --format=ustar -czf $FILENAME.tar.gz topgrade
|
||||
@@ -111,7 +116,7 @@ jobs:
|
||||
run: |
|
||||
cargo install default-target
|
||||
mkdir assets
|
||||
FILENAME=topgrade-${{ github.event.client_payload.tag }}-$(default-target)
|
||||
FILENAME=topgrade-${tag}-$(default-target)
|
||||
mv target/release/topgrade.exe assets/topgrade.exe
|
||||
cd assets
|
||||
powershell Compress-Archive -Path * -Destination ${FILENAME}.zip
|
||||
@@ -121,8 +126,8 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
- name: Upload assets
|
||||
run:
|
||||
gh release upload "${{ github.event.client_payload.tag }}" assets/*
|
||||
run: |
|
||||
gh release upload "${tag}" assets/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -155,8 +160,13 @@ jobs:
|
||||
# Even though this is cross-compiled, it links to the libc6-<arch>-cross installed on the host
|
||||
# (see the apt-get install calls below)
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
matrix_target: ${{ matrix.target }}
|
||||
tag: ${{ github.event.client_payload.tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install needed components
|
||||
run: |
|
||||
@@ -179,20 +189,20 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
- name: install targets
|
||||
run: rustup target add ${{ matrix.target }}
|
||||
run: rustup target add "${matrix_target}"
|
||||
|
||||
- name: install cross
|
||||
# Install from source to fix `ld: cannot find -lgeom` for freebsd build
|
||||
run: cargo +stable install --git https://github.com/cross-rs/cross cross
|
||||
|
||||
- name: Run clippy
|
||||
run: cross clippy --all-targets --locked --target ${{matrix.target}} -- -D warnings
|
||||
run: cross clippy --all-targets --locked --target "${matrix_target}" -- -D warnings
|
||||
|
||||
- name: Run clippy (All features)
|
||||
run: cross clippy --locked --all-features --target ${{matrix.target}} -- -D warnings
|
||||
run: cross clippy --locked --all-features --target "${matrix_target}" -- -D warnings
|
||||
|
||||
- name: Run tests
|
||||
run: cross test --target ${{matrix.target}}
|
||||
run: cross test --target "${matrix_target}"
|
||||
# Running tests on FreeBSD is impossible; see https://github.com/cross-rs/cross/wiki/FAQ#running-bsd-tests
|
||||
# Not that this is *NOT* the same as the original issue with `ld: cannot find -lgeom`, but a new issue:
|
||||
# error: test failed, to rerun pass `--lib`
|
||||
@@ -222,23 +232,24 @@ jobs:
|
||||
mkdir -p "$dir"
|
||||
echo "DEPLOY_DIR=$dir" >> $GITHUB_ENV
|
||||
|
||||
- name: Generate shell completions
|
||||
- name: Generate man page and shell completions
|
||||
shell: bash
|
||||
run: |
|
||||
"$BIN" --gen-manpage > "$DEPLOY_DIR/topgrade.1"
|
||||
"$BIN" --gen-completion bash > "$DEPLOY_DIR/topgrade.bash"
|
||||
"$BIN" --gen-completion fish > "$DEPLOY_DIR/topgrade.fish"
|
||||
"$BIN" --gen-completion zsh > "$DEPLOY_DIR/_topgrade"
|
||||
|
||||
- name: Build in Release profile with all features enabled
|
||||
run: cross build --release --all-features --target ${{matrix.target}}
|
||||
run: cross build --release --all-features --target "${matrix_target}"
|
||||
|
||||
- name: Rename Release
|
||||
run: |
|
||||
mkdir -p assets
|
||||
FILENAME=topgrade-${{ github.event.client_payload.tag }}-${{matrix.target}}
|
||||
mv target/${{matrix.target}}/release/topgrade assets
|
||||
FILENAME=topgrade-${tag}-${matrix_target}
|
||||
mv "target/${matrix_target}/release/topgrade" assets
|
||||
cd assets
|
||||
tar --format=ustar -czf $FILENAME.tar.gz topgrade
|
||||
tar --format=ustar -czf "$FILENAME.tar.gz" topgrade
|
||||
rm topgrade
|
||||
ls .
|
||||
|
||||
@@ -247,23 +258,23 @@ jobs:
|
||||
# because we don't want the auto-update feature,
|
||||
# then build the new binary without auto-updating.
|
||||
run: |
|
||||
rm -rf target/${{matrix.target}}
|
||||
cross build --release --target ${{matrix.target}}
|
||||
cargo deb --target=${{matrix.target}} --no-build --no-strip
|
||||
rm -rf "target/${matrix_target}"
|
||||
cross build --release --target "${matrix_target}"
|
||||
cargo deb --target="${matrix_target}" --no-build --no-strip
|
||||
if: ${{ matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'armv7-unknown-linux-gnueabihf' }}
|
||||
shell: bash
|
||||
|
||||
- name: Move Debian-based system package
|
||||
run: |
|
||||
mkdir -p assets
|
||||
mv target/${{matrix.target}}/debian/*.deb assets
|
||||
mv "target/${matrix_target}/debian/*.deb" assets
|
||||
if: ${{ matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'armv7-unknown-linux-gnueabihf' }}
|
||||
shell: bash
|
||||
|
||||
|
||||
- name: Upload assets
|
||||
run:
|
||||
gh release upload "${{ github.event.client_payload.tag }}" assets/*
|
||||
gh release upload "${tag}" assets/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -275,11 +286,13 @@ jobs:
|
||||
triggers:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ native_build, cross_build ]
|
||||
env:
|
||||
tag: ${{ github.event.client_payload.tag }}
|
||||
steps:
|
||||
- name: Trigger workflows
|
||||
run: |
|
||||
gh api repos/${{ github.repository }}/dispatches \
|
||||
gh api "repos/${GITHUB_REPOSITORY}/dispatches" \
|
||||
-f "event_type=release-assets-built" \
|
||||
-F "client_payload[tag]=${{ github.event.client_payload.tag }}"
|
||||
-F "client_payload[tag]=${tag}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
3
.github/workflows/dependency-review.yml
vendored
3
.github/workflows/dependency-review.yml
vendored
@@ -18,5 +18,8 @@ jobs:
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1
|
||||
|
||||
19
.github/workflows/lint_pr.yml
vendored
Normal file
19
.github/workflows/lint_pr.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: 'Lint PR'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
|
||||
jobs:
|
||||
main:
|
||||
name: Validate PR title
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: read
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v6.1.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
24
.github/workflows/release-plz.yml
vendored
24
.github/workflows/release-plz.yml
vendored
@@ -16,14 +16,12 @@ jobs:
|
||||
contents: write
|
||||
id-token: write # For trusted publishing
|
||||
steps:
|
||||
- &checkout
|
||||
name: Checkout repository
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- &install-rust
|
||||
name: Install Rust toolchain
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: Run release-plz
|
||||
id: release-plz
|
||||
@@ -35,12 +33,13 @@ jobs:
|
||||
|
||||
- name: Trigger workflows
|
||||
if: steps.release-plz.outputs.releases_created == 'true'
|
||||
run: |
|
||||
gh api repos/${{ github.repository }}/dispatches \
|
||||
-f "event_type=release-created" \
|
||||
-F "client_payload[tag]=${{ fromJSON(steps.release-plz.outputs.releases)[0].tag }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ fromJSON(steps.release-plz.outputs.releases)[0].tag }}
|
||||
run: |
|
||||
gh api "repos/${GITHUB_REPOSITORY}/dispatches" \
|
||||
-f "event_type=release-created" \
|
||||
-F "client_payload[tag]=${tag}"
|
||||
|
||||
# Create a PR with the new versions and changelog, preparing the next release.
|
||||
release-plz-pr:
|
||||
@@ -53,8 +52,13 @@ jobs:
|
||||
group: release-plz-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- *checkout
|
||||
- *install-rust
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: Run release-plz
|
||||
uses: release-plz/action@v0.5
|
||||
with:
|
||||
|
||||
3
.github/workflows/release_to_aur.yml
vendored
3
.github/workflows/release_to_aur.yml
vendored
@@ -13,9 +13,10 @@ jobs:
|
||||
steps:
|
||||
- name: Determine version
|
||||
id: determine_version
|
||||
env:
|
||||
tag: ${{ github.event.client_payload.tag }}
|
||||
run: |
|
||||
# tag should be something like "v16.0.4", remove the prefix v here
|
||||
tag="${{ github.event.client_payload.tag }}"
|
||||
echo "version=${tag#v}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Publish source AUR package
|
||||
|
||||
25
.github/workflows/release_to_homebrew.yml
vendored
25
.github/workflows/release_to_homebrew.yml
vendored
@@ -11,28 +11,11 @@ jobs:
|
||||
homebrew-publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@24a0b15df658487e137fcd20fba32757d41a9411 # master
|
||||
|
||||
- name: Cache Homebrew Bundler RubyGems
|
||||
id: cache
|
||||
uses: actions/cache@v4.3.0
|
||||
with:
|
||||
path: ${{ steps.set-up-homebrew.outputs.gems-path }}
|
||||
key: ${{ runner.os }}-rubygems-${{ steps.set-up-homebrew.outputs.gems-hash }}
|
||||
restore-keys: ${{ runner.os }}-rubygems-
|
||||
|
||||
- name: Install Homebrew Bundler RubyGems
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: brew install-bundler-gems
|
||||
|
||||
- name: Bump formulae
|
||||
uses: Homebrew/actions/bump-packages@24a0b15df658487e137fcd20fba32757d41a9411 # master
|
||||
continue-on-error: true
|
||||
uses: dawidd6/action-homebrew-bump-formula@3428a0601bba3173ec0bdcc945be23fa27aa4c31 # v5
|
||||
with:
|
||||
# Custom GitHub access token with only the 'public_repo' scope enabled
|
||||
token: ${{secrets.HOMEBREW_ACCESS_TOKEN}}
|
||||
# Bump only these formulae if outdated
|
||||
formulae: |
|
||||
topgrade
|
||||
formula: topgrade
|
||||
tag: ${{ github.event.client_payload.tag }}
|
||||
org: topgrade-rs
|
||||
|
||||
12
.github/workflows/release_to_pypi.yml
vendored
12
.github/workflows/release_to_pypi.yml
vendored
@@ -16,6 +16,9 @@ jobs:
|
||||
target: [x86_64, x86, aarch64]
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Build wheels
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
@@ -35,6 +38,9 @@ jobs:
|
||||
target: [x64, x86]
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Build wheels
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
@@ -53,6 +59,9 @@ jobs:
|
||||
target: [x86_64, aarch64]
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Build wheels
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
@@ -68,6 +77,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Build sdist
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
|
||||
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
@@ -71,6 +71,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@v4.31.0
|
||||
uses: github/codeql-action/upload-sarif@v4.31.2
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
55
CHANGELOG.md
55
CHANGELOG.md
@@ -7,6 +7,61 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [16.2.0](https://github.com/topgrade-rs/topgrade/compare/v16.1.2...v16.2.0) - 2025-11-10
|
||||
|
||||
### Added
|
||||
|
||||
- *(mise)* run `mise self-update` ([#1450](https://github.com/topgrade-rs/topgrade/pull/1450))
|
||||
- *(falconf)* add falconf step ([#1219](https://github.com/topgrade-rs/topgrade/pull/1219))
|
||||
- *(hyprpm)* add hyprpm step ([#1213](https://github.com/topgrade-rs/topgrade/pull/1213))
|
||||
- *(doom)* add doom.aot option ([#1214](https://github.com/topgrade-rs/topgrade/pull/1214))
|
||||
- add show_distribution_summary config option ([#1259](https://github.com/topgrade-rs/topgrade/pull/1259))
|
||||
- *(rustup)* add rustup.channels config ([#1206](https://github.com/topgrade-rs/topgrade/pull/1206))
|
||||
- *(os)* add AOSC OS support ([#1424](https://github.com/topgrade-rs/topgrade/pull/1424))
|
||||
- add damp run type ([#1217](https://github.com/topgrade-rs/topgrade/pull/1217))
|
||||
|
||||
### Fixed
|
||||
|
||||
- *(release)* fix homebrew releases by migrating to dawidd6/action-homebrew-bump-formula ([#1457](https://github.com/topgrade-rs/topgrade/pull/1457))
|
||||
- *(mise)* fix mise self-update failing when installed via a package manager ([#1456](https://github.com/topgrade-rs/topgrade/pull/1456))
|
||||
- *(release)* Add man page to .deb distribution ([#1455](https://github.com/topgrade-rs/topgrade/pull/1455))
|
||||
- *(self-update)* fix windows self-update reporting failure on successful self-update ([#1452](https://github.com/topgrade-rs/topgrade/pull/1452))
|
||||
- *(pkgfile)* make pkgfile opt-in ([#1449](https://github.com/topgrade-rs/topgrade/pull/1449))
|
||||
- *(vcpkg)* fix permission denied when updating vcpkg if it's installed as root ([#1447](https://github.com/topgrade-rs/topgrade/pull/1447))
|
||||
- *(zh_TW)* fixed zh_TW strings ([#1446](https://github.com/topgrade-rs/topgrade/pull/1446))
|
||||
- *(git)* fix shellexpand::tilde in git_repos in topgrade.d/* ([#1223](https://github.com/topgrade-rs/topgrade/pull/1223))
|
||||
- *(auto-cpufreq)* skip when install script is not used ([#1215](https://github.com/topgrade-rs/topgrade/pull/1215))
|
||||
- *(vim)* change nvimrc base_dir for windows ([#1433](https://github.com/topgrade-rs/topgrade/pull/1433))
|
||||
- *(guix)* fix overcomplicated Guix step ([#1290](https://github.com/topgrade-rs/topgrade/pull/1290))
|
||||
- *(gem)* fix incorrectly placed debug message in `gem` step ([#1212](https://github.com/topgrade-rs/topgrade/pull/1212))
|
||||
- *(conda)* replace deprecated `auto_activate_base` ([#1158](https://github.com/topgrade-rs/topgrade/pull/1158))
|
||||
- *(containers)* fix panic in `containers` step ([#1150](https://github.com/topgrade-rs/topgrade/pull/1150))
|
||||
- *(jetbrains-toolbox)* fix step not dry running ([#1253](https://github.com/topgrade-rs/topgrade/pull/1253))
|
||||
|
||||
### Other
|
||||
|
||||
- comment run_config_update ([#1448](https://github.com/topgrade-rs/topgrade/pull/1448))
|
||||
- Expand LLM guidelines in CONTRIBUTING.md ([#1445](https://github.com/topgrade-rs/topgrade/pull/1445))
|
||||
- Add AI guidelines to CONTRIBUTING.md ([#1444](https://github.com/topgrade-rs/topgrade/pull/1444))
|
||||
- add comments to Config::allowed_steps ([#1291](https://github.com/topgrade-rs/topgrade/pull/1291))
|
||||
- *(nix)* Deduplicate run_nix and run_nix_self_upgrade nix --version checking ([#1376](https://github.com/topgrade-rs/topgrade/pull/1376))
|
||||
- remove commented-out library code and unnecessary bin declaration ([#1373](https://github.com/topgrade-rs/topgrade/pull/1373))
|
||||
- Simplify target cfgs ([#1346](https://github.com/topgrade-rs/topgrade/pull/1346))
|
||||
- tidy up binary-conflict code ([#1329](https://github.com/topgrade-rs/topgrade/pull/1329))
|
||||
- Improve installation section ([#1442](https://github.com/topgrade-rs/topgrade/pull/1442))
|
||||
- *(deps)* Update jetbrains-toolbox-updater ([#1438](https://github.com/topgrade-rs/topgrade/pull/1438))
|
||||
- remove template expansion in code contexts ([#1434](https://github.com/topgrade-rs/topgrade/pull/1434))
|
||||
- *(deps)* bump github/codeql-action from 4.31.0 to 4.31.2 ([#1427](https://github.com/topgrade-rs/topgrade/pull/1427))
|
||||
- don't persist credentials in actions/checkout ([#1422](https://github.com/topgrade-rs/topgrade/pull/1422))
|
||||
- Improve CONTRIBUTING.md ([#1420](https://github.com/topgrade-rs/topgrade/pull/1420))
|
||||
- Update SECURITY.md ([#1421](https://github.com/topgrade-rs/topgrade/pull/1421))
|
||||
- Enforce conventional commits in PR titles ([#1418](https://github.com/topgrade-rs/topgrade/pull/1418))
|
||||
- Improve contributing section
|
||||
- Remove roadmap
|
||||
- Reformat README.md
|
||||
- Update installation methods
|
||||
- *(release)* Fix dispatch error in create_release_assets.yml ([#1406](https://github.com/topgrade-rs/topgrade/pull/1406))
|
||||
|
||||
## [16.1.2](https://github.com/topgrade-rs/topgrade/compare/v16.1.1...v16.1.2) - 2025-11-01
|
||||
|
||||
### Fixed
|
||||
|
||||
117
CONTRIBUTING.md
117
CONTRIBUTING.md
@@ -7,13 +7,36 @@ We welcome and encourage contributions of all kinds, such as:
|
||||
2. Documentation improvements
|
||||
3. Code (PR or PR Review)
|
||||
|
||||
Please follow the [Karma Runner guidelines](http://karma-runner.github.io/6.2/dev/git-commit-msg.html)
|
||||
for commit messages.
|
||||
### LLM/AI guidelines
|
||||
|
||||
## Adding a new `step`
|
||||
You may use LLMs (AI tools) for:
|
||||
|
||||
In `topgrade`'s term, package manager is called `step`.
|
||||
To add a new `step` to `topgrade`:
|
||||
* Inspiration, problem solving, help with Rust, translation, etc.
|
||||
* Generating small and self-contained snippets of code (e.g., shell scripts or utility functions)
|
||||
|
||||
Do **not** use LLMs to:
|
||||
|
||||
* Generate ("vibe code") entire pull requests
|
||||
* Write or generate issue or pull request descriptions
|
||||
|
||||
### General guidelines
|
||||
|
||||
**Please use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) for your PR title**.
|
||||
|
||||
We use [pre-commit](https://github.com/pre-commit/pre-commit). It runs in CI, but you can optionally install the hook
|
||||
locally with `pre-commit install`. If you don't want to use pre-commit, make sure the following pass before submitting
|
||||
your PR:
|
||||
|
||||
```shell
|
||||
$ cargo fmt
|
||||
$ cargo clippy
|
||||
$ cargo test
|
||||
```
|
||||
|
||||
### Adding a new step
|
||||
|
||||
In `topgrade`'s terms, a package manager (or something else that can be upgraded) is called a step.
|
||||
To add a new step to `topgrade`:
|
||||
|
||||
1. Add a new variant to
|
||||
[`enum Step`](https://github.com/topgrade-rs/topgrade/blob/main/src/step.rs)
|
||||
@@ -33,8 +56,9 @@ To add a new `step` to `topgrade`:
|
||||
|
||||
You need to find the appropriate location where this update function goes, it should be
|
||||
a file under [`src/steps`](https://github.com/topgrade-rs/topgrade/tree/main/src/steps),
|
||||
the file names are self-explanatory, for example, `step`s related to `zsh` are
|
||||
placed in [`steps/zsh.rs`](https://github.com/topgrade-rs/topgrade/blob/main/src/steps/zsh.rs).
|
||||
the file names are self-explanatory, for example, steps related to `zsh` are
|
||||
placed in [`steps/zsh.rs`](https://github.com/topgrade-rs/topgrade/blob/main/src/steps/zsh.rs), and steps that run on
|
||||
Linux only are placed in [`steps/linux.rs`](https://github.com/topgrade-rs/topgrade/blob/main/src/steps/linux.rs).
|
||||
|
||||
Then you implement the update function, and put it in the file where it belongs.
|
||||
|
||||
@@ -53,19 +77,17 @@ To add a new `step` to `topgrade`:
|
||||
}
|
||||
```
|
||||
|
||||
Such a update function would be conventionally named `run_xxx()`, where `xxx`
|
||||
is the name of the new step, and it should take a argument of type
|
||||
`&ExecutionContext`, this is adequate for most cases unless some extra stuff is
|
||||
needed (You can find some examples where extra arguments are needed
|
||||
[here](https://github.com/topgrade-rs/topgrade/blob/7e48c5dedcfd5d0124bb9f39079a03e27ed23886/src/main.rs#L201-L219)).
|
||||
Such an update function would be conventionally named `run_xxx()`, where `xxx`
|
||||
is the name of the new step, and it should take an argument of type
|
||||
`&ExecutionContext`.
|
||||
|
||||
Update function would usually do 3 things:
|
||||
The update function should usually do 3 things:
|
||||
1. Check if the step is installed
|
||||
2. Output the Separator
|
||||
3. Invoke the step
|
||||
2. Output the separator
|
||||
3. Execute commands
|
||||
|
||||
Still, this is sufficient for most tools, but you may need some extra stuff
|
||||
with complicated `step`.
|
||||
This is sufficient for most tools, but you may need some extra stuff
|
||||
for complicated steps.
|
||||
|
||||
3. Add a match arm to `Step::run()`
|
||||
|
||||
@@ -74,7 +96,7 @@ To add a new `step` to `topgrade`:
|
||||
```
|
||||
|
||||
We use [conditional compilation](https://doc.rust-lang.org/reference/conditional-compilation.html)
|
||||
to separate the steps, for example, for steps that are Linux-only, it goes
|
||||
to separate the steps. For example, for steps that are Linux-only, it goes
|
||||
like this:
|
||||
|
||||
```rust
|
||||
@@ -89,11 +111,11 @@ To add a new `step` to `topgrade`:
|
||||
```rust
|
||||
steps.push(Xxx)
|
||||
```
|
||||
Try to keep the conditional compilation the same as in the above step 3.
|
||||
Keep the conditional compilation the same as in the above step 3.
|
||||
|
||||
Congrats, you just added a new `step` :)
|
||||
Congrats, you just added a new step :)
|
||||
|
||||
## Modification to the configuration entries
|
||||
### Modification to the configuration entries
|
||||
|
||||
If your PR has the configuration options
|
||||
(in [`src/config.rs`](https://github.com/topgrade-rs/topgrade/blob/main/src/config.rs))
|
||||
@@ -106,10 +128,10 @@ Be sure to apply your changes to
|
||||
[`config.example.toml`](https://github.com/topgrade-rs/topgrade/blob/main/config.example.toml),
|
||||
and have some basic documentations guiding user how to use these options.
|
||||
|
||||
## Breaking changes
|
||||
### Breaking changes
|
||||
|
||||
If your PR introduces a breaking change, document it in [`BREAKINGCHANGES_dev.md`][bc_dev],
|
||||
it should be written in Markdown and wrapped at 80, for example:
|
||||
If your PR introduces a breaking change, document it in [`BREAKINGCHANGES_dev.md`][bc_dev].
|
||||
It should be written in Markdown and wrapped at 80, for example:
|
||||
|
||||
```md
|
||||
1. The configuration location has been updated to x.
|
||||
@@ -121,25 +143,12 @@ it should be written in Markdown and wrapped at 80, for example:
|
||||
|
||||
[bc_dev]: https://github.com/topgrade-rs/topgrade/blob/main/BREAKINGCHANGES_dev.md
|
||||
|
||||
## Before you submit your PR
|
||||
|
||||
Make sure your patch passes the following tests on your host:
|
||||
|
||||
```shell
|
||||
$ cargo build
|
||||
$ cargo fmt
|
||||
$ cargo clippy
|
||||
$ cargo test
|
||||
```
|
||||
|
||||
Don't worry about other platforms, we have most of them covered in our CI.
|
||||
|
||||
## I18n
|
||||
### I18n
|
||||
|
||||
If your PR introduces user-facing messages, we need to ensure they are translated.
|
||||
Please add the translations to [`locales/app.yml`][app_yml]. For simple messages
|
||||
without arguments (e.g., "hello world"), we can simply translate them according
|
||||
(Tip: ChatGPT or similar LLMs is good at translation). If a message contains
|
||||
(Tip: LLMs are good at translation). If a message contains
|
||||
arguments, e.g., "hello <NAME>", please follow this convention:
|
||||
|
||||
```yml
|
||||
@@ -152,24 +161,22 @@ a preceding `%` when used in translations.
|
||||
|
||||
[app_yml]: https://github.com/topgrade-rs/topgrade/blob/main/locales/app.yml
|
||||
|
||||
## Some tips
|
||||
### Locales
|
||||
|
||||
1. Locale
|
||||
Some steps respect locale, which means their output can be in language other
|
||||
than English. In those cases, we cannot rely on the output of a command.
|
||||
|
||||
Some `step` respects locale, which means their output can be in language other
|
||||
than English, we should not do check on it.
|
||||
For example, one may want to check if a tool works by doing this:
|
||||
|
||||
For example, one may want to check if a tool works by doing this:
|
||||
```rust
|
||||
let output = Command::new("xxx").arg("--help").output().unwrap();
|
||||
let stdout = from_utf8(output.stdout).expect("Assume it is UTF-8 encoded");
|
||||
|
||||
```rust
|
||||
let output = Command::new("xxx").arg("--help").output().unwrap();
|
||||
let stdout = from_utf8(output.stdout).expect("Assume it is UTF-8 encoded");
|
||||
if stdout.contains("help") {
|
||||
// xxx works
|
||||
}
|
||||
```
|
||||
|
||||
if stdout.contains("help") {
|
||||
// xxx works
|
||||
}
|
||||
```
|
||||
|
||||
If `xxx` respects locale, then the above code should work on English system,
|
||||
on a system that does not use English, e.g., it uses Chinese, that `"help"` may be
|
||||
translated to `"帮助"`, and the above code won't work.
|
||||
If `xxx` respects locale, then the above code should work on English system,
|
||||
on a system that does not use English, e.g., it uses Chinese, that `"help"` may be
|
||||
translated to `"帮助"`, and the above code won't work.
|
||||
|
||||
371
Cargo.lock
generated
371
Cargo.lock
generated
@@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -202,7 +202,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -237,7 +237,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -293,9 +293,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
@@ -355,18 +355,19 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.16"
|
||||
version = "1.2.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
|
||||
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
@@ -434,7 +435,7 @@ dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -623,7 +624,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -703,8 +704,8 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users 0.5.0",
|
||||
"windows-sys 0.59.0",
|
||||
"redox_users 0.5.2",
|
||||
"windows-sys 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -726,7 +727,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -799,7 +800,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -893,6 +894,12 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.30"
|
||||
@@ -918,6 +925,19 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "freedesktop-desktop-entry"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aceca3da6b2371414d06c5e5c28a267f0f60288fefa1bf2e053db037388e2176"
|
||||
dependencies = [
|
||||
"log",
|
||||
"memchr",
|
||||
"thiserror 2.0.17",
|
||||
"unicase",
|
||||
"xdg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.30"
|
||||
@@ -987,7 +1007,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1032,9 +1052,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@@ -1356,7 +1376,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1442,7 +1462,7 @@ version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
@@ -1476,12 +1496,14 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "jetbrains-toolbox-updater"
|
||||
version = "5.0.0"
|
||||
version = "5.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c6bb35a4c18ced364ba2a3952bf5ca2b9231451974f5c2a4c8fa14f300a545b"
|
||||
checksum = "f66feaa93d7af6a82669172d6f3117889b1e7210dd6d9cf71e8ddcf9fd48c74f"
|
||||
dependencies = [
|
||||
"dirs 6.0.0",
|
||||
"json",
|
||||
"freedesktop-desktop-entry",
|
||||
"log",
|
||||
"serde_json",
|
||||
"sysinfo",
|
||||
]
|
||||
|
||||
@@ -1494,31 +1516,25 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "json"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
version = "0.2.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.10.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -1542,9 +1558,9 @@ checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
version = "0.4.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
|
||||
[[package]]
|
||||
name = "mac-notification-sys"
|
||||
@@ -1579,9 +1595,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
@@ -1646,7 +1662,7 @@ version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases 0.1.1",
|
||||
"libc",
|
||||
@@ -1659,7 +1675,7 @@ version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases 0.2.1",
|
||||
"libc",
|
||||
@@ -1748,11 +1764,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.0"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1853,7 +1879,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1957,9 +1983,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.94"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1984,9 +2010,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -2043,20 +2069,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.5.0"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
|
||||
checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox",
|
||||
"thiserror 2.0.12",
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.5"
|
||||
version = "1.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
|
||||
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -2066,9 +2092,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.7"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -2086,9 +2112,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.4"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
@@ -2180,7 +2206,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2235,7 +2261,7 @@ version = "0.38.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.10.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
@@ -2372,7 +2398,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2396,7 +2422,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2585,7 +2611,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2607,9 +2633,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.99"
|
||||
version = "2.0.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
|
||||
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2630,7 +2656,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2644,15 +2670,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.34.2"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4b93974b3d3aeaa036504b8eefd4c039dced109171c1ae973f1dc63b2c7e4b2"
|
||||
checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"memchr",
|
||||
"ntapi",
|
||||
"objc2-core-foundation",
|
||||
"windows 0.56.0",
|
||||
"objc2-io-kit",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2700,11 +2727,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.12"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
|
||||
dependencies = [
|
||||
"thiserror-impl 2.0.12",
|
||||
"thiserror-impl 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2715,18 +2742,18 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.12"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2890,7 +2917,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "topgrade"
|
||||
version = "16.1.2"
|
||||
version = "16.2.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
@@ -2982,7 +3009,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3076,10 +3103,16 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
name = "unicase"
|
||||
version = "2.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
@@ -3161,9 +3194,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
@@ -3186,7 +3219,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -3220,7 +3253,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -3315,17 +3348,39 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.61.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
||||
dependencies = [
|
||||
"windows-collections 0.2.0",
|
||||
"windows-core 0.61.2",
|
||||
"windows-future 0.2.1",
|
||||
"windows-link 0.1.3",
|
||||
"windows-numerics 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9579d0e6970fd5250aa29aba5994052385ff55cf7b28a059e484bb79ea842e42"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-collections 0.3.0",
|
||||
"windows-core 0.62.0",
|
||||
"windows-future",
|
||||
"windows-link",
|
||||
"windows-numerics",
|
||||
"windows-future 0.3.0",
|
||||
"windows-link 0.2.0",
|
||||
"windows-numerics 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3358,17 +3413,41 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.0",
|
||||
"windows-interface 0.59.1",
|
||||
"windows-link",
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-link 0.2.0",
|
||||
"windows-result 0.4.0",
|
||||
"windows-strings",
|
||||
"windows-strings 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link 0.1.3",
|
||||
"windows-threading 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3378,8 +3457,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2194dee901458cb79e1148a4e9aac2b164cc95fa431891e7b296ff0b2f1d8a6"
|
||||
dependencies = [
|
||||
"windows-core 0.62.0",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
"windows-link 0.2.0",
|
||||
"windows-threading 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3390,18 +3469,18 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3412,26 +3491,42 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.0"
|
||||
@@ -3439,7 +3534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ce3498fe0aba81e62e477408383196b4b0363db5e0c27646f932676283b43d8"
|
||||
dependencies = [
|
||||
"windows-core 0.62.0",
|
||||
"windows-link",
|
||||
"windows-link 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3448,9 +3543,9 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f91f87ce112ffb7275000ea98eb1940912c21c1567c9312fde20261f3eadd29"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.2.0",
|
||||
"windows-result 0.4.0",
|
||||
"windows-strings",
|
||||
"windows-strings 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3462,13 +3557,31 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3477,7 +3590,7 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3507,6 +3620,15 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
|
||||
dependencies = [
|
||||
"windows-link 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
@@ -3538,13 +3660,22 @@ dependencies = [
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab47f085ad6932defa48855254c758cdd0e2f2d48e62a34118a268d8f345e118"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3703,6 +3834,12 @@ dependencies = [
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xdg"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fb433233f2df9344722454bc7e96465c9d03bff9d77c248f9e7523fe79585b5"
|
||||
|
||||
[[package]]
|
||||
name = "xdg-home"
|
||||
version = "1.2.0"
|
||||
@@ -3742,7 +3879,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -3793,7 +3930,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
@@ -3825,7 +3962,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -3854,7 +3991,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3903,7 +4040,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
@@ -3915,5 +4052,5 @@ checksum = "fc242db087efc22bd9ade7aa7809e4ba828132edc312871584a6b4391bdf8786"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.108",
|
||||
]
|
||||
|
||||
14
Cargo.toml
14
Cargo.toml
@@ -6,20 +6,13 @@ keywords = ["upgrade", "update"]
|
||||
license = "GPL-3.0"
|
||||
repository = "https://github.com/topgrade-rs/topgrade"
|
||||
rust-version = "1.84.1"
|
||||
version = "16.1.2"
|
||||
version = "16.2.0"
|
||||
authors = ["Roey Darwish Dror <roey.ghost@gmail.com>", "Thomas Schönauer <t.schoenauer@hgs-wt.at>"]
|
||||
exclude = ["doc/screenshot.gif", "BREAKINGCHANGES_dev.md"]
|
||||
edition = "2021"
|
||||
|
||||
readme = "README.md"
|
||||
|
||||
[[bin]]
|
||||
name = "topgrade"
|
||||
path = "src/main.rs"
|
||||
|
||||
##[lib]
|
||||
##name = "topgrade_lib"
|
||||
|
||||
[dependencies]
|
||||
home = "~0.5"
|
||||
etcetera = "~0.8"
|
||||
@@ -75,8 +68,9 @@ default-features = true
|
||||
assets = [
|
||||
["target/release/topgrade", "usr/bin/", "755"],
|
||||
["README.md", "usr/share/doc/topgrade/README.md", "644"],
|
||||
# The man page is automatically generated by topgrade's build process in CI, so
|
||||
# these files aren't actually committed.
|
||||
# The man page and shell completions are automatically generated by topgrade's build process in CI,
|
||||
# so these files aren't actually committed.
|
||||
["deployment/deb/topgrade.1", "usr/share/man/man1/topgrade.1", "644"],
|
||||
["deployment/deb/topgrade.bash", "usr/share/bash-completion/completions/topgrade", "644"],
|
||||
["deployment/deb/topgrade.fish", "usr/share/fish/vendor_completions.d/topgrade.fish", "644"],
|
||||
["deployment/deb/_topgrade", "usr/share/zsh/vendor-completions/", "644"],
|
||||
|
||||
68
README.md
68
README.md
@@ -11,7 +11,6 @@
|
||||
<img alt="Demo" src="doc/topgrade_demo.gif">
|
||||
</div>
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
> **Note**
|
||||
@@ -25,20 +24,32 @@ To remedy this, **Topgrade** detects which tools you use and runs the appropriat
|
||||
|
||||
[](https://repology.org/project/topgrade/versions)
|
||||
|
||||
- Arch Linux: [AUR](https://aur.archlinux.org/packages/topgrade)
|
||||
- NixOS: [Nixpkgs](https://search.nixos.org/packages?show=topgrade)
|
||||
- Void Linux: [XBPS](https://voidlinux.org/packages/?arch=x86_64&q=topgrade)
|
||||
- macOS: [Homebrew](https://formulae.brew.sh/formula/topgrade) or [MacPorts](https://ports.macports.org/port/topgrade/)
|
||||
- Windows: [Chocolatey][choco], [Scoop][scoop] or [Winget][winget]
|
||||
- PyPi: [pip](https://pypi.org/project/topgrade/)
|
||||
- Fedora: [Copr](https://copr.fedorainfracloud.org/coprs/lilay/topgrade/)
|
||||
### Official
|
||||
|
||||
[choco]: https://community.chocolatey.org/packages/topgrade
|
||||
[scoop]: https://scoop.sh/#/apps?q=topgrade
|
||||
[winget]: https://winstall.app/apps/topgrade-rs.topgrade
|
||||
- Self-updating binary (all platforms): [releases](https://github.com/topgrade-rs/topgrade/releases)
|
||||
- Install from source (all platforms): [`cargo install topgrade`](https://crates.io/crates/topgrade)
|
||||
- Debian/Ubuntu ([deb-get](https://github.com/wimpysworld/deb-get)):
|
||||
[`deb-get install topgrade`](https://github.com/wimpysworld/deb-get/blob/main/01-main/packages/topgrade)
|
||||
- Arch Linux (AUR): [topgrade](https://aur.archlinux.org/packages/topgrade)
|
||||
or [topgrade-bin](https://aur.archlinux.org/packages/topgrade-bin)
|
||||
- [PyPi](https://pypi.org/): `pip`, `pipx`, or `uv tool` [
|
||||
`install topgrade`](https://pypi.org/project/topgrade/)
|
||||
- Windows ([Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/)): [
|
||||
`winget install --id=topgrade-rs.topgrade -e`](https://winstall.app/apps/topgrade-rs.topgrade)
|
||||
- macOS or Linux ([Homebrew](https://brew.sh/)): [`brew install topgrade`](https://formulae.brew.sh/formula/topgrade)
|
||||
|
||||
Other systems users can either use `cargo install` or the compiled binaries from the release page.
|
||||
The compiled binaries contain a self-upgrading feature.
|
||||
### Community-maintained
|
||||
|
||||
- Windows ([Chocolatey](https://chocolatey.org/)): [
|
||||
`choco install topgrade`](https://community.chocolatey.org/packages/topgrade)
|
||||
- Windows ([Scoop](https://scoop.sh/)): [
|
||||
`scoop bucket add main && scoop install main/topgrade`](https://scoop.sh/#/apps?q=topgrade)
|
||||
- macOS ([MacPorts](https://www.macports.org/)): [
|
||||
`sudo port install topgrade`](https://ports.macports.org/port/topgrade/)
|
||||
- Fedora ([Copr](https://copr.fedorainfracloud.org/)): [
|
||||
`dnf copr enable lilay/topgrade && dnf install topgrade`](https://copr.fedorainfracloud.org/coprs/lilay/topgrade/)
|
||||
- NixOS or Nix (nixpkgs): [topgrade](https://search.nixos.org/packages?show=topgrade)
|
||||
- Void Linux: [`sudo xbps-install -S topgrade`](https://voidlinux.org/packages/?arch=x86_64&q=topgrade)
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -59,6 +70,7 @@ it when updated to a major release.
|
||||
### Configuration Path
|
||||
|
||||
#### `CONFIG_DIR` on each platform
|
||||
|
||||
- **Windows**: `%APPDATA%`
|
||||
- **macOS** and **other Unix systems**: `${XDG_CONFIG_HOME:-~/.config}`
|
||||
|
||||
@@ -67,16 +79,21 @@ it when updated to a major release.
|
||||
1. `CONFIG_DIR/topgrade.toml`
|
||||
2. `CONFIG_DIR/topgrade/topgrade.toml`
|
||||
|
||||
If the file with higher priority is present, no matter it is valid or not, the other configuration files will be ignored.
|
||||
If the file with higher priority is present, no matter it is valid or not, the other configuration files will be
|
||||
ignored.
|
||||
|
||||
On the first run(no configuration file exists), `topgrade` will create a configuration file at `CONFIG_DIR/topgrade.toml` for you.
|
||||
On the first run(no configuration file exists), `topgrade` will create a configuration file at
|
||||
`CONFIG_DIR/topgrade.toml` for you.
|
||||
|
||||
### Custom Commands
|
||||
|
||||
Custom commands can be defined in the config file which can be run before, during, or after the inbuilt commands, as required.
|
||||
By default, the custom commands are run using a new shell according to the `$SHELL` environment variable on unix (falls back to `sh`) or `pwsh` on windows (falls back to `powershell`).
|
||||
Custom commands can be defined in the config file which can be run before, during, or after the inbuilt commands, as
|
||||
required.
|
||||
By default, the custom commands are run using a new shell according to the `$SHELL` environment variable on unix (falls
|
||||
back to `sh`) or `pwsh` on windows (falls back to `powershell`).
|
||||
|
||||
On unix, if you want to run your command using an interactive shell, for example to source your shell's rc files, you can add `-i` at the start of your custom command.
|
||||
On unix, if you want to run your command using an interactive shell, for example to source your shell's rc files, you
|
||||
can add `-i` at the start of your custom command.
|
||||
But note that this requires the command to exit the shell correctly or else the shell will hang indefinitely.
|
||||
|
||||
## Remote Execution
|
||||
@@ -95,22 +112,13 @@ Open a new issue describing your problem and if possible provide a solution.
|
||||
### Missing a feature or found an unsupported tool/distro?
|
||||
|
||||
Just let us now what you are missing by opening an issue.
|
||||
For tools, please open an issue describing the tool, which platforms it supports and if possible, give us an example of its usage.
|
||||
For tools, please open an issue describing the tool, which platforms it supports and if possible, give us an example of
|
||||
its usage.
|
||||
|
||||
### Want to contribute to the code?
|
||||
|
||||
Just fork the repository and start coding.
|
||||
|
||||
### Contribution Guidelines
|
||||
### Want to contribute?
|
||||
|
||||
See [CONTRIBUTING.md](https://github.com/topgrade-rs/topgrade/blob/master/CONTRIBUTING.md)
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [ ] Add a proper testing framework to the code base.
|
||||
- [ ] Add unit tests for package managers.
|
||||
- [ ] Split up code into more maintainable parts, eg. putting every linux package manager in a own submodule of linux.rs.
|
||||
|
||||
## Discord server
|
||||
|
||||
Welcome to [join](https://discord.gg/Q8HGGWundY) our Discord server if you want
|
||||
|
||||
11
SECURITY.md
11
SECURITY.md
@@ -1,10 +1,9 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
To report a security vulnerability, go to [the security tab](https://github.com/topgrade-rs/topgrade/security) and click "Report a vulnerability".
|
||||
|
||||
## Supported Versions
|
||||
|
||||
We only support the latest major version and each subversion.
|
||||
|
||||
| Version | Supported |
|
||||
| -------- | ------------------ |
|
||||
| 16.0.x | :white_check_mark: |
|
||||
| < 16.0 | :x: |
|
||||
We only support the latest version of Topgrade. Fixes are not backported.
|
||||
|
||||
@@ -91,6 +91,11 @@
|
||||
# See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives
|
||||
# log_filters = ["topgrade::command=debug", "warn"]
|
||||
|
||||
# Whether to show a distribution-specific summary if applicable, e.g. listing
|
||||
# Pacman backup configuration files (*.pacsave and *.pacnew)
|
||||
# (default: true)
|
||||
# show_distribution_summary = false
|
||||
|
||||
|
||||
# Commands to run before anything
|
||||
[pre_commands]
|
||||
@@ -223,6 +228,13 @@
|
||||
# enable = true
|
||||
|
||||
|
||||
[pkgfile]
|
||||
# Enable the pkgfile step (to update the pkgfile database).
|
||||
# Pkgfile is sometimes installed by default, but often not used and heavy to update.
|
||||
# (default: false)
|
||||
# enable = true
|
||||
|
||||
|
||||
[git]
|
||||
# How many repos to pull at max in parallel
|
||||
# max_concurrency = 5
|
||||
@@ -376,3 +388,14 @@
|
||||
# during the pixi step
|
||||
# (default: false)
|
||||
# include_release_notes = false
|
||||
|
||||
[doom]
|
||||
# If this is set to true, the `--aot` flag is added to `doom upgrade`,
|
||||
# which enables ahead-of-time native compilation of packages.
|
||||
# (default: false)
|
||||
# aot = true
|
||||
|
||||
[rustup]
|
||||
# If set, updates only these channels.
|
||||
# (default: [] (all channels))
|
||||
# channels = ["stable"]
|
||||
|
||||
130
locales/app.yml
130
locales/app.yml
@@ -16,6 +16,22 @@ _version: 2
|
||||
zh_CN: "正在模拟 %{program_name} %{arguments} 的运行过程"
|
||||
zh_TW: "正在模擬 %{program_name} %{arguments} 的執行過程"
|
||||
de: "Testlauf: %{program_name} %{arguments}"
|
||||
"Executing: {program_name} {arguments}":
|
||||
en: "Executing: %{program_name} %{arguments}"
|
||||
lt: "Vykdymas: %{program_name} %{arguments}"
|
||||
es: "Ejecutando: %{program_name} %{arguments}"
|
||||
fr: "Exécution: %{program_name} %{arguments}"
|
||||
zh_CN: "执行: %{program_name} %{arguments}"
|
||||
zh_TW: "执行: %{program_name} %{arguments}"
|
||||
de: "Ausführung: %{program_name} %{arguments}"
|
||||
"with env: {env}":
|
||||
en: "with env: %{env}"
|
||||
lt: "su env: %{env}"
|
||||
es: "con env: %{env}"
|
||||
fr: "avec env: %{env}"
|
||||
zh_CN: "与env: %{env}"
|
||||
zh_TW: "與env: %{env}"
|
||||
de: "mit env: %{env}"
|
||||
"in {directory}":
|
||||
en: "in %{directory}"
|
||||
lt: "kataloge %{directory}"
|
||||
@@ -70,7 +86,7 @@ _version: 2
|
||||
es: "Cambiando al shell. Arregla lo que necesites y luego sal del shell."
|
||||
fr: "Ouverture d'un shell. Réparez ce dont vous avez besoin et quittez le shell."
|
||||
zh_CN: "已切换到 Shell 环境。请修复需要的内容,完成后退出 Shell 。"
|
||||
zh_TW: "已切換到終端殼層。修復完畢後請退出殼層以繼續。"
|
||||
zh_TW: "已切換到 shell 環境。修復完畢後請退出 shell 以繼續。"
|
||||
de: "Wechsel zur Shell. Beheben Sie die Probleme und verlassen Sie dann die Shell."
|
||||
"Topgrade launched in a new tmux session":
|
||||
en: "Topgrade launched in a new tmux session"
|
||||
@@ -78,7 +94,7 @@ _version: 2
|
||||
es: "Topgrade lanzado en una nueva sesión tmux"
|
||||
fr: "Topgrade lancé dans une nouvelle session tmux"
|
||||
zh_CN: "Topgrade 已在新的 tmux 会话中启动"
|
||||
zh_TW: "Topgrade 已啟動新 tmux 程序"
|
||||
zh_TW: "Topgrade 已啟動新 tmux 程式"
|
||||
de: "Topgrade in einer neuen tmux-Sitzung gestartet"
|
||||
"Topgrade upgraded to {version}:\n":
|
||||
en: "Topgrade upgraded to %{version}:\n"
|
||||
@@ -228,7 +244,7 @@ _version: 2
|
||||
es: "La auditoría del paquete fue exitosa, pero aún quedan paquetes vulnerables en el sistema"
|
||||
fr: "L'audit des paquets a réussi, mais des paquets vulnérables restent toujours sur le système"
|
||||
zh_CN: "软件包审计已通过,但系统中仍存在含漏洞的软件包"
|
||||
zh_TW: "雖然套件檢測成功,但系統仍然包含危險套件"
|
||||
zh_TW: "雖然套件審查成功,但系統仍然殘留危險套件"
|
||||
de: "Das Paket-Audit war erfolgreich, aber es befinden sich noch anfällige Pakete im System"
|
||||
"Syncing portage":
|
||||
en: "Syncing portage"
|
||||
@@ -244,7 +260,7 @@ _version: 2
|
||||
es: "Buscando software disponible"
|
||||
fr: "Recherche de logiciels disponible"
|
||||
zh_CN: "正在寻找可用的软件"
|
||||
zh_TW: "正在尋找軟體"
|
||||
zh_TW: "正在尋找可用的軟體"
|
||||
de: "Suche nach verfügbarer Software"
|
||||
"A system update is available. Do you wish to install it?":
|
||||
en: "A system update is available. Do you wish to install it?"
|
||||
@@ -252,14 +268,14 @@ _version: 2
|
||||
es: "Hay una actualización del sistema disponible. ¿Desea instalarla?"
|
||||
fr: "Une mise à jour du système est disponible. Voulez-vous l'installer ?"
|
||||
zh_CN: "系统更新可用。是否立即安装?"
|
||||
zh_TW: "系統更新已就緒。是否現在安裝?"
|
||||
zh_TW: "系統更新已就緒。是否立即安裝?"
|
||||
de: "Ein System-Update ist verfügbar. Möchten Sie es installieren?"
|
||||
"No new software available.":
|
||||
en: "No new software available."
|
||||
lt: "Nėra naujos programinės įrangos."
|
||||
es: "No hay ningún software nuevo disponible."
|
||||
fr: "Aucun nouveau logiciel disponible."
|
||||
zh_CN: "没有新的可用的软件包"
|
||||
zh_CN: "没有新的可用的软件包。"
|
||||
zh_TW: "沒有新軟體。"
|
||||
de: "Keine neue Software verfügbar."
|
||||
"No Xcode releases installed.":
|
||||
@@ -267,7 +283,7 @@ _version: 2
|
||||
lt: "Nėra įdiegtų Xcode versijų."
|
||||
es: "No hay versiones de Xcode instaladas."
|
||||
fr: "Aucune version de Xcode installée."
|
||||
zh_CN: "尚未安装 Xcode 发行版"
|
||||
zh_CN: "尚未安装 Xcode 发行版。"
|
||||
zh_TW: "尚未安裝 Xcode 發行版。"
|
||||
de: "Keine Xcode-Versionen installiert."
|
||||
"Would you like to move the former Xcode release to the trash?":
|
||||
@@ -292,7 +308,7 @@ _version: 2
|
||||
es: "¿Le gustaría instalarlo?"
|
||||
fr: "Voulez-vous l'installer ?"
|
||||
zh_CN: "是否立即安装?"
|
||||
zh_TW: "是否現在安裝?"
|
||||
zh_TW: "是否立即安裝?"
|
||||
de: "Möchten Sie sie installieren?"
|
||||
"No global packages installed":
|
||||
en: "No global packages installed"
|
||||
@@ -324,7 +340,7 @@ _version: 2
|
||||
es: "Recolectando cajas Vagrant"
|
||||
fr: "Collecte des boîtes Vagrant"
|
||||
zh_CN: "正在收集 Vagrant 容器"
|
||||
zh_TW: "正在蒐集 Vagrant 容器"
|
||||
zh_TW: "正在收集 Vagrant 容器"
|
||||
de: "Sammle Vagrant-Boxen"
|
||||
"No Vagrant directories were specified in the configuration file":
|
||||
en: "No Vagrant directories were specified in the configuration file"
|
||||
@@ -348,7 +364,7 @@ _version: 2
|
||||
es: "Sin cajas obsoletas"
|
||||
fr: "Aucune boîte obsolète"
|
||||
zh_CN: "没有需要更新的容器"
|
||||
zh_TW: "未有需要更新的容器"
|
||||
zh_TW: "沒有需要更新的容器"
|
||||
de: "Keine veralteten Boxen"
|
||||
"Summary":
|
||||
en: "Summary"
|
||||
@@ -382,14 +398,6 @@ _version: 2
|
||||
zh_CN: "Topgrade %{version_str} 破坏性更改"
|
||||
zh_TW: "Topgrade %{version_str} 重大更改"
|
||||
de: "Topgrade %{version_str} Inkompatible Änderungen"
|
||||
"Path {path} expanded to {expanded}":
|
||||
en: "Path %{path} expanded to %{expanded}"
|
||||
lt: "Kelias %{path} išplėstas į %{expanded}"
|
||||
es: "Ruta %{path} expandida a %{expanded}"
|
||||
fr: "Le chemin %{path} a été transformé en %{expanded}"
|
||||
zh_CN: "已扩展 %{path} 至 %{expanded}"
|
||||
zh_TW: "已擴展 %{path} 至 %{expanded}"
|
||||
de: "Pfad %{path} erweitert zu %{expanded}"
|
||||
"Path {path} doesn't exist":
|
||||
en: "Path %{path} doesn't exist"
|
||||
lt: "Kelias %{path} neegzistuoja"
|
||||
@@ -476,7 +484,7 @@ _version: 2
|
||||
es: "Auditoría de DragonFly BSD"
|
||||
fr: "Audit de DragonFly BSD"
|
||||
zh_CN: "DragonFly BSD 审计"
|
||||
zh_TW: "DragonFly BSD 紀錄"
|
||||
zh_TW: "DragonFly BSD 審查"
|
||||
de: "DragonFly BSD Audit"
|
||||
"FreeBSD Update":
|
||||
en: "FreeBSD Update"
|
||||
@@ -500,7 +508,7 @@ _version: 2
|
||||
es: "Auditoría FreeBSD"
|
||||
fr: "Audit de FreeBSD"
|
||||
zh_CN: "FreeBSD 审计"
|
||||
zh_TW: "FreeBSD 紀錄"
|
||||
zh_TW: "FreeBSD 審查"
|
||||
de: "FreeBSD Audit"
|
||||
"System update":
|
||||
en: "System update"
|
||||
@@ -532,7 +540,7 @@ _version: 2
|
||||
es: "No se debe ejecutar en WSL"
|
||||
fr: "Ne doit pas être exécuté dans WSL"
|
||||
zh_CN: "不应在 WSL 中运行"
|
||||
zh_TW: "不該在 WSL 中執行"
|
||||
zh_TW: "不應在 WSL 中執行"
|
||||
de: "Sollte nicht in WSL ausgeführt werden"
|
||||
"Firmware upgrades":
|
||||
en: "Firmware upgrades"
|
||||
@@ -556,7 +564,7 @@ _version: 2
|
||||
es: "El socket Snapd no existe"
|
||||
fr: "Le socket Snapd n'existe pas"
|
||||
zh_CN: "找不到 Snapd 程序"
|
||||
zh_TW: "找不到 Snapd 程序"
|
||||
zh_TW: "找不到 Snapd 程式"
|
||||
de: "Snapd-Socket existiert nicht"
|
||||
"You need to specify at least one container":
|
||||
en: "You need to specify at least one container"
|
||||
@@ -596,7 +604,7 @@ _version: 2
|
||||
es: "Omitiendo el paso de Waydroid debido a que el usuario no quiere continuar"
|
||||
fr: "Passer l'étape Waydroid car l'utilisateur ne souhaite pas l'exécuter"
|
||||
zh_CN: "使用者指定跳过 Waydroid 程序"
|
||||
zh_TW: "使用者指定略過 Waydroid 程序"
|
||||
zh_TW: "使用者指定略過 Waydroid 程式"
|
||||
de: "Überspringe den Waydroid-Schritt, da der Benutzer nicht fortfahren möchte"
|
||||
"macOS App Store":
|
||||
en: "macOS App Store"
|
||||
@@ -942,13 +950,21 @@ _version: 2
|
||||
zh_CN: "拉取 %{repo}"
|
||||
zh_TW: "拉取 %{repo}"
|
||||
de: "Würde %{repo} abrufen"
|
||||
"No Neovim config found":
|
||||
en: "No Neovim config found"
|
||||
lt: "Neovim konfigūracija nerasta"
|
||||
es: "No se encontró ninguna configuración de Neovim"
|
||||
fr: "Aucune configuration Neovim trouvée"
|
||||
zh_CN: "未找到 Neovim 配置"
|
||||
zh_TW: "未找到 Neovim 設定"
|
||||
de: "Keine Neovim-Konfiguration gefunden"
|
||||
"Node Package Manager":
|
||||
en: "Node Package Manager"
|
||||
lt: "Node paketų tvarkyklė (npm)"
|
||||
es: "Node Package Manager (npm)"
|
||||
fr: "Gestionnaire de paquets Node (npm)"
|
||||
zh_CN: "Node Package Manager(npm)"
|
||||
zh_TW: "Node 套件管理員(npm)"
|
||||
zh_TW: "Node Package Manager(npm)"
|
||||
de: "Node Package Manager (npm)"
|
||||
"Performant Node Package Manager":
|
||||
en: "Performant Node Package Manager"
|
||||
@@ -956,7 +972,7 @@ _version: 2
|
||||
es: "Performant Node Package Manager (pnpm)"
|
||||
fr: "Gestionnaire de paquets Node performant (pnpm)"
|
||||
zh_CN: "Performant Node Package Manager (pnpm)"
|
||||
zh_TW: "效能 Node 套件管理員(pnpm)"
|
||||
zh_TW: "Performant Node Package Manager(pnpm)"
|
||||
de: "Performanter Node Package Manager (pnpm)"
|
||||
"Yarn Package Manager":
|
||||
en: "Yarn Package Manager"
|
||||
@@ -1012,7 +1028,7 @@ _version: 2
|
||||
es: "Distribución de Linux desconocida"
|
||||
fr: "Distribution Linux inconnue"
|
||||
zh_CN: "未知 Linux 发行版"
|
||||
zh_TW: "未知 Linux"
|
||||
zh_TW: "未知 Linux 發行版"
|
||||
de: "Unbekannte Linux-Distribution"
|
||||
'File "/etc/os-release" does not exist or is empty':
|
||||
en: 'File "/etc/os-release" does not exist or is empty'
|
||||
@@ -1046,14 +1062,6 @@ _version: 2
|
||||
zh_CN: "模拟运行"
|
||||
zh_TW: "模擬執行"
|
||||
de: "Testlauf"
|
||||
"Topgrade Upgraded":
|
||||
en: "Topgrade Upgraded"
|
||||
lt: "Topgrade atnaujintas"
|
||||
es: "Topgrade Actualizado"
|
||||
fr: "Topgrade mis à jour"
|
||||
zh_CN: "已升级 Topgrade"
|
||||
zh_TW: "已更新 Topgrade"
|
||||
de: "Topgrade aktualisiert"
|
||||
|
||||
# Summary texts
|
||||
"OK":
|
||||
@@ -1108,7 +1116,7 @@ _version: 2
|
||||
es: "¿Reintentar? (y) Si / (N) No / (s) Shell / (q) Salir"
|
||||
fr: "Réessayer ? (y) Oui / (N) Non / (s) Shell / (q) Quitter"
|
||||
zh_CN: "再试一次?(y)是/(N)否/(s)Shell/(q)退出"
|
||||
zh_TW: "再試一次? (y)是/(N)否/(s)殼層/(q)退出"
|
||||
zh_TW: "再試一次? (y)是/(N)否/(s)Shell/(q)退出"
|
||||
de: "Wiederholen? (y) Ja / (n) Nein / (s) Shell / (q) Beenden"
|
||||
|
||||
# 'R', 'S', 'Q' have to stay the same throughout all translations. Eg German would look like "\n(R) Neustarten\n(S) Konsole\n(Q) Beenden"
|
||||
@@ -1118,7 +1126,7 @@ _version: 2
|
||||
es: "\n(R) Reiniciar\n(S) Shell\n(Q) Salir"
|
||||
fr: "\n(R) Redémarrer\n(S) Shell\n(Q) Quitter"
|
||||
zh_CN: "\n(R)重启\n(S)Shell\n(Q)退出"
|
||||
zh_TW: "\n(R)重新啟動\n(S)殼層\n(Q)退出"
|
||||
zh_TW: "\n(R)重新啟動\n(S)shell\n(Q)退出"
|
||||
de: "\n(R) Neustarten\n(S)hell\n(Q)uit beenden"
|
||||
|
||||
"Continue?":
|
||||
@@ -1160,7 +1168,7 @@ _version: 2
|
||||
es: "\nAlgunos pasos se omitieron porque no se pudo encontrar sudo o equivalente."
|
||||
fr: "\nCertaines étapes ont été ignorées car sudo ou équivalent est introuvable."
|
||||
zh_CN: "\n由于未找到 sudo 或等效工具,某些步骤被跳过。"
|
||||
zh_TW: "\n由於找不到 sudo 或等效工具,某些步驟已跳過。"
|
||||
zh_TW: "\n某些步驟因為找不到 sudo 或同等的工具而被跳過。"
|
||||
de: "\nEinige Schritte wurden übersprungen, da sudo oder ein Äquivalent nicht gefunden wurde."
|
||||
"Install one of `sudo`, `doas`, `pkexec`, `run0` or `please` to run these steps.":
|
||||
en: "Install one of `sudo`, `doas`, `pkexec`, `run0` or `please` to run these steps."
|
||||
@@ -1168,7 +1176,7 @@ _version: 2
|
||||
es: "Instale uno de `sudo`, `doas`, `pkexec`, `run0` o `please` para ejecutar estos pasos."
|
||||
fr: "Installez l’un de `sudo`, `doas`, `pkexec`, `run0` ou `please` pour exécuter ces étapes."
|
||||
zh_CN: "请安装 `sudo`、`doas`、`pkexec`、`run0` 或 `please` 之一来运行这些步骤。"
|
||||
zh_TW: "請安裝 `sudo`、`doas`、`pkexec`、`run0` 或 `please` 之一來執行這些步驟。"
|
||||
zh_TW: "請安裝 `sudo`、`doas`、`pkexec`、`run0` 或 `please` 以執行這些步驟。"
|
||||
de: "Installieren Sie `sudo`, `doas`, `pkexec`, `run0` oder `please`, um diese Schritte auszuführen."
|
||||
"Install gsudo to run these steps.":
|
||||
en: "Install gsudo to run these steps."
|
||||
@@ -1232,7 +1240,7 @@ _version: 2
|
||||
es: "sudo como usuario '%{user}'"
|
||||
fr: "sudo en tant qu'utilisateur '%{user}'"
|
||||
zh_CN: "sudo 作为用户 '%{user}'"
|
||||
zh_TW: "sudo 以使用者 '%{user}'"
|
||||
zh_TW: "sudo 作為使用者 '%{user}'"
|
||||
de: "sudo als Benutzer '%{user}'"
|
||||
"Updating aqua ...":
|
||||
en: "Updating aqua ..."
|
||||
@@ -1279,7 +1287,7 @@ _version: 2
|
||||
lt: "Vėl paleidžiama..."
|
||||
es: "Reapareciendo..."
|
||||
fr: "Relancement..."
|
||||
zh_CN: "正在重新生成"
|
||||
zh_CN: "正在重新生成..."
|
||||
zh_TW: "正在重新生成..."
|
||||
de: "Neustarten..."
|
||||
"Could not find Topgrade in any WSL distribution":
|
||||
@@ -1288,7 +1296,7 @@ _version: 2
|
||||
es: "No se pudo encontrar Topgrade en ninguna distribución WSL"
|
||||
fr: "Impossible de trouver Topgrade installé dans WSL"
|
||||
zh_CN: "无法在任何 WSL 发行版中找到 Topgrade"
|
||||
zh_TW: "在所有 WSL 中找不到 Topgrade"
|
||||
zh_TW: "無法在任何 WSL 發行版中找到 Topgrade"
|
||||
de: "Konnte Topgrade in keiner WSL-Distribution finden"
|
||||
"Windows Update":
|
||||
en: "Windows Update"
|
||||
@@ -1298,30 +1306,14 @@ _version: 2
|
||||
zh_CN: "Windows 更新"
|
||||
zh_TW: "Windows 更新"
|
||||
de: "Windows-Update"
|
||||
"Would check if OpenBSD is -current":
|
||||
en: "Would check if OpenBSD is -current"
|
||||
lt: "Patikrintų, ar OpenBSD yra -current"
|
||||
es: "Comprobaría si OpenBSD está en -current"
|
||||
fr: "Vérifierait si OpenBSD est à -curent"
|
||||
zh_CN: "将检查 OpenBSD 是否为 -current"
|
||||
zh_TW: "會檢查 OpenBSD 是否為 -current"
|
||||
de: "Würde überprüfen, ob OpenBSD -current ist"
|
||||
"Would upgrade the OpenBSD system":
|
||||
en: "Would upgrade the OpenBSD system"
|
||||
lt: "Atnaujintų OpenBSD sistemą"
|
||||
es: "Actualizaría el sistema OpenBSD"
|
||||
fr: "Mettrait à jour le système OpenBSD"
|
||||
zh_CN: "将升级 OpenBSD 系统"
|
||||
zh_TW: "會升級 OpenBSD 系統"
|
||||
de: "Würde das OpenBSD-System aktualisieren"
|
||||
"Would upgrade OpenBSD packages":
|
||||
en: "Would upgrade OpenBSD packages"
|
||||
lt: "Atnaujintų OpenBSD paketus"
|
||||
es: "Actualizaría los paquetes de OpenBSD"
|
||||
fr: "Mettrait à jour les paquets OpenBSD"
|
||||
zh_CN: "将升级 OpenBSD 软件包"
|
||||
zh_TW: "會升級 OpenBSD 套件"
|
||||
de: "Würde OpenBSD-Pakete aktualisieren"
|
||||
"Checking if /etc/motd contains -current or -beta":
|
||||
en: "Checking if /etc/motd contains -current or -beta"
|
||||
lt: "Tikrinimas, jei /etc/motd yra -current arba -beta"
|
||||
es: "Comprobación de si /etc/motd contiene -current o -beta"
|
||||
fr: "Vérification si /etc/motd contient -current ou -beta"
|
||||
zh_CN: "检查 /etc/motd 是否包含 -current 或 -beta"
|
||||
zh_TW: "檢查 /etc/motd 是否包含 -current 或 -beta"
|
||||
de: "Überprüfen, ob /etc/motd -current oder -beta enthält"
|
||||
"Microsoft Store":
|
||||
en: "Microsoft Store"
|
||||
lt: "Microsoft parduotuvė"
|
||||
@@ -1367,7 +1359,7 @@ _version: 2
|
||||
lt: "jetbrains-toolbox-updater susidūrė su netikėta klaida ieškant:"
|
||||
es: "jetbrains-toolbox-updater encontró un error inesperado durante la búsqueda:"
|
||||
fr: "jetbrains-toolbox-updater a rencontré une erreur inattendue lors de la recherche:"
|
||||
zh_CN: "jetbrains-toolbox-updater 在寻找过程中遇到意外错误"
|
||||
zh_CN: "jetbrains-toolbox-updater 在寻找过程中遇到意外错误:"
|
||||
zh_TW: "jetbrains-toolbox-updater 在尋找過程中遇到意外錯誤:"
|
||||
de: "jetbrains-toolbox-updater ist auf einen unerwarteten Fehler bei der Suche gestoßen:"
|
||||
"jetbrains-toolbox-updater encountered an unexpected error during updating:":
|
||||
@@ -1375,7 +1367,7 @@ _version: 2
|
||||
lt: "jetbrains-toolbox-updater susidūrė su netikėta klaida atnaujinant:"
|
||||
es: "jetbrains-toolbox-updater encontró un error inesperado durante la actualización:"
|
||||
fr: "jetbrains-toolbox-updater a rencontré une erreur inattendue lors de la mise à jour:"
|
||||
zh_CN: "jetbrains-toolbox-updater 在更新过程中遇到意外错误"
|
||||
zh_CN: "jetbrains-toolbox-updater 在更新过程中遇到意外错误:"
|
||||
zh_TW: "jetbrains-toolbox-updater 在更新過程中遇到意外錯誤:"
|
||||
de: "jetbrains-toolbox-updater ist auf einen unerwarteten Fehler während der Aktualisierung gestoßen:"
|
||||
"<output from `deb-get clean` omitted>":
|
||||
@@ -1391,16 +1383,16 @@ _version: 2
|
||||
lt: "Jūs turite flake viduje $FLAKE. Tai yra pasenę nh."
|
||||
es: "Tienes un flake dentro de $FLAKE. Esto está en desuso para nh."
|
||||
fr: "Vous avez un flake à l'intérieur de $FLAKE. Ceci est obsolète pour nh."
|
||||
zh_TW: "你在 $FLAKE 裡有一個 flake。這在 nh 中已被棄用。"
|
||||
zh_CN: "你在 $FLAKE 里有一个 flake。这在 nh 中已被弃用。"
|
||||
zh_TW: "你在 $FLAKE 裡有一個 flake。這在 nh 中已被棄用。"
|
||||
de: "Sie haben ein flake in $FLAKE. Dies ist für nh veraltet."
|
||||
"nh cannot find any configured flakes":
|
||||
en: "nh cannot find any configured flakes"
|
||||
lt: "nh nepavyksta rasti jokių sukonfigūruotų flake"
|
||||
es: "nh no puede encontrar ningún flake configurado"
|
||||
fr: "nh ne peut trouver aucun flake configuré"
|
||||
zh_TW: "nh 找不到任何已設定的 flake"
|
||||
zh_CN: "nh 无法找到任何已配置的 flake"
|
||||
zh_TW: "nh 找不到任何已設定的 flake"
|
||||
de: "nh kann keine konfigurierten flakes finden"
|
||||
"System Manuals":
|
||||
en: "System Manuals"
|
||||
|
||||
@@ -115,6 +115,9 @@ pub trait CommandExt {
|
||||
///
|
||||
/// Returns an `Err` if the command failed to execute, if `succeeded` returns an `Err`, or if
|
||||
/// the output contains invalid UTF-8.
|
||||
// This function is currently unused, but is useful and makes sense with `output_checked_with`
|
||||
// and `output_checked_utf8` existing.
|
||||
#[allow(dead_code)]
|
||||
#[track_caller]
|
||||
fn output_checked_with_utf8(
|
||||
&mut self,
|
||||
|
||||
@@ -15,17 +15,17 @@ use indexmap::IndexMap;
|
||||
use merge::Merge;
|
||||
use regex::Regex;
|
||||
use regex_split::RegexSplit;
|
||||
use rust_i18n::t;
|
||||
use serde::Deserialize;
|
||||
use strum::IntoEnumIterator;
|
||||
use tracing::{debug, error};
|
||||
use which_crate::which;
|
||||
|
||||
use super::utils::editor;
|
||||
use crate::command::CommandExt;
|
||||
use crate::execution_context::RunType;
|
||||
use crate::step::Step;
|
||||
use crate::sudo::SudoKind;
|
||||
use crate::utils::string_prepend_str;
|
||||
use tracing::{debug, error};
|
||||
|
||||
// TODO: Add i18n to this. Tracking issue: https://github.com/topgrade-rs/topgrade/issues/859
|
||||
pub static EXAMPLE_CONFIG: &str = include_str!("../config.example.toml");
|
||||
@@ -346,6 +346,8 @@ pub struct Misc {
|
||||
no_self_update: Option<bool>,
|
||||
|
||||
log_filters: Option<Vec<String>>,
|
||||
|
||||
show_distribution_summary: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, ValueEnum)]
|
||||
@@ -388,6 +390,24 @@ pub struct VscodeConfig {
|
||||
profile: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Merge)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct DoomConfig {
|
||||
aot: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Merge)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Rustup {
|
||||
channels: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Merge)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Pkgfile {
|
||||
enable: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Merge)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
/// Configuration file
|
||||
@@ -472,6 +492,15 @@ pub struct ConfigFile {
|
||||
|
||||
#[merge(strategy = crate::utils::merge_strategies::inner_merge_opt)]
|
||||
vscode: Option<VscodeConfig>,
|
||||
|
||||
#[merge(strategy = crate::utils::merge_strategies::inner_merge_opt)]
|
||||
doom: Option<DoomConfig>,
|
||||
|
||||
#[merge(strategy = crate::utils::merge_strategies::inner_merge_opt)]
|
||||
rustup: Option<Rustup>,
|
||||
|
||||
#[merge(strategy = crate::utils::merge_strategies::inner_merge_opt)]
|
||||
pkgfile: Option<Pkgfile>,
|
||||
}
|
||||
|
||||
fn config_directory() -> PathBuf {
|
||||
@@ -638,17 +667,6 @@ impl ConfigFile {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(paths) = result.git.as_mut().and_then(|git| git.repos.as_mut()) {
|
||||
for path in paths.iter_mut() {
|
||||
let expanded = shellexpand::tilde::<&str>(&path.as_ref()).into_owned();
|
||||
debug!(
|
||||
"{}",
|
||||
t!("Path {path} expanded to {expanded}", path = path, expanded = expanded)
|
||||
);
|
||||
*path = expanded;
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Loaded configuration: {:?}", result);
|
||||
Ok(result)
|
||||
}
|
||||
@@ -708,9 +726,15 @@ pub struct CommandLineArgs {
|
||||
cleanup: bool,
|
||||
|
||||
/// Print what would be done
|
||||
///
|
||||
/// Alias for --run-type dry
|
||||
#[arg(short = 'n', long = "dry-run")]
|
||||
dry_run: bool,
|
||||
|
||||
/// Pick between just running commands, running and logging commands, and just logging commands
|
||||
#[arg(short = 'r', long = "run-type", value_enum, default_value_t)]
|
||||
run_type: RunType,
|
||||
|
||||
/// Do not ask to retry failed steps
|
||||
#[arg(long = "no-retry")]
|
||||
no_retry: bool,
|
||||
@@ -933,16 +957,21 @@ impl Config {
|
||||
}
|
||||
|
||||
fn allowed_steps(opt: &CommandLineArgs, config_file: &ConfigFile) -> Vec<Step> {
|
||||
// The enabled steps are
|
||||
let mut enabled_steps: Vec<Step> = Vec::new();
|
||||
// Any steps that are passed with `--only`
|
||||
enabled_steps.extend(&opt.only);
|
||||
|
||||
// Plus any steps in the config file's `misc.only`
|
||||
if let Some(misc) = config_file.misc.as_ref() {
|
||||
if let Some(only) = misc.only.as_ref() {
|
||||
enabled_steps.extend(only);
|
||||
}
|
||||
}
|
||||
|
||||
// If neither of those contain anything
|
||||
if enabled_steps.is_empty() {
|
||||
// All steps are enabled
|
||||
enabled_steps.extend(Step::iter());
|
||||
}
|
||||
|
||||
@@ -954,6 +983,7 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
// All steps that are disabled are not enabled, except ones that are passed to `--only`
|
||||
enabled_steps.retain(|e| !disabled_steps.contains(e) || opt.only.contains(e));
|
||||
enabled_steps
|
||||
}
|
||||
@@ -1001,9 +1031,13 @@ impl Config {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Tell whether we are dry-running.
|
||||
pub fn dry_run(&self) -> bool {
|
||||
self.opt.dry_run
|
||||
/// Get the [RunType] for the current execution
|
||||
pub fn run_type(&self) -> RunType {
|
||||
if self.opt.dry_run {
|
||||
RunType::Dry
|
||||
} else {
|
||||
self.opt.run_type
|
||||
}
|
||||
}
|
||||
|
||||
/// Tell whether we should not attempt to retry anything.
|
||||
@@ -1482,6 +1516,14 @@ impl Config {
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
pub fn rustup_channels(&self) -> Vec<String> {
|
||||
self.config_file
|
||||
.rustup
|
||||
.as_ref()
|
||||
.and_then(|rustup| rustup.channels.clone())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn verbose(&self) -> bool {
|
||||
self.opt.verbose
|
||||
}
|
||||
@@ -1565,6 +1607,14 @@ impl Config {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn show_distribution_summary(&self) -> bool {
|
||||
self.config_file
|
||||
.misc
|
||||
.as_ref()
|
||||
.and_then(|misc| misc.show_distribution_summary)
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn npm_use_sudo(&self) -> bool {
|
||||
self.config_file
|
||||
@@ -1734,6 +1784,22 @@ impl Config {
|
||||
Some(profile.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn doom_aot(&self) -> bool {
|
||||
self.config_file
|
||||
.doom
|
||||
.as_ref()
|
||||
.and_then(|doom| doom.aot)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn enable_pkgfile(&self) -> bool {
|
||||
self.config_file
|
||||
.pkgfile
|
||||
.as_ref()
|
||||
.and_then(|pkgfile| pkgfile.enable)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
11
src/error.rs
11
src/error.rs
@@ -116,14 +116,3 @@ impl Display for SkipStep {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(windows, feature = "self-update"))]
|
||||
#[derive(Error, Debug)]
|
||||
pub struct Upgraded(pub ExitStatus);
|
||||
|
||||
#[cfg(all(windows, feature = "self-update"))]
|
||||
impl Display for Upgraded {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", t!("Topgrade Upgraded"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#![allow(dead_code)]
|
||||
use color_eyre::eyre::Result;
|
||||
use rust_i18n::t;
|
||||
use std::env::var;
|
||||
use std::ffi::OsStr;
|
||||
use std::process::Command;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
|
||||
use clap::ValueEnum;
|
||||
use color_eyre::eyre::Result;
|
||||
use rust_i18n::t;
|
||||
use serde::Deserialize;
|
||||
use strum::EnumString;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::error::MissingSudo;
|
||||
use crate::executor::{DryCommand, Executor};
|
||||
@@ -16,30 +20,26 @@ use crate::sudo::Sudo;
|
||||
use crate::utils::require_option;
|
||||
|
||||
/// An enum telling whether Topgrade should perform dry runs or actually perform the steps.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Default, EnumString, ValueEnum)]
|
||||
pub enum RunType {
|
||||
/// Executing commands will just print the command with its argument.
|
||||
Dry,
|
||||
|
||||
/// Executing commands will perform actual execution.
|
||||
#[default]
|
||||
Wet,
|
||||
|
||||
/// Executing commands will print the command and perform actual execution.
|
||||
Damp,
|
||||
}
|
||||
|
||||
impl RunType {
|
||||
/// Create a new instance from a boolean telling whether to dry run.
|
||||
pub fn new(dry_run: bool) -> Self {
|
||||
if dry_run {
|
||||
RunType::Dry
|
||||
} else {
|
||||
RunType::Wet
|
||||
}
|
||||
}
|
||||
|
||||
/// Tells whether we're performing a dry run.
|
||||
pub fn dry(self) -> bool {
|
||||
match self {
|
||||
RunType::Dry => true,
|
||||
RunType::Wet => false,
|
||||
RunType::Damp => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@ impl<'a> ExecutionContext<'a> {
|
||||
match self.run_type {
|
||||
RunType::Dry => Executor::Dry(DryCommand::new(program)),
|
||||
RunType::Wet => Executor::Wet(Command::new(program)),
|
||||
RunType::Damp => Executor::Damp(Command::new(program)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
137
src/executor.rs
137
src/executor.rs
@@ -1,11 +1,13 @@
|
||||
//! Utilities for command execution
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fmt::Debug;
|
||||
use std::iter;
|
||||
use std::path::Path;
|
||||
use std::process::{Child, Command, ExitStatus, Output};
|
||||
|
||||
use color_eyre::eyre::Result;
|
||||
use rust_i18n::t;
|
||||
use tracing::debug;
|
||||
use tracing::{debug, enabled, Level};
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::error::DryRun;
|
||||
@@ -15,6 +17,7 @@ use crate::error::DryRun;
|
||||
/// If the enum is set to `Dry`, execution will just print the command with its arguments.
|
||||
pub enum Executor {
|
||||
Wet(Command),
|
||||
Damp(Command),
|
||||
Dry(DryCommand),
|
||||
}
|
||||
|
||||
@@ -24,7 +27,7 @@ impl Executor {
|
||||
/// Will give weird results for non-UTF-8 programs; see `to_string_lossy()`.
|
||||
pub fn get_program(&self) -> String {
|
||||
match self {
|
||||
Executor::Wet(c) => c.get_program().to_string_lossy().into_owned(),
|
||||
Executor::Wet(c) | Executor::Damp(c) => c.get_program().to_string_lossy().into_owned(),
|
||||
Executor::Dry(c) => c.program.to_string_lossy().into_owned(),
|
||||
}
|
||||
}
|
||||
@@ -32,7 +35,7 @@ impl Executor {
|
||||
/// See `std::process::Command::arg`
|
||||
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Executor {
|
||||
match self {
|
||||
Executor::Wet(c) => {
|
||||
Executor::Wet(c) | Executor::Damp(c) => {
|
||||
c.arg(arg);
|
||||
}
|
||||
Executor::Dry(c) => {
|
||||
@@ -50,7 +53,7 @@ impl Executor {
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
match self {
|
||||
Executor::Wet(c) => {
|
||||
Executor::Wet(c) | Executor::Damp(c) => {
|
||||
c.args(args);
|
||||
}
|
||||
Executor::Dry(c) => {
|
||||
@@ -65,7 +68,7 @@ impl Executor {
|
||||
/// See `std::process::Command::current_dir`
|
||||
pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Executor {
|
||||
match self {
|
||||
Executor::Wet(c) => {
|
||||
Executor::Wet(c) | Executor::Damp(c) => {
|
||||
c.current_dir(dir);
|
||||
}
|
||||
Executor::Dry(c) => c.directory = Some(dir.as_ref().into()),
|
||||
@@ -81,7 +84,7 @@ impl Executor {
|
||||
K: AsRef<OsStr>,
|
||||
{
|
||||
match self {
|
||||
Executor::Wet(c) => {
|
||||
Executor::Wet(c) | Executor::Damp(c) => {
|
||||
c.env_remove(key);
|
||||
}
|
||||
Executor::Dry(_) => (),
|
||||
@@ -98,7 +101,7 @@ impl Executor {
|
||||
V: AsRef<OsStr>,
|
||||
{
|
||||
match self {
|
||||
Executor::Wet(c) => {
|
||||
Executor::Wet(c) | Executor::Damp(c) => {
|
||||
c.env(key, val);
|
||||
}
|
||||
Executor::Dry(_) => (),
|
||||
@@ -109,18 +112,16 @@ impl Executor {
|
||||
|
||||
/// See `std::process::Command::spawn`
|
||||
pub fn spawn(&mut self) -> Result<ExecutorChild> {
|
||||
self.log_command();
|
||||
let result = match self {
|
||||
Executor::Wet(c) => {
|
||||
Executor::Wet(c) | Executor::Damp(c) => {
|
||||
debug!("Running {:?}", c);
|
||||
// We should use `spawn()` here rather than `spawn_checked()` since
|
||||
// their semantics and behaviors are different.
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
c.spawn().map(ExecutorChild::Wet)?
|
||||
}
|
||||
Executor::Dry(c) => {
|
||||
c.dry_run();
|
||||
ExecutorChild::Dry
|
||||
}
|
||||
Executor::Dry(_) => ExecutorChild::Dry,
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
@@ -128,17 +129,15 @@ impl Executor {
|
||||
|
||||
/// See `std::process::Command::output`
|
||||
pub fn output(&mut self) -> Result<ExecutorOutput> {
|
||||
self.log_command();
|
||||
match self {
|
||||
Executor::Wet(c) => {
|
||||
Executor::Wet(c) | Executor::Damp(c) => {
|
||||
// We should use `output()` here rather than `output_checked()` since
|
||||
// their semantics and behaviors are different.
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
Ok(ExecutorOutput::Wet(c.output()?))
|
||||
}
|
||||
Executor::Dry(c) => {
|
||||
c.dry_run();
|
||||
Ok(ExecutorOutput::Dry)
|
||||
}
|
||||
Executor::Dry(_) => Ok(ExecutorOutput::Dry),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,18 +145,38 @@ impl Executor {
|
||||
/// that can indicate success of a script
|
||||
#[allow(dead_code)]
|
||||
pub fn status_checked_with_codes(&mut self, codes: &[i32]) -> Result<()> {
|
||||
self.log_command();
|
||||
match self {
|
||||
Executor::Wet(c) => c.status_checked_with(|status| {
|
||||
Executor::Wet(c) | Executor::Damp(c) => c.status_checked_with(|status| {
|
||||
if status.success() || status.code().as_ref().is_some_and(|c| codes.contains(c)) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}),
|
||||
Executor::Dry(c) => {
|
||||
c.dry_run();
|
||||
Ok(())
|
||||
Executor::Dry(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn log_command(&self) {
|
||||
match self {
|
||||
Executor::Wet(_) => (),
|
||||
Executor::Damp(c) => {
|
||||
log_command(
|
||||
"Executing: {program_name} {arguments}",
|
||||
c.get_program(),
|
||||
c.get_args(),
|
||||
c.get_envs(),
|
||||
c.get_current_dir(),
|
||||
);
|
||||
}
|
||||
Executor::Dry(c) => log_command(
|
||||
"Dry running: {program_name} {arguments}",
|
||||
&c.program,
|
||||
&c.args,
|
||||
iter::empty(),
|
||||
c.directory.as_ref(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,30 +201,11 @@ impl DryCommand {
|
||||
directory: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn dry_run(&self) {
|
||||
print!(
|
||||
"{}",
|
||||
t!(
|
||||
"Dry running: {program_name} {arguments}",
|
||||
program_name = self.program.to_string_lossy(),
|
||||
arguments = shell_words::join(
|
||||
self.args
|
||||
.iter()
|
||||
.map(|a| String::from(a.to_string_lossy()))
|
||||
.collect::<Vec<String>>()
|
||||
)
|
||||
)
|
||||
);
|
||||
match &self.directory {
|
||||
Some(dir) => println!(" {}", t!("in {directory}", directory = dir.to_string_lossy())),
|
||||
None => println!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// The Result of spawn. Contains an actual `std::process::Child` if executed by a wet command.
|
||||
pub enum ExecutorChild {
|
||||
// Both RunType::Wet and RunType::Damp use this variant
|
||||
#[allow(unused)] // this type has not been used
|
||||
Wet(Child),
|
||||
Dry,
|
||||
@@ -218,22 +218,18 @@ impl CommandExt for Executor {
|
||||
// variant for wet/dry runs.
|
||||
|
||||
fn output_checked_with(&mut self, succeeded: impl Fn(&Output) -> Result<(), ()>) -> Result<Output> {
|
||||
self.log_command();
|
||||
match self {
|
||||
Executor::Wet(c) => c.output_checked_with(succeeded),
|
||||
Executor::Dry(c) => {
|
||||
c.dry_run();
|
||||
Err(DryRun().into())
|
||||
}
|
||||
Executor::Wet(c) | Executor::Damp(c) => c.output_checked_with(succeeded),
|
||||
Executor::Dry(_) => Err(DryRun().into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn status_checked_with(&mut self, succeeded: impl Fn(ExitStatus) -> Result<(), ()>) -> Result<()> {
|
||||
self.log_command();
|
||||
match self {
|
||||
Executor::Wet(c) => c.status_checked_with(succeeded),
|
||||
Executor::Dry(c) => {
|
||||
c.dry_run();
|
||||
Ok(())
|
||||
}
|
||||
Executor::Wet(c) | Executor::Damp(c) => c.status_checked_with(succeeded),
|
||||
Executor::Dry(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,3 +237,42 @@ impl CommandExt for Executor {
|
||||
self.spawn()
|
||||
}
|
||||
}
|
||||
|
||||
fn log_command<
|
||||
'a,
|
||||
I: ExactSizeIterator<Item = (&'a (impl Debug + 'a + ?Sized), Option<&'a (impl Debug + 'a + ?Sized)>)>,
|
||||
>(
|
||||
prefix: &str,
|
||||
exec: &OsStr,
|
||||
args: impl IntoIterator<Item = &'a (impl AsRef<OsStr> + ?Sized + 'a)>,
|
||||
env: impl IntoIterator<Item = (&'a OsStr, Option<&'a OsStr>), IntoIter = I>,
|
||||
dir: Option<&'a (impl AsRef<Path> + ?Sized)>,
|
||||
) {
|
||||
println!(
|
||||
"{}",
|
||||
t!(
|
||||
prefix,
|
||||
program_name = exec.to_string_lossy(),
|
||||
arguments = shell_words::join(args.into_iter().map(|s| s.as_ref().to_string_lossy()))
|
||||
)
|
||||
);
|
||||
|
||||
let env_iter = env.into_iter();
|
||||
if env_iter.len() != 0 && enabled!(Level::DEBUG) {
|
||||
println!(
|
||||
" {}",
|
||||
t!(
|
||||
"with env: {env}",
|
||||
env = env_iter
|
||||
.filter(|(_, val)| val.is_some())
|
||||
.map(|(key, val)| format!("{:?}={:?}", key, val.unwrap()))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if let Some(d) = dir {
|
||||
println!(" {}", t!("in {directory}", directory = d.as_ref().display()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
//pub mod steps;
|
||||
//pub mod utils;
|
||||
15
src/main.rs
15
src/main.rs
@@ -23,8 +23,6 @@ use tracing::debug;
|
||||
|
||||
use self::config::{CommandLineArgs, Config};
|
||||
use self::error::StepFailed;
|
||||
#[cfg(all(windows, feature = "self-update"))]
|
||||
use self::error::Upgraded;
|
||||
use self::runner::StepResult;
|
||||
#[allow(clippy::wildcard_imports)]
|
||||
use self::steps::{remote::*, *};
|
||||
@@ -124,7 +122,7 @@ fn run() -> Result<()> {
|
||||
debug!("Version: {}", crate_version!());
|
||||
debug!("OS: {}", env!("TARGET"));
|
||||
debug!("{:?}", env::args());
|
||||
debug!("Binary path: {:?}", std::env::current_exe());
|
||||
debug!("Binary path: {:?}", env::current_exe());
|
||||
debug!("self-update Feature Enabled: {:?}", cfg!(feature = "self-update"));
|
||||
debug!("Configuration: {:?}", config);
|
||||
|
||||
@@ -163,7 +161,7 @@ fn run() -> Result<()> {
|
||||
#[cfg(target_os = "linux")]
|
||||
let distribution = linux::Distribution::detect();
|
||||
|
||||
let run_type = execution_context::RunType::new(config.dry_run());
|
||||
let run_type = config.run_type();
|
||||
let ctx = execution_context::ExecutionContext::new(
|
||||
run_type,
|
||||
sudo,
|
||||
@@ -276,7 +274,7 @@ fn run() -> Result<()> {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if config.show_distribution_summary() {
|
||||
if let Ok(distribution) = &distribution {
|
||||
distribution.show_summary();
|
||||
}
|
||||
@@ -335,13 +333,6 @@ fn main() {
|
||||
exit(0);
|
||||
}
|
||||
Err(error) => {
|
||||
#[cfg(all(windows, feature = "self-update"))]
|
||||
{
|
||||
if let Some(Upgraded(status)) = error.downcast_ref::<Upgraded>() {
|
||||
exit(status.code().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
let skip_print = (error.downcast_ref::<StepFailed>().is_some())
|
||||
|| (error
|
||||
.downcast_ref::<io::Error>()
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use std::env;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::process::CommandExt as _;
|
||||
#[cfg(windows)]
|
||||
use std::process::exit;
|
||||
use std::process::Command;
|
||||
|
||||
use crate::step::Step;
|
||||
use color_eyre::eyre::{bail, Result};
|
||||
#[cfg(unix)]
|
||||
use color_eyre::eyre::bail;
|
||||
use color_eyre::eyre::Result;
|
||||
use rust_i18n::t;
|
||||
use self_update_crate::backends::github::Update;
|
||||
use self_update_crate::update::UpdateStatus;
|
||||
|
||||
use super::terminal::{print_info, print_separator};
|
||||
#[cfg(windows)]
|
||||
use crate::error::Upgraded;
|
||||
|
||||
use crate::execution_context::ExecutionContext;
|
||||
|
||||
pub fn self_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
@@ -63,7 +64,7 @@ pub fn self_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
{
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
let status = command.status()?;
|
||||
bail!(Upgraded(status));
|
||||
exit(status.code().expect("This cannot return None on Windows"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
src/step.rs
10
src/step.rs
@@ -53,6 +53,7 @@ pub enum Step {
|
||||
Dotnet,
|
||||
Elan,
|
||||
Emacs,
|
||||
Falconf,
|
||||
Firmware,
|
||||
Flatpak,
|
||||
Flutter,
|
||||
@@ -69,6 +70,7 @@ pub enum Step {
|
||||
Helix,
|
||||
Helm,
|
||||
HomeManager,
|
||||
Hyprpm,
|
||||
// These names are miscapitalized on purpose, so the CLI name is
|
||||
// `jetbrains_pycharm` instead of `jet_brains_py_charm`.
|
||||
JetbrainsAqua,
|
||||
@@ -304,6 +306,7 @@ impl Step {
|
||||
Dotnet => runner.execute(*self, ".NET", || generic::run_dotnet_upgrade(ctx))?,
|
||||
Elan => runner.execute(*self, "elan", || generic::run_elan(ctx))?,
|
||||
Emacs => runner.execute(*self, "Emacs", || emacs::Emacs::new().upgrade(ctx))?,
|
||||
Falconf => runner.execute(*self, "falconf sync", || generic::run_falconf(ctx))?,
|
||||
Firmware =>
|
||||
{
|
||||
#[cfg(target_os = "linux")]
|
||||
@@ -345,6 +348,11 @@ impl Step {
|
||||
#[cfg(unix)]
|
||||
runner.execute(*self, "home-manager", || unix::run_home_manager(ctx))?
|
||||
}
|
||||
Hyprpm =>
|
||||
{
|
||||
#[cfg(unix)]
|
||||
runner.execute(*self, "hyprpm", || unix::run_hyprpm(ctx))?
|
||||
}
|
||||
JetbrainsAqua => runner.execute(*self, "JetBrains Aqua Plugins", || generic::run_jetbrains_aqua(ctx))?,
|
||||
JetbrainsClion => runner.execute(*self, "JetBrains CL", || generic::run_jetbrains_clion(ctx))?,
|
||||
JetbrainsDatagrip => {
|
||||
@@ -767,6 +775,7 @@ pub(crate) fn default_steps() -> Vec<Step> {
|
||||
Sdkman,
|
||||
Rcm,
|
||||
Maza,
|
||||
Hyprpm,
|
||||
Atuin,
|
||||
]);
|
||||
|
||||
@@ -876,6 +885,7 @@ pub(crate) fn default_steps() -> Vec<Step> {
|
||||
// JetBrains Space Desktop does not have a CLI
|
||||
JetbrainsWebstorm,
|
||||
Yazi,
|
||||
Falconf,
|
||||
Powershell,
|
||||
CustomCommands,
|
||||
Vagrant,
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use color_eyre::eyre::eyre;
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
use color_eyre::eyre::{eyre, OptionExt};
|
||||
use tracing::{debug, error, warn};
|
||||
use wildmatch::WildMatch;
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::error::{self, TopgradeError};
|
||||
use crate::error::{self, SkipStep, TopgradeError};
|
||||
use crate::terminal::print_separator;
|
||||
use crate::{execution_context::ExecutionContext, utils::require};
|
||||
use rust_i18n::t;
|
||||
@@ -21,6 +23,9 @@ use rust_i18n::t;
|
||||
// themselves or when using docker-compose.
|
||||
const NONEXISTENT_REPO: &str = "repository does not exist";
|
||||
|
||||
// A string found in the output of docker when Docker Desktop is not running.
|
||||
const DOCKER_NOT_RUNNING: &str = "We recommend to activate the WSL integration in Docker Desktop settings.";
|
||||
|
||||
/// Uniquely identifies a `Container`.
|
||||
#[derive(Debug)]
|
||||
struct Container {
|
||||
@@ -74,7 +79,7 @@ fn list_containers(crt: &Path, ignored_containers: Option<&Vec<String>>) -> Resu
|
||||
);
|
||||
let output = Command::new(crt)
|
||||
.args(["image", "ls", "--format", "{{.Repository}}:{{.Tag}} {{.ID}}"])
|
||||
.output_checked_with_utf8(|_| Ok(()))?;
|
||||
.output_checked_utf8()?;
|
||||
|
||||
let mut retval = vec![];
|
||||
for line in output.stdout.lines() {
|
||||
@@ -99,7 +104,12 @@ fn list_containers(crt: &Path, ignored_containers: Option<&Vec<String>>) -> Resu
|
||||
|
||||
// line is of format: `Repository:Tag ImageID`, e.g., `nixos/nix:latest d80fea9c32b4`
|
||||
let split_res = line.split(' ').collect::<Vec<&str>>();
|
||||
assert_eq!(split_res.len(), 2);
|
||||
if split_res.len() != 2 {
|
||||
return Err(eyre!(format!(
|
||||
"Got erroneous output from `{} image ls --format \"{{.Repository}}:{{.Tag}} {{.ID}}\"; Expected line to split into 2 parts",
|
||||
crt.display()
|
||||
)));
|
||||
}
|
||||
let (repo_tag, image_id) = (split_res[0], split_res[1]);
|
||||
|
||||
if let Some(ref ignored_containers) = ignored_containers {
|
||||
@@ -116,11 +126,16 @@ fn list_containers(crt: &Path, ignored_containers: Option<&Vec<String>>) -> Resu
|
||||
);
|
||||
let inspect_output = Command::new(crt)
|
||||
.args(["image", "inspect", image_id, "--format", "{{.Os}}/{{.Architecture}}"])
|
||||
.output_checked_with_utf8(|_| Ok(()))?;
|
||||
.output_checked_utf8()?;
|
||||
let mut platform = inspect_output.stdout;
|
||||
// truncate the tailing new line character
|
||||
platform.truncate(platform.len() - 1);
|
||||
assert!(platform.contains('/'));
|
||||
if !platform.contains('/') {
|
||||
return Err(eyre!(format!(
|
||||
"Got erroneous output from `{} image ls --format \"{{.Repository}}:{{.Tag}} {{.ID}}\"; Expected platform to contain '/'",
|
||||
crt.display()
|
||||
)));
|
||||
}
|
||||
|
||||
retval.push(Container::new(repo_tag.to_string(), platform));
|
||||
}
|
||||
@@ -135,6 +150,41 @@ pub fn run_containers(ctx: &ExecutionContext) -> Result<()> {
|
||||
debug!("Using container runtime '{}'", crt.display());
|
||||
|
||||
print_separator(t!("Containers"));
|
||||
|
||||
let output = Command::new(&crt).arg("--help").output_checked_with(|_| Ok(()))?;
|
||||
let status_code = output
|
||||
.status
|
||||
.code()
|
||||
.ok_or_eyre("Couldn't get status code (terminated by signal)")?;
|
||||
let stdout = std::str::from_utf8(&output.stdout).wrap_err("Expected output to be valid UTF-8")?;
|
||||
if stdout.contains(DOCKER_NOT_RUNNING) && status_code == 1 {
|
||||
// Write the output
|
||||
io::stdout().write_all(&output.stdout)?;
|
||||
io::stderr().write_all(&output.stderr)?;
|
||||
// Don't crash, but don't be silent either.
|
||||
// This can happen in other ways than Docker Desktop not running, but even in those cases
|
||||
// we don't want to crash, since the containers step is enabled by default.
|
||||
warn!(
|
||||
"{} seems to be non-functional right now (see above). Is WSL integration enabled for Docker Desktop? Is Docker Desktop running?",
|
||||
crt.display()
|
||||
);
|
||||
return Err(SkipStep(format!(
|
||||
"{} seems to be non-functional right now. Possibly WSL integration is not enabled for Docker Desktop, or Docker Desktop is not running.",
|
||||
crt.display()
|
||||
)).into());
|
||||
} else if !output.status.success() {
|
||||
// Write the output
|
||||
io::stdout().write_all(&output.stdout)?;
|
||||
io::stderr().write_all(&output.stderr)?;
|
||||
// If we saw the message, but the code is not 1 (e.g. 0, or a non-1 failure), crash, as we expect a 1.
|
||||
// If we did not see the message, it's broken in some way we do not understand.
|
||||
return Err(eyre!(
|
||||
"{0} seems to be non-functional (`{0} --help` returned non-zero exit code {1})",
|
||||
crt.display(),
|
||||
status_code,
|
||||
));
|
||||
}
|
||||
|
||||
let mut success = true;
|
||||
let containers =
|
||||
list_containers(&crt, ctx.config().containers_ignored_tags()).context("Failed to list Docker containers")?;
|
||||
|
||||
@@ -65,7 +65,11 @@ impl Emacs {
|
||||
command.arg("--force");
|
||||
}
|
||||
|
||||
command.args(["upgrade"]);
|
||||
command.arg("upgrade");
|
||||
|
||||
if ctx.config().doom_aot() {
|
||||
command.arg("--aot");
|
||||
}
|
||||
|
||||
command.status_checked()
|
||||
}
|
||||
|
||||
@@ -106,8 +106,9 @@ pub fn run_gem(ctx: &ExecutionContext) -> Result<()> {
|
||||
command.arg("update");
|
||||
|
||||
if env::var_os("RBENV_SHELL").is_none() {
|
||||
debug!("Detected rbenv. Avoiding --user-install");
|
||||
command.arg("--user-install");
|
||||
} else {
|
||||
debug!("Detected rbenv. Avoiding --user-install");
|
||||
}
|
||||
|
||||
command.status_checked()
|
||||
@@ -227,25 +228,25 @@ impl Aqua {
|
||||
Aqua::AquaCLI(_) => Err(SkipStep("Command `aqua` probably points to Aqua CLI".to_string()).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_aqua(ctx: &ExecutionContext) -> Result<Aqua> {
|
||||
let aqua = require("aqua")?;
|
||||
fn get(ctx: &ExecutionContext) -> Result<Self> {
|
||||
let aqua = require("aqua")?;
|
||||
|
||||
// Check if `aqua --help` mentions "aqua". JetBrains Aqua does not, Aqua CLI does.
|
||||
let output = ctx.execute(&aqua).arg("--help").output_checked()?;
|
||||
// Check if `aqua --help` mentions "aqua". JetBrains Aqua does not, Aqua CLI does.
|
||||
let output = ctx.execute(&aqua).arg("--help").output_checked()?;
|
||||
|
||||
if String::from_utf8(output.stdout)?.contains("aqua") {
|
||||
debug!("Detected `aqua` as Aqua CLI");
|
||||
Ok(Aqua::AquaCLI(aqua))
|
||||
} else {
|
||||
debug!("Detected `aqua` as JetBrains Aqua");
|
||||
Ok(Aqua::JetBrainsAqua(aqua))
|
||||
if String::from_utf8(output.stdout)?.contains("aqua") {
|
||||
debug!("Detected `aqua` as Aqua CLI");
|
||||
Ok(Self::AquaCLI(aqua))
|
||||
} else {
|
||||
debug!("Detected `aqua` as JetBrains Aqua");
|
||||
Ok(Self::JetBrainsAqua(aqua))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_aqua(ctx: &ExecutionContext) -> Result<()> {
|
||||
let aqua = get_aqua(ctx)?.aqua_cli()?;
|
||||
let aqua = Aqua::get(ctx)?.aqua_cli()?;
|
||||
|
||||
print_separator("Aqua");
|
||||
if ctx.run_type().dry() {
|
||||
@@ -262,7 +263,11 @@ pub fn run_rustup(ctx: &ExecutionContext) -> Result<()> {
|
||||
let rustup = require("rustup")?;
|
||||
|
||||
print_separator("rustup");
|
||||
ctx.execute(rustup).arg("update").status_checked()
|
||||
|
||||
ctx.execute(rustup)
|
||||
.arg("update")
|
||||
.args(ctx.config().rustup_channels())
|
||||
.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_rye(ctx: &ExecutionContext) -> Result<()> {
|
||||
@@ -431,10 +436,10 @@ pub fn run_vcpkg_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
let is_root_install = false;
|
||||
|
||||
let mut command = if is_root_install {
|
||||
ctx.execute(&vcpkg)
|
||||
} else {
|
||||
let sudo = ctx.require_sudo()?;
|
||||
sudo.execute(ctx, &vcpkg)?
|
||||
} else {
|
||||
ctx.execute(&vcpkg)
|
||||
};
|
||||
|
||||
command.args(["upgrade", "--no-dry-run"]).status_checked()
|
||||
@@ -602,11 +607,11 @@ pub fn run_conda_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
let conda = require("conda")?;
|
||||
|
||||
let output = Command::new(&conda)
|
||||
.args(["config", "--show", "auto_activate_base"])
|
||||
.args(["config", "--show", "auto_activate"])
|
||||
.output_checked_utf8()?;
|
||||
debug!("Conda output: {}", output.stdout);
|
||||
if output.stdout.contains("False") {
|
||||
return Err(SkipStep("auto_activate_base is set to False".to_string()).into());
|
||||
return Err(SkipStep("auto_activate is set to False".to_string()).into());
|
||||
}
|
||||
|
||||
print_separator("Conda");
|
||||
@@ -1108,25 +1113,25 @@ impl Hx {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_hx(ctx: &ExecutionContext) -> Result<Hx> {
|
||||
let hx = require("hx")?;
|
||||
fn get(ctx: &ExecutionContext) -> Result<Self> {
|
||||
let hx = require("hx")?;
|
||||
|
||||
// Check if `hx --help` mentions "helix". Helix does, hx (hexdump alternative) doesn't.
|
||||
let output = ctx.execute(&hx).arg("--help").output_checked()?;
|
||||
// Check if `hx --help` mentions "helix". Helix does, hx (hexdump alternative) doesn't.
|
||||
let output = ctx.execute(&hx).arg("--help").output_checked()?;
|
||||
|
||||
if String::from_utf8(output.stdout)?.contains("helix") {
|
||||
debug!("Detected `hx` as Helix");
|
||||
Ok(Hx::Helix(hx))
|
||||
} else {
|
||||
debug!("Detected `hx` as hx (hexdump alternative)");
|
||||
Ok(Hx::HxHexdump)
|
||||
if String::from_utf8(output.stdout)?.contains("helix") {
|
||||
debug!("Detected `hx` as Helix");
|
||||
Ok(Self::Helix(hx))
|
||||
} else {
|
||||
debug!("Detected `hx` as hx (hexdump alternative)");
|
||||
Ok(Self::HxHexdump)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_helix_grammars(ctx: &ExecutionContext) -> Result<()> {
|
||||
let helix = require("helix").or(get_hx(ctx)?.helix())?;
|
||||
let helix = require("helix").or(Hx::get(ctx)?.helix())?;
|
||||
|
||||
print_separator("Helix");
|
||||
|
||||
@@ -1600,7 +1605,7 @@ pub fn run_zigup(ctx: &ExecutionContext) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_jetbrains_toolbox(_ctx: &ExecutionContext) -> Result<()> {
|
||||
pub fn run_jetbrains_toolbox(ctx: &ExecutionContext) -> Result<()> {
|
||||
let installation = find_jetbrains_toolbox();
|
||||
match installation {
|
||||
Err(FindError::NotFound) => {
|
||||
@@ -1623,6 +1628,11 @@ pub fn run_jetbrains_toolbox(_ctx: &ExecutionContext) -> Result<()> {
|
||||
Ok(installation) => {
|
||||
print_separator("JetBrains Toolbox");
|
||||
|
||||
if ctx.run_type().dry() {
|
||||
println!("Dry running jetbrains-toolbox-updater");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match update_jetbrains_toolbox(installation) {
|
||||
Err(e) => {
|
||||
// Unexpected error
|
||||
@@ -1697,7 +1707,7 @@ pub fn run_android_studio(ctx: &ExecutionContext) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn run_jetbrains_aqua(ctx: &ExecutionContext) -> Result<()> {
|
||||
run_jetbrains_ide(ctx, get_aqua(ctx)?.jetbrains_aqua()?, "Aqua")
|
||||
run_jetbrains_ide(ctx, Aqua::get(ctx)?.jetbrains_aqua()?, "Aqua")
|
||||
}
|
||||
|
||||
pub fn run_jetbrains_clion(ctx: &ExecutionContext) -> Result<()> {
|
||||
@@ -1818,3 +1828,11 @@ pub fn run_typst(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
ctx.execute(typst).args(["update"]).status_checked()
|
||||
}
|
||||
|
||||
pub fn run_falconf(ctx: &ExecutionContext) -> Result<()> {
|
||||
let falconf = require("falconf")?;
|
||||
|
||||
print_separator("falconf sync");
|
||||
|
||||
ctx.execute(falconf).arg("sync").status_checked()
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ pub fn run_git_pull(ctx: &ExecutionContext) -> Result<()> {
|
||||
// Handle user-defined repos
|
||||
if let Some(custom_git_repos) = config.git_repos() {
|
||||
for git_repo in custom_git_repos {
|
||||
repos.glob_insert(git_repo);
|
||||
repos.glob_insert(&shellexpand::tilde(git_repo));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ static OS_RELEASE_PATH: &str = "/etc/os-release";
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Distribution {
|
||||
Alpine,
|
||||
AOSC,
|
||||
Wolfi,
|
||||
Arch,
|
||||
Bedrock,
|
||||
@@ -58,6 +59,7 @@ impl Distribution {
|
||||
|
||||
Ok(match id {
|
||||
Some("alpine") => Distribution::Alpine,
|
||||
Some("aosc") => Distribution::AOSC,
|
||||
Some("chimera") => Distribution::Chimera,
|
||||
Some("wolfi") => Distribution::Wolfi,
|
||||
Some("centos") | Some("rhel") | Some("ol") => Distribution::CentOS,
|
||||
@@ -161,6 +163,7 @@ impl Distribution {
|
||||
Distribution::PCLinuxOS => upgrade_pclinuxos(ctx),
|
||||
Distribution::Nobara => upgrade_nobara(ctx),
|
||||
Distribution::NILRT => upgrade_nilrt(ctx),
|
||||
Distribution::AOSC => upgrade_aosc(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +200,20 @@ fn update_bedrock(ctx: &ExecutionContext) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn upgrade_aosc(ctx: &ExecutionContext) -> Result<()> {
|
||||
let oma = require("oma")?;
|
||||
let sudo = ctx.require_sudo()?;
|
||||
|
||||
let mut cmd = sudo.execute(ctx, &oma)?;
|
||||
cmd.arg("upgrade");
|
||||
|
||||
if ctx.config().yes(Step::System) {
|
||||
cmd.arg("-y");
|
||||
}
|
||||
|
||||
cmd.status_checked()
|
||||
}
|
||||
|
||||
fn upgrade_alpine_linux(ctx: &ExecutionContext) -> Result<()> {
|
||||
let apk = require("apk")?;
|
||||
let sudo = ctx.require_sudo()?;
|
||||
@@ -693,6 +710,10 @@ pub fn run_pacstall(ctx: &ExecutionContext) -> Result<()> {
|
||||
pub fn run_pkgfile(ctx: &ExecutionContext) -> Result<()> {
|
||||
let pkgfile = require("pkgfile")?;
|
||||
|
||||
if !ctx.config().enable_pkgfile() {
|
||||
return Err(SkipStep("Pkgfile isn't enabled".to_string()).into());
|
||||
}
|
||||
|
||||
print_separator("pkgfile");
|
||||
|
||||
let sudo = ctx.require_sudo()?;
|
||||
@@ -1013,6 +1034,7 @@ pub fn run_dkp_pacman_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn run_config_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
// The `config_update` step always requests user input, so when running with `--yes` we need to skip the step entirely
|
||||
if ctx.config().yes(Step::ConfigUpdate) {
|
||||
return Err(SkipStep(t!("Skipped in --yes").to_string()).into());
|
||||
}
|
||||
@@ -1022,6 +1044,7 @@ pub fn run_config_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
let sudo = ctx.require_sudo()?;
|
||||
sudo.execute(ctx, etc_update)?.status_checked()?;
|
||||
} else if let Ok(pacdiff) = require("pacdiff") {
|
||||
// When `DIFFPROG` is unset, `pacdiff` uses `vim` by default
|
||||
if std::env::var("DIFFPROG").is_err() {
|
||||
require("vim")?;
|
||||
}
|
||||
@@ -1099,6 +1122,12 @@ pub fn run_waydroid(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
pub fn run_auto_cpufreq(ctx: &ExecutionContext) -> Result<()> {
|
||||
let auto_cpu_freq = require("auto-cpufreq")?;
|
||||
if auto_cpu_freq != PathBuf::from("/usr/local/bin/auto-cpufreq") {
|
||||
return Err(SkipStep(String::from(
|
||||
"`auto-cpufreq` was not installed by the official installer, but presumably by a package manager.",
|
||||
))
|
||||
.into());
|
||||
}
|
||||
|
||||
print_separator("auto-cpufreq");
|
||||
|
||||
@@ -1137,6 +1166,11 @@ mod tests {
|
||||
test_template(include_str!("os_release/arch32"), Distribution::Arch);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aosc() {
|
||||
test_template(include_str!("os_release/aosc"), Distribution::AOSC);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_centos() {
|
||||
test_template(include_str!("os_release/centos"), Distribution::CentOS);
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn run_mas(ctx: &ExecutionContext) -> Result<()> {
|
||||
pub fn upgrade_macos(ctx: &ExecutionContext) -> Result<()> {
|
||||
print_separator(t!("macOS system update"));
|
||||
|
||||
let should_ask = !(ctx.config().yes(Step::System) || ctx.config().dry_run());
|
||||
let should_ask = !(ctx.config().yes(Step::System) || ctx.run_type().dry());
|
||||
if should_ask {
|
||||
println!("{}", t!("Finding available software"));
|
||||
if system_update_available()? {
|
||||
@@ -95,7 +95,7 @@ pub fn update_xcodes(ctx: &ExecutionContext) -> Result<()> {
|
||||
let xcodes = require("xcodes")?;
|
||||
print_separator("Xcodes");
|
||||
|
||||
let should_ask = !(ctx.config().yes(Step::Xcodes) || ctx.config().dry_run());
|
||||
let should_ask = !(ctx.config().yes(Step::Xcodes) || ctx.run_type().dry());
|
||||
|
||||
let releases = ctx.execute(&xcodes).args(["update"]).output_checked_utf8()?.stdout;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ pub mod macos;
|
||||
pub mod openbsd;
|
||||
#[cfg(unix)]
|
||||
pub mod unix;
|
||||
#[cfg(target_os = "windows")]
|
||||
#[cfg(windows)]
|
||||
pub mod windows;
|
||||
|
||||
#[cfg(windows)]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::command::CommandExt;
|
||||
use crate::execution_context::ExecutionContext;
|
||||
use crate::executor::RunType;
|
||||
use crate::terminal::print_separator;
|
||||
use color_eyre::eyre::Result;
|
||||
use rust_i18n::t;
|
||||
@@ -8,12 +9,13 @@ use std::fs;
|
||||
fn is_openbsd_current(ctx: &ExecutionContext) -> Result<bool> {
|
||||
let motd_content = fs::read_to_string("/etc/motd")?;
|
||||
let is_current = ["-current", "-beta"].iter().any(|&s| motd_content.contains(s));
|
||||
if ctx.config().dry_run() {
|
||||
println!("{}", t!("Would check if OpenBSD is -current"));
|
||||
Ok(is_current)
|
||||
} else {
|
||||
Ok(is_current)
|
||||
match ctx.config.run_type() {
|
||||
RunType::Dry | RunType::Damp => {
|
||||
println!("{}", t!("Checking if /etc/motd contains -current or -beta"));
|
||||
}
|
||||
RunType::Wet => {}
|
||||
}
|
||||
Ok(is_current)
|
||||
}
|
||||
|
||||
pub fn upgrade_openbsd(ctx: &ExecutionContext) -> Result<()> {
|
||||
@@ -42,11 +44,6 @@ pub fn upgrade_packages(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
let is_current = is_openbsd_current(ctx)?;
|
||||
|
||||
if ctx.config().dry_run() {
|
||||
println!("{}", t!("Would upgrade OpenBSD packages"));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if ctx.config().cleanup() {
|
||||
sudo.execute(ctx, "/usr/sbin/pkg_delete")?.arg("-ac").status_checked()?;
|
||||
}
|
||||
|
||||
10
src/steps/os/os_release/aosc
Normal file
10
src/steps/os/os_release/aosc
Normal file
@@ -0,0 +1,10 @@
|
||||
PRETTY_NAME="AOSC OS (12.2.2)"
|
||||
NAME="AOSC OS"
|
||||
VERSION_ID="12.2.2"
|
||||
VERSION="12.2.2 (localhost)"
|
||||
BUILD_ID="20250916"
|
||||
ID=aosc
|
||||
ANSI_COLOR="1;36"
|
||||
HOME_URL="https://aosc.io/"
|
||||
SUPPORT_URL="https://github.com/AOSC-Dev/aosc-os-abbs"
|
||||
BUG_REPORT_URL="https://github.com/AOSC-Dev/aosc-os-abbs/issues"
|
||||
@@ -1,6 +1,6 @@
|
||||
use color_eyre::eyre::eyre;
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
use color_eyre::eyre::{eyre, OptionExt};
|
||||
use etcetera::BaseStrategy;
|
||||
use home;
|
||||
use ini::Ini;
|
||||
@@ -10,13 +10,14 @@ use regex::Regex;
|
||||
use rust_i18n::t;
|
||||
use semver::Version;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::Component;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::sync::LazyLock;
|
||||
use std::{env::var, path::Path};
|
||||
use std::{fs, io};
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::command::CommandExt;
|
||||
@@ -410,17 +411,80 @@ pub fn run_brew_cask(ctx: &ExecutionContext, variant: BrewVariant) -> Result<()>
|
||||
pub fn run_guix(ctx: &ExecutionContext) -> Result<()> {
|
||||
let guix = require("guix")?;
|
||||
|
||||
let output = Command::new(&guix).arg("pull").output_checked_utf8();
|
||||
debug!("guix pull output: {:?}", output);
|
||||
let should_upgrade = output.is_ok();
|
||||
debug!("Can Upgrade Guix: {:?}", should_upgrade);
|
||||
|
||||
print_separator("Guix");
|
||||
|
||||
if should_upgrade {
|
||||
return ctx.execute(&guix).args(["package", "-u"]).status_checked();
|
||||
ctx.execute(&guix).arg("pull").status_checked()?;
|
||||
ctx.execute(&guix).args(["package", "-u"]).status_checked()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct NixVersion {
|
||||
version_string: String,
|
||||
}
|
||||
|
||||
impl NixVersion {
|
||||
fn new(ctx: &ExecutionContext, nix: &Path) -> Result<Self> {
|
||||
let version_output = ctx.execute(nix).arg("--version").output_checked_utf8()?;
|
||||
|
||||
debug!(
|
||||
output=%version_output,
|
||||
"`nix --version` output"
|
||||
);
|
||||
|
||||
let version_string = version_output
|
||||
.stdout
|
||||
.lines()
|
||||
.next()
|
||||
.ok_or_else(|| eyre!("`nix --version` output is empty"))?
|
||||
.to_string();
|
||||
|
||||
if version_string.is_empty() {
|
||||
return Err(eyre!("`nix --version` output was empty"));
|
||||
}
|
||||
|
||||
Ok(Self { version_string })
|
||||
}
|
||||
|
||||
fn version(&self) -> Result<Version> {
|
||||
static NIX_VERSION_REGEX: LazyLock<Regex> =
|
||||
LazyLock::new(|| Regex::new(r"^nix \([^)]*\) ([0-9.]+)").expect("Nix version regex always compiles"));
|
||||
|
||||
let captures = NIX_VERSION_REGEX
|
||||
.captures(&self.version_string)
|
||||
.ok_or_else(|| eyre!(output_changed_message!("nix --version", "regex did not match")))?;
|
||||
let raw_version = &captures[1];
|
||||
|
||||
debug!("Raw Nix version: {raw_version}");
|
||||
|
||||
// Nix 2.29.0 outputs "2.29" instead of "2.29.0", so we need to add that if necessary.
|
||||
let corrected_raw_version = if raw_version.chars().filter(|&c| c == '.').count() == 1 {
|
||||
&format!("{raw_version}.0")
|
||||
} else {
|
||||
raw_version
|
||||
};
|
||||
|
||||
debug!("Corrected raw Nix version: {corrected_raw_version}");
|
||||
|
||||
let version = Version::parse(corrected_raw_version)
|
||||
.wrap_err_with(|| output_changed_message!("nix --version", "Invalid version"))?;
|
||||
|
||||
debug!("Nix version: {:?}", version);
|
||||
|
||||
Ok(version)
|
||||
}
|
||||
|
||||
fn is_lix(&self) -> bool {
|
||||
let is_lix = self.version_string.contains("Lix");
|
||||
debug!(?is_lix);
|
||||
is_lix
|
||||
}
|
||||
|
||||
fn is_determinate_nix(&self) -> bool {
|
||||
let is_determinate_nix = self.version_string.contains("Determinate Nix");
|
||||
debug!(?is_determinate_nix);
|
||||
is_determinate_nix
|
||||
}
|
||||
Err(SkipStep(t!("Guix Pull Failed, Skipping").to_string()).into())
|
||||
}
|
||||
|
||||
pub fn run_nix(ctx: &ExecutionContext) -> Result<()> {
|
||||
@@ -452,54 +516,11 @@ pub fn run_nix(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
ctx.execute(nix_channel).arg("--update").status_checked()?;
|
||||
|
||||
let mut get_version_cmd = ctx.execute(&nix);
|
||||
get_version_cmd.arg("--version");
|
||||
let get_version_cmd_output = get_version_cmd.output_checked_utf8()?;
|
||||
let get_version_cmd_first_line_stdout = get_version_cmd_output
|
||||
.stdout
|
||||
.lines()
|
||||
.next()
|
||||
.ok_or_else(|| eyre!("`nix --version` output is empty"))?;
|
||||
|
||||
let is_lix = get_version_cmd_first_line_stdout.contains("Lix");
|
||||
|
||||
debug!(
|
||||
output=%get_version_cmd_output,
|
||||
?is_lix,
|
||||
"`nix --version` output"
|
||||
);
|
||||
|
||||
static NIX_VERSION_REGEX: LazyLock<Regex> =
|
||||
LazyLock::new(|| Regex::new(r"^nix \([^)]*\) ([0-9.]+)").expect("Nix version regex always compiles"));
|
||||
|
||||
if get_version_cmd_first_line_stdout.is_empty() {
|
||||
return Err(eyre!("`nix --version` output was empty"));
|
||||
}
|
||||
|
||||
let captures = NIX_VERSION_REGEX
|
||||
.captures(get_version_cmd_first_line_stdout)
|
||||
.ok_or_else(|| eyre!(output_changed_message!("nix --version", "regex did not match")))?;
|
||||
let raw_version = &captures[1];
|
||||
|
||||
debug!("Raw Nix version: {raw_version}");
|
||||
|
||||
// Nix 2.29.0 outputs "2.29" instead of "2.29.0", so we need to add that if necessary.
|
||||
let corrected_raw_version = if raw_version.chars().filter(|&c| c == '.').count() == 1 {
|
||||
&format!("{raw_version}.0")
|
||||
} else {
|
||||
raw_version
|
||||
};
|
||||
|
||||
debug!("Corrected raw Nix version: {corrected_raw_version}");
|
||||
|
||||
let version = Version::parse(corrected_raw_version)
|
||||
.wrap_err_with(|| output_changed_message!("nix --version", "Invalid version"))?;
|
||||
|
||||
debug!("Nix version: {:?}", version);
|
||||
let nix_version = NixVersion::new(ctx, &nix)?;
|
||||
|
||||
// Nix since 2.21.0 uses `--all --impure` rather than `.*` to upgrade all packages.
|
||||
// Lix is based on Nix 2.18, so it doesn't!
|
||||
let packages = if version >= Version::new(2, 21, 0) && !is_lix {
|
||||
let packages = if nix_version.version()? >= Version::new(2, 21, 0) && !nix_version.is_lix() {
|
||||
vec!["--all", "--impure"]
|
||||
} else {
|
||||
vec![".*"]
|
||||
@@ -550,22 +571,9 @@ pub fn run_nix_self_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
print_separator(t!("Nix (self-upgrade)"));
|
||||
|
||||
let version_output = ctx.execute(&nix).arg("--version").output_checked_utf8()?;
|
||||
let version = version_output
|
||||
.stdout
|
||||
.lines()
|
||||
.next()
|
||||
.ok_or_else(|| eyre!("`nix --version` output is empty"))?;
|
||||
let nix_version = NixVersion::new(ctx, &nix)?;
|
||||
|
||||
let is_determinate_nix = version.contains("Determinate Nix");
|
||||
|
||||
debug!(
|
||||
output=%version_output,
|
||||
?is_determinate_nix,
|
||||
"`nix --version` output"
|
||||
);
|
||||
|
||||
if is_determinate_nix {
|
||||
if nix_version.is_determinate_nix() {
|
||||
let nixd = require("determinate-nixd");
|
||||
let nixd = match nixd {
|
||||
Err(_) => {
|
||||
@@ -796,6 +804,26 @@ pub fn run_mise(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
ctx.execute(&mise).args(["plugins", "update"]).status_checked()?;
|
||||
|
||||
let output = ctx
|
||||
.execute(&mise)
|
||||
.args(["self-update"])
|
||||
.output_checked_with(|_| Ok(()))?;
|
||||
let status_code = output
|
||||
.status
|
||||
.code()
|
||||
.ok_or_eyre("Couldn't get status code (terminated by signal)")?;
|
||||
let stderr = std::str::from_utf8(&output.stderr).wrap_err("Expected output to be valid UTF-8")?;
|
||||
if stderr.contains("mise is installed via a package manager") && status_code == 1 {
|
||||
debug!("Mise self-update not available")
|
||||
} else {
|
||||
// Write the output
|
||||
io::stdout().write_all(&output.stdout)?;
|
||||
io::stderr().write_all(&output.stderr)?;
|
||||
if status_code != 0 {
|
||||
return Err(StepFailed.into());
|
||||
}
|
||||
}
|
||||
|
||||
ctx.execute(&mise).arg("upgrade").status_checked()
|
||||
}
|
||||
|
||||
@@ -927,6 +955,14 @@ pub fn run_maza(ctx: &ExecutionContext) -> Result<()> {
|
||||
ctx.execute(maza).arg("update").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_hyprpm(ctx: &ExecutionContext) -> Result<()> {
|
||||
let hyprpm = require("hyprpm")?;
|
||||
|
||||
print_separator("hyprpm");
|
||||
|
||||
ctx.execute(hyprpm).arg("update").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_atuin(ctx: &ExecutionContext) -> Result<()> {
|
||||
let atuin = require("atuin-update")?;
|
||||
|
||||
|
||||
@@ -29,15 +29,32 @@ pub fn vimrc() -> Result<PathBuf> {
|
||||
|
||||
fn nvimrc() -> Result<PathBuf> {
|
||||
#[cfg(unix)]
|
||||
let base_dir = crate::XDG_DIRS.config_dir();
|
||||
let bases: Vec<PathBuf> = vec![crate::XDG_DIRS.config_dir()];
|
||||
|
||||
#[cfg(windows)]
|
||||
let base_dir = crate::WINDOWS_DIRS.cache_dir();
|
||||
let mut bases: Vec<PathBuf> = vec![crate::WINDOWS_DIRS.cache_dir()];
|
||||
|
||||
base_dir
|
||||
.join("nvim/init.vim")
|
||||
.require()
|
||||
.or_else(|_| base_dir.join("nvim/init.lua").require())
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let Some(xdg) = std::env::var_os("XDG_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.filter(|path| path.is_absolute())
|
||||
{
|
||||
bases.insert(0, xdg);
|
||||
}
|
||||
}
|
||||
|
||||
for base_dir in bases {
|
||||
if let Ok(p) = base_dir
|
||||
.join("nvim/init.vim")
|
||||
.require()
|
||||
.or_else(|_| base_dir.join("nvim/init.lua").require())
|
||||
{
|
||||
return Ok(p);
|
||||
}
|
||||
}
|
||||
|
||||
Err(SkipStep(format!("{}", t!("No Neovim config found"))).into())
|
||||
}
|
||||
|
||||
fn upgrade_script() -> Result<tempfile::NamedTempFile> {
|
||||
|
||||
@@ -151,7 +151,7 @@ pub fn string_prepend_str(string: &mut String, s: &str) {
|
||||
*string = new_string;
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
#[cfg(unix)]
|
||||
pub fn hostname() -> Result<String> {
|
||||
match nix::unistd::gethostname() {
|
||||
Ok(os_str) => Ok(os_str
|
||||
@@ -161,7 +161,7 @@ pub fn hostname() -> Result<String> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
#[cfg(windows)]
|
||||
pub fn hostname() -> Result<String> {
|
||||
Command::new("hostname")
|
||||
.output_checked_utf8()
|
||||
|
||||
10
translate.sh
Executable file
10
translate.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
## Translate the given string into $langs using translate-shell, outputting to the yaml structure expected for locales/app.yml
|
||||
|
||||
langs="en lt es fr zh_CN zh_TW de"
|
||||
|
||||
printf "\"%s\":\n" "$@"
|
||||
for lang in $langs; do
|
||||
result=$(trans -brief -no-auto -s en -t "${lang/_/-/}" "$@")
|
||||
printf " %s: \"%s\"\n" "$lang" "$result"
|
||||
done
|
||||
Reference in New Issue
Block a user