summaryrefslogtreecommitdiff
path: root/apt-private
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2021-04-23 12:54:46 +0000
committerJulian Andres Klode <jak@debian.org>2021-04-23 12:54:46 +0000
commit64376abd263aa3ea684c4d8debaec2b321306b47 (patch)
tree1c7bd0e0fd4c51f1d5a40e65de90535db9ed4a39 /apt-private
parent6970632b35890238da97db8b7ec4a28298911051 (diff)
parent64127478630b676838735b509fec5cdfa36874c8 (diff)
Merge branch 'pu/json-hooks-21.04' into 'main'
JSON Hooks 0.2 See merge request apt-team/apt!166
Diffstat (limited to 'apt-private')
-rw-r--r--apt-private/private-install.cc11
-rw-r--r--apt-private/private-install.h6
-rw-r--r--apt-private/private-json-hooks.cc98
-rw-r--r--apt-private/private-upgrade.cc16
4 files changed, 109 insertions, 22 deletions
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index 402f8f4b6..0c26c4275 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -100,7 +100,7 @@ static void RemoveDownloadNeedingItemsFromFetcher(pkgAcquire &Fetcher, bool &Tra
I = Fetcher.ItemsBegin();
}
}
-bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
+bool InstallPackages(CacheFile &Cache, bool ShwKept, bool Ask, bool Safety, std::string const &Hook, CommandLine const &CmdL)
{
if (not RunScripts("APT::Install::Pre-Invoke"))
return false;
@@ -168,7 +168,12 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
if (_config->FindB("APT::Get::Download-Only",false) == false)
Essential = !ShowEssential(c1out,Cache);
+ if (not Hook.empty())
+ RunJsonHook(Hook, "org.debian.apt.hooks.install.package-list", CmdL.FileList, Cache);
+
Stats(c1out,Cache);
+ if (not Hook.empty())
+ RunJsonHook(Hook, "org.debian.apt.hooks.install.statistics", CmdL.FileList, Cache);
// Sanity check
if (Cache->BrokenCount() != 0)
@@ -944,9 +949,9 @@ bool DoInstall(CommandLine &CmdL)
// See if we need to prompt
// FIXME: check if really the packages in the set are going to be installed
if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
- result = InstallPackages(Cache, false, false);
+ result = InstallPackages(Cache, false, false, true, "AptCli::Hooks::Install", CmdL);
else
- result = InstallPackages(Cache, false);
+ result = InstallPackages(Cache, false, true, true, "AptCli::Hooks::Install", CmdL);
if (result)
result = RunJsonHook("AptCli::Hooks::Install", "org.debian.apt.hooks.install.post", CmdL.FileList, Cache);
diff --git a/apt-private/private-install.h b/apt-private/private-install.h
index 39a040e7d..52f055963 100644
--- a/apt-private/private-install.h
+++ b/apt-private/private-install.h
@@ -36,8 +36,10 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<PseudoPkg
bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<PseudoPkg> &VolatileCmdL, CacheFile &Cache, int UpgradeMode);
bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode);
-APT_PUBLIC bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
- bool Safety = true);
+APT_PUBLIC bool InstallPackages(CacheFile &Cache, bool ShwKept, bool Ask = true,
+ bool Safety = true,
+ std::string const &Hook = "",
+ CommandLine const &CmdL = {});
bool CheckNothingBroken(CacheFile &Cache);
bool DoAutomaticRemove(CacheFile &Cache);
diff --git a/apt-private/private-json-hooks.cc b/apt-private/private-json-hooks.cc
index 6bf70b1c6..acb9a3bf0 100644
--- a/apt-private/private-json-hooks.cc
+++ b/apt-private/private-json-hooks.cc
@@ -17,6 +17,7 @@
#include <ostream>
#include <sstream>
#include <stack>
+#include <unordered_map>
#include <signal.h>
#include <sys/socket.h>
@@ -199,6 +200,33 @@ class APT_HIDDEN JsonWriter
};
/**
+ * @brief Write a VerFileIterator to a JsonWriter
+ */
+static void verFiletoJson(JsonWriter &writer, CacheFile &, pkgCache::VerFileIterator const &vf)
+{
+ auto pf = vf.File(); // Packages file
+ auto rf = pf.ReleaseFile(); // release file
+
+ writer.beginObject();
+ if (not rf.end()) {
+ if (rf->Archive != 0)
+ writer.name("archive").value(rf.Archive());
+ if (rf->Codename != 0)
+ writer.name("codename").value(rf.Codename());
+ if (rf->Version != 0)
+ writer.name("version").value(rf.Version());
+ if (rf->Origin != 0)
+ writer.name("origin").value(rf.Origin());
+ if (rf->Label != 0)
+ writer.name("label").value(rf.Label());
+ if (rf->Site != 0)
+ writer.name("site").value(rf.Site());
+ }
+
+ writer.endObject();
+}
+
+/**
* @brief Write a VerIterator to a JsonWriter
*/
static void verIterToJson(JsonWriter &writer, CacheFile &Cache, pkgCache::VerIterator const &Ver)
@@ -208,6 +236,14 @@ static void verIterToJson(JsonWriter &writer, CacheFile &Cache, pkgCache::VerIte
writer.name("version").value(Ver.VerStr());
writer.name("architecture").value(Ver.Arch());
writer.name("pin").value(Cache->GetPolicy().GetPriority(Ver));
+
+ writer.name("origins");
+ writer.beginArray();
+ for (auto vf = Ver.FileList(); !vf.end(); vf++)
+ if ((vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
+ verFiletoJson(writer, Cache, vf);
+ writer.endArray();
+
writer.endObject();
}
@@ -230,7 +266,7 @@ static void DpkgChrootDirectory()
/**
* @brief Send a notification to the hook's stream
*/
-static void NotifyHook(std::ostream &os, std::string const &method, const char **FileList, CacheFile &Cache, std::set<std::string> const &UnknownPackages)
+static void NotifyHook(std::ostream &os, std::string const &method, const char **FileList, CacheFile &Cache, std::set<std::string> const &UnknownPackages, int hookVersion)
{
SortedPackageUniverse Universe(Cache);
JsonWriter jsonWriter{os};
@@ -242,11 +278,14 @@ static void NotifyHook(std::ostream &os, std::string const &method, const char *
/* Build params */
jsonWriter.name("params").beginObject();
- jsonWriter.name("command").value(FileList[0]);
- jsonWriter.name("search-terms").beginArray();
- for (int i = 1; FileList[i] != NULL; i++)
- jsonWriter.value(FileList[i]);
- jsonWriter.endArray();
+ if (FileList != nullptr)
+ {
+ jsonWriter.name("command").value(FileList[0]);
+ jsonWriter.name("search-terms").beginArray();
+ for (int i = 1; FileList[i] != NULL; i++)
+ jsonWriter.value(FileList[i]);
+ jsonWriter.endArray();
+ }
jsonWriter.name("unknown-packages").beginArray();
for (auto const &PkgName : UnknownPackages)
jsonWriter.value(PkgName);
@@ -273,7 +312,14 @@ static void NotifyHook(std::ostream &os, std::string const &method, const char *
switch (Cache[Pkg].Mode)
{
case pkgDepCache::ModeInstall:
- jsonWriter.name("mode").value("install");
+ if (Pkg->CurrentVer != 0 && Cache[Pkg].Upgrade() && hookVersion >= 0x020)
+ jsonWriter.name("mode").value("upgrade");
+ else if (Pkg->CurrentVer != 0 && Cache[Pkg].Downgrade() && hookVersion >= 0x020)
+ jsonWriter.name("mode").value("downgrade");
+ else if (Pkg->CurrentVer != 0 && Cache[Pkg].ReInstall() && hookVersion >= 0x020)
+ jsonWriter.name("mode").value("reinstall");
+ else
+ jsonWriter.name("mode").value("install");
break;
case pkgDepCache::ModeDelete:
jsonWriter.name("mode").value(Cache[Pkg].Purge() ? "purge" : "deinstall");
@@ -306,7 +352,7 @@ static void NotifyHook(std::ostream &os, std::string const &method, const char *
static std::string BuildHelloMessage()
{
std::stringstream Hello;
- JsonWriter(Hello).beginObject().name("jsonrpc").value("2.0").name("method").value("org.debian.apt.hooks.hello").name("id").value(0).name("params").beginObject().name("versions").beginArray().value("0.1").endArray().endObject().endObject();
+ JsonWriter(Hello).beginObject().name("jsonrpc").value("2.0").name("method").value("org.debian.apt.hooks.hello").name("id").value(0).name("params").beginObject().name("versions").beginArray().value("0.1").value("0.2").endArray().endObject().endObject();
return Hello.str();
}
@@ -323,11 +369,10 @@ static std::string BuildByeMessage()
/// @brief Run the Json hook processes in the given option.
bool RunJsonHook(std::string const &option, std::string const &method, const char **FileList, CacheFile &Cache, std::set<std::string> const &UnknownPackages)
{
- std::stringstream ss;
- NotifyHook(ss, method, FileList, Cache, UnknownPackages);
- std::string TheData = ss.str();
+ std::unordered_map<int, std::string> notifications;
std::string HelloData = BuildHelloMessage();
std::string ByeData = BuildByeMessage();
+ int hookVersion;
bool result = true;
@@ -427,6 +472,21 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
goto out;
}
+ if (strstr(line, "\"0.1\""))
+ {
+ _error->Warning("Hook %s uses deprecated 0.1 protocol", Opts->Value.c_str());
+ hookVersion = 0x010;
+ }
+ else if (strstr(line, "\"0.2\""))
+ {
+ hookVersion = 0x020;
+ }
+ else
+ {
+ _error->Error("Unknown hook version in handshake from hook %s: %s", Opts->Value.c_str(), line);
+ goto out;
+ }
+
size = getline(&line, &linesize, F);
if (size < 0)
{
@@ -438,9 +498,18 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
_error->Error("Expected empty line after handshake from %s, received %s", Opts->Value.c_str(), line);
goto out;
}
-
- fwrite(TheData.data(), TheData.size(), 1, F);
- fwrite("\n\n", 2, 1, F);
+ {
+ std::string &data = notifications[hookVersion];
+ if (data.empty())
+ {
+ std::stringstream ss;
+ NotifyHook(ss, method, FileList, Cache, UnknownPackages, hookVersion);
+ ;
+ data = ss.str();
+ }
+ fwrite(data.data(), data.size(), 1, F);
+ fwrite("\n\n", 2, 1, F);
+ }
fwrite(ByeData.data(), ByeData.size(), 1, F);
fwrite("\n\n", 2, 1, F);
@@ -452,6 +521,7 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
result = _error->Error("Failure running hook %s", Opts->Value.c_str());
break;
}
+
}
signal(SIGINT, old_sigint);
signal(SIGPIPE, old_sigpipe);
diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc
index aeaf5066b..c41e4d2f3 100644
--- a/apt-private/private-upgrade.cc
+++ b/apt-private/private-upgrade.cc
@@ -1,12 +1,14 @@
// Includes /*{{{*/
#include <config.h>
+#include <apt-pkg/cmndline.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
#include <apt-pkg/upgrade.h>
#include <apt-private/private-cachefile.h>
#include <apt-private/private-install.h>
+#include <apt-private/private-json-hooks.h>
#include <apt-private/private-output.h>
#include <apt-private/private-upgrade.h>
@@ -24,10 +26,18 @@ static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags)
if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
return false;
- if(!DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, UpgradeFlags))
+ std::map<unsigned short, APT::VersionSet> verset;
+ std::set<std::string> UnknownPackages;
+ if (!DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeFlags, UnknownPackages))
+ {
+ RunJsonHook("AptCli::Hooks::Upgrade", "org.debian.apt.hooks.install.fail", CmdL.FileList, Cache, UnknownPackages);
return false;
-
- return InstallPackages(Cache,true);
+ }
+ RunJsonHook("AptCli::Hooks::Upgrade", "org.debian.apt.hooks.install.pre-prompt", CmdL.FileList, Cache);
+ if (InstallPackages(Cache, true, true, true, "AptCli::Hooks::Upgrade", CmdL))
+ return RunJsonHook("AptCli::Hooks::Upgrade", "org.debian.apt.hooks.install.post", CmdL.FileList, Cache);
+ else
+ return RunJsonHook("AptCli::Hooks::Upgrade", "org.debian.apt.hooks.install.fail", CmdL.FileList, Cache);
}
// DoDistUpgrade - Automatic smart upgrader /*{{{*/