Fixup Mac curl $URL | sudo sh -s
(#99)
* Fixup Mac curl sh * We not longer require sudo for the script
This commit is contained in:
parent
0e4fcd3c3b
commit
fe83b35199
39
Cargo.lock
generated
39
Cargo.lock
generated
|
@ -492,6 +492,16 @@ dependencies = [
|
||||||
"dirs-sys",
|
"dirs-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-next"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"dirs-sys-next",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys"
|
name = "dirs-sys"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -503,6 +513,17 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys-next"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dyn-clone"
|
name = "dyn-clone"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
|
@ -805,6 +826,7 @@ dependencies = [
|
||||||
"sxd-xpath",
|
"sxd-xpath",
|
||||||
"tar",
|
"tar",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
|
"term",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
|
@ -1595,6 +1617,12 @@ dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -1859,6 +1887,17 @@ version = "0.12.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
|
checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "term"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-next",
|
||||||
|
"rustversion",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
|
|
@ -57,6 +57,7 @@ typetag = "0.2.3"
|
||||||
dyn-clone = "1.0.9"
|
dyn-clone = "1.0.9"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
semver = { version = "1.0.14", features = ["serde"] }
|
semver = { version = "1.0.14", features = ["serde"] }
|
||||||
|
term = "0.7.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
|
|
|
@ -7,7 +7,7 @@ Harmonic is an opinionated, experimental Nix installer.
|
||||||
> Try it on a machine/VM you don't care about!
|
> Try it on a machine/VM you don't care about!
|
||||||
>
|
>
|
||||||
> ```bash
|
> ```bash
|
||||||
> curl -L https://install.determinate.systems/nix | sudo sh -s -- install
|
> curl -L https://install.determinate.systems/nix | sh -s -- install
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
|
@ -93,6 +93,11 @@ main() {
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local maybe_sudo=""
|
||||||
|
if [ "$EUID" -ne 0 ] && command -v sudo > /dev/null; then
|
||||||
|
maybe_sudo="sudo"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$need_tty" = "yes" ] && [ ! -t 0 ]; then
|
if [ "$need_tty" = "yes" ] && [ ! -t 0 ]; then
|
||||||
# The installer is going to want to ask for confirmation by
|
# The installer is going to want to ask for confirmation by
|
||||||
# reading stdin. This script was piped into `sh` though and
|
# reading stdin. This script was piped into `sh` though and
|
||||||
|
@ -102,9 +107,9 @@ main() {
|
||||||
err "Unable to run interactively. Run with -y to accept defaults, --help for additional options"
|
err "Unable to run interactively. Run with -y to accept defaults, --help for additional options"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ignore "$_file" "$@" < /dev/tty
|
ignore "$maybe_sudo" "$_file" "$@" < /dev/tty
|
||||||
else
|
else
|
||||||
ignore "$_file" "$@"
|
ignore "$maybe_sudo" "$_file" "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local _retval=$?
|
local _retval=$?
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
|
use std::io::{stdin, stdout, BufRead, Write};
|
||||||
|
|
||||||
use crossterm::event::{EventStream, KeyCode};
|
use crossterm::event::{EventStream, KeyCode};
|
||||||
use eyre::{eyre, WrapErr};
|
use eyre::{eyre, WrapErr};
|
||||||
use futures::{FutureExt, StreamExt};
|
use futures::{FutureExt, StreamExt};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use tokio::io::AsyncWriteExt;
|
|
||||||
|
|
||||||
pub(crate) async fn confirm(question: impl AsRef<str>) -> eyre::Result<bool> {
|
// Do not try to get clever!
|
||||||
let mut stdout = tokio::io::stdout();
|
//
|
||||||
|
// Mac is extremely janky if you `curl $URL | sudo sh` and the TTY may not be set up right.
|
||||||
|
// The below method was adopted from Rustup at https://github.com/rust-lang/rustup/blob/3331f34c01474bf216c99a1b1706725708833de1/src/cli/term2.rs#L37
|
||||||
|
pub(crate) async fn confirm(question: impl AsRef<str>, default: bool) -> eyre::Result<bool> {
|
||||||
|
let stdout = stdout();
|
||||||
|
let mut term =
|
||||||
|
term::terminfo::TerminfoTerminal::new(stdout).ok_or(eyre!("Couldn't get terminal"))?;
|
||||||
let with_confirm = format!(
|
let with_confirm = format!(
|
||||||
"\
|
"\
|
||||||
{question}\n\
|
{question}\n\
|
||||||
|
@ -18,42 +25,31 @@ pub(crate) async fn confirm(question: impl AsRef<str>) -> eyre::Result<bool> {
|
||||||
yes = "y".green(),
|
yes = "y".green(),
|
||||||
);
|
);
|
||||||
|
|
||||||
stdout.write_all(with_confirm.as_bytes()).await?;
|
term.write_all(with_confirm.as_bytes())?;
|
||||||
stdout.flush().await?;
|
term.flush()?;
|
||||||
|
|
||||||
// crossterm::terminal::enable_raw_mode()?;
|
let input = read_line()?;
|
||||||
let mut reader = EventStream::new();
|
|
||||||
|
|
||||||
let retval = loop {
|
let r = match &*input.to_lowercase() {
|
||||||
let event = reader.next().fuse().await;
|
"y" | "yes" => true,
|
||||||
match event {
|
"n" | "no" => false,
|
||||||
Some(Ok(event)) => {
|
"" => default,
|
||||||
if let crossterm::event::Event::Key(key) = event {
|
_ => false,
|
||||||
match key.code {
|
|
||||||
KeyCode::Char('y') | KeyCode::Char('Y') => {
|
|
||||||
stdout
|
|
||||||
.write_all("Confirmed!\n".green().to_string().as_bytes())
|
|
||||||
.await?;
|
|
||||||
stdout.flush().await?;
|
|
||||||
break Ok(true);
|
|
||||||
},
|
|
||||||
KeyCode::Char('N') | KeyCode::Char('n') => {
|
|
||||||
stdout
|
|
||||||
.write_all("Cancelled!\n".red().to_string().as_bytes())
|
|
||||||
.await?;
|
|
||||||
stdout.flush().await?;
|
|
||||||
break Ok(false);
|
|
||||||
},
|
|
||||||
KeyCode::Enter | _ => continue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(Err(err)) => break Err(err).wrap_err("Getting response"),
|
|
||||||
None => break Err(eyre!("Bailed, no confirmation event")),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// crossterm::terminal::disable_raw_mode()?;
|
|
||||||
retval
|
Ok(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_line() -> eyre::Result<String> {
|
||||||
|
let stdin = stdin();
|
||||||
|
let stdin = stdin.lock();
|
||||||
|
let mut lines = stdin.lines();
|
||||||
|
let lines = lines.next().transpose()?;
|
||||||
|
match lines {
|
||||||
|
None => Err(eyre!("no lines found from stdin")),
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
}
|
||||||
|
.context("unable to read from stdin for confirmation")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn clean_exit_with_message(message: impl AsRef<str>) -> ! {
|
pub(crate) async fn clean_exit_with_message(message: impl AsRef<str>) -> ! {
|
||||||
|
|
|
@ -111,6 +111,7 @@ impl CommandExecute for Install {
|
||||||
install_plan
|
install_plan
|
||||||
.describe_install(explain)
|
.describe_install(explain)
|
||||||
.map_err(|e| eyre!(e))?,
|
.map_err(|e| eyre!(e))?,
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -128,6 +129,7 @@ impl CommandExecute for Install {
|
||||||
install_plan
|
install_plan
|
||||||
.describe_uninstall(explain)
|
.describe_uninstall(explain)
|
||||||
.map_err(|e| eyre!(e))?,
|
.map_err(|e| eyre!(e))?,
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,8 +53,11 @@ impl CommandExecute for Uninstall {
|
||||||
let mut plan: InstallPlan = serde_json::from_str(&install_receipt_string)?;
|
let mut plan: InstallPlan = serde_json::from_str(&install_receipt_string)?;
|
||||||
|
|
||||||
if !no_confirm {
|
if !no_confirm {
|
||||||
if !interaction::confirm(plan.describe_uninstall(explain).map_err(|e| eyre!(e))?)
|
if !interaction::confirm(
|
||||||
.await?
|
plan.describe_uninstall(explain).map_err(|e| eyre!(e))?,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
{
|
{
|
||||||
interaction::clean_exit_with_message("Okay, didn't do anything! Bye!").await;
|
interaction::clean_exit_with_message("Okay, didn't do anything! Bye!").await;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue