summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-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();
+};
/*}}}*/
/** @} */