Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion sqlx-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ clap_complete = { version = "4.3.1", optional = true }
chrono = { version = "0.4.34", default-features = false, features = ["clock"] }
anyhow = "1.0.58"
console = "0.15.0"
dialoguer = { version = "0.11", default-features = false }
serde_json = "1.0.142"
glob = "0.3.0"
openssl = { version = "0.10.46", optional = true }
Expand Down
62 changes: 23 additions & 39 deletions sqlx-cli/src/database.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::opt::{ConnectOpts, MigrationSourceOpt};
use crate::{migrate, Config};
use console::{style, Term};
use dialoguer::Confirm;
use console::style;
use sqlx::any::Any;
use sqlx::migrate::MigrateDatabase;
use std::{io, mem};
use std::io::{self, BufRead, Write};
use tokio::task;

pub async fn create(connect_opts: &ConnectOpts) -> anyhow::Result<()> {
Expand Down Expand Up @@ -75,45 +74,30 @@ pub async fn setup(
}

async fn ask_to_continue_drop(db_url: String) -> bool {
// If the setup operation is cancelled while we are waiting for the user to decide whether
// or not to drop the database, this will restore the terminal's cursor to its normal state.
struct RestoreCursorGuard {
disarmed: bool,
}

impl Drop for RestoreCursorGuard {
fn drop(&mut self) {
if !self.disarmed {
Term::stderr().show_cursor().unwrap()
}
}
}
// Plain line-based prompt rather than dialoguer::Confirm. dialoguer puts
// the terminal into raw mode for the y/N toggle even with
// wait_for_newline(true), which means keypresses never echo and the whole
// prompt gets repainted on every flip. That's confusing in general and
// hostile to screen-reader users (#4236). Reading a line of stdin echoes
// input the way users expect and doesn't need a cursor-restore guard.
let prompt = format!("Drop database at {}? (y/N): ", style(&db_url).cyan());

let mut guard = RestoreCursorGuard { disarmed: false };
let decision = task::spawn_blocking(move || -> io::Result<bool> {
let mut stderr = io::stderr().lock();
stderr.write_all(prompt.as_bytes())?;
stderr.flush()?;

let decision_result = task::spawn_blocking(move || {
Confirm::new()
.with_prompt(format!("Drop database at {}?", style(&db_url).cyan()))
.wait_for_newline(true)
.default(false)
.show_default(true)
.interact()
let mut line = String::new();
io::stdin().lock().read_line(&mut line)?;
let answer = line.trim();
Ok(answer.eq_ignore_ascii_case("y") || answer.eq_ignore_ascii_case("yes"))
})
.await
.expect("Confirm thread panicked");
match decision_result {
Ok(decision) => {
guard.disarmed = true;
decision
}
Err(dialoguer::Error::IO(err)) if err.kind() == io::ErrorKind::Interrupted => {
// Sometimes CTRL + C causes this error to be returned
mem::drop(guard);
false
}
Err(err) => {
mem::drop(guard);
panic!("Confirm dialog failed with {err}")
}
.expect("drop-confirm thread panicked");

match decision {
Ok(d) => d,
Err(err) if err.kind() == io::ErrorKind::Interrupted => false,
Err(err) => panic!("Confirm dialog failed with {err}"),
}
}
2 changes: 0 additions & 2 deletions sqlx-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ pub fn maybe_apply_dotenv() {
pub async fn run(opt: Opt) -> anyhow::Result<()> {
// This `select!` is here so that when the process receives a `SIGINT` (CTRL + C),
// the futures currently running on this task get dropped before the program exits.
// This is currently necessary for the consumers of the `dialoguer` crate to restore
// the user's terminal if the process is interrupted while a dialog is being displayed.

let ctrlc_fut = signal::ctrl_c();
let do_run_fut = do_run(opt);
Expand Down