summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2017-05-28 16:55:45 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2017-06-28 19:18:47 +0200
commitca8da1bf83ecc90ba882520b79c1cda03ee7485d (patch)
tree0c5d1cd61d0a62d2029ae4bd0a0bc733f2a151e6
parent96ebab48c25fcd1ee83729cdba4be8a6343a8766 (diff)
allow frontends to override releaseinfo change behaviour
Having messages being printed on the error stack and confirm them by commandline flags is an okayish first step, but some frontends will probably want to have a more interactive feeling here with a proper question the user can just press yes/no for as for some frontends a commandline flag makes no sense…
-rw-r--r--apt-pkg/acquire-item.cc61
-rw-r--r--apt-pkg/acquire.cc31
-rw-r--r--apt-pkg/acquire.h43
3 files changed, 105 insertions, 30 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index ddcff5808..975116d1a 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -1609,6 +1609,7 @@ bool pkgAcqMetaBase::VerifyVendor(string const &) /*{{{*/
// changed info potentially breaks user config like pinning
if (TransactionManager->LastMetaIndexParser != nullptr)
{
+ std::vector<pkgAcquireStatus::ReleaseInfoChange> Changes;
auto const AllowInfoChange = _config->FindB("Acquire::AllowReleaseInfoChange", false);
auto const quietInfoChange = _config->FindB("quiet::ReleaseInfoChange", false);
struct {
@@ -1623,24 +1624,21 @@ bool pkgAcqMetaBase::VerifyVendor(string const &) /*{{{*/
{ "Codename", AllowInfoChange, &metaIndex::GetCodename },
{ nullptr, false, nullptr }
};
- _error->PushToStack();
auto const CheckReleaseInfo = [&](char const * const Type, bool const AllowChange, decltype(checkers[0].Getter) const Getter) {
std::string const Last = (TransactionManager->LastMetaIndexParser->*Getter)();
std::string const Now = (TransactionManager->MetaIndexParser->*Getter)();
if (Last == Now)
- return true;
- auto const Allow = _config->FindB(std::string("Acquire::AllowReleaseInfoChange::").append(Type), AllowChange);
- auto const msg = _("Repository '%s' changed its '%s' value from '%s' to '%s'");
- if (Allow == false)
- _error->Error(msg, Desc.Description.c_str(), Type, Last.c_str(), Now.c_str());
- else if (_config->FindB(std::string("quiet::ReleaseInfoChange::").append(Type), quietInfoChange) == false)
- _error->Notice(msg, Desc.Description.c_str(), Type, Last.c_str(), Now.c_str());
- return Allow;
+ return;
+ auto const Allow = _config->FindB(std::string("Acquire::AllowReleaseInfoChange::").append(Type), AllowChange);
+ if (Allow == true && _config->FindB(std::string("quiet::ReleaseInfoChange::").append(Type), quietInfoChange) == true)
+ return;
+ std::string msg;
+ strprintf(msg, _("Repository '%s' changed its '%s' value from '%s' to '%s'"),
+ Desc.Description.c_str(), Type, Last.c_str(), Now.c_str());
+ Changes.push_back({Type, std::move(Last), std::move(Now), std::move(msg), Allow});
};
- bool CRI = true;
for (short i = 0; checkers[i].Type != nullptr; ++i)
- if (CheckReleaseInfo(checkers[i].Type, checkers[i].Allowed, checkers[i].Getter) == false)
- CRI = false;
+ CheckReleaseInfo(checkers[i].Type, checkers[i].Allowed, checkers[i].Getter);
{
auto const Last = TransactionManager->LastMetaIndexParser->GetDefaultPin();
@@ -1648,31 +1646,38 @@ bool pkgAcqMetaBase::VerifyVendor(string const &) /*{{{*/
if (Last != Now)
{
auto const Allow = _config->FindB("Acquire::AllowReleaseInfoChange::DefaultPin", AllowInfoChange);
- auto const msg = _("Repository '%s' changed its default priority for %s from %hi to %hi.");
- if (Allow == false)
- _error->Error(msg, Desc.Description.c_str(), "apt_preferences(5)", Last, Now);
- else if (_config->FindB("quiet::ReleaseInfoChange::DefaultPin", quietInfoChange) == false)
- _error->Notice(msg, Desc.Description.c_str(), "apt_preferences(5)", Last, Now);
- CRI &= Allow;
+ if (Allow == false || _config->FindB("quiet::ReleaseInfoChange::DefaultPin", quietInfoChange) == false)
+ {
+ std::string msg;
+ strprintf(msg, _("Repository '%s' changed its default priority for %s from %hi to %hi."),
+ Desc.Description.c_str(), "apt_preferences(5)", Last, Now);
+ Changes.push_back({"DefaultPin", std::to_string(Last), std::to_string(Now), std::move(msg), Allow});
+ }
}
}
- if (_error->empty(GlobalError::NOTICE) == false)
+ if (Changes.empty() == false)
{
auto const notes = TransactionManager->MetaIndexParser->GetReleaseNotes();
if (notes.empty() == false)
{
+ std::string msg;
// TRANSLATOR: the "this" refers to changes in the repository like a new release or owner change
- _error->Notice(_("More information about this can be found online in the Release notes at: %s"), notes.c_str());
+ strprintf(msg, _("More information about this can be found online in the Release notes at: %s"), notes.c_str());
+ Changes.push_back({"Release-Notes", "", std::move(notes), std::move(msg), true});
}
+ if (std::any_of(Changes.begin(),Changes.end(),[](pkgAcquireStatus::ReleaseInfoChange const &c) { return c.DefaultAction == false; }))
+ {
+ std::string msg;
+ // TRANSLATOR: %s is the name of the manpage in question, e.g. apt-secure(8)
+ strprintf(msg, _("This must be accepted explicitly before updates for "
+ "this repository can be applied. See %s manpage for details."), "apt-secure(8)");
+ Changes.push_back({"Confirmation", "", "", std::move(msg), true});
+ }
+
}
- _error->MergeWithStack();
- if (CRI == false)
- {
- // TRANSLATOR: %s is the name of the manpage in question, e.g. apt-secure(8)
- _error->Notice(_("This must be accepted explicitly before updates for "
- "this repository can be applied. See %s manpage for details."), "apt-secure(8)");
- return false;
- }
+ if (Owner->Log == nullptr)
+ return pkgAcquireStatus::ReleaseInfoChangesAsGlobalErrors(std::move(Changes));
+ return Owner->Log->ReleaseInfoChanges(TransactionManager->LastMetaIndexParser, TransactionManager->MetaIndexParser, std::move(Changes));
}
return true;
}
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc
index 8a6928fb9..f1dbff9f1 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -1406,10 +1406,39 @@ void pkgAcquireStatus::Stop()
// ---------------------------------------------------------------------
/* This is used to get accurate final transfer rate reporting. */
void pkgAcquireStatus::Fetched(unsigned long long Size,unsigned long long Resume)
-{
+{
FetchedBytes += Size - Resume;
}
/*}}}*/
+bool pkgAcquireStatus::ReleaseInfoChanges(metaIndex const * const LastRelease, metaIndex const * const CurrentRelease, std::vector<ReleaseInfoChange> &&Changes)/*{{{*/
+{
+ auto const virt = dynamic_cast<pkgAcquireStatus2*>(this);
+ if (virt != nullptr)
+ return virt->ReleaseInfoChanges(LastRelease, CurrentRelease, std::move(Changes));
+ return ReleaseInfoChangesAsGlobalErrors(std::move(Changes));
+}
+ /*}}}*/
+bool pkgAcquireStatus::ReleaseInfoChangesAsGlobalErrors(std::vector<ReleaseInfoChange> &&Changes)/*{{{*/
+{
+ bool AllOkay = true;
+ for (auto const &c: Changes)
+ if (c.DefaultAction)
+ _error->Notice("%s", c.Message.c_str());
+ else
+ {
+ _error->Error("%s", c.Message.c_str());
+ AllOkay = false;
+ }
+ return AllOkay;
+}
+ /*}}}*/
+bool pkgAcquireStatus2::ReleaseInfoChanges(metaIndex const * const, metaIndex const * const, std::vector<ReleaseInfoChange> &&Changes)
+{
+ return ReleaseInfoChangesAsGlobalErrors(std::move(Changes));
+}
+pkgAcquireStatus2::pkgAcquireStatus2() : pkgAcquireStatus() {}
+pkgAcquireStatus2::~pkgAcquireStatus2() {}
+
pkgAcquire::UriIterator::UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), CurItem(0)
{
diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h
index 5f1212338..8331c56e9 100644
--- a/apt-pkg/acquire.h
+++ b/apt-pkg/acquire.h
@@ -86,6 +86,7 @@ using std::string;
#endif
class pkgAcquireStatus;
+class metaIndex;
/** \brief The core download scheduler. {{{
*
@@ -794,7 +795,39 @@ class pkgAcquireStatus
* with prejudice.
*/
virtual bool MediaChange(std::string Media,std::string Drive) = 0;
-
+
+ struct ReleaseInfoChange
+ {
+ std::string Type; /*!< Type of the change like "Origin", "Codename", "Version", … */
+ std::string From; /*!< old value */
+ std::string To; /*!< new value */
+ std::string Message; /*!< translated message describing the change */
+ bool DefaultAction; /*!< true if the change is informational, false if it must be explicitly confirmed */
+ };
+ /** \brief ask the user for confirmation of changes to infos about a repository
+ *
+ * This method should present the user with a choice of accepting the change
+ * or not and indicate the user opinion via the return value. If DefaultAction is true
+ * it is acceptable to only notify the user about the change, but to accept the change
+ * automatically on behalf of the user.
+ *
+ * The default implementation will fail if any Change has DefaultAction == false. Regardless of
+ * success it will print for each change the message attached to it via GlobalError either as an
+ * error (if DefaultAction == false) or as a notice otherwise.
+ *
+ * \b Note: To keep ABI compatibility for now this method isn't marked as
+ * virtual, but you can derive your class from #pkgAcquireStatus2 which has it
+ * marked as virtual. TODO on next ABI break: merge both classes.
+ *
+ * @param LastRelease can be used to extract further information from the previous Release file
+ * @param CurrentRelease can be used to extract further information from the current Release file
+ * @param Changes is an array of changes alongside explanatory messages
+ * which should be presented in some way to the user.
+ * @return \b true if all changes are accepted by user, otherwise or if user can't be asked \b false
+ */
+ bool ReleaseInfoChanges(metaIndex const * const LastRelease, metaIndex const * const CurrentRelease, std::vector<ReleaseInfoChange> &&Changes);
+ APT_HIDDEN static bool ReleaseInfoChangesAsGlobalErrors(std::vector<ReleaseInfoChange> &&Changes);
+
/** \brief Invoked when an item is confirmed to be up-to-date.
* For instance, when an HTTP download is informed that the file on
@@ -835,6 +868,14 @@ class pkgAcquireStatus
pkgAcquireStatus();
virtual ~pkgAcquireStatus();
};
+class pkgAcquireStatus2: public pkgAcquireStatus
+{
+public:
+ virtual bool ReleaseInfoChanges(metaIndex const * const LastRelease, metaIndex const * const CurrentRelease, std::vector<ReleaseInfoChange> &&Changes);
+
+ pkgAcquireStatus2();
+ virtual ~pkgAcquireStatus2();
+};
/*}}}*/
/** @} */