Compare commits
10 Commits
renovate/i
...
renovate/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed59b3c261 | ||
|
|
9ec8e83f41 | ||
|
|
c70984d458 | ||
|
|
a3503c0c70 | ||
|
|
ca2d16edfd | ||
|
|
722b1ad09e | ||
|
|
743845a66b | ||
|
|
2594f4c0fb | ||
|
|
639d055f9a | ||
|
|
ea2ccdd69f |
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!
|
before filing a new one!
|
||||||
|
|
||||||
Questions labeled with `Optional` can be skipped.
|
Questions labeled with `Optional` can be skipped.
|
||||||
-->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If you're here to report about a "No asset found" error, please make sure that
|
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.
|
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
|
## Erroneous Behavior
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
What actually happened?
|
What actually happened?
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Expected Behavior
|
## Expected Behavior
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Describe the expected behavior
|
Describe the expected behavior.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Steps to reproduce
|
## Steps to reproduce
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
A minimal example to reproduce the issue
|
A minimal example to reproduce the issue.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Possible Cause (Optional)
|
## Possible Cause (Optional)
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
If you know the possible cause of the issue, please tell us.
|
If you know the possible cause of the issue, please tell us.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Problem persists without calling from topgrade
|
## 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
|
- [ ] Yes
|
||||||
- [ ] No
|
- [ ] No
|
||||||
|
|
||||||
## Did you run topgrade through `Remote Execution`
|
## Ran through `Remote Execution`
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Did you run topgrade through `Remote Execution`?
|
||||||
|
-->
|
||||||
|
|
||||||
- [ ] Yes
|
- [ ] Yes
|
||||||
- [ ] No
|
- [ ] No
|
||||||
|
|
||||||
If yes, does the issue still occur when you run topgrade directly in your
|
If yes, does the issue still occur when you run topgrade directly in your
|
||||||
remote host
|
remote host?
|
||||||
|
|
||||||
- [ ] Yes
|
- [ ] Yes
|
||||||
- [ ] No
|
- [ ] No
|
||||||
|
|
||||||
## Configuration file (Optional)
|
## Configuration file (Optional)
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Paste your configuration file inside the code block if you think this issue is
|
Paste your configuration file inside the code block if you think this issue is
|
||||||
related to configuration.
|
related to configuration.
|
||||||
@@ -70,6 +83,7 @@ related to configuration.
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Additional Details
|
## Additional Details
|
||||||
|
|
||||||
- Operation System/Version
|
- Operation System/Version
|
||||||
<!-- For example, Fedora Linux 38 -->
|
<!-- For example, Fedora Linux 38 -->
|
||||||
|
|
||||||
@@ -82,6 +96,7 @@ related to configuration.
|
|||||||
- Topgrade version (`topgrade -V`)
|
- Topgrade version (`topgrade -V`)
|
||||||
|
|
||||||
## Verbose Output (`topgrade -v`)
|
## Verbose Output (`topgrade -v`)
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Paste the verbose output into the pre-tags
|
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
|
name: General feature request
|
||||||
about: Can you please support...?
|
about: Suggest a general feature, or feature within an already existing step
|
||||||
title: ''
|
title: ''
|
||||||
labels: 'C-feature request'
|
labels: C-feature request
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## I want to suggest a new step
|
## Checklist
|
||||||
|
|
||||||
* Which tool is this about? Where is its repository?
|
- [ ] I have searched the issue tracker for relevant or duplicate issues.
|
||||||
* 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 want to suggest some general feature
|
## I want to suggest some general feature
|
||||||
|
|
||||||
@@ -25,3 +19,5 @@ Topgrade should...
|
|||||||
|
|
||||||
<!-- Assuming that someone else implements the feature,
|
<!-- Assuming that someone else implements the feature,
|
||||||
please state if you know how to test it from a side branch of Topgrade. -->
|
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
|
||||||
@@ -32,6 +32,6 @@ jobs:
|
|||||||
uses: microsoft/DevSkim-Action@4b5047945a44163b94642a1cecc0d93a3f428cc6 # v1.0.16
|
uses: microsoft/DevSkim-Action@4b5047945a44163b94642a1cecc0d93a3f428cc6 # v1.0.16
|
||||||
|
|
||||||
- name: Upload DevSkim scan results to GitHub Security tab
|
- name: Upload DevSkim scan results to GitHub Security tab
|
||||||
uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
|
uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3
|
||||||
with:
|
with:
|
||||||
sarif_file: devskim-results.sarif
|
sarif_file: devskim-results.sarif
|
||||||
|
|||||||
3
.github/workflows/lint_pr.yml
vendored
3
.github/workflows/lint_pr.yml
vendored
@@ -1,11 +1,12 @@
|
|||||||
name: 'Lint PR'
|
name: 'Lint PR'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target: # zizmor: ignore[dangerous-triggers] this is the only way, and we're not running user code
|
||||||
types:
|
types:
|
||||||
- opened
|
- opened
|
||||||
- edited
|
- edited
|
||||||
- reopened
|
- reopened
|
||||||
|
- synchronize
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
main:
|
||||||
|
|||||||
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.
|
# Upload the results to GitHub's code scanning dashboard.
|
||||||
- name: "Upload to code-scanning"
|
- name: "Upload to code-scanning"
|
||||||
uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
|
uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/gitleaks/gitleaks
|
- repo: https://github.com/gitleaks/gitleaks
|
||||||
rev: v8.28.0
|
rev: v8.29.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: gitleaks
|
- id: gitleaks
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ repos:
|
|||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
|
|
||||||
- repo: https://github.com/crate-ci/typos
|
- repo: https://github.com/crate-ci/typos
|
||||||
rev: v1.38.1
|
rev: v1.39.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: typos
|
- id: typos
|
||||||
|
|
||||||
|
|||||||
544
Cargo.lock
generated
544
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
32
Cargo.toml
32
Cargo.toml
@@ -14,32 +14,31 @@ edition = "2021"
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
home = "~0.5,<0.5.11"
|
home = "=0.5.11"
|
||||||
etcetera = "~0.8"
|
etcetera = "=0.10.0"
|
||||||
serde = { version = "~1.0", features = ["derive"] }
|
serde = { version = "~1.0", features = ["derive"] }
|
||||||
toml = "0.8"
|
toml = "=0.9.8"
|
||||||
which_crate = { version = "~6.0", package = "which" }
|
which_crate = { version = "~8.0", package = "which" }
|
||||||
shellexpand = "~3.1"
|
shellexpand = "~3.1"
|
||||||
clap = { version = "~4.5", features = ["cargo", "derive"] }
|
clap = { version = "~4.5", features = ["cargo", "derive"] }
|
||||||
clap_complete = "~4.5"
|
clap_complete = "~4.5"
|
||||||
clap_mangen = "~0.2"
|
clap_mangen = "~0.2"
|
||||||
walkdir = "~2.5"
|
walkdir = "~2.5"
|
||||||
console = "~0.15"
|
console = "~0.16"
|
||||||
chrono = "~0.4"
|
chrono = "~0.4"
|
||||||
glob = "~0.3"
|
glob = "~0.3"
|
||||||
strum = { version = "~0.26", features = ["derive"] }
|
strum = { version = "~0.27", features = ["derive"] }
|
||||||
thiserror = "~1.0"
|
thiserror = "~2.0"
|
||||||
tempfile = "~3.10"
|
tempfile = "~3.23"
|
||||||
cfg-if = "~1.0"
|
tokio = { version = "~1.48", features = ["process", "rt-multi-thread"] }
|
||||||
tokio = { version = "~1.47", features = ["process", "rt-multi-thread"] }
|
|
||||||
futures = "~0.3"
|
futures = "~0.3"
|
||||||
regex = "~1.10"
|
regex = "~1.12"
|
||||||
semver = "~1.0"
|
semver = "~1.0"
|
||||||
shell-words = "~1.1"
|
shell-words = "~1.1"
|
||||||
color-eyre = "~0.6"
|
color-eyre = "~0.6"
|
||||||
tracing = { version = "~0.1", features = ["attributes", "log"] }
|
tracing = { version = "~0.1", features = ["attributes", "log"] }
|
||||||
tracing-subscriber = { version = "~0.3.20", features = ["env-filter", "time"] }
|
tracing-subscriber = { version = "~0.3.20", features = ["env-filter", "time"] }
|
||||||
merge = "~0.1"
|
merge = "~0.2.0"
|
||||||
regex-split = "~0.1"
|
regex-split = "~0.1"
|
||||||
notify-rust = "~4.11"
|
notify-rust = "~4.11"
|
||||||
wildmatch = "2.3.0"
|
wildmatch = "2.3.0"
|
||||||
@@ -53,6 +52,9 @@ ignore = "=0.4.23"
|
|||||||
globset = "=0.4.16"
|
globset = "=0.4.16"
|
||||||
base64ct = "<1.8.0"
|
base64ct = "<1.8.0"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
mac-notification-sys = { git = "https://github.com/h4llow3En/mac-notification-sys" }
|
||||||
|
|
||||||
[package.metadata.generate-rpm]
|
[package.metadata.generate-rpm]
|
||||||
assets = [{ source = "target/release/topgrade", dest = "/usr/bin/topgrade" }]
|
assets = [{ source = "target/release/topgrade", dest = "/usr/bin/topgrade" }]
|
||||||
|
|
||||||
@@ -81,14 +83,14 @@ assets = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
nix = { version = "~0.29", features = ["hostname", "signal", "user"] }
|
nix = { version = "~0.30", features = ["hostname", "signal", "user"] }
|
||||||
rust-ini = "~0.21"
|
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]
|
[target.'cfg(windows)'.dependencies]
|
||||||
is_elevated = "~0.1"
|
is_elevated = "~0.1"
|
||||||
parselnk = "~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 = { version = "~0.62", features = ["Win32_System_Console"] }
|
||||||
windows-registry = "~0.6"
|
windows-registry = "~0.6"
|
||||||
|
|
||||||
|
|||||||
15
src/main.rs
15
src/main.rs
@@ -12,7 +12,6 @@ use clap::{crate_version, Parser};
|
|||||||
use color_eyre::eyre::Context;
|
use color_eyre::eyre::Context;
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use console::Key;
|
use console::Key;
|
||||||
use etcetera::base_strategy::BaseStrategy;
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use etcetera::base_strategy::Windows;
|
use etcetera::base_strategy::Windows;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@@ -209,7 +208,19 @@ fn run() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for step in step::default_steps() {
|
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;
|
let mut failed = false;
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::{Result, WrapErr};
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::io;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::ctrlc;
|
use crate::ctrlc;
|
||||||
use crate::error::{DryRun, MissingSudo, SkipStep};
|
use crate::error::{DryRun, MissingSudo, SkipStep};
|
||||||
use crate::execution_context::ExecutionContext;
|
use crate::execution_context::ExecutionContext;
|
||||||
use crate::step::Step;
|
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 {
|
pub enum StepResult {
|
||||||
Success,
|
Success,
|
||||||
@@ -98,12 +99,13 @@ impl<'a> Runner<'a> {
|
|||||||
let should_ask = interrupted || !(self.ctx.config().no_retry() || ignore_failure);
|
let should_ask = interrupted || !(self.ctx.config().no_retry() || ignore_failure);
|
||||||
let should_retry = if should_ask {
|
let should_retry = if should_ask {
|
||||||
print_error(&key, format!("{e:?}"));
|
print_error(&key, format!("{e:?}"));
|
||||||
should_retry(interrupted, key.as_ref())?
|
should_retry(key.as_ref())?
|
||||||
} else {
|
} else {
|
||||||
false
|
ShouldRetry::No
|
||||||
};
|
};
|
||||||
|
|
||||||
if !should_retry {
|
match should_retry {
|
||||||
|
ShouldRetry::No | ShouldRetry::Quit => {
|
||||||
self.push_result(
|
self.push_result(
|
||||||
key,
|
key,
|
||||||
if ignore_failure {
|
if ignore_failure {
|
||||||
@@ -112,8 +114,14 @@ impl<'a> Runner<'a> {
|
|||||||
StepResult::Failure
|
StepResult::Failure
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
if let ShouldRetry::Quit = should_retry {
|
||||||
|
return Err(io::Error::from(io::ErrorKind::Interrupted))
|
||||||
|
.context("Quit from user input");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ShouldRetry::Yes => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,6 +282,17 @@ pub fn run_elan(ctx: &ExecutionContext) -> Result<()> {
|
|||||||
|
|
||||||
print_separator("elan");
|
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 disabled_error_msg = "self-update is disabled";
|
||||||
let executor_output = ctx.execute(&elan).args(["self", "update"]).output()?;
|
let executor_output = ctx.execute(&elan).args(["self", "update"]).output()?;
|
||||||
match executor_output {
|
match executor_output {
|
||||||
@@ -310,7 +321,12 @@ pub fn run_elan(ctx: &ExecutionContext) -> Result<()> {
|
|||||||
ExecutorOutput::Dry => { /* nothing needed because in a dry run */ }
|
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<()> {
|
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<()> {
|
pub fn run_tlmgr_update(ctx: &ExecutionContext) -> Result<()> {
|
||||||
cfg_if::cfg_if! {
|
if cfg!(any(target_os = "linux", target_os = "android")) && !ctx.config().enable_tlmgr_linux() {
|
||||||
if #[cfg(any(target_os = "linux", target_os = "android"))] {
|
return Err(SkipStep(String::from(
|
||||||
if !ctx.config().enable_tlmgr_linux() {
|
"tlmgr must be explicitly enabled in the configuration to run in Android/Linux",
|
||||||
return Err(SkipStep(String::from("tlmgr must be explicitly enabled in the configuration to run in Android/Linux")).into());
|
))
|
||||||
}
|
.into());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let tlmgr = require("tlmgr")?;
|
let tlmgr = require("tlmgr")?;
|
||||||
@@ -983,25 +998,21 @@ pub fn run_composer_update(ctx: &ExecutionContext) -> Result<()> {
|
|||||||
print_separator(t!("Composer"));
|
print_separator(t!("Composer"));
|
||||||
|
|
||||||
if ctx.config().composer_self_update() {
|
if ctx.config().composer_self_update() {
|
||||||
cfg_if::cfg_if! {
|
if cfg!(unix) {
|
||||||
if #[cfg(unix)] {
|
|
||||||
// If self-update fails without sudo then there's probably an update
|
// If self-update fails without sudo then there's probably an update
|
||||||
let has_update = match ctx.execute(&composer).arg("self-update").output()? {
|
let has_update = match ctx.execute(&composer).arg("self-update").output()? {
|
||||||
ExecutorOutput::Wet(output) => !output.status.success(),
|
ExecutorOutput::Wet(output) => !output.status.success(),
|
||||||
_ => false
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if has_update {
|
if has_update {
|
||||||
let sudo = ctx.require_sudo()?;
|
let sudo = ctx.require_sudo()?;
|
||||||
sudo.execute(ctx, &composer)?
|
sudo.execute(ctx, &composer)?.arg("self-update").status_checked()?;
|
||||||
.arg("self-update")
|
|
||||||
.status_checked()?;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.execute(&composer).arg("self-update").status_checked()?;
|
ctx.execute(&composer).arg("self-update").status_checked()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let output = ctx.execute(&composer).args(["global", "update"]).output()?;
|
let output = ctx.execute(&composer).args(["global", "update"]).output()?;
|
||||||
if let ExecutorOutput::Wet(output) = output {
|
if let ExecutorOutput::Wet(output) = output {
|
||||||
|
|||||||
@@ -201,10 +201,11 @@ impl Terminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[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() {
|
if self.width.is_none() {
|
||||||
return Ok(false);
|
return Ok(ShouldRetry::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.set_title {
|
if self.set_title {
|
||||||
@@ -223,7 +224,7 @@ impl Terminal {
|
|||||||
|
|
||||||
let answer = loop {
|
let answer = loop {
|
||||||
match self.term.read_key() {
|
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')) => {
|
Ok(Key::Char('s' | 'S')) => {
|
||||||
println!(
|
println!(
|
||||||
"\n\n{}\n",
|
"\n\n{}\n",
|
||||||
@@ -232,16 +233,16 @@ impl Terminal {
|
|||||||
if let Err(err) = run_shell().context("Failed to run shell") {
|
if let Err(err) = run_shell().context("Failed to run shell") {
|
||||||
self.term.write_fmt(format_args!("{err:?}\n{prompt_inner}")).ok();
|
self.term.write_fmt(format_args!("{err:?}\n{prompt_inner}")).ok();
|
||||||
} else {
|
} 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) => {
|
Err(e) => {
|
||||||
error!("Error reading from terminal: {}", e);
|
error!("Error reading from terminal: {}", e);
|
||||||
break Ok(false);
|
break Ok(ShouldRetry::No);
|
||||||
}
|
}
|
||||||
Ok(Key::Char('q' | 'Q')) => {
|
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 {
|
impl Default for Terminal {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn should_retry(interrupted: bool, step_name: &str) -> eyre::Result<bool> {
|
pub fn should_retry(step_name: &str) -> eyre::Result<ShouldRetry> {
|
||||||
TERMINAL.lock().unwrap().should_retry(interrupted, step_name)
|
TERMINAL.lock().unwrap().should_retry(step_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_separator<P: AsRef<str>>(message: P) {
|
pub fn print_separator<P: AsRef<str>>(message: P) {
|
||||||
|
|||||||
Reference in New Issue
Block a user