From cee01f171a505cc91dcfa2f1ecb9c9f6e2a9bd17 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 7 Jul 2018 12:51:32 +0200 Subject: Move prompt facility from bpkg to libbutl --- bpkg/utility.cxx | 43 +++++++++---------------------------------- bpkg/utility.hxx | 10 +++++----- tests/rep-auth.test | 8 ++++---- 3 files changed, 18 insertions(+), 43 deletions(-) diff --git a/bpkg/utility.cxx b/bpkg/utility.cxx index 8a456d0..c6f2fae 100644 --- a/bpkg/utility.cxx +++ b/bpkg/utility.cxx @@ -6,6 +6,7 @@ #include // cout, cin +#include #include #include @@ -85,42 +86,16 @@ namespace bpkg bool stderr_term; bool - yn_prompt (const char* prompt, char def) + yn_prompt (const string& p, char d) { - // Writing a robust Y/N prompt is more difficult than one would - // expect... - // - string a; - do + try { - *diag_stream << prompt << ' '; - - // getline() will set the failbit if it failed to extract anything, - // not even the delimiter and eofbit if it reached eof before seeing - // the delimiter. - // - getline (cin, a); - - bool f (cin.fail ()); - bool e (cin.eof ()); - - if (f || e) - *diag_stream << endl; // Assume no delimiter (newline). - - if (f) - fail << "unable to read y/n answer from STDOUT"; - - if (a.empty () && def != '\0') - { - // Don't treat eof as the default answer. We need to see the - // actual newline. - // - if (!e) - a = def; - } - } while (a != "y" && a != "n"); - - return a == "y"; + return butl::yn_prompt (p, d); + } + catch (io_error&) + { + fail << "unable to read y/n answer from stdin"; + } } bool diff --git a/bpkg/utility.hxx b/bpkg/utility.hxx index 19d664e..c0c361f 100644 --- a/bpkg/utility.hxx +++ b/bpkg/utility.hxx @@ -88,13 +88,13 @@ namespace bpkg // extern bool stderr_term; // True if stderr is a terminal. - // Y/N prompt. The def argument, if specified, should be either 'y' - // or 'n'. It is used as the default answer, in case the user just - // hits enter. Issue diagnostics and throw failed if no answer could - // be extracted from STDOUT (e.g., because it was closed). + // Y/N prompt. See butl::yn_prompt() for details (this is a thin wrapper). + // + // Issue diagnostics and throw failed if no answer could be extracted from + // stdin (e.g., because it was closed). // bool - yn_prompt (const char* prompt, char def = '\0'); + yn_prompt (const string& prompt, char def = '\0'); // Filesystem. // diff --git a/tests/rep-auth.test b/tests/rep-auth.test index e27aae2..640f828 100644 --- a/tests/rep-auth.test +++ b/tests/rep-auth.test @@ -183,7 +183,7 @@ sc = " " # Space character to append to here-document line when required. certificate SHA256 fingerprint: $cert_fp trust this certificate? [y/n]$sc - error: unable to read y/n answer from STDOUT + error: unable to read y/n answer from stdin EOE $not_fetched @@ -293,7 +293,7 @@ sc = " " # Space character to append to here-document line when required. certificate SHA256 fingerprint: $cert_fp trust this certificate? [y/n]$sc - error: unable to read y/n answer from STDOUT + error: unable to read y/n answer from stdin EOE : trust-fp @@ -457,7 +457,7 @@ sc = " " # Space character to append to here-document line when required. fetching pkg:build2.org/rep-auth/unsigned1 warning: repository pkg:build2.org/rep-auth/unsigned1 is unsigned %continue without authenticating repositories at .+\? \[y/n\] % - error: unable to read y/n answer from STDOUT + error: unable to read y/n answer from stdin EOE $not_fetched @@ -535,7 +535,7 @@ sc = " " # Space character to append to here-document line when required. $rep_info 2>>~%EOE% != 0 warning: repository pkg:build2.org/rep-auth/unsigned1 is unsigned %continue without authenticating repositories at .+\? \[y/n\] % - error: unable to read y/n answer from STDOUT + error: unable to read y/n answer from stdin EOE : trust-yes -- cgit v1.1