Compare commits
30 Commits
v10.1.0-cd
...
v10.1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e161d3cd3c | ||
|
|
318f935b43 | ||
|
|
3dc245245d | ||
|
|
9de111aa0f | ||
|
|
18951c8447 | ||
|
|
b6e50a38af | ||
|
|
8acdfc8d1c | ||
|
|
a6da5181f2 | ||
|
|
60ff087048 | ||
|
|
3ebaac3a1d | ||
|
|
e4f8488837 | ||
|
|
d8748b004b | ||
|
|
2a11df40ee | ||
|
|
16953409fd | ||
|
|
c85adb8980 | ||
|
|
0f0cbc1453 | ||
|
|
91554cac56 | ||
|
|
7256aaffc8 | ||
|
|
66e0b94e85 | ||
|
|
4dcb5a214b | ||
|
|
8731fd2b3f | ||
|
|
9233846479 | ||
|
|
94bdb8c3fd | ||
|
|
632fcb5b77 | ||
|
|
55ba2d30c1 | ||
|
|
ff66611ec0 | ||
|
|
edc3dd6b0b | ||
|
|
623a11cf21 | ||
|
|
7a83f38ca8 | ||
|
|
9a19b547c6 |
26
.github/workflows/check-and-lint.yaml
vendored
26
.github/workflows/check-and-lint.yaml
vendored
@@ -10,7 +10,10 @@ name: Check and Lint
|
||||
jobs:
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
@@ -24,7 +27,10 @@ jobs:
|
||||
|
||||
fmt:
|
||||
name: Rustfmt
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
@@ -40,7 +46,10 @@ jobs:
|
||||
|
||||
clippy:
|
||||
name: Clippy
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
@@ -48,8 +57,13 @@ jobs:
|
||||
toolchain: stable
|
||||
components: clippy
|
||||
override: true
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
- uses: actions-rs/cargo@v1.0.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --all-features
|
||||
command: clippy
|
||||
args: --all-targets --locked -- -D warnings
|
||||
name: Clippy Output
|
||||
- uses: actions-rs/cargo@v1.0.1
|
||||
with:
|
||||
command: clippy
|
||||
args: --all-targets --locked --all-features -- -D warnings
|
||||
name: Clippy (All features) Output
|
||||
|
||||
2
.github/workflows/crates-publish.yml
vendored
2
.github/workflows/crates-publish.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly-2022-08-03
|
||||
toolchain: stable
|
||||
override: true
|
||||
|
||||
publish:
|
||||
|
||||
2
.github/workflows/release-cross.yml
vendored
2
.github/workflows/release-cross.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.57.0
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
default: true
|
||||
override: true
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.57.0
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
open an issue on GitHub .
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
89
Cargo.lock
generated
89
Cargo.lock
generated
@@ -225,24 +225,26 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.18"
|
||||
version = "3.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b"
|
||||
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"once_cell",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.18"
|
||||
version = "3.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3"
|
||||
checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c"
|
||||
dependencies = [
|
||||
"heck 0.4.0",
|
||||
"proc-macro-error",
|
||||
@@ -253,9 +255,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.0"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
@@ -658,9 +660,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.15"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
|
||||
checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@@ -983,14 +985,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.5"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
|
||||
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1032,6 +1044,15 @@ dependencies = [
|
||||
"zvariant_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
@@ -1356,9 +1377,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
version = "1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -1604,6 +1625,12 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
||||
|
||||
[[package]]
|
||||
name = "shell-words"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
||||
|
||||
[[package]]
|
||||
name = "shellexpand"
|
||||
version = "2.1.2"
|
||||
@@ -1753,13 +1780,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"rand",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
@@ -1784,6 +1811,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
@@ -1861,9 +1894,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.21.2"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
|
||||
checksum = "cd3b82e6e823a9ee7d7f64b08f8ac3d5f08ac988f23157194bd32af3f2f92767"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
@@ -1871,9 +1904,9 @@ dependencies = [
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@@ -1890,16 +1923,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.4"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740"
|
||||
checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1913,7 +1946,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "topgrade"
|
||||
version = "10.1.0"
|
||||
version = "10.1.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
@@ -1935,6 +1968,7 @@ dependencies = [
|
||||
"self_update",
|
||||
"semver",
|
||||
"serde",
|
||||
"shell-words",
|
||||
"shellexpand",
|
||||
"strum 0.24.1",
|
||||
"sys-info",
|
||||
@@ -2202,13 +2236,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.3.0"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b"
|
||||
checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe"
|
||||
dependencies = [
|
||||
"either",
|
||||
"libc",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
63
Cargo.toml
63
Cargo.toml
@@ -5,7 +5,7 @@ categories = ["os"]
|
||||
keywords = ["upgrade", "update"]
|
||||
license-file = "LICENSE"
|
||||
repository = "https://github.com/topgrade-rs/topgrade"
|
||||
version = "10.1.0"
|
||||
version = "10.1.2"
|
||||
authors = ["Roey Darwish Dror <roey.ghost@gmail.com>", "Thomas Schönauer <t.schoenauer@hgs-wt.at>"]
|
||||
exclude = ["doc/screenshot.gif"]
|
||||
edition = "2021"
|
||||
@@ -20,43 +20,44 @@ path = "src/main.rs"
|
||||
##name = "topgrade_lib"
|
||||
|
||||
[dependencies]
|
||||
home = "0.5"
|
||||
directories = "4.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
home = "~0.5"
|
||||
directories = "~4.0"
|
||||
serde = { version = "~1.0", features = ["derive"] }
|
||||
toml = "0.5"
|
||||
which_crate = { version = "4.1", package = "which" }
|
||||
shellexpand = "2.1"
|
||||
clap = { version = "4.0.18", features = ["cargo", "derive"] }
|
||||
log = "0.4"
|
||||
walkdir = "2.3"
|
||||
console = "0.15"
|
||||
lazy_static = "1.4"
|
||||
chrono = "0.4"
|
||||
pretty_env_logger = "0.4"
|
||||
glob = "0.3"
|
||||
strum = { version = "0.24", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
anyhow = "1.0"
|
||||
tempfile = "3.2"
|
||||
cfg-if = "1.0"
|
||||
tokio = { version = "1.5", features = ["process", "rt-multi-thread"] }
|
||||
futures = "0.3"
|
||||
regex = "1.5"
|
||||
sys-info = "0.9"
|
||||
semver = "1.0"
|
||||
which_crate = { version = "~4.1", package = "which" }
|
||||
shellexpand = "~2.1"
|
||||
clap = { version = "~3.1", features = ["cargo", "derive"] }
|
||||
log = "~0.4"
|
||||
walkdir = "~2.3"
|
||||
console = "~0.15"
|
||||
lazy_static = "~1.4"
|
||||
chrono = "~0.4"
|
||||
pretty_env_logger = "~0.4"
|
||||
glob = "~0.3"
|
||||
strum = { version = "~0.24", features = ["derive"] }
|
||||
thiserror = "~1.0"
|
||||
anyhow = "~1.0"
|
||||
tempfile = "~3.2"
|
||||
cfg-if = "~1.0"
|
||||
tokio = { version = "~1.5", features = ["process", "rt-multi-thread"] }
|
||||
futures = "~0.3"
|
||||
regex = "~1.5"
|
||||
sys-info = "~0.9"
|
||||
semver = "~1.0"
|
||||
shell-words = "~1.1"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
notify-rust = "4.5"
|
||||
notify-rust = "~4.5"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = "0.24"
|
||||
rust-ini = "0.18"
|
||||
self_update_crate = { version = "0.30", default-features = false, optional = true, package = "self_update", features = ["archive-tar", "compression-flate2", "rustls"] }
|
||||
nix = "~0.24"
|
||||
rust-ini = "~0.18"
|
||||
self_update_crate = { version = "~0.30", default-features = false, optional = true, package = "self_update", features = ["archive-tar", "compression-flate2", "rustls"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
self_update_crate = { version = "0.30", default-features = false, optional = true, package = "self_update", features = ["archive-zip", "compression-zip-deflate", "rustls"] }
|
||||
winapi = "0.3"
|
||||
parselnk = "0.1"
|
||||
self_update_crate = { version = "~0.30", default-features = false, optional = true, package = "self_update", features = ["archive-zip", "compression-zip-deflate", "rustls"] }
|
||||
winapi = "~0.3"
|
||||
parselnk = "~0.1"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
@@ -24,6 +24,7 @@ To remedy this, **Topgrade** detects which tools you use and runs the appropriat
|
||||
|
||||
- Arch Linux: [AUR](https://aur.archlinux.org/packages/topgrade) package.
|
||||
- NixOS: _topgrade_ package in `nixpkgs`.
|
||||
- Void Linux: _topgrade_ package
|
||||
- macOS: [Homebrew](https://formulae.brew.sh/formula/topgrade) or [MacPorts](https://ports.macports.org/port/topgrade/).
|
||||
|
||||
Other systems users can either use `cargo install` or use the compiled binaries from the release page.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#![allow(dead_code)]
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use clap::{ArgEnum, Parser};
|
||||
use directories::BaseDirs;
|
||||
use log::debug;
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::write;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::{env, fs};
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, ValueEnum};
|
||||
use directories::BaseDirs;
|
||||
use log::debug;
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use strum::{EnumIter, EnumString, EnumVariantNames, IntoEnumIterator};
|
||||
use sys_info::hostname;
|
||||
use which_crate::which;
|
||||
@@ -62,7 +62,7 @@ macro_rules! get_deprecated {
|
||||
|
||||
type Commands = BTreeMap<String, String>;
|
||||
|
||||
#[derive(ValueEnum, EnumString, EnumVariantNames, Debug, Clone, PartialEq, Eq, Deserialize, EnumIter, Copy)]
|
||||
#[derive(ArgEnum, EnumString, EnumVariantNames, Debug, Clone, PartialEq, Eq, Deserialize, EnumIter, Copy)]
|
||||
#[clap(rename_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
@@ -397,78 +397,85 @@ impl ConfigFile {
|
||||
|
||||
// Command line arguments
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name = "Topgrade", version)]
|
||||
#[clap(name = "Topgrade", version)]
|
||||
pub struct CommandLineArgs {
|
||||
/// Edit the configuration file
|
||||
#[arg(long = "edit-config")]
|
||||
#[clap(long = "edit-config")]
|
||||
edit_config: bool,
|
||||
|
||||
/// Show config reference
|
||||
#[arg(long = "config-reference")]
|
||||
#[clap(long = "config-reference")]
|
||||
show_config_reference: bool,
|
||||
|
||||
/// Run inside tmux
|
||||
#[arg(short = 't', long = "tmux")]
|
||||
#[clap(short = 't', long = "tmux")]
|
||||
run_in_tmux: bool,
|
||||
|
||||
/// Cleanup temporary or old files
|
||||
#[arg(short = 'c', long = "cleanup")]
|
||||
#[clap(short = 'c', long = "cleanup")]
|
||||
cleanup: bool,
|
||||
|
||||
/// Print what would be done
|
||||
#[arg(short = 'n', long = "dry-run")]
|
||||
#[clap(short = 'n', long = "dry-run")]
|
||||
dry_run: bool,
|
||||
|
||||
/// Do not ask to retry failed steps
|
||||
#[arg(long = "no-retry")]
|
||||
#[clap(long = "no-retry")]
|
||||
no_retry: bool,
|
||||
|
||||
/// Do not perform upgrades for the given steps
|
||||
#[arg(long = "disable", value_name = "STEP", value_enum, num_args = 1..)]
|
||||
#[clap(long = "disable", value_name = "STEP", arg_enum, multiple_values = true)]
|
||||
disable: Vec<Step>,
|
||||
|
||||
/// Perform only the specified steps (experimental)
|
||||
#[arg(long = "only", value_name = "STEP", value_enum, num_args = 1..)]
|
||||
#[clap(long = "only", value_name = "STEP", arg_enum, multiple_values = true)]
|
||||
only: Vec<Step>,
|
||||
|
||||
/// Run only specific custom commands
|
||||
#[arg(long = "custom-commands", value_name = "NAME", num_args = 1..)]
|
||||
#[clap(long = "custom-commands", value_name = "NAME", multiple_values = true)]
|
||||
custom_commands: Vec<String>,
|
||||
|
||||
/// Set environment variables
|
||||
#[arg(long = "env", value_name = "NAME=VALUE", num_args = 1..)]
|
||||
#[clap(long = "env", value_name = "NAME=VALUE", multiple_values = true)]
|
||||
env: Vec<String>,
|
||||
|
||||
/// Output logs
|
||||
#[arg(short = 'v', long = "verbose")]
|
||||
#[clap(short = 'v', long = "verbose")]
|
||||
pub verbose: bool,
|
||||
|
||||
/// Prompt for a key before exiting
|
||||
#[arg(short = 'k', long = "keep")]
|
||||
#[clap(short = 'k', long = "keep")]
|
||||
keep_at_end: bool,
|
||||
|
||||
/// Skip sending a notification at the end of a run
|
||||
#[arg(long = "skip-notify")]
|
||||
#[clap(long = "skip-notify")]
|
||||
skip_notify: bool,
|
||||
|
||||
/// Say yes to package manager's prompt
|
||||
#[arg(short = 'y', long = "yes", value_name = "STEP", value_enum, num_args = 0..)]
|
||||
#[clap(
|
||||
short = 'y',
|
||||
long = "yes",
|
||||
value_name = "STEP",
|
||||
arg_enum,
|
||||
multiple_values = true,
|
||||
min_values = 0
|
||||
)]
|
||||
yes: Option<Vec<Step>>,
|
||||
|
||||
/// Don't pull the predefined git repos
|
||||
#[arg(long = "disable-predefined-git-repos")]
|
||||
#[clap(long = "disable-predefined-git-repos")]
|
||||
disable_predefined_git_repos: bool,
|
||||
|
||||
/// Alternative configuration file
|
||||
#[arg(long = "config", value_name = "PATH")]
|
||||
#[clap(long = "config", value_name = "PATH")]
|
||||
config: Option<PathBuf>,
|
||||
|
||||
/// A regular expression for restricting remote host execution
|
||||
#[arg(long = "remote-host-limit", value_name = "REGEX")]
|
||||
#[clap(long = "remote-host-limit", value_name = "REGEX")]
|
||||
remote_host_limit: Option<Regex>,
|
||||
|
||||
/// Show the reason for skipped steps
|
||||
#[arg(long = "show-skipped")]
|
||||
#[clap(long = "show-skipped")]
|
||||
show_skipped: bool,
|
||||
}
|
||||
|
||||
@@ -626,8 +633,16 @@ impl Config {
|
||||
}
|
||||
|
||||
/// Extra Tmux arguments
|
||||
pub fn tmux_arguments(&self) -> &Option<String> {
|
||||
&self.config_file.tmux_arguments
|
||||
pub fn tmux_arguments(&self) -> anyhow::Result<Vec<String>> {
|
||||
let args = &self.config_file.tmux_arguments.as_deref().unwrap_or_default();
|
||||
shell_words::split(args)
|
||||
// The only time the parse failed is in case of a missing close quote.
|
||||
// The error message looks like this:
|
||||
// Error: Failed to parse `tmux_arguments`: `'foo`
|
||||
//
|
||||
// Caused by:
|
||||
// missing closing quote
|
||||
.with_context(|| format!("Failed to parse `tmux_arguments`: `{args}`"))
|
||||
}
|
||||
|
||||
/// Prompt for a key before exiting
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use lazy_static::lazy_static;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
lazy_static! {
|
||||
/// A global variable telling whether the application has been interrupted.
|
||||
static ref INTERRUPTED: AtomicBool = AtomicBool::new(false);
|
||||
}
|
||||
/// A global variable telling whether the application has been interrupted.
|
||||
static INTERRUPTED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// Tells whether the program has been interrupted
|
||||
pub fn interrupted() -> bool {
|
||||
|
||||
@@ -194,11 +194,12 @@ impl DryCommand {
|
||||
print!(
|
||||
"Dry running: {} {}",
|
||||
self.program.to_string_lossy(),
|
||||
self.args
|
||||
.iter()
|
||||
.map(|a| String::from(a.to_string_lossy()))
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ")
|
||||
shell_words::join(
|
||||
self.args
|
||||
.iter()
|
||||
.map(|a| String::from(a.to_string_lossy()))
|
||||
.collect::<Vec<String>>()
|
||||
)
|
||||
);
|
||||
match &self.directory {
|
||||
Some(dir) => println!(" in {}", dir.to_string_lossy()),
|
||||
|
||||
@@ -79,7 +79,7 @@ fn run() -> Result<()> {
|
||||
if config.run_in_tmux() && env::var("TOPGRADE_INSIDE_TMUX").is_err() {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
tmux::run_in_tmux(config.tmux_arguments());
|
||||
tmux::run_in_tmux(config.tmux_arguments()?);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,6 +351,7 @@ fn run() -> Result<()> {
|
||||
runner.execute(Step::Kakoune, "Kakoune", || kakoune::upgrade_kak_plug(&ctx))?;
|
||||
runner.execute(Step::Node, "npm", || node::run_npm_upgrade(&ctx))?;
|
||||
runner.execute(Step::Node, "yarn", || node::run_yarn_upgrade(&ctx))?;
|
||||
runner.execute(Step::Node, "pnpm", || node::run_pnpm_upgrade(&ctx))?;
|
||||
runner.execute(Step::Containers, "Containers", || containers::run_containers(&ctx))?;
|
||||
runner.execute(Step::Deno, "deno", || node::deno_upgrade(&ctx))?;
|
||||
runner.execute(Step::Composer, "composer", || generic::run_composer_update(&ctx))?;
|
||||
@@ -523,7 +524,10 @@ fn main() {
|
||||
.is_some());
|
||||
|
||||
if !skip_print {
|
||||
println!("Error: {}", error);
|
||||
// The `Debug` implementation of `anyhow::Result` prints a multi-line
|
||||
// error message that includes all the 'causes' added with
|
||||
// `.with_context(...)` calls.
|
||||
println!("Error: {:?}", error);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -18,11 +18,7 @@ pub fn self_update() -> Result<()> {
|
||||
.repo_owner("topgrade-rs")
|
||||
.repo_name("topgrade")
|
||||
.target(target)
|
||||
.bin_name(if cfg!(windows) {
|
||||
"topgrade-rs.exe"
|
||||
} else {
|
||||
"topgrade-rs"
|
||||
})
|
||||
.bin_name(if cfg!(windows) { "topgrade.exe" } else { "topgrade" })
|
||||
.show_output(false)
|
||||
.show_download_progress(true)
|
||||
.current_version(self_update_crate::cargo_crate_version!())
|
||||
|
||||
@@ -196,12 +196,16 @@ pub fn run_krew_upgrade(run_type: RunType) -> Result<()> {
|
||||
pub fn run_gcloud_components_update(run_type: RunType) -> Result<()> {
|
||||
let gcloud = utils::require("gcloud")?;
|
||||
|
||||
print_separator("gcloud");
|
||||
if gcloud.starts_with("/snap") {
|
||||
Ok(())
|
||||
} else {
|
||||
print_separator("gcloud");
|
||||
|
||||
run_type
|
||||
.execute(gcloud)
|
||||
.args(["components", "update", "--quiet"])
|
||||
.check_run()
|
||||
run_type
|
||||
.execute(gcloud)
|
||||
.args(["components", "update", "--quiet"])
|
||||
.check_run()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_jetpack(run_type: RunType) -> Result<()> {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use std::fmt::Display;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::prelude::MetadataExt;
|
||||
use std::path::PathBuf;
|
||||
@@ -17,24 +18,71 @@ use crate::terminal::print_separator;
|
||||
use crate::utils::{require, PathExt};
|
||||
use crate::{error::SkipStep, execution_context::ExecutionContext};
|
||||
|
||||
enum NPMVariant {
|
||||
Npm,
|
||||
Pnpm,
|
||||
}
|
||||
|
||||
impl NPMVariant {
|
||||
const fn long_name(&self) -> &str {
|
||||
match self {
|
||||
NPMVariant::Npm => "Node Package Manager",
|
||||
NPMVariant::Pnpm => "PNPM",
|
||||
}
|
||||
}
|
||||
|
||||
const fn short_name(&self) -> &str {
|
||||
match self {
|
||||
NPMVariant::Npm => "npm",
|
||||
NPMVariant::Pnpm => "pnpm",
|
||||
}
|
||||
}
|
||||
|
||||
const fn is_npm(&self) -> bool {
|
||||
matches!(self, NPMVariant::Npm)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for NPMVariant {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.short_name())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
struct NPM {
|
||||
command: PathBuf,
|
||||
variant: NPMVariant,
|
||||
}
|
||||
|
||||
impl NPM {
|
||||
fn new(command: PathBuf) -> Self {
|
||||
Self { command }
|
||||
fn new(command: PathBuf, variant: NPMVariant) -> Self {
|
||||
Self { command, variant }
|
||||
}
|
||||
|
||||
/// Is the “NPM” version larger than 8.11.0?
|
||||
fn is_npm_8(&self) -> bool {
|
||||
let v = self.version();
|
||||
|
||||
self.variant.is_npm() && matches!(v, Ok(v) if v >= Version::new(8, 11, 0))
|
||||
}
|
||||
|
||||
/// Get the most suitable “global location” argument
|
||||
/// of this NPM instance.
|
||||
///
|
||||
/// If the “NPM” version is larger than 8.11.0, we use
|
||||
/// `--location=global`; otherwise, use `-g`.
|
||||
fn global_location_arg(&self) -> &str {
|
||||
if self.is_npm_8() {
|
||||
"--location=global"
|
||||
} else {
|
||||
"-g"
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn root(&self) -> Result<PathBuf> {
|
||||
let version = self.version()?;
|
||||
let args = if version < Version::new(8, 11, 0) {
|
||||
["root", "-g"]
|
||||
} else {
|
||||
["root", "--location=global"]
|
||||
};
|
||||
let args = ["root", self.global_location_arg()];
|
||||
Command::new(&self.command)
|
||||
.args(args)
|
||||
.check_output()
|
||||
@@ -50,13 +98,8 @@ impl NPM {
|
||||
}
|
||||
|
||||
fn upgrade(&self, run_type: RunType, use_sudo: bool) -> Result<()> {
|
||||
print_separator("Node Package Manager");
|
||||
let version = self.version()?;
|
||||
let args = if version < Version::new(8, 11, 0) {
|
||||
["update", "-g"]
|
||||
} else {
|
||||
["update", "--location=global"]
|
||||
};
|
||||
print_separator(self.variant.long_name());
|
||||
let args = ["update", self.global_location_arg()];
|
||||
if use_sudo {
|
||||
run_type.execute("sudo").args(args).check_run()?;
|
||||
} else {
|
||||
@@ -70,7 +113,7 @@ impl NPM {
|
||||
pub fn should_use_sudo(&self) -> Result<bool> {
|
||||
let npm_root = self.root()?;
|
||||
if !npm_root.exists() {
|
||||
return Err(SkipStep(format!("NPM root at {} doesn't exist", npm_root.display(),)).into());
|
||||
return Err(SkipStep(format!("{} root at {} doesn't exist", self.variant, npm_root.display())).into());
|
||||
}
|
||||
|
||||
let metadata = std::fs::metadata(&npm_root)?;
|
||||
@@ -93,6 +136,17 @@ impl Yarn {
|
||||
}
|
||||
}
|
||||
|
||||
fn has_global_subcmd(&self) -> bool {
|
||||
// Get the version of Yarn. After Yarn 2.x (berry),
|
||||
// “yarn global” has been replaced with “yarn dlx”.
|
||||
//
|
||||
// As “yarn dlx” don't need to “upgrade”, we
|
||||
// ignore the whole task if Yarn is 2.x or above.
|
||||
let version = Command::new(&self.command).args(["--version"]).check_output();
|
||||
|
||||
matches!(version, Ok(ver) if ver.starts_with('1') || ver.starts_with('0'))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn root(&self) -> Result<PathBuf> {
|
||||
let args = ["global", "dir"];
|
||||
@@ -123,7 +177,7 @@ impl Yarn {
|
||||
pub fn should_use_sudo(&self) -> Result<bool> {
|
||||
let yarn_root = self.root()?;
|
||||
if !yarn_root.exists() {
|
||||
return Err(SkipStep(format!("NPM root at {} doesn't exist", yarn_root.display(),)).into());
|
||||
return Err(SkipStep(format!("Yarn root at {} doesn't exist", yarn_root.display(),)).into());
|
||||
}
|
||||
|
||||
let metadata = std::fs::metadata(&yarn_root)?;
|
||||
@@ -162,7 +216,7 @@ fn should_use_sudo_yarn(yarn: &Yarn, ctx: &ExecutionContext) -> Result<bool> {
|
||||
}
|
||||
|
||||
pub fn run_npm_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
let npm = require("pnpm").or_else(|_| require("npm")).map(NPM::new)?;
|
||||
let npm = require("npm").map(|b| NPM::new(b, NPMVariant::Npm))?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
@@ -175,9 +229,28 @@ pub fn run_npm_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_pnpm_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
let pnpm = require("pnpm").map(|b| NPM::new(b, NPMVariant::Pnpm))?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
pnpm.upgrade(ctx.run_type(), should_use_sudo(&pnpm, ctx)?)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
pnpm.upgrade(ctx.run_type(), false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_yarn_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
let yarn = require("yarn").map(Yarn::new)?;
|
||||
|
||||
if !yarn.has_global_subcmd() {
|
||||
debug!("Yarn is 2.x or above, skipping global upgrade");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
yarn.upgrade(ctx.run_type(), should_use_sudo_yarn(&yarn, ctx)?)
|
||||
|
||||
@@ -245,7 +245,7 @@ impl Aura {
|
||||
|
||||
impl ArchPackageManager for Aura {
|
||||
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
|
||||
let sudo = which("sudo").unwrap_or(PathBuf::new());
|
||||
let sudo = which("sudo").unwrap_or_else(PathBuf::new);
|
||||
let mut aur_update = ctx.run_type().execute(&sudo);
|
||||
|
||||
if sudo.ends_with("sudo") {
|
||||
|
||||
@@ -607,10 +607,12 @@ pub fn run_protonup_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn run_distrobox_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
let distrobox = require("distrobox")?;
|
||||
|
||||
print_separator("Distrobox");
|
||||
match (
|
||||
match (
|
||||
ctx.run_type().execute("distrobox").arg("upgrade"),
|
||||
ctx.run_type().execute(distrobox).arg("upgrade"),
|
||||
ctx.config().distrobox_containers(),
|
||||
) {
|
||||
(r, Some(c)) => {
|
||||
@@ -626,7 +628,8 @@ pub fn run_distrobox_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
(r, true) => r.arg("--root"),
|
||||
(r, false) => r,
|
||||
}
|
||||
.check_run()
|
||||
.check_run()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_config_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
|
||||
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
|
||||
NAME="Debian GNU/Linux"
|
||||
VERSION_ID="8"
|
||||
VERSION="8 (jessie)"
|
||||
VERSION_ID="11"
|
||||
VERSION="11 (bullseye)"
|
||||
VERSION_CODENAME=bullseye
|
||||
ID=debian
|
||||
HOME_URL="http://www.debian.org/"
|
||||
SUPPORT_URL="http://www.debian.org/support"
|
||||
HOME_URL="https://www.debian.org/"
|
||||
SUPPORT_URL="https://www.debian.org/support"
|
||||
BUG_REPORT_URL="https://bugs.debian.org/"
|
||||
|
||||
@@ -26,7 +26,7 @@ pub fn run_chocolatey(ctx: &ExecutionContext) -> Result<()> {
|
||||
args.insert(0, "choco");
|
||||
}
|
||||
|
||||
let mut command = ctx.run_type().execute(&cmd);
|
||||
let mut command = ctx.run_type().execute(cmd);
|
||||
|
||||
command.args(&args);
|
||||
|
||||
@@ -47,7 +47,7 @@ pub fn run_winget(ctx: &ExecutionContext) -> Result<()> {
|
||||
return Err(SkipStep(String::from("Winget is disabled by default")).into());
|
||||
}
|
||||
|
||||
ctx.run_type().execute(&winget).args(&["upgrade", "--all"]).check_run()
|
||||
ctx.run_type().execute(&winget).args(["upgrade", "--all"]).check_run()
|
||||
}
|
||||
|
||||
pub fn run_scoop(cleanup: bool, run_type: RunType) -> Result<()> {
|
||||
@@ -55,34 +55,34 @@ pub fn run_scoop(cleanup: bool, run_type: RunType) -> Result<()> {
|
||||
|
||||
print_separator("Scoop");
|
||||
|
||||
run_type.execute(&scoop).args(&["update"]).check_run()?;
|
||||
run_type.execute(&scoop).args(&["update", "*"]).check_run()?;
|
||||
run_type.execute(&scoop).args(["update"]).check_run()?;
|
||||
run_type.execute(&scoop).args(["update", "*"]).check_run()?;
|
||||
|
||||
if cleanup {
|
||||
run_type.execute(&scoop).args(&["cleanup", "*"]).check_run()?;
|
||||
run_type.execute(&scoop).args(["cleanup", "*"]).check_run()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_wsl_distributions(wsl: &Path) -> Result<Vec<String>> {
|
||||
let output = Command::new(wsl).args(&["--list", "-q"]).check_output()?;
|
||||
let output = Command::new(wsl).args(["--list", "-q"]).check_output()?;
|
||||
Ok(output
|
||||
.lines()
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|x| x.replace('\u{0}', "").replace('\r', ""))
|
||||
.map(|x| x.replace(['\u{0}', '\r'], ""))
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn upgrade_wsl_distribution(wsl: &Path, dist: &str, ctx: &ExecutionContext) -> Result<()> {
|
||||
let topgrade = Command::new(&wsl)
|
||||
.args(&["-d", dist, "bash", "-lc", "which topgrade"])
|
||||
let topgrade = Command::new(wsl)
|
||||
.args(["-d", dist, "bash", "-lc", "which topgrade"])
|
||||
.check_output()
|
||||
.map_err(|_| SkipStep(String::from("Could not find Topgrade installed in WSL")))?;
|
||||
|
||||
let mut command = ctx.run_type().execute(&wsl);
|
||||
let mut command = ctx.run_type().execute(wsl);
|
||||
command
|
||||
.args(&["-d", dist, "bash", "-c"])
|
||||
.args(["-d", dist, "bash", "-c"])
|
||||
.arg(format!("TOPGRADE_PREFIX={} exec {}", dist, topgrade));
|
||||
|
||||
if ctx.config().yes(Step::Wsl) {
|
||||
@@ -134,7 +134,7 @@ pub fn windows_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn reboot() {
|
||||
Command::new("shutdown").args(&["/R", "/T", "0"]).spawn().ok();
|
||||
Command::new("shutdown").args(["/R", "/T", "0"]).spawn().ok();
|
||||
}
|
||||
|
||||
pub fn insert_startup_scripts(ctx: &ExecutionContext, git_repos: &mut Repositories) -> Result<()> {
|
||||
|
||||
@@ -46,8 +46,8 @@ impl Powershell {
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn has_module(powershell: &Path, command: &str) -> bool {
|
||||
Command::new(&powershell)
|
||||
.args(&[
|
||||
Command::new(powershell)
|
||||
.args([
|
||||
"-NoProfile",
|
||||
"-Command",
|
||||
&format!("Get-Module -ListAvailable {}", command),
|
||||
@@ -79,6 +79,7 @@ impl Powershell {
|
||||
println!("Updating modules...");
|
||||
ctx.run_type()
|
||||
.execute(powershell)
|
||||
// This probably doesn't need `shell_words::join`.
|
||||
.args(["-NoProfile", "-Command", &cmd.join(" ")])
|
||||
.check_run()
|
||||
}
|
||||
@@ -99,14 +100,14 @@ impl Powershell {
|
||||
|
||||
let mut command = if let Some(sudo) = ctx.sudo() {
|
||||
let mut command = ctx.run_type().execute(sudo);
|
||||
command.arg(&powershell);
|
||||
command.arg(powershell);
|
||||
command
|
||||
} else {
|
||||
ctx.run_type().execute(&powershell)
|
||||
ctx.run_type().execute(powershell)
|
||||
};
|
||||
|
||||
command
|
||||
.args(&[
|
||||
.args([
|
||||
"-NoProfile",
|
||||
"-Command",
|
||||
&format!(
|
||||
|
||||
@@ -24,7 +24,7 @@ pub fn ssh_step(ctx: &ExecutionContext, hostname: &str) -> Result<()> {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
prepare_async_ssh_command(&mut args);
|
||||
crate::tmux::run_command(ctx, &args.join(" "))?;
|
||||
crate::tmux::run_command(ctx, &shell_words::join(args))?;
|
||||
Err(SkipStep(String::from("Remote Topgrade launched in Tmux")).into())
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,10 @@ struct Tmux {
|
||||
}
|
||||
|
||||
impl Tmux {
|
||||
fn new(args: &Option<String>) -> Self {
|
||||
fn new(args: Vec<String>) -> Self {
|
||||
Self {
|
||||
tmux: which("tmux").expect("Could not find tmux"),
|
||||
args: args
|
||||
.as_ref()
|
||||
.map(|args| args.split_whitespace().map(String::from).collect()),
|
||||
args: if args.is_empty() { None } else { Some(args) },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +73,7 @@ impl Tmux {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_in_tmux(args: &Option<String>) -> ! {
|
||||
pub fn run_in_tmux(args: Vec<String>) -> ! {
|
||||
let command = {
|
||||
let mut command = vec![
|
||||
String::from("env"),
|
||||
@@ -83,7 +81,7 @@ pub fn run_in_tmux(args: &Option<String>) -> ! {
|
||||
String::from("TOPGRADE_INSIDE_TMUX=1"),
|
||||
];
|
||||
command.extend(env::args());
|
||||
command.join(" ")
|
||||
shell_words::join(command)
|
||||
};
|
||||
|
||||
let tmux = Tmux::new(args);
|
||||
@@ -108,7 +106,7 @@ pub fn run_in_tmux(args: &Option<String>) -> ! {
|
||||
}
|
||||
|
||||
pub fn run_command(ctx: &ExecutionContext, command: &str) -> Result<()> {
|
||||
Tmux::new(ctx.config().tmux_arguments())
|
||||
Tmux::new(ctx.config().tmux_arguments()?)
|
||||
.build()
|
||||
.args(["new-window", "-a", "-t", "topgrade:1", command])
|
||||
.env_remove("TMUX")
|
||||
|
||||
Reference in New Issue
Block a user