From fd78974020e23679e9e810cf01dc5c8f3012bb8a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 13 May 2016 16:59:09 +0200 Subject: [PATCH] show globalerrors before asking for confirmation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Errors cause a kind of automatic no already, but warnings and notices are only displayed at the end of the apt execution even through they could effect the choice of saying yes/no to questions: E.g. if a configuration (file) was ignored you wanted to have an effect or if an external solver you used generated warnings suggesting that the solution might be valid, but bogus non-the-less and similar things. Note that this only moves those messages up to the question if the answer is interactive – not if e.g. -y is used or no question is asked at all so this has an effect only on interactive usage of apt(-get), not script who might be parsing apt output. --- apt-private/private-download.cc | 3 +-- apt-private/private-install.cc | 9 +++---- apt-private/private-output.cc | 27 ++++++++++++++++--- apt-private/private-output.h | 4 +-- apt-private/private-sources.cc | 16 +++++------ .../test-bug-604401-files-are-directories | 9 ++++--- 6 files changed, 41 insertions(+), 27 deletions(-) diff --git a/apt-private/private-download.cc b/apt-private/private-download.cc index 1ae0f4a0e..4ffe78b24 100644 --- a/apt-private/private-download.cc +++ b/apt-private/private-download.cc @@ -66,8 +66,7 @@ bool AuthPrompt(std::vector const &UntrustedList, bool const Prompt if (_config->FindI("quiet",0) < 2 && _config->FindB("APT::Get::Assume-Yes",false) == false) { - c2out << _("Install these packages without verification?") << std::flush; - if (!YnPrompt(false)) + if (!YnPrompt(_("Install these packages without verification?"), false)) return _error->Error(_("Some packages could not be authenticated")); return true; diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index a4917c5af..44980ceed 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -234,12 +234,12 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be // careful with hard to type or special characters (like non-breaking spaces) const char *Prompt = _("Yes, do as I say!"); - ioprintf(c2out, + std::string question; + strprintf(question, _("You are about to do something potentially harmful.\n" "To continue type in the phrase '%s'\n" " ?] "),Prompt); - c2out << std::flush; - if (AnalPrompt(Prompt) == false) + if (AnalPrompt(question, Prompt) == false) { c2out << _("Abort.") << std::endl; exit(1); @@ -256,8 +256,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) if (_config->FindI("quiet",0) < 2 && _config->FindB("APT::Get::Assume-Yes",false) == false) { - c2out << _("Do you want to continue?") << std::flush; - if (YnPrompt() == false) + if (YnPrompt(_("Do you want to continue?")) == false) { c2out << _("Abort.") << std::endl; exit(1); diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 458d78dc4..301aa5519 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -650,8 +650,21 @@ void Stats(ostream &out,pkgDepCache &Dep) // YnPrompt - Yes No Prompt. /*{{{*/ // --------------------------------------------------------------------- /* Returns true on a Yes.*/ -bool YnPrompt(bool Default) +bool YnPrompt(char const * const Question, bool Default) { + auto const AssumeYes = _config->FindB("APT::Get::Assume-Yes",false); + auto const AssumeNo = _config->FindB("APT::Get::Assume-No",false); + // if we ask interactively, show warnings/notices before the question + if (AssumeYes == false && AssumeNo == false) + { + if (_config->FindI("quiet",0) > 0) + _error->DumpErrors(c2out); + else + _error->DumpErrors(c2out, GlobalError::DEBUG); + } + + c2out << Question << std::flush; + /* nl_langinfo does not support LANGUAGE setting, so we unset it here to have the help-message (hopefully) match the expected characters */ char * language = getenv("LANGUAGE"); @@ -679,13 +692,13 @@ bool YnPrompt(bool Default) free(language); } - if (_config->FindB("APT::Get::Assume-Yes",false) == true) + if (AssumeYes) { // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set c1out << _("Y") << std::endl; return true; } - else if (_config->FindB("APT::Get::Assume-No",false) == true) + else if (AssumeNo) { // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set c1out << _("N") << std::endl; @@ -722,8 +735,14 @@ bool YnPrompt(bool Default) // AnalPrompt - Annoying Yes No Prompt. /*{{{*/ // --------------------------------------------------------------------- /* Returns true on a Yes.*/ -bool AnalPrompt(const char *Text) +bool AnalPrompt(std::string const &Question, const char *Text) { + if (_config->FindI("quiet",0) > 0) + _error->DumpErrors(c2out); + else + _error->DumpErrors(c2out, GlobalError::DEBUG); + c2out << Question << std::flush; + char Buf[1024]; std::cin.getline(Buf,sizeof(Buf)); if (strcmp(Buf,Text) == 0) diff --git a/apt-private/private-output.h b/apt-private/private-output.h index 8e4b50ed1..bb9428d7f 100644 --- a/apt-private/private-output.h +++ b/apt-private/private-output.h @@ -101,8 +101,8 @@ bool ShowEssential(std::ostream &out,CacheFile &Cache); void Stats(std::ostream &out, pkgDepCache &Dep); // prompting -bool YnPrompt(bool Default=true); -bool AnalPrompt(const char *Text); +bool YnPrompt(char const * const Question, bool Default=true); +bool AnalPrompt(std::string const &Question, const char *Text); std::string PrettyFullName(pkgCache::PkgIterator const &Pkg); std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg); diff --git a/apt-private/private-sources.cc b/apt-private/private-sources.cc index 6a32931ba..5f61a23ab 100644 --- a/apt-private/private-sources.cc +++ b/apt-private/private-sources.cc @@ -30,7 +30,6 @@ bool EditSources(CommandLine &CmdL) { bool res; pkgSourceList sl; - std::string outs; std::string sourceslist; if (CmdL.FileList[1] != NULL) @@ -48,28 +47,25 @@ bool EditSources(CommandLine &CmdL) int lockfd = GetLock(sourceslist); if (lockfd < 0) return false; - + do { EditFileInSensibleEditor(sourceslist); _error->PushToStack(); res = sl.Read(sourceslist); if (!res) { - _error->DumpErrors(std::cerr, GlobalError::DEBUG, false); - strprintf(outs, _("Failed to parse %s. Edit again? "), - sourceslist.c_str()); - std::cout << outs; + std::string outs; + strprintf(outs, _("Failed to parse %s. Edit again? "), sourceslist.c_str()); // FIXME: should we add a "restore previous" option here? - res = !YnPrompt(true); + res = !YnPrompt(outs.c_str(), true); } _error->RevertToStack(); } while (res == false); close(lockfd); if (FileExists(sourceslist) && !before.VerifyFile(sourceslist)) { - strprintf( - outs, _("Your '%s' file changed, please run 'apt-get update'."), + ioprintf( + std::cout, _("Your '%s' file changed, please run 'apt-get update'."), sourceslist.c_str()); - std::cout << outs << std::endl; } return true; diff --git a/test/integration/test-bug-604401-files-are-directories b/test/integration/test-bug-604401-files-are-directories index 129a429c3..4261d544d 100755 --- a/test/integration/test-bug-604401-files-are-directories +++ b/test/integration/test-bug-604401-files-are-directories @@ -17,7 +17,7 @@ rmdir rootdir/etc/apt/apt.conf msgtest "Good link instead of a file as apt.conf ignored" echo 'Test::APT::Link "good";' > rootdir/etc/apt/good-link.conf ln -s rootdir/etc/apt/good-link.conf rootdir/etc/apt/apt.conf -test -n "$(aptconfig shell TestLink 'Test::APT::Link')" && msgfail || msgpass +testempty aptconfig shell TestLink 'Test::APT::Link' rm rootdir/etc/apt/apt.conf msgtest "Broken link instead of a file as apt.conf ignored" @@ -36,12 +36,12 @@ rmdir rootdir/etc/apt/sources.list msgtest "Good link instead of a file as sources.list ignored" echo 'deb file:///tmp/debian sid main' > rootdir/etc/apt/good-link.list ln -s rootdir/etc/apt/good-link.list rootdir/etc/apt/sources.list -test -n "$(aptget update --print-uris)" && msgfail || msgpass +testempty aptget update --print-uris rm rootdir/etc/apt/sources.list msgtest "Broken link instead of a file as sources.list ignored" ln -s /tmp/doesnt-exist rootdir/etc/apt/sources.list -test -n "$(aptget update --print-uris)" && msgfail || msgpass +testempty aptget update --print-uris rm rootdir/etc/apt/sources.list @@ -57,7 +57,8 @@ echo 'Package: apt Pin: release a=now Pin-Value: 1000' > rootdir/etc/apt/good-link.pref ln -s rootdir/etc/apt/good-link.pref rootdir/etc/apt/preferences -test -n "$(aptcache policy | grep '1000 ')" && msgfail || msgpass +testsuccess aptcache policy +testfailure grep '1000 ' rootdir/tmp/testsucess.output rm rootdir/etc/apt/preferences msgtest "Broken link instead of a file as preferences ignored" -- 2.45.2