From 24b5bc4e41ed527799a9fa01dec9c29294d0a3f2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 28 May 2017 17:44:11 +0200 Subject: ask for releaseinfo change interactively in apt If we have a user sitting around we can let 'apt' ask the user for a confirmation rather than print errors at the end and require the user to figure out which commandline flags are needed to confirm the changes non-interactively. --- apt-private/acqprogress.cc | 22 +++++++++++++++++++++- apt-private/acqprogress.h | 3 ++- apt-private/private-cmndline.cc | 1 + apt-private/private-output.cc | 26 +++++++++++++++----------- apt-private/private-output.h | 1 + 5 files changed, 40 insertions(+), 13 deletions(-) (limited to 'apt-private') diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc index e4bfbd4e5..1f053cb9f 100644 --- a/apt-private/acqprogress.cc +++ b/apt-private/acqprogress.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -32,7 +33,7 @@ // --------------------------------------------------------------------- /* */ AcqTextStatus::AcqTextStatus(std::ostream &out, unsigned int &ScreenWidth,unsigned int const Quiet) : - pkgAcquireStatus(), out(out), ScreenWidth(ScreenWidth), LastLineLength(0), ID(0), Quiet(Quiet) + pkgAcquireStatus2(), out(out), ScreenWidth(ScreenWidth), LastLineLength(0), ID(0), Quiet(Quiet) { // testcases use it to disable pulses without disabling other user messages if (Quiet == 0 && _config->FindB("quiet::NoUpdate", false) == true) @@ -330,6 +331,25 @@ bool AcqTextStatus::MediaChange(std::string Media, std::string Drive) return bStatus; } /*}}}*/ +bool AcqTextStatus::ReleaseInfoChanges(metaIndex const * const L, metaIndex const * const N, std::vector &&Changes)/*{{{*/ +{ + if (Quiet >= 2 || isatty(STDOUT_FILENO) != 1 || isatty(STDIN_FILENO) != 1 || + _config->FindB("APT::Get::Update::InteractiveReleaseInfoChanges", false) == false) + return pkgAcquireStatus2::ReleaseInfoChanges(nullptr, nullptr, std::move(Changes)); + + _error->PushToStack(); + auto const confirmed = pkgAcquireStatus2::ReleaseInfoChanges(L, N, std::move(Changes)); + if (confirmed == true) + { + _error->MergeWithStack(); + return true; + } + clearLastLine(); + _error->DumpErrors(out, GlobalError::NOTICE, false); + _error->RevertToStack(); + return YnPrompt(_("Do you want to accept these changes and continue updating from this repository?"), false, false, out, out); +} + /*}}}*/ void AcqTextStatus::clearLastLine() { /*{{{*/ if (Quiet > 0 || LastLineLength == 0) return; diff --git a/apt-private/acqprogress.h b/apt-private/acqprogress.h index 6b6d555b1..196995ac4 100644 --- a/apt-private/acqprogress.h +++ b/apt-private/acqprogress.h @@ -15,7 +15,7 @@ #include #include -class APT_PUBLIC AcqTextStatus : public pkgAcquireStatus +class APT_PUBLIC AcqTextStatus : public pkgAcquireStatus2 { std::ostream &out; unsigned int &ScreenWidth; @@ -28,6 +28,7 @@ class APT_PUBLIC AcqTextStatus : public pkgAcquireStatus public: + virtual bool ReleaseInfoChanges(metaIndex const * const LastRelease, metaIndex const * const CurrentRelease, std::vector &&Changes) APT_OVERRIDE; virtual bool MediaChange(std::string Media,std::string Drive) APT_OVERRIDE; virtual void IMSHit(pkgAcquire::ItemDesc &Itm) APT_OVERRIDE; virtual void Fetch(pkgAcquire::ItemDesc &Itm) APT_OVERRIDE; diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index b035d99f0..6b84324de 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -469,6 +469,7 @@ static void BinarySpecificConfiguration(char const * const Binary) /*{{{*/ _config->CndSet("Binary::apt::APT::Cmd::Show-Update-Stats", true); _config->CndSet("Binary::apt::DPkg::Progress-Fancy", true); _config->CndSet("Binary::apt::APT::Keep-Downloaded-Packages", false); + _config->CndSet("Binary::apt::APT::Get::Update::InteractiveReleaseInfoChanges", true); } _config->Set("Binary", binary); diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 9c25cda6d..3b8832c21 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -650,20 +650,20 @@ void Stats(ostream &out,pkgDepCache &Dep) // YnPrompt - Yes No Prompt. /*{{{*/ // --------------------------------------------------------------------- /* Returns true on a Yes.*/ -bool YnPrompt(char const * const Question, bool Default) +bool YnPrompt(char const * const Question, bool const Default, bool const ShowGlobalErrors, std::ostream &c1o, std::ostream &c2o) { 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 (ShowGlobalErrors == true && AssumeYes == false && AssumeNo == false) { if (_config->FindI("quiet",0) > 0) - _error->DumpErrors(c2out); + _error->DumpErrors(c2o); else - _error->DumpErrors(c2out, GlobalError::DEBUG); + _error->DumpErrors(c2o, GlobalError::DEBUG); } - c2out << Question << std::flush; + c2o << 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 */ @@ -678,13 +678,13 @@ bool YnPrompt(char const * const Question, bool Default) // e.g. "Do you want to continue? [Y/n] " // The user has to answer with an input matching the // YESEXPR/NOEXPR defined in your l10n. - c2out << " " << _("[Y/n]") << " " << std::flush; + c2o << " " << _("[Y/n]") << " " << std::flush; else // TRANSLATOR: Yes/No question help-text: defaulting to N[o] // e.g. "Should this file be removed? [y/N] " // The user has to answer with an input matching the // YESEXPR/NOEXPR defined in your l10n. - c2out << " " << _("[y/N]") << " " << std::flush; + c2o << " " << _("[y/N]") << " " << std::flush; if (language != NULL) { @@ -695,13 +695,13 @@ bool YnPrompt(char const * const Question, bool Default) if (AssumeYes) { // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set - c1out << _("Y") << std::endl; + c1o << _("Y") << std::endl; return true; } else if (AssumeNo) { // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set - c1out << _("N") << std::endl; + c1o << _("N") << std::endl; return false; } @@ -721,15 +721,19 @@ bool YnPrompt(char const * const Question, bool Default) REG_EXTENDED|REG_ICASE|REG_NOSUB); if (Res != 0) { - char Error[300]; + char Error[300]; regerror(Res,&Pattern,Error,sizeof(Error)); return _error->Error(_("Regex compilation error - %s"),Error); } - + Res = regexec(&Pattern, response, 0, NULL, 0); if (Res == 0) return true; return false; +} +bool YnPrompt(char const * const Question, bool const Default) +{ + return YnPrompt(Question, Default, true, c1out, c2out); } /*}}}*/ // AnalPrompt - Annoying Yes No Prompt. /*{{{*/ diff --git a/apt-private/private-output.h b/apt-private/private-output.h index bb9428d7f..79da3d130 100644 --- a/apt-private/private-output.h +++ b/apt-private/private-output.h @@ -102,6 +102,7 @@ void Stats(std::ostream &out, pkgDepCache &Dep); // prompting bool YnPrompt(char const * const Question, bool Default=true); +bool YnPrompt(char const * const Question, bool const Default, bool const ShowGlobalErrors, std::ostream &c1o, std::ostream &c2o); bool AnalPrompt(std::string const &Question, const char *Text); std::string PrettyFullName(pkgCache::PkgIterator const &Pkg); -- cgit v1.2.3