Compare commits
23 Commits
v16.2.1
...
renovate/e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b71e944797 | ||
|
|
9ec8e83f41 | ||
|
|
c70984d458 | ||
|
|
a3503c0c70 | ||
|
|
ca2d16edfd | ||
|
|
722b1ad09e | ||
|
|
743845a66b | ||
|
|
2594f4c0fb | ||
|
|
639d055f9a | ||
|
|
ea2ccdd69f | ||
|
|
84a50afa83 | ||
|
|
b13c1bd2d7 | ||
|
|
7749f41d56 | ||
|
|
593a2a33d9 | ||
|
|
4f693aeaf3 | ||
|
|
c3d34184d0 | ||
|
|
4aa224de87 | ||
|
|
320b13c06b | ||
|
|
907d778c55 | ||
|
|
f3fccb86c0 | ||
|
|
bb4afb71e9 | ||
|
|
ec8d30f634 | ||
|
|
50d318641a |
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -14,52 +14,65 @@ Please make sure to
|
||||
before filing a new one!
|
||||
|
||||
Questions labeled with `Optional` can be skipped.
|
||||
-->
|
||||
|
||||
<!--
|
||||
If you're here to report about a "No asset found" error, please make sure that
|
||||
an hour has been passed since the last release was made.
|
||||
-->
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] I have searched the issue tracker for relevant or duplicate issues.
|
||||
|
||||
## Erroneous Behavior
|
||||
|
||||
<!--
|
||||
What actually happened?
|
||||
-->
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
<!--
|
||||
Describe the expected behavior
|
||||
Describe the expected behavior.
|
||||
-->
|
||||
|
||||
## Steps to reproduce
|
||||
|
||||
<!--
|
||||
A minimal example to reproduce the issue
|
||||
A minimal example to reproduce the issue.
|
||||
-->
|
||||
|
||||
## Possible Cause (Optional)
|
||||
|
||||
<!--
|
||||
If you know the possible cause of the issue, please tell us.
|
||||
-->
|
||||
|
||||
## Problem persists without calling from topgrade
|
||||
|
||||
<!--
|
||||
Execute the erroneous command directly to see if the problem persists
|
||||
Execute the erroneous command directly to see if the problem persists.
|
||||
-->
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
## Did you run topgrade through `Remote Execution`
|
||||
## Ran through `Remote Execution`
|
||||
|
||||
<!--
|
||||
Did you run topgrade through `Remote Execution`?
|
||||
-->
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
If yes, does the issue still occur when you run topgrade directly in your
|
||||
remote host
|
||||
remote host?
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
## Configuration file (Optional)
|
||||
|
||||
<!--
|
||||
Paste your configuration file inside the code block if you think this issue is
|
||||
related to configuration.
|
||||
@@ -70,6 +83,7 @@ related to configuration.
|
||||
```
|
||||
|
||||
## Additional Details
|
||||
|
||||
- Operation System/Version
|
||||
<!-- For example, Fedora Linux 38 -->
|
||||
|
||||
@@ -82,6 +96,7 @@ related to configuration.
|
||||
- Topgrade version (`topgrade -V`)
|
||||
|
||||
## Verbose Output (`topgrade -v`)
|
||||
|
||||
<!--
|
||||
Paste the verbose output into the pre-tags
|
||||
-->
|
||||
|
||||
18
.github/ISSUE_TEMPLATE/feature_request.md
vendored
18
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,21 +1,15 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Can you please support...?
|
||||
name: General feature request
|
||||
about: Suggest a general feature, or feature within an already existing step
|
||||
title: ''
|
||||
labels: 'C-feature request'
|
||||
labels: C-feature request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## I want to suggest a new step
|
||||
## Checklist
|
||||
|
||||
* Which tool is this about? Where is its repository?
|
||||
* Which operating systems are supported by this tool?
|
||||
* What should Topgrade do to figure out if the tool needs to be invoked?
|
||||
* Which exact commands should Topgrade run?
|
||||
* Does it have a `--dry-run` option? i.e., print what should be done and exit
|
||||
* Does it need the user to confirm the execution? And does it provide a `--yes`
|
||||
option to skip this step?
|
||||
- [ ] I have searched the issue tracker for relevant or duplicate issues.
|
||||
|
||||
## I want to suggest some general feature
|
||||
|
||||
@@ -25,3 +19,5 @@ Topgrade should...
|
||||
|
||||
<!-- Assuming that someone else implements the feature,
|
||||
please state if you know how to test it from a side branch of Topgrade. -->
|
||||
|
||||
- [ ] I am able and willing to implement this feature myself
|
||||
|
||||
29
.github/ISSUE_TEMPLATE/step_request.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE/step_request.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: New step request
|
||||
about: Suggest a new step/package manager to update
|
||||
title: ''
|
||||
labels: C-feature request, request step
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] I have searched the issue tracker for relevant or duplicate issues.
|
||||
|
||||
## I want to suggest a new step
|
||||
|
||||
* Which tool is this about? Where is its repository?
|
||||
* Which operating systems are supported by this tool?
|
||||
* What should Topgrade do to figure out if the tool needs to be invoked?
|
||||
* Which exact commands should Topgrade run?
|
||||
* Does it have a `--dry-run` option? i.e., print what should be done and exit
|
||||
* Does it need the user to confirm the execution? And does it provide a `--yes`
|
||||
option to skip this?
|
||||
|
||||
## More information
|
||||
|
||||
<!-- Assuming that someone else implements the step,
|
||||
please state if you know how to test it from a side branch of Topgrade. -->
|
||||
|
||||
- [ ] I am able and willing to implement this step myself
|
||||
24
.github/dependabot.yml
vendored
24
.github/dependabot.yml
vendored
@@ -1,24 +0,0 @@
|
||||
# Set update schedule for GitHub Actions
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: cargo
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
time: "06:00"
|
||||
timezone: "UTC"
|
||||
versioning-strategy: increase
|
||||
labels: ["dependencies", "cargo"]
|
||||
commit-message:
|
||||
prefix: "deps(cargo)"
|
||||
include: "scope"
|
||||
groups:
|
||||
cargo-minor-patch:
|
||||
update-types: ["minor", "patch"]
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
2
.github/workflows/check_i18n.yml
vendored
2
.github/workflows/check_i18n.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -32,6 +32,6 @@ jobs:
|
||||
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.2
|
||||
uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3
|
||||
with:
|
||||
sarif_file: devskim-results.sarif
|
||||
|
||||
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -135,7 +135,7 @@ jobs:
|
||||
matrix_target: ${{ matrix.target }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
8
.github/workflows/create_release_assets.yml
vendored
8
.github/workflows/create_release_assets.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
env:
|
||||
tag: ${{ github.event.client_payload.tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Generate artifact attestations
|
||||
uses: actions/attest-build-provenance@v3.0.0
|
||||
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
|
||||
with:
|
||||
subject-path: assets/*
|
||||
|
||||
@@ -169,7 +169,7 @@ jobs:
|
||||
matrix_target: ${{ matrix.target }}
|
||||
tag: ${{ github.event.client_payload.tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -284,7 +284,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Generate artifact attestations
|
||||
uses: actions/attest-build-provenance@v3.0.0
|
||||
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
|
||||
with:
|
||||
subject-path: assets/*
|
||||
|
||||
|
||||
4
.github/workflows/dependency-review.yml
vendored
4
.github/workflows/dependency-review.yml
vendored
@@ -17,9 +17,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1
|
||||
uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2
|
||||
|
||||
5
.github/workflows/lint_pr.yml
vendored
5
.github/workflows/lint_pr.yml
vendored
@@ -1,11 +1,12 @@
|
||||
name: 'Lint PR'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
pull_request_target: # zizmor: ignore[dangerous-triggers] this is the only way, and we're not running user code
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
main:
|
||||
@@ -14,6 +15,6 @@ jobs:
|
||||
permissions:
|
||||
pull-requests: read
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v6.1.1
|
||||
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
8
.github/workflows/release-plz.yml
vendored
8
.github/workflows/release-plz.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
id-token: write # For trusted publishing
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: Run release-plz
|
||||
id: release-plz
|
||||
uses: release-plz/action@v0.5
|
||||
uses: release-plz/action@d529f731ae3e89610ada96eda34e5c6ba3b12214 # v0.5
|
||||
with:
|
||||
command: release
|
||||
env:
|
||||
@@ -53,14 +53,14 @@ jobs:
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 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
|
||||
uses: release-plz/action@d529f731ae3e89610ada96eda34e5c6ba3b12214 # v0.5
|
||||
with:
|
||||
command: release-pr
|
||||
env:
|
||||
|
||||
3
.github/workflows/release_to_homebrew.yml
vendored
3
.github/workflows/release_to_homebrew.yml
vendored
@@ -18,4 +18,5 @@ jobs:
|
||||
token: ${{secrets.HOMEBREW_ACCESS_TOKEN}}
|
||||
formula: topgrade
|
||||
tag: ${{ github.event.client_payload.tag }}
|
||||
org: topgrade-rs
|
||||
# We cannot use an org because org forks cannot give push access to maintainers, which Homebrew requires.
|
||||
# org: topgrade-rs
|
||||
|
||||
20
.github/workflows/release_to_pypi.yml
vendored
20
.github/workflows/release_to_pypi.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
matrix:
|
||||
target: [x86_64, x86, aarch64]
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
args: --release --out dist
|
||||
manylinux: auto
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v5.0.0
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||
with:
|
||||
name: wheels-linux-${{ matrix.target }}
|
||||
path: dist
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
matrix:
|
||||
target: [x64, x86]
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
args: --release --out dist
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v5.0.0
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||
with:
|
||||
name: wheels-windows-${{ matrix.target }}
|
||||
path: dist
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
matrix:
|
||||
target: [x86_64, aarch64]
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
args: --release --out dist
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v5.0.0
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||
with:
|
||||
name: wheels-macos-${{ matrix.target }}
|
||||
path: dist
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
sdist:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5.0.0
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
command: sdist
|
||||
args: --out dist
|
||||
- name: Upload sdist
|
||||
uses: actions/upload-artifact@v5.0.0
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||
with:
|
||||
name: wheels-sdist
|
||||
path: dist
|
||||
@@ -103,10 +103,10 @@ jobs:
|
||||
# Used to generate artifact attestation
|
||||
attestations: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v6.0.0
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v3.0.0
|
||||
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
|
||||
with:
|
||||
subject-path: 'wheels-*/*'
|
||||
|
||||
|
||||
6
.github/workflows/scorecards.yml
vendored
6
.github/workflows/scorecards.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v5.0.0
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -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.2
|
||||
uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/gitleaks/gitleaks
|
||||
rev: v8.28.0
|
||||
rev: v8.29.0
|
||||
hooks:
|
||||
- id: gitleaks
|
||||
|
||||
@@ -16,7 +16,7 @@ repos:
|
||||
- id: trailing-whitespace
|
||||
|
||||
- repo: https://github.com/crate-ci/typos
|
||||
rev: v1.38.1
|
||||
rev: v1.39.2
|
||||
hooks:
|
||||
- id: typos
|
||||
|
||||
|
||||
2235
Cargo.lock
generated
2235
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
34
Cargo.toml
34
Cargo.toml
@@ -14,26 +14,25 @@ edition = "2021"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
home = "~0.5"
|
||||
etcetera = "~0.8"
|
||||
home = "=0.5.11"
|
||||
etcetera = "=0.11.0"
|
||||
serde = { version = "~1.0", features = ["derive"] }
|
||||
toml = "0.8"
|
||||
which_crate = { version = "~6.0", package = "which" }
|
||||
toml = "=0.9.8"
|
||||
which_crate = { version = "~8.0", package = "which" }
|
||||
shellexpand = "~3.1"
|
||||
clap = { version = "~4.5", features = ["cargo", "derive"] }
|
||||
clap_complete = "~4.5"
|
||||
clap_mangen = "~0.2"
|
||||
walkdir = "~2.5"
|
||||
console = "~0.15"
|
||||
console = "~0.16"
|
||||
chrono = "~0.4"
|
||||
glob = "~0.3"
|
||||
strum = { version = "~0.26", features = ["derive"] }
|
||||
thiserror = "~1.0"
|
||||
tempfile = "~3.10"
|
||||
cfg-if = "~1.0"
|
||||
tokio = { version = "~1.47", features = ["process", "rt-multi-thread"] }
|
||||
strum = { version = "~0.27", features = ["derive"] }
|
||||
thiserror = "~2.0"
|
||||
tempfile = "~3.23"
|
||||
tokio = { version = "~1.48", features = ["process", "rt-multi-thread"] }
|
||||
futures = "~0.3"
|
||||
regex = "~1.10"
|
||||
regex = "~1.12"
|
||||
semver = "~1.0"
|
||||
shell-words = "~1.1"
|
||||
color-eyre = "~0.6"
|
||||
@@ -48,6 +47,13 @@ sys-locale = "0.3.1"
|
||||
jetbrains-toolbox-updater = "5.0.0"
|
||||
indexmap = { version = "2.9.0", features = ["serde"] }
|
||||
serde_json = "1.0.145"
|
||||
# Temporary transitive dependency pins
|
||||
ignore = "=0.4.23"
|
||||
globset = "=0.4.16"
|
||||
base64ct = "<1.8.0"
|
||||
|
||||
[patch.crates-io]
|
||||
mac-notification-sys = { git = "https://github.com/h4llow3En/mac-notification-sys" }
|
||||
|
||||
[package.metadata.generate-rpm]
|
||||
assets = [{ source = "target/release/topgrade", dest = "/usr/bin/topgrade" }]
|
||||
@@ -77,14 +83,14 @@ assets = [
|
||||
]
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = { version = "~0.29", features = ["hostname", "signal", "user"] }
|
||||
nix = { version = "~0.30", features = ["hostname", "signal", "user"] }
|
||||
rust-ini = "~0.21"
|
||||
self_update_crate = { version = "~0.40", default-features = false, optional = true, package = "self_update", features = ["archive-tar", "compression-flate2", "rustls"] }
|
||||
self_update_crate = { version = "~0.42", default-features = false, optional = true, package = "self_update", features = ["archive-tar", "compression-flate2", "rustls"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
is_elevated = "~0.1"
|
||||
parselnk = "~0.1"
|
||||
self_update_crate = { version = "~0.40", default-features = false, optional = true, package = "self_update", features = ["archive-zip", "compression-zip-deflate", "rustls"] }
|
||||
self_update_crate = { version = "~0.42", default-features = false, optional = true, package = "self_update", features = ["archive-zip", "compression-zip-deflate", "rustls"] }
|
||||
windows = { version = "~0.62", features = ["Win32_System_Console"] }
|
||||
windows-registry = "~0.6"
|
||||
|
||||
|
||||
@@ -286,6 +286,11 @@
|
||||
# winget_use_sudo = true
|
||||
|
||||
|
||||
[chezmoi]
|
||||
# Exclude encrypted files from update
|
||||
# (default: false)
|
||||
# exclude_encrypted = false
|
||||
|
||||
[npm]
|
||||
# Use sudo if the NPM directory isn't owned by the current user
|
||||
# use_sudo = true
|
||||
|
||||
@@ -1306,14 +1306,6 @@ _version: 2
|
||||
zh_CN: "Windows 更新"
|
||||
zh_TW: "Windows 更新"
|
||||
de: "Windows-Update"
|
||||
"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ė"
|
||||
|
||||
10
renovate.json
Normal file
10
renovate.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:best-practices",
|
||||
":semanticCommits"
|
||||
],
|
||||
"lockFileMaintenance": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
@@ -165,6 +165,13 @@ pub struct Deno {
|
||||
version: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Merge)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub struct Chezmoi {
|
||||
exclude_encrypted: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Merge)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
@@ -457,6 +464,9 @@ pub struct ConfigFile {
|
||||
#[merge(strategy = crate::utils::merge_strategies::inner_merge_opt)]
|
||||
npm: Option<NPM>,
|
||||
|
||||
#[merge(strategy = crate::utils::merge_strategies::inner_merge_opt)]
|
||||
chezmoi: Option<Chezmoi>,
|
||||
|
||||
#[merge(strategy = crate::utils::merge_strategies::inner_merge_opt)]
|
||||
yarn: Option<Yarn>,
|
||||
|
||||
@@ -1597,8 +1607,7 @@ impl Config {
|
||||
self.config_file.misc.as_ref().and_then(|misc| misc.sudo_command)
|
||||
}
|
||||
|
||||
/// If `true`, `sudo` should be called after `pre_commands` in order to elevate at the
|
||||
/// start of the session (and not in the middle).
|
||||
/// If `true`, `sudo -v` should be called to cache credentials at the start of the run
|
||||
pub fn pre_sudo(&self) -> bool {
|
||||
self.config_file
|
||||
.misc
|
||||
@@ -1774,6 +1783,14 @@ impl Config {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn chezmoi_exclude_encrypted(&self) -> bool {
|
||||
self.config_file
|
||||
.chezmoi
|
||||
.as_ref()
|
||||
.and_then(|chezmoi| chezmoi.exclude_encrypted)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn vscode_profile(&self) -> Option<&str> {
|
||||
let vscode_cfg = self.config_file.vscode.as_ref()?;
|
||||
let profile = vscode_cfg.profile.as_ref()?;
|
||||
|
||||
39
src/main.rs
39
src/main.rs
@@ -12,7 +12,6 @@ use clap::{crate_version, Parser};
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
use console::Key;
|
||||
use etcetera::base_strategy::BaseStrategy;
|
||||
#[cfg(windows)]
|
||||
use etcetera::base_strategy::Windows;
|
||||
#[cfg(unix)]
|
||||
@@ -187,17 +186,7 @@ fn run() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
// Self-Update step, this will execute only if:
|
||||
// 1. the `self-update` feature is enabled
|
||||
// 2. it is not disabled from configuration (env var/CLI opt/file)
|
||||
#[cfg(feature = "self-update")]
|
||||
{
|
||||
let should_self_update = env::var("TOPGRADE_NO_SELF_UPGRADE").is_err() && !config.no_self_update();
|
||||
|
||||
if should_self_update {
|
||||
runner.execute(step::Step::SelfUpdate, "Self Update", || self_update::self_update(&ctx))?;
|
||||
}
|
||||
}
|
||||
step::Step::SelfUpdate.run(&mut runner, &ctx)?;
|
||||
|
||||
#[cfg(windows)]
|
||||
let _self_rename = if config.self_rename() {
|
||||
@@ -206,20 +195,32 @@ fn run() -> Result<()> {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(commands) = config.pre_commands() {
|
||||
for (name, command) in commands {
|
||||
generic::run_custom_command(name, command, &ctx)?;
|
||||
}
|
||||
}
|
||||
|
||||
if config.pre_sudo() {
|
||||
if let Some(sudo) = ctx.sudo() {
|
||||
sudo.elevate(&ctx)?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(commands) = config.pre_commands() {
|
||||
for (name, command) in commands {
|
||||
generic::run_custom_command(name, command, &ctx)?;
|
||||
}
|
||||
}
|
||||
|
||||
for step in step::default_steps() {
|
||||
step.run(&mut runner, &ctx)?
|
||||
match step.run(&mut runner, &ctx) {
|
||||
Ok(()) => (),
|
||||
Err(error)
|
||||
if error
|
||||
.downcast_ref::<io::Error>()
|
||||
.is_some_and(|e| e.kind() == io::ErrorKind::Interrupted) =>
|
||||
{
|
||||
println!();
|
||||
debug!("Interrupted (possibly with 'q' during retry prompt). Printing summary.");
|
||||
break;
|
||||
}
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
let mut failed = false;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use color_eyre::eyre::Result;
|
||||
use color_eyre::eyre::{Result, WrapErr};
|
||||
use rust_i18n::t;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Debug;
|
||||
use std::io;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::ctrlc;
|
||||
use crate::error::{DryRun, MissingSudo, SkipStep};
|
||||
use crate::execution_context::ExecutionContext;
|
||||
use crate::step::Step;
|
||||
use crate::terminal::{print_error, print_warning, should_retry};
|
||||
use crate::terminal::{print_error, print_warning, should_retry, ShouldRetry};
|
||||
|
||||
pub enum StepResult {
|
||||
Success,
|
||||
@@ -98,21 +99,28 @@ impl<'a> Runner<'a> {
|
||||
let should_ask = interrupted || !(self.ctx.config().no_retry() || ignore_failure);
|
||||
let should_retry = if should_ask {
|
||||
print_error(&key, format!("{e:?}"));
|
||||
should_retry(interrupted, key.as_ref())?
|
||||
should_retry(key.as_ref())?
|
||||
} else {
|
||||
false
|
||||
ShouldRetry::No
|
||||
};
|
||||
|
||||
if !should_retry {
|
||||
self.push_result(
|
||||
key,
|
||||
if ignore_failure {
|
||||
StepResult::Ignored
|
||||
} else {
|
||||
StepResult::Failure
|
||||
},
|
||||
);
|
||||
break;
|
||||
match should_retry {
|
||||
ShouldRetry::No | ShouldRetry::Quit => {
|
||||
self.push_result(
|
||||
key,
|
||||
if ignore_failure {
|
||||
StepResult::Ignored
|
||||
} else {
|
||||
StepResult::Failure
|
||||
},
|
||||
);
|
||||
if let ShouldRetry::Quit = should_retry {
|
||||
return Err(io::Error::from(io::ErrorKind::Interrupted))
|
||||
.context("Quit from user input");
|
||||
}
|
||||
break;
|
||||
}
|
||||
ShouldRetry::Yes => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,6 +544,9 @@ impl Step {
|
||||
runner.execute(*self, "SDKMAN!", || unix::run_sdkman(ctx))?
|
||||
}
|
||||
SelfUpdate => {
|
||||
// Self-Update step, this will execute only if:
|
||||
// 1. the `self-update` feature is enabled
|
||||
// 2. it is not disabled from configuration (env var/CLI opt/file)
|
||||
#[cfg(feature = "self-update")]
|
||||
{
|
||||
if std::env::var("TOPGRADE_NO_SELF_UPGRADE").is_err() && !ctx.config().no_self_update() {
|
||||
|
||||
@@ -282,6 +282,17 @@ pub fn run_elan(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
print_separator("elan");
|
||||
|
||||
let version_output = ctx.execute(&elan).arg("--version").output_checked_utf8()?;
|
||||
let version_string = version_output.stdout.split_whitespace().nth(1).ok_or_else(|| {
|
||||
eyre!(output_changed_message!(
|
||||
"elan --version",
|
||||
"Expected version after 'elan '"
|
||||
))
|
||||
})?;
|
||||
let version = Version::parse(version_string)
|
||||
.wrap_err_with(|| output_changed_message!("elan --version", "Invalid version"))?;
|
||||
debug!("Detected elan version as: {}", version);
|
||||
|
||||
let disabled_error_msg = "self-update is disabled";
|
||||
let executor_output = ctx.execute(&elan).args(["self", "update"]).output()?;
|
||||
match executor_output {
|
||||
@@ -310,7 +321,12 @@ pub fn run_elan(ctx: &ExecutionContext) -> Result<()> {
|
||||
ExecutorOutput::Dry => { /* nothing needed because in a dry run */ }
|
||||
}
|
||||
|
||||
ctx.execute(&elan).arg("update").status_checked()
|
||||
// In elan 4.0.0, `elan update` was removed, as toolchains are now updated automatically
|
||||
if version < Version::new(4, 0, 0) {
|
||||
ctx.execute(&elan).arg("update").status_checked()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_juliaup(ctx: &ExecutionContext) -> Result<()> {
|
||||
@@ -873,12 +889,11 @@ pub fn run_tldr(ctx: &ExecutionContext) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn run_tlmgr_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_os = "linux", target_os = "android"))] {
|
||||
if !ctx.config().enable_tlmgr_linux() {
|
||||
return Err(SkipStep(String::from("tlmgr must be explicitly enabled in the configuration to run in Android/Linux")).into());
|
||||
}
|
||||
}
|
||||
if cfg!(any(target_os = "linux", target_os = "android")) && !ctx.config().enable_tlmgr_linux() {
|
||||
return Err(SkipStep(String::from(
|
||||
"tlmgr must be explicitly enabled in the configuration to run in Android/Linux",
|
||||
))
|
||||
.into());
|
||||
}
|
||||
|
||||
let tlmgr = require("tlmgr")?;
|
||||
@@ -916,9 +931,17 @@ pub fn run_chezmoi_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
let chezmoi = require("chezmoi")?;
|
||||
HOME_DIR.join(".local/share/chezmoi").require()?;
|
||||
|
||||
let mut cmd = ctx.execute(chezmoi);
|
||||
|
||||
print_separator("chezmoi");
|
||||
|
||||
ctx.execute(chezmoi).arg("update").status_checked()
|
||||
cmd.arg("update");
|
||||
|
||||
if ctx.config().chezmoi_exclude_encrypted() {
|
||||
cmd.arg("--exclude=encrypted");
|
||||
}
|
||||
|
||||
cmd.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_myrepos_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
@@ -975,23 +998,19 @@ pub fn run_composer_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
print_separator(t!("Composer"));
|
||||
|
||||
if ctx.config().composer_self_update() {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
// If self-update fails without sudo then there's probably an update
|
||||
let has_update = match ctx.execute(&composer).arg("self-update").output()? {
|
||||
ExecutorOutput::Wet(output) => !output.status.success(),
|
||||
_ => false
|
||||
};
|
||||
if cfg!(unix) {
|
||||
// If self-update fails without sudo then there's probably an update
|
||||
let has_update = match ctx.execute(&composer).arg("self-update").output()? {
|
||||
ExecutorOutput::Wet(output) => !output.status.success(),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if has_update {
|
||||
let sudo = ctx.require_sudo()?;
|
||||
sudo.execute(ctx, &composer)?
|
||||
.arg("self-update")
|
||||
.status_checked()?;
|
||||
}
|
||||
} else {
|
||||
ctx.execute(&composer).arg("self-update").status_checked()?;
|
||||
if has_update {
|
||||
let sudo = ctx.require_sudo()?;
|
||||
sudo.execute(ctx, &composer)?.arg("self-update").status_checked()?;
|
||||
}
|
||||
} else {
|
||||
ctx.execute(&composer).arg("self-update").status_checked()?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1561,9 +1580,25 @@ pub fn run_zvm(ctx: &ExecutionContext) -> Result<()> {
|
||||
pub fn run_bun(ctx: &ExecutionContext) -> Result<()> {
|
||||
let bun = require("bun")?;
|
||||
|
||||
print_separator("Bun");
|
||||
// From the official install script (both install.sh and install.ps1), Bun uses
|
||||
// the path set in this variable as the install root, and its defaults to
|
||||
// `$HOME/.bun`
|
||||
//
|
||||
// UNIX: https://bun.sh/install.sh
|
||||
// Windows: https://bun.sh/install.ps1
|
||||
let bun_install_env = env::var("BUN_INSTALL")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or(HOME_DIR.join(".bun"));
|
||||
|
||||
ctx.execute(bun).arg("upgrade").status_checked()
|
||||
// If `bun` is a descendant of `bun_install_env`, then Bun is installed
|
||||
// through the official script
|
||||
if bun.is_descendant_of(&bun_install_env) {
|
||||
print_separator("Bun");
|
||||
|
||||
ctx.execute(bun).arg("upgrade").status_checked()
|
||||
} else {
|
||||
Err(SkipStep("Not installed through the official script".to_string()).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_zigup(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
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;
|
||||
use std::fs;
|
||||
use tracing::debug;
|
||||
|
||||
fn is_openbsd_current(ctx: &ExecutionContext) -> Result<bool> {
|
||||
fn is_openbsd_current() -> Result<bool> {
|
||||
let motd_content = fs::read_to_string("/etc/motd")?;
|
||||
let is_current = ["-current", "-beta"].iter().any(|&s| motd_content.contains(s));
|
||||
match ctx.config.run_type() {
|
||||
RunType::Dry | RunType::Damp => {
|
||||
println!("{}", t!("Checking if /etc/motd contains -current or -beta"));
|
||||
}
|
||||
RunType::Wet => {}
|
||||
}
|
||||
|
||||
debug!("OpenBSD is -current/-beta: {is_current}");
|
||||
|
||||
Ok(is_current)
|
||||
}
|
||||
|
||||
@@ -23,12 +20,7 @@ pub fn upgrade_openbsd(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
let sudo = ctx.require_sudo()?;
|
||||
|
||||
let is_current = is_openbsd_current(ctx)?;
|
||||
|
||||
if ctx.config().dry_run() {
|
||||
println!("{}", t!("Would upgrade the OpenBSD system"));
|
||||
return Ok(());
|
||||
}
|
||||
let is_current = is_openbsd_current()?;
|
||||
|
||||
if is_current {
|
||||
sudo.execute(ctx, "/usr/sbin/sysupgrade")?.arg("-sn").status_checked()
|
||||
@@ -42,7 +34,7 @@ pub fn upgrade_packages(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
let sudo = ctx.require_sudo()?;
|
||||
|
||||
let is_current = is_openbsd_current(ctx)?;
|
||||
let is_current = is_openbsd_current()?;
|
||||
|
||||
if ctx.config().cleanup() {
|
||||
sudo.execute(ctx, "/usr/sbin/pkg_delete")?.arg("-ac").status_checked()?;
|
||||
|
||||
@@ -201,10 +201,11 @@ impl Terminal {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn should_retry(&mut self, interrupted: bool, step_name: &str) -> eyre::Result<bool> {
|
||||
fn should_retry(&mut self, step_name: &str) -> eyre::Result<ShouldRetry> {
|
||||
if self.width.is_none() {
|
||||
return Ok(false);
|
||||
return Ok(ShouldRetry::No);
|
||||
}
|
||||
|
||||
if self.set_title {
|
||||
@@ -223,7 +224,7 @@ impl Terminal {
|
||||
|
||||
let answer = loop {
|
||||
match self.term.read_key() {
|
||||
Ok(Key::Char('y' | 'Y')) => break Ok(true),
|
||||
Ok(Key::Char('y' | 'Y')) => break Ok(ShouldRetry::Yes),
|
||||
Ok(Key::Char('s' | 'S')) => {
|
||||
println!(
|
||||
"\n\n{}\n",
|
||||
@@ -232,16 +233,16 @@ impl Terminal {
|
||||
if let Err(err) = run_shell().context("Failed to run shell") {
|
||||
self.term.write_fmt(format_args!("{err:?}\n{prompt_inner}")).ok();
|
||||
} else {
|
||||
break Ok(true);
|
||||
break Ok(ShouldRetry::Yes);
|
||||
}
|
||||
}
|
||||
Ok(Key::Char('n' | 'N') | Key::Enter) => break Ok(false),
|
||||
Ok(Key::Char('n' | 'N') | Key::Enter) => break Ok(ShouldRetry::No),
|
||||
Err(e) => {
|
||||
error!("Error reading from terminal: {}", e);
|
||||
break Ok(false);
|
||||
break Ok(ShouldRetry::No);
|
||||
}
|
||||
Ok(Key::Char('q' | 'Q')) => {
|
||||
return Err(io::Error::from(io::ErrorKind::Interrupted)).context("Quit from user input")
|
||||
break Ok(ShouldRetry::Quit);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
@@ -257,14 +258,21 @@ impl Terminal {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ShouldRetry {
|
||||
Yes,
|
||||
No,
|
||||
Quit,
|
||||
}
|
||||
|
||||
impl Default for Terminal {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn should_retry(interrupted: bool, step_name: &str) -> eyre::Result<bool> {
|
||||
TERMINAL.lock().unwrap().should_retry(interrupted, step_name)
|
||||
pub fn should_retry(step_name: &str) -> eyre::Result<ShouldRetry> {
|
||||
TERMINAL.lock().unwrap().should_retry(step_name)
|
||||
}
|
||||
|
||||
pub fn print_separator<P: AsRef<str>>(message: P) {
|
||||
|
||||
Reference in New Issue
Block a user