diff -Nru apt-2.0.5/apt-pkg/acquire-item.cc apt-2.0.6/apt-pkg/acquire-item.cc --- apt-2.0.5/apt-pkg/acquire-item.cc 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/apt-pkg/acquire-item.cc 2021-06-15 11:05:46.000000000 +0000 @@ -3474,6 +3474,12 @@ Version.VerStr(), Version.ParentPkg().FullName(false).c_str()); return; } + if (FileSize == 0 && not _config->FindB("Acquire::AllowUnsizedPackages", false)) + { + _error->Warning("Repository is broken: %s (= %s) has no Size information", + Version.ParentPkg().FullName(false).c_str(), + Version.VerStr()); + } // Check if we already downloaded the file struct stat Buf; diff -Nru apt-2.0.5/apt-pkg/contrib/fileutl.cc apt-2.0.6/apt-pkg/contrib/fileutl.cc --- apt-2.0.5/apt-pkg/contrib/fileutl.cc 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/apt-pkg/contrib/fileutl.cc 2021-06-15 11:05:46.000000000 +0000 @@ -140,10 +140,6 @@ return _error->Errno("waitpid","Couldn't wait for subprocess"); } - // Restore sig int/quit - signal(SIGQUIT,SIG_DFL); - signal(SIGINT,SIG_DFL); - // Check for an error code. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) { diff -Nru apt-2.0.5/apt-private/acqprogress.cc apt-2.0.6/apt-private/acqprogress.cc --- apt-2.0.5/apt-private/acqprogress.cc 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/apt-private/acqprogress.cc 2021-06-15 11:05:46.000000000 +0000 @@ -322,8 +322,10 @@ while (C != '\n' && C != '\r') { int len = read(STDIN_FILENO,&C,1); - if(C == 'c' || len <= 0) + if(C == 'c' || len <= 0) { bStatus = false; + break; + } } if(bStatus) diff -Nru apt-2.0.5/apt-private/private-install.cc apt-2.0.6/apt-private/private-install.cc --- apt-2.0.5/apt-private/private-install.cc 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/apt-private/private-install.cc 2021-06-15 11:05:46.000000000 +0000 @@ -100,7 +100,7 @@ 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 @@ 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) @@ -934,9 +939,9 @@ // 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 -Nru apt-2.0.5/apt-private/private-install.h apt-2.0.6/apt-private/private-install.h --- apt-2.0.5/apt-private/private-install.h 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/apt-private/private-install.h 2021-06-15 11:05:46.000000000 +0000 @@ -36,8 +36,10 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector &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 -Nru apt-2.0.5/apt-private/private-json-hooks.cc apt-2.0.6/apt-private/private-json-hooks.cc --- apt-2.0.5/apt-private/private-json-hooks.cc 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/apt-private/private-json-hooks.cc 2021-06-15 11:05:46.000000000 +0000 @@ -11,10 +11,13 @@ #include #include #include +#include +#include #include #include #include +#include #include #include @@ -23,7 +26,7 @@ /** * @brief Simple JSON writer * - * This performs no error checking, or string escaping, be careful. + * This performs no error checking, so be careful. */ class APT_HIDDEN JsonWriter { @@ -78,6 +81,7 @@ void popState() { this->state = old_states.top(); + old_states.pop(); } public: @@ -109,22 +113,40 @@ os << '}'; return *this; } + std::ostream &encodeString(std::ostream &out, std::string const &str) + { + out << '"'; + + for (std::string::const_iterator c = str.begin(); c != str.end(); c++) + { + if (*c <= 0x1F || *c == '"' || *c == '\\') + ioprintf(out, "\\u%04X", *c); + else + out << *c; + } + + out << '"'; + return out; + } JsonWriter &name(std::string const &name) { maybeComma(); - os << '"' << name << '"' << ':'; + encodeString(os, name) << ':'; return *this; } JsonWriter &value(std::string const &value) { maybeComma(); - os << '"' << value << '"'; + encodeString(os, value); return *this; } JsonWriter &value(const char *value) { maybeComma(); - os << '"' << value << '"'; + if (value == nullptr) + os << "null"; + else + encodeString(os, value); return *this; } JsonWriter &value(int value) @@ -178,6 +200,33 @@ }; /** + * @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) @@ -187,6 +236,14 @@ 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(); } @@ -209,7 +266,7 @@ /** * @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 const &UnknownPackages) +static void NotifyHook(std::ostream &os, std::string const &method, const char **FileList, CacheFile &Cache, std::set const &UnknownPackages, int hookVersion) { SortedPackageUniverse Universe(Cache); JsonWriter jsonWriter{os}; @@ -221,11 +278,14 @@ /* 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); @@ -252,7 +312,14 @@ 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"); @@ -285,7 +352,7 @@ 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(); } @@ -302,11 +369,10 @@ /// @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 const &UnknownPackages) { - std::stringstream ss; - NotifyHook(ss, method, FileList, Cache, UnknownPackages); - std::string TheData = ss.str(); + std::unordered_map notifications; std::string HelloData = BuildHelloMessage(); std::string ByeData = BuildByeMessage(); + int hookVersion; bool result = true; @@ -315,6 +381,13 @@ return true; Opts = Opts->Child; + // Flush output before calling hooks + std::clog.flush(); + std::cerr.flush(); + std::cout.flush(); + c2out.flush(); + c1out.flush(); + sighandler_t old_sigpipe = signal(SIGPIPE, SIG_IGN); sighandler_t old_sigint = signal(SIGINT, SIG_IGN); sighandler_t old_sigquit = signal(SIGQUIT, SIG_IGN); @@ -399,6 +472,20 @@ goto out; } + if (strstr(line, "\"0.1\"")) + { + 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) { @@ -410,9 +497,18 @@ _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); @@ -424,6 +520,7 @@ result = _error->Error("Failure running hook %s", Opts->Value.c_str()); break; } + } signal(SIGINT, old_sigint); signal(SIGPIPE, old_sigpipe); diff -Nru apt-2.0.5/apt-private/private-upgrade.cc apt-2.0.6/apt-private/private-upgrade.cc --- apt-2.0.5/apt-private/private-upgrade.cc 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/apt-private/private-upgrade.cc 2021-06-15 11:05:46.000000000 +0000 @@ -1,12 +1,14 @@ // Includes /*{{{*/ #include +#include #include #include #include #include #include +#include #include #include @@ -24,10 +26,18 @@ if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; - if(!DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, UpgradeFlags)) + std::map verset; + std::set 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 /*{{{*/ diff -Nru apt-2.0.5/CMakeLists.txt apt-2.0.6/CMakeLists.txt --- apt-2.0.5/CMakeLists.txt 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/CMakeLists.txt 2021-06-15 11:05:46.000000000 +0000 @@ -204,7 +204,7 @@ # Configure some variables like package, version and architecture. set(PACKAGE ${PROJECT_NAME}) set(PACKAGE_MAIL "APT Development Team ") -set(PACKAGE_VERSION "2.0.5") +set(PACKAGE_VERSION "2.0.6") string(REGEX MATCH "^[0-9.]+" PROJECT_VERSION ${PACKAGE_VERSION}) if (NOT DEFINED DPKG_DATADIR) diff -Nru apt-2.0.5/debian/changelog apt-2.0.6/debian/changelog --- apt-2.0.5/debian/changelog 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/debian/changelog 2021-06-15 11:05:46.000000000 +0000 @@ -1,3 +1,29 @@ +apt (2.0.6) focal; urgency=medium + + * RunScripts: Do not reset SIGQUIT and SIGINT to SIG_DFL (LP: #1898026) + * test suite fix: Check for and discard expected warning from MaybeAddAuth + * Fix downloads of unsized files that are largest in pipeline (LP: #1921626), + and warn about packages without size (option Acquire::AllowUnsizedPackages) + * JSON hooks 0.2 and assorted JSON bugfixes (LP: #1926150) + - encoder fixes: + + json: Escape strings using \u escape sequences, add test + + json: Actually pop states + + json: Encode NULL strings as null + - json: Flush standard file descriptors before calling hooks + (this avoids output from hooks in middle of apt output) + - non-code changes: + + test/json: Make the test hook more reliable + + Fix a typo in json-hooks-protocol.md (thanks to Brian Murray) + - semantic changes (new fields, hooks, and protocol 0.2): + + json: Add origins fields to version + + upgrade: Add JSON hook support (AptCli::Hooks::Upgrade) + + json: Add `package-list` and `statistics` install hooks + + json: Hook protocol 0.2 (added upgrade,downgrade,reinstall modes) + + Fix a typo in json-hooks-protocol.md (thanks to Brian Murray) + * Avoid infinite loop on EOF on media change prompt (LP: #1928687) + + -- Julian Andres Klode Tue, 15 Jun 2021 13:05:46 +0200 + apt (2.0.5) focal; urgency=medium [ Julian Andres Klode ] diff -Nru apt-2.0.5/doc/apt-verbatim.ent apt-2.0.6/doc/apt-verbatim.ent --- apt-2.0.5/doc/apt-verbatim.ent 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/doc/apt-verbatim.ent 2021-06-15 11:05:46.000000000 +0000 @@ -274,7 +274,7 @@ "> - + diff -Nru apt-2.0.5/doc/examples/configure-index apt-2.0.6/doc/examples/configure-index --- apt-2.0.5/doc/examples/configure-index 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/doc/examples/configure-index 2021-06-15 11:05:46.000000000 +0000 @@ -248,6 +248,7 @@ AllowInsecureRepositories ""; AllowWeakRepositories ""; AllowDowngradeToInsecureRepositories ""; + AllowUnsizedPackages ""; // allow repositories to change information potentially breaking user config like pinning AllowReleaseInfoChange "" { diff -Nru apt-2.0.5/doc/json-hooks-protocol.md apt-2.0.6/doc/json-hooks-protocol.md --- apt-2.0.5/doc/json-hooks-protocol.md 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/doc/json-hooks-protocol.md 2021-06-15 11:05:46.000000000 +0000 @@ -1,3 +1,5 @@ +Version: 0.2 + ## JSON Hooks APT 1.6 introduces support for hooks that talk JSON-RPC 2.0. Hooks act @@ -23,7 +25,7 @@ 1. Hook is started 2. Hello handshake is exchanged 3. One or more calls or notifications are sent from apt to the hook -4. Bye notification is send +4. Bye notification is sent It is unspecified whether a hook is sent one or more messages. For example, a hook may be started only once for the lifetime of the apt @@ -57,7 +59,9 @@ The following methods are supported: -1. `org.debian.apt.hooks.install.pre-prompt` - Run before the y/n prompt +1. `org.debian.apt.hooks.install.pre-prompt` - Run before the package list and y/n prompt +1. `org.debian.apt.hooks.install.package-list` - (optional in 0.1) Run after the package list. You could display additional lists of packages here +1. `org.debian.apt.hooks.install.statistics` - (optional in 0.1) Run after the count of packages to upgrade/install. You could display additional information here, such as `5 security upgrades` 1. `org.debian.apt.hooks.install.post` - Run after success 1. `org.debian.apt.hooks.install.fail` - Run after failed install 1. `org.debian.apt.hooks.search.pre` - Run before search @@ -88,24 +92,39 @@ - *id*: An unsigned integer describing the package - *name*: The name of the package - *architecture*: The architecture of the package. For `"all"` packages, this will be the native architecture; - use per-version architecture fields to see `"all"`. + use per-version architecture fields to see `"all"`. -- *mode*: One of `install`, `deinstall`, `purge`, or `keep`. `keep` - is not exposed in 0.1. To determine an upgrade, check - that a current version is installed. +- *mode*: One of `install`, `upgrade`, `downgrade`, `reinstall`, `deinstall`, `purge`, `keep`. + Version 0.1 does not implement `upgrade`, `downgrade`, and `reinstall` - all of them are represented + as `install`, and you have to compare the `current` version to the `install` version to figure out if + is one of those. +- One of the following optional fields may be set to true to indicate a change relative to an installed version: +- *downgrade*: true if downgrading +- *upgrade*: true if upgrading +- *reinstall*: true if reinstall flag is set - *automatic*: Whether the package is/will be automatically installed - *versions*: An array with up to 3 fields: - - *candidate*: The candidate version - - *install*: The version to be installed - - *current*: The version currently installed - - Each version is represented as an object with the following fields: - - - *id*: An unsigned integer - - *version*: The version as a string - - *architecture*: Architecture of the version - - *pin*: The pin priority (optional) +- *candidate*: The candidate version +- *install*: The version to be installed +- *current*: The version currently installed + +Each version is represented as an object with the following fields: + +- *id*: An unsigned integer +- *version*: The version as a string +- *architecture*: Architecture of the version +- *pin*: The pin priority (optional) +- *origins*: Sources from which the package is retrieved (since 0.2) + + Each origin is represented as an object with the following fields: + + - *archive*: string (optional) + - *codename*: string (optional) + - *version*: string (optional) + - *origin*: string (optional) + - *label*: string (optional) + - *site*: string, empty for local repositories or when using mirror+file:/ method (optional) #### Example @@ -157,3 +176,14 @@ Additional fields may be added to objects without bumping the protocol version. + +# Changes: + +## Version 0.2 + +The 0.2 protocol makes one incompatible change, and adds several new compatible changes, all of which are optional in 0.1, +but mandatory in 0.2. + +* (incompatible change) The `mode` flag of arguments gained `upgrade`, `downgrade`, `reinstall` modes. All of these are `install` +* (compatible change) The hooks `org.debian.apt.hooks.install.package-list` and `org.debian.apt.hooks.install.statistics` have been added +* (compatible change) Version objects gained a new `origins` array diff -Nru apt-2.0.5/doc/po/apt-doc.pot apt-2.0.6/doc/po/apt-doc.pot --- apt-2.0.5/doc/po/apt-doc.pot 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/doc/po/apt-doc.pot 2021-06-15 11:05:46.000000000 +0000 @@ -5,9 +5,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: apt-doc 2.0.5\n" +"Project-Id-Version: apt-doc 2.0.6\n" "Report-Msgid-Bugs-To: APT Development Team \n" -"POT-Creation-Date: 2021-03-12 11:47+0000\n" +"POT-Creation-Date: 2021-06-15 08:01+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff -Nru apt-2.0.5/methods/basehttp.cc apt-2.0.6/methods/basehttp.cc --- apt-2.0.5/methods/basehttp.cc 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/methods/basehttp.cc 2021-06-15 11:05:46.000000000 +0000 @@ -870,7 +870,11 @@ { unsigned long long MaxSizeInQueue = 0; for (FetchItem *I = Queue; I != 0 && I != QueueBack; I = I->Next) + { + if (I->MaximumSize == 0) + return 0; MaxSizeInQueue = std::max(MaxSizeInQueue, I->MaximumSize); + } return MaxSizeInQueue; } /*}}}*/ diff -Nru apt-2.0.5/po/apt-all.pot apt-2.0.6/po/apt-all.pot --- apt-2.0.5/po/apt-all.pot 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/po/apt-all.pot 2021-06-15 11:05:46.000000000 +0000 @@ -5,9 +5,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: apt 2.0.5\n" +"Project-Id-Version: apt 2.0.6\n" "Report-Msgid-Bugs-To: APT Development Team \n" -"POT-Creation-Date: 2021-03-12 11:47+0000\n" +"POT-Creation-Date: 2021-06-15 08:01+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff -Nru apt-2.0.5/test/integration/framework apt-2.0.6/test/integration/framework --- apt-2.0.5/test/integration/framework 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/test/integration/framework 2021-06-15 11:05:46.000000000 +0000 @@ -484,6 +484,10 @@ # Allow release files to be 10 hours in the future, rather than 10 seconds echo 'Acquire::Max-FutureTime "'$((10 * 60 * 60))'";' > rootdir/etc/apt/apt.conf.d/future-time + # XXX: We really ought to make the packages in the test suite all have Size fields. + # But this needs a lot more changes, so let's keep it simple for stable updates. + echo 'Acquire::AllowUnsizedPackages "true";' >> rootdir/etc/apt/apt.conf.d/temporary-allow-unsized-packages + configcompression '.' 'gz' #'bz2' 'lzma' 'xz' confighashes 'SHA256' # these are tests, not security best-practices diff -Nru apt-2.0.5/test/integration/test-apt-cli-json-hooks apt-2.0.6/test/integration/test-apt-cli-json-hooks --- apt-2.0.5/test/integration/test-apt-cli-json-hooks 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/test/integration/test-apt-cli-json-hooks 2021-06-15 11:05:46.000000000 +0000 @@ -4,6 +4,10 @@ TESTDIR="$(readlink -f "$(dirname "$0")")" . "$TESTDIR/framework" +getoriginfromsuite() { echo 'Oranges'; } +getlabelfromsuite() { echo 'Lemons'; } +getversionfromsuite() { echo 'Volkamer'; } + setupenvironment configarchitecture "i386" @@ -14,20 +18,22 @@ . and paragraphs and everything." insertpackage 'testing' 'bar' 'i386' '2.0' '' '' "$DESCR2" +insertpackage 'testing' 'upgrade' 'i386' '2.0' +insertinstalledpackage 'upgrade' 'i386' '1.0' setupaptarchive APTARCHIVE="$(readlink -f ./aptarchive)" +export TEST_HOOK_VERSION=0.2 cat >> json-hook.sh << EOF #!/bin/bash +trap '' SIGPIPE while true; do - read request <&\$APT_HOOK_SOCKET - read empty <&\$APT_HOOK_SOCKET + read request <&\$APT_HOOK_SOCKET || exit 1 if echo "\$request" | grep -q ".hello"; then echo "HOOK: HELLO" - printf '{"jsonrpc": "2.0", "result": {"version": "0.1"}, "id": 0}\n\n' >&\$APT_HOOK_SOCKET fi if echo "\$request" | grep -q ".bye"; then @@ -36,7 +42,16 @@ fi echo HOOK: request \$request + + read empty <&\$APT_HOOK_SOCKET || exit 1 + echo HOOK: empty \$empty + + if echo "\$request" | grep -q ".hello"; then + printf '{"jsonrpc": "2.0", "result": {"version": "'\$TEST_HOOK_VERSION'"}, "id": 0}\n\n' >&\$APT_HOOK_SOCKET 2>/dev/null || exit 1 + fi + + done EOF @@ -47,13 +62,14 @@ # Setup all hooks cat >> rootdir/etc/apt/apt.conf.d/99-json-hooks << EOF AptCli::Hooks::Install:: "$HOOK"; + AptCli::Hooks::Upgrade:: "$HOOK"; AptCli::Hooks::Search:: "$HOOK"; EOF ############################# Success search ####################### testsuccessequal 'HOOK: HELLO -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} HOOK: empty HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.search.pre","params":{"command":"search","search-terms":["foo"],"unknown-packages":[],"packages":[]}} HOOK: empty @@ -64,7 +80,7 @@ Some description that has a unusual word xxyyzz and aabbcc and a UPPERCASE HOOK: HELLO -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} HOOK: empty HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.search.post","params":{"command":"search","search-terms":["foo"],"unknown-packages":[],"packages":[]}} HOOK: empty @@ -72,7 +88,7 @@ ############################# Failed search ####################### testsuccessequal 'HOOK: HELLO -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} HOOK: empty HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.search.pre","params":{"command":"search","search-terms":["foox"],"unknown-packages":[],"packages":[]}} HOOK: empty @@ -80,7 +96,7 @@ Sorting... Full Text Search... HOOK: HELLO -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} HOOK: empty HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.search.fail","params":{"command":"search","search-terms":["foox"],"unknown-packages":[],"packages":[]}} HOOK: empty @@ -92,7 +108,7 @@ testfailureequal 'Reading package lists... Building dependency tree... HOOK: HELLO -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} HOOK: empty HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.fail","params":{"command":"install","search-terms":["foxxx"],"unknown-packages":["foxxx"],"packages":[]}} HOOK: empty @@ -104,23 +120,138 @@ testsuccessequal 'Reading package lists... Building dependency tree... HOOK: HELLO -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} HOOK: empty -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.pre-prompt","params":{"command":"install","search-terms":["foo"],"unknown-packages":[],"packages":[{"id":1,"name":"foo","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":1,"version":"1.0","architecture":"all","pin":500},"install":{"id":1,"version":"1.0","architecture":"all","pin":500}}}]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.pre-prompt","params":{"command":"install","search-terms":["foo"],"unknown-packages":[],"packages":[{"id":2,"name":"foo","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":2,"version":"1.0","architecture":"all","pin":500,"origins":[{"archive":"unstable","codename":"sid","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":2,"version":"1.0","architecture":"all","pin":500,"origins":[{"archive":"unstable","codename":"sid","origin":"Oranges","label":"Lemons","site":""}]}}}]}} HOOK: empty HOOK: BYE The following NEW packages will be installed: foo -0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. -Inst foo (1.0 unstable [all]) -Conf foo (1.0 unstable [all]) HOOK: HELLO -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.package-list","params":{"command":"install","search-terms":["foo"],"unknown-packages":[],"packages":[{"id":2,"name":"foo","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":2,"version":"1.0","architecture":"all","pin":500,"origins":[{"archive":"unstable","codename":"sid","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":2,"version":"1.0","architecture":"all","pin":500,"origins":[{"archive":"unstable","codename":"sid","origin":"Oranges","label":"Lemons","site":""}]}}}]}} +HOOK: empty +HOOK: BYE +0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.statistics","params":{"command":"install","search-terms":["foo"],"unknown-packages":[],"packages":[{"id":2,"name":"foo","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":2,"version":"1.0","architecture":"all","pin":500,"origins":[{"archive":"unstable","codename":"sid","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":2,"version":"1.0","architecture":"all","pin":500,"origins":[{"archive":"unstable","codename":"sid","origin":"Oranges","label":"Lemons","site":""}]}}}]}} +HOOK: empty +HOOK: BYE +Inst foo (1.0 Lemons:unstable [all]) +Conf foo (1.0 Lemons:unstable [all]) +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} HOOK: empty -HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.post","params":{"command":"install","search-terms":["foo"],"unknown-packages":[],"packages":[{"id":1,"name":"foo","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":1,"version":"1.0","architecture":"all","pin":500},"install":{"id":1,"version":"1.0","architecture":"all","pin":500}}}]}} +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.post","params":{"command":"install","search-terms":["foo"],"unknown-packages":[],"packages":[{"id":2,"name":"foo","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":2,"version":"1.0","architecture":"all","pin":500,"origins":[{"archive":"unstable","codename":"sid","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":2,"version":"1.0","architecture":"all","pin":500,"origins":[{"archive":"unstable","codename":"sid","origin":"Oranges","label":"Lemons","site":""}]}}}]}} HOOK: empty HOOK: BYE' apt install foo -s +############################# Failed dist-upgrade ####################### + +testfailureequal 'Reading package lists... +Building dependency tree... +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.fail","params":{"command":"dist-upgrade","search-terms":["foxxx"],"unknown-packages":["foxxx"],"packages":[]}} +HOOK: empty +HOOK: BYE +E: Unable to locate package foxxx' apt dist-upgrade foxxx + +############################# Success install ####################### + +testsuccessequal 'Reading package lists... +Building dependency tree... +Calculating upgrade... +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.pre-prompt","params":{"command":"dist-upgrade","search-terms":[],"unknown-packages":[],"packages":[{"id":1,"name":"upgrade","architecture":"i386","mode":"upgrade","automatic":false,"versions":{"candidate":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"current":{"id":4,"version":"1.0","architecture":"i386","pin":100,"origins":[]}}}]}} +HOOK: empty +HOOK: BYE +The following packages will be upgraded: + upgrade +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.package-list","params":{"command":"dist-upgrade","search-terms":[],"unknown-packages":[],"packages":[{"id":1,"name":"upgrade","architecture":"i386","mode":"upgrade","automatic":false,"versions":{"candidate":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"current":{"id":4,"version":"1.0","architecture":"i386","pin":100,"origins":[]}}}]}} +HOOK: empty +HOOK: BYE +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.statistics","params":{"command":"dist-upgrade","search-terms":[],"unknown-packages":[],"packages":[{"id":1,"name":"upgrade","architecture":"i386","mode":"upgrade","automatic":false,"versions":{"candidate":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"current":{"id":4,"version":"1.0","architecture":"i386","pin":100,"origins":[]}}}]}} +HOOK: empty +HOOK: BYE +Inst upgrade [1.0] (2.0 Lemons:testing [i386]) +Conf upgrade (2.0 Lemons:testing [i386]) +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.post","params":{"command":"dist-upgrade","search-terms":[],"unknown-packages":[],"packages":[{"id":1,"name":"upgrade","architecture":"i386","mode":"upgrade","automatic":false,"versions":{"candidate":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"current":{"id":4,"version":"1.0","architecture":"i386","pin":100,"origins":[]}}}]}} +HOOK: empty +HOOK: BYE' apt dist-upgrade -s + + +################## version 0.1 ######################### +TEST_HOOK_VERSION=0.1 + +testsuccessequal 'Reading package lists... +Building dependency tree... +Calculating upgrade... +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.pre-prompt","params":{"command":"dist-upgrade","search-terms":[],"unknown-packages":[],"packages":[{"id":1,"name":"upgrade","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"current":{"id":4,"version":"1.0","architecture":"i386","pin":100,"origins":[]}}}]}} +HOOK: empty +HOOK: BYE +The following packages will be upgraded: + upgrade +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.package-list","params":{"command":"dist-upgrade","search-terms":[],"unknown-packages":[],"packages":[{"id":1,"name":"upgrade","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"current":{"id":4,"version":"1.0","architecture":"i386","pin":100,"origins":[]}}}]}} +HOOK: empty +HOOK: BYE +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.statistics","params":{"command":"dist-upgrade","search-terms":[],"unknown-packages":[],"packages":[{"id":1,"name":"upgrade","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"current":{"id":4,"version":"1.0","architecture":"i386","pin":100,"origins":[]}}}]}} +HOOK: empty +HOOK: BYE +Inst upgrade [1.0] (2.0 Lemons:testing [i386]) +Conf upgrade (2.0 Lemons:testing [i386]) +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.post","params":{"command":"dist-upgrade","search-terms":[],"unknown-packages":[],"packages":[{"id":1,"name":"upgrade","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"install":{"id":1,"version":"2.0","architecture":"i386","pin":500,"origins":[{"archive":"testing","codename":"testing","origin":"Oranges","label":"Lemons","site":""}]},"current":{"id":4,"version":"1.0","architecture":"i386","pin":100,"origins":[]}}}]}} +HOOK: empty +HOOK: BYE' apt dist-upgrade -s + + +################## Wrong version ######################### +TEST_HOOK_VERSION=42 + +testfailureequal 'Reading package lists... +Building dependency tree... +Calculating upgrade... +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +HOOK: HELLO +HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1","0.2"]}} +HOOK: empty +E: Unknown hook version in handshake from hook '$HOOK': {"jsonrpc": "2.0", "result": {"version": "42"}, "id": 0} +E: Sub-process '$HOOK' returned an error code (1) +E: Failure running hook '$HOOK' +E: Unknown hook version in handshake from hook '$HOOK': {"jsonrpc": "2.0", "result": {"version": "42"}, "id": 0} +E: Sub-process '$HOOK' returned an error code (1) +E: Failure running hook '$HOOK'' apt dist-upgrade -s ################## Error in hello response ######################### cat > json-hook.sh << EOF @@ -201,9 +332,9 @@ Building dependency tree... The following NEW packages will be installed: foo -0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. -Inst foo (1.0 unstable [all]) -Conf foo (1.0 unstable [all])' apt install foo -s +0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. +Inst foo (1.0 Lemons:unstable [all]) +Conf foo (1.0 Lemons:unstable [all])' apt install foo -s diff -Nru apt-2.0.5/test/integration/test-ubuntu-bug-1921626-unsized-packages apt-2.0.6/test/integration/test-ubuntu-bug-1921626-unsized-packages --- apt-2.0.5/test/integration/test-ubuntu-bug-1921626-unsized-packages 1970-01-01 00:00:00.000000000 +0000 +++ apt-2.0.6/test/integration/test-ubuntu-bug-1921626-unsized-packages 2021-06-15 11:05:46.000000000 +0000 @@ -0,0 +1,46 @@ +#!/bin/sh +set -e + +TESTDIR="$(readlink -f "$(dirname "$0")")" +. "$TESTDIR/framework" + +setupenvironment +configarchitecture "i386" +confighashes 'SHA512' + +mkdir tree +head -c $((5*1024)) /dev/urandom > tree/data-file + +buildsimplenativepackage 'a' 'all' '1.0' 'stable' +buildsimplenativepackage 'b' 'all' '1.0' 'stable' '' '' '' '' "$PWD/tree" +buildsimplenativepackage 'c' 'all' '1.0' 'stable' + +setupaptarchive +changetowebserver + +# Disable sandbox +echo 'APT::Sandbox::User "root";' > rootdir/etc/apt/apt.conf.d/no-acquire-sandbox +# XXX: Remove temporary hack +rm rootdir/etc/apt/apt.conf.d/temporary-allow-unsized-packages + +testsuccess apt update + +for file in rootdir/var/lib/apt/lists/*Packages; do + awk '!(/^Size/ && ++cnt==2)' $file > $file.new + mv $file.new $file +done + + +size_a=$(wc -c aptarchive/pool/a_1.0_all.deb | awk '{print $1}') +size_b=$(wc -c aptarchive/pool/b_1.0_all.deb | awk '{print $1}') +size_c=$(wc -c aptarchive/pool/c_1.0_all.deb | awk '{print $1}') + +testsuccessequal "Get:1 http://localhost:${APTHTTPPORT} stable/main all a all 1.0 [$size_a B] +Get:2 http://localhost:${APTHTTPPORT} stable/main all b all 1.0 [$size_b B] +Get:3 http://localhost:${APTHTTPPORT} stable/main all c all 1.0 [$size_c B]" apt download a b c -o Acquire::AllowUnsizedPackages=true + +rm *.deb +testwarningequal "Get:1 http://localhost:${APTHTTPPORT} stable/main all a all 1.0 [$size_a B] +Get:2 http://localhost:${APTHTTPPORT} stable/main all b all 1.0 [$size_b B] +Get:3 http://localhost:${APTHTTPPORT} stable/main all c all 1.0 [$size_c B] +W: Repository is broken: b:i386 (= 1.0) has no Size information" apt download a b c diff -Nru apt-2.0.5/test/libapt/authconf_test.cc apt-2.0.6/test/libapt/authconf_test.cc --- apt-2.0.5/test/libapt/authconf_test.cc 2021-03-12 11:47:30.000000000 +0000 +++ apt-2.0.6/test/libapt/authconf_test.cc 2021-06-15 11:05:46.000000000 +0000 @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -235,11 +236,15 @@ EXPECT_EQ("foo1", U.User); EXPECT_EQ("bar", U.Password); + _error->PushToStack(); EXPECT_TRUE(fd.Seek(0)); U = URI("http://https.example/foo"); EXPECT_TRUE(MaybeAddAuth(fd, U)); EXPECT_TRUE(U.User.empty()); EXPECT_TRUE(U.Password.empty()); + EXPECT_FALSE(_error->empty()); + EXPECT_TRUE(U.Password.empty()); + _error->RevertToStack(); EXPECT_TRUE(fd.Seek(0)); U = URI("http://http.example/foo"); diff -Nru apt-2.0.5/test/libapt/json_test.cc apt-2.0.6/test/libapt/json_test.cc --- apt-2.0.5/test/libapt/json_test.cc 1970-01-01 00:00:00.000000000 +0000 +++ apt-2.0.6/test/libapt/json_test.cc 2021-06-15 11:05:46.000000000 +0000 @@ -0,0 +1,69 @@ +#include +#include "../../apt-private/private-cachefile.cc" +#include "../../apt-private/private-json-hooks.cc" +#include +#include + +TEST(JsonTest, JsonString) +{ + std::ostringstream os; + + // Check for escaping backslash and quotation marks, and ensure that we do not change number formatting + JsonWriter(os).value("H al\"l\\o").value(17); + + EXPECT_EQ("\"H al\\u0022l\\u005Co\"17", os.str()); + + for (int i = 0; i <= 0x1F; i++) + { + os.str(""); + + JsonWriter(os).encodeString(os, std::string("X") + char(i) + "Z"); + + std::string exp; + strprintf(exp, "\"X\\u%04XZ\"", i); + + EXPECT_EQ(exp, os.str()); + } +} + +TEST(JsonTest, JsonObject) +{ + std::ostringstream os; + + JsonWriter(os).beginObject().name("key").value("value").endObject(); + + EXPECT_EQ("{\"key\":\"value\"}", os.str()); +} + +TEST(JsonTest, JsonArrayAndValues) +{ + std::ostringstream os; + + JsonWriter(os).beginArray().value(0).value("value").value(1).value(true).endArray(); + + EXPECT_EQ("[0,\"value\",1,true]", os.str()); +} +TEST(JsonTest, JsonStackRegression) +{ + std::ostringstream os; + + JsonWriter w(os); + + // Nest those things deeply such that we transition states: + // object -> array -> object; -> array -> object + // Older versions never popped back and got stuck on array state. + w.beginObject(); + w.name("a").beginArray().beginObject().endObject().endArray(); + w.name("b").beginArray().beginObject().endObject().endArray(); + w.endObject(); + + EXPECT_EQ("{\"a\":[{}],\"b\":[{}]}", os.str()); +} +TEST(JsonTest, JsonNull) +{ + std::ostringstream os; + + JsonWriter(os).value(nullptr); + + EXPECT_EQ("null", os.str()); +}