diff options
| author | Julian Andres Klode <jak@debian.org> | 2021-04-23 12:54:46 +0000 |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2021-04-23 12:54:46 +0000 |
| commit | 64376abd263aa3ea684c4d8debaec2b321306b47 (patch) | |
| tree | 1c7bd0e0fd4c51f1d5a40e65de90535db9ed4a39 /apt-private | |
| parent | 6970632b35890238da97db8b7ec4a28298911051 (diff) | |
| parent | 64127478630b676838735b509fec5cdfa36874c8 (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.cc | 11 | ||||
| -rw-r--r-- | apt-private/private-install.h | 6 | ||||
| -rw-r--r-- | apt-private/private-json-hooks.cc | 98 | ||||
| -rw-r--r-- | apt-private/private-upgrade.cc | 16 |
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 /*{{{*/ |
