From 89a1aa5dd55a3469c92720c7fcb90779f90b61f0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 6 Jun 2011 21:23:00 +0200 Subject: add a very dumb pause method to stop test-execution --- test/integration/framework | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'test') diff --git a/test/integration/framework b/test/integration/framework index cc5af798c..96cdb5f5e 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -708,3 +708,9 @@ testmarkedauto() { fi aptmark showauto 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail } + +pause() { + echo "STOPPED execution. Press enter to continue" + local IGNORE + read IGNORE +} -- cgit v1.2.3-70-g09d2 From 2e3c9d6452e69dcb5c83732fbda27b747bc997f4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 6 Jun 2011 21:29:16 +0200 Subject: * apt-pkg/indexcopy.cc: - Verify that the first line of an InRelease file is a PGP header for a signed message. Otherwise a man-in-the-middle can prefix a valid InRelease file with his own data! (CVE-2011-1829) --- apt-pkg/indexcopy.cc | 21 ++++++++++++++- debian/changelog | 6 ++++- methods/gpgv.cc | 13 +++++---- ...st-ubuntu-bug-784473-InRelease-one-message-only | 31 ++++++++++++++++++++++ 4 files changed, 64 insertions(+), 7 deletions(-) create mode 100755 test/integration/test-ubuntu-bug-784473-InRelease-one-message-only (limited to 'test') diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 064fb007c..31c577705 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -664,6 +664,21 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector &SigList, bool SigVerify::RunGPGV(std::string const &File, std::string const &FileGPG, int const &statusfd, int fd[2]) { + if (File == FileGPG) + { + #define SIGMSG "-----BEGIN PGP SIGNED MESSAGE-----\n" + char buffer[sizeof(SIGMSG)]; + FILE* gpg = fopen(File.c_str(), "r"); + if (gpg == NULL) + return _error->Errno("RunGPGV", _("Could not open file %s"), File.c_str()); + char const * const test = fgets(buffer, sizeof(buffer), gpg); + fclose(gpg); + if (test == NULL || strcmp(buffer, SIGMSG) != 0) + return _error->Error(_("File %s doesn't start with a clearsigned message"), File.c_str()); + #undef SIGMSG + } + + string const gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv"); // FIXME: remove support for deprecated APT::GPGV setting string const trustedFile = _config->Find("APT::GPGV::TrustedKeyring", _config->FindFile("Dir::Etc::Trusted")); @@ -688,7 +703,11 @@ bool SigVerify::RunGPGV(std::string const &File, std::string const &FileGPG, Args.reserve(30); if (keyrings.empty() == true) - return false; + { + // TRANSLATOR: %s is the trusted keyring parts directory + return _error->Error(_("No keyring installed in %s."), + _config->FindDir("Dir::Etc::TrustedParts").c_str()); + } Args.push_back(gpgvpath.c_str()); Args.push_back("--ignore-time-conflict"); diff --git a/debian/changelog b/debian/changelog index 971cf53b7..c2cf8257e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,6 +16,10 @@ apt (0.8.14.2) UNRELEASED; urgency=low * Galician translation update (Miguel Anxo Bouzada). Closes: #626505 [ David Kalnischkies ] + * apt-pkg/indexcopy.cc: + - Verify that the first line of an InRelease file is a PGP header + for a signed message. Otherwise a man-in-the-middle can prefix + a valid InRelease file with his own data! (CVE-2011-1829) * fix a bunch of cppcheck warnings/errors based on a patch by Niels Thykier, thanks! (Closes: #622805) * apt-pkg/depcache.cc: @@ -78,7 +82,7 @@ apt (0.8.14.2) UNRELEASED; urgency=low - show Acquire::Languages and APT::Architectures settings in 'dump' (Closes: 626739) - -- David Kalnischkies Sat, 28 May 2011 10:54:23 +0200 + -- David Kalnischkies Mon, 06 Jun 2011 21:24:28 +0200 apt (0.8.14.1) unstable; urgency=low diff --git a/methods/gpgv.cc b/methods/gpgv.cc index efe1f73f7..960c06180 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -65,13 +65,16 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, return string("Couldn't spawn new process") + strerror(errno); else if (pid == 0) { - if (SigVerify::RunGPGV(outfile, file, 3, fd) == false) + _error->PushToStack(); + bool const success = SigVerify::RunGPGV(outfile, file, 3, fd); + if (success == false) { - // TRANSLATOR: %s is the trusted keyring parts directory - ioprintf(ret, _("No keyring installed in %s."), - _config->FindDir("Dir::Etc::TrustedParts").c_str()); - return ret.str(); + string errmsg; + _error->PopMessage(errmsg); + _error->RevertToStack(); + return errmsg; } + _error->RevertToStack(); exit(111); } close(fd[1]); diff --git a/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only b/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only new file mode 100755 index 000000000..d97011914 --- /dev/null +++ b/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only @@ -0,0 +1,31 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'i386' + +insertpackage 'unstable' 'apt' 'i386' '0.8.11' + +setupaptarchive + +rm -rf rootdir/var/lib/apt/lists + +find aptarchive/ -name 'Release.gpg' -delete +find aptarchive/ -name 'InRelease' -exec cp {} {}.old \; + +for RELEASE in $(find aptarchive/ -name 'InRelease'); do + (echo 'Origin: Marvin +Label: Marvin +Suite: experimental +Codename: experimental +MD5Sum: + 65fd410587b6978de2277f2912523f09 9360 Packages + d27b294ed172a1fa9dd5a53949914c5d 4076 Packages.bz2 + 2182897e0a2a0c09e760beaae117a015 2023 Packages.diff/Index + 1b895931853981ad8204d2439821b999 4144 Packages.gz'; echo; cat ${RELEASE}.old;) > ${RELEASE} +done +aptget update -qq > /dev/null 2> starts-with-unsigned.msg +sed -i 's#File .*InRelease#File InRelease#' starts-with-unsigned.msg +testfileequal starts-with-unsigned.msg "W: GPG error: file: unstable InRelease: File InRelease doesn't start with a clearsigned message" -- cgit v1.2.3-70-g09d2 From 5b7d1ee67575e311871fb73be421ea7fd2f6fd73 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 29 Jun 2011 22:38:59 +0200 Subject: * apt-pkg/policy.cc: - do not segfault in pinning if a package with this name doesn't exist. Thanks to Ferdinand Thommes for the report! --- apt-pkg/policy.cc | 3 ++ debian/changelog | 5 ++- test/integration/test-pin-non-existent-package | 44 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100755 test/integration/test-pin-non-existent-package (limited to 'test') diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 2cc2e5e39..291d83c67 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -231,6 +231,9 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, // Get a spot to put the pin pkgCache::GrpIterator Grp = Cache->FindGrp(Name); + if (Grp.end() == true) + return; + for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) { diff --git a/debian/changelog b/debian/changelog index 5c21cc4e5..e527142c4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,8 +11,11 @@ apt (0.8.15.1) unstable; urgency=low - forgot 'mips' in the list for all architecture dependent symbols - comment out gcc-4.5 specific symbols as gcc-4.6 is now default - the symbol for PrintStatus() is architecture dependent + * apt-pkg/policy.cc: + - do not segfault in pinning if a package with this name doesn't exist. + Thanks to Ferdinand Thommes for the report! - -- David Kalnischkies Wed, 29 Jun 2011 18:46:06 +0200 + -- David Kalnischkies Wed, 29 Jun 2011 22:05:50 +0200 apt (0.8.15) unstable; urgency=low diff --git a/test/integration/test-pin-non-existent-package b/test/integration/test-pin-non-existent-package new file mode 100755 index 000000000..1031272e2 --- /dev/null +++ b/test/integration/test-pin-non-existent-package @@ -0,0 +1,44 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture "i386" + +insertpackage 'unstable' 'apt' 'i386' '0.8.15' + +setupaptarchive + +testcandidate() { + msgtest "Test that the Candidate for $1 is" $2 + test "$(aptcache policy $1 | grep '^ Candidate:')" = " Candidate: $2" && msgpass || msgfail +} + +testcandidate apt '0.8.15' +testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0 +testequal 'Reading package lists... +Building dependency tree... +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade + +echo 'Package: apt +Pin: release a=unstable +Pin-Priority: -1' > rootdir/etc/apt/preferences + +testcandidate apt '(none)' +testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0 +testequal 'Reading package lists... +Building dependency tree... +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade + +echo ' +Package: doesntexist +Pin: release a=unstable +Pin-Priority: 1000' >> rootdir/etc/apt/preferences + +testcandidate apt '(none)' +testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0 + +testequal 'Reading package lists... +Building dependency tree... +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade -- cgit v1.2.3-70-g09d2 From e2bba11c9a1858c98954e7c5299d20a6c0966cc7 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 29 Jun 2011 23:26:38 +0200 Subject: - ensure that only the first specific stanza for a package is used - save all stanzas which had no effect in Unmatched --- apt-pkg/policy.cc | 27 ++++++++++++-------------- apt-pkg/policy.h | 1 + debian/changelog | 4 +++- test/integration/test-pin-non-existent-package | 15 +++++++++++++- 4 files changed, 30 insertions(+), 17 deletions(-) (limited to 'test') diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 827c9145c..78f44d635 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -229,28 +229,25 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, return; } - // Get a spot to put the pin + // find the package group this pin applies to pkgCache::GrpIterator Grp = Cache->FindGrp(Name); if (Grp.end() == true) + { + Pin *P = &*Unmatched.insert(Unmatched.end(),PkgPin(Name)); + P->Type = Type; + P->Priority = Priority; + P->Data = Data; return; + } for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) { - Pin *P = 0; - if (Pkg.end() == false) - P = Pins + Pkg->ID; - else - { - // Check the unmatched table - for (vector::iterator I = Unmatched.begin(); - I != Unmatched.end() && P == 0; I++) - if (I->Pkg == Name) - P = &*I; - - if (P == 0) - P = &*Unmatched.insert(Unmatched.end(),PkgPin()); - } + Pin *P = Pins + Pkg->ID; + // the first specific stanza for a package is the ruler, + // all others need to be ignored + if (P->Type != pkgVersionMatch::None) + P = &*Unmatched.insert(Unmatched.end(),PkgPin(Pkg.FullName())); P->Type = Type; P->Priority = Priority; P->Data = Data; diff --git a/apt-pkg/policy.h b/apt-pkg/policy.h index f8b2678de..a5e6c6048 100644 --- a/apt-pkg/policy.h +++ b/apt-pkg/policy.h @@ -55,6 +55,7 @@ class pkgPolicy : public pkgDepCache::Policy struct PkgPin : Pin { string Pkg; + PkgPin(string const &Pkg) : Pin(), Pkg(Pkg) {}; }; Pin *Pins; diff --git a/debian/changelog b/debian/changelog index c4f7af623..77b448e77 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,8 +15,10 @@ apt (0.8.15.1) unstable; urgency=low - do not segfault in pinning if a package with this name doesn't exist. Thanks to Ferdinand Thommes for the report! - Defaults is a vector of Pin not of PkgPin + - ensure that only the first specific stanza for a package is used + - save all stanzas which had no effect in Unmatched - -- David Kalnischkies Wed, 29 Jun 2011 23:15:35 +0200 + -- David Kalnischkies Wed, 29 Jun 2011 23:21:12 +0200 apt (0.8.15) unstable; urgency=low diff --git a/test/integration/test-pin-non-existent-package b/test/integration/test-pin-non-existent-package index 1031272e2..bd6ccc476 100755 --- a/test/integration/test-pin-non-existent-package +++ b/test/integration/test-pin-non-existent-package @@ -12,7 +12,13 @@ setupaptarchive testcandidate() { msgtest "Test that the Candidate for $1 is" $2 - test "$(aptcache policy $1 | grep '^ Candidate:')" = " Candidate: $2" && msgpass || msgfail + if [ "$(aptcache policy $1 | grep '^ Candidate:')" = " Candidate: $2" ]; then + msgpass + else + echo + aptcache policy $1 + msgfail + fi } testcandidate apt '0.8.15' @@ -36,6 +42,13 @@ Package: doesntexist Pin: release a=unstable Pin-Priority: 1000' >> rootdir/etc/apt/preferences +testcandidate apt '(none)' + +echo ' +Package: apt +Pin: release a=unstable +Pin-Priority: 1000' >> rootdir/etc/apt/preferences + testcandidate apt '(none)' testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0 -- cgit v1.2.3-70-g09d2 From 9164e147eb78de6b4f8c8ce4b71e93ad71a44725 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 30 Jun 2011 00:03:26 +0200 Subject: allow package:architecure in Package: --- apt-pkg/policy.cc | 40 ++++++++++++++++++++------ debian/changelog | 3 +- test/integration/test-pin-non-existent-package | 15 ++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 78f44d635..bd213e0ce 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -216,7 +216,14 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, P->Data = Data; return; } - + + size_t found = Name.rfind(':'); + string Arch; + if (found != string::npos) { + Arch = Name.substr(found+1); + Name.erase(found); + } + // Allow pinning by wildcards // TODO: Maybe we should always prefer specific pins over non- // specific ones. @@ -225,23 +232,38 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, pkgVersionMatch match(Data, Type); for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() != true; ++G) if (match.ExpressionMatches(Name, G.Name())) - CreatePin(Type, G.Name(), Data, Priority); + { + if (Arch.empty() == false) + CreatePin(Type, string(G.Name()).append(":").append(Arch), Data, Priority); + else + CreatePin(Type, G.Name(), Data, Priority); + } return; } - // find the package group this pin applies to - pkgCache::GrpIterator Grp = Cache->FindGrp(Name); - if (Grp.end() == true) + // find the package (group) this pin applies to + pkgCache::GrpIterator Grp; + pkgCache::PkgIterator Pkg; + if (Arch.empty() == false) + Pkg = Cache->FindPkg(Name, Arch); + else { + Grp = Cache->FindGrp(Name); + if (Grp.end() == false) + Pkg = Grp.PackageList(); + } + + if (Pkg.end() == true) { - Pin *P = &*Unmatched.insert(Unmatched.end(),PkgPin(Name)); + PkgPin *P = &*Unmatched.insert(Unmatched.end(),PkgPin(Name)); + if (Arch.empty() == false) + P->Pkg.append(":").append(Arch); P->Type = Type; P->Priority = Priority; P->Data = Data; return; } - for (pkgCache::PkgIterator Pkg = Grp.PackageList(); - Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) + for (; Pkg.end() != true; Pkg = Grp.NextPkg(Pkg)) { Pin *P = Pins + Pkg->ID; // the first specific stanza for a package is the ruler, @@ -251,6 +273,8 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, P->Type = Type; P->Priority = Priority; P->Data = Data; + if (Grp.end() == true) + break; } } /*}}}*/ diff --git a/debian/changelog b/debian/changelog index 77b448e77..03a314679 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,8 +17,9 @@ apt (0.8.15.1) unstable; urgency=low - Defaults is a vector of Pin not of PkgPin - ensure that only the first specific stanza for a package is used - save all stanzas which had no effect in Unmatched + - allow package:architecure in Package: - -- David Kalnischkies Wed, 29 Jun 2011 23:21:12 +0200 + -- David Kalnischkies Thu, 30 Jun 2011 00:02:15 +0200 apt (0.8.15) unstable; urgency=low diff --git a/test/integration/test-pin-non-existent-package b/test/integration/test-pin-non-existent-package index bd6ccc476..c91e77844 100755 --- a/test/integration/test-pin-non-existent-package +++ b/test/integration/test-pin-non-existent-package @@ -7,6 +7,7 @@ setupenvironment configarchitecture "i386" insertpackage 'unstable' 'apt' 'i386' '0.8.15' +insertpackage 'unstable' 'arch' 'i386' '1.0' setupaptarchive @@ -55,3 +56,17 @@ testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist testequal 'Reading package lists... Building dependency tree... 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade + +echo 'Package: arch:amd64 +Pin: release a=unstable +Pin-Priority: -1' > rootdir/etc/apt/preferences + +testcandidate arch '1.0' + +echo ' +Package: arch:i386 +Pin: release a=unstable +Pin-Priority: -1' >> rootdir/etc/apt/preferences + +testcandidate arch '(none)' + -- cgit v1.2.3-70-g09d2 From b41929c0139d0658046fb4e4088a8de167705a99 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 6 Jul 2011 12:46:29 +0200 Subject: * cmdline/apt-get.cc: - restore all important dependencies for garbage packages (LP: #806274) --- cmdline/apt-get.cc | 6 +- debian/changelog | 4 +- .../test-ubuntu-bug-806274-install-suggests | 81 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 4 deletions(-) create mode 100755 test/integration/test-ubuntu-bug-806274-install-suggests (limited to 'test') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 845c92026..3292ae745 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1697,7 +1697,7 @@ bool DoAutomaticRemove(CacheFile &Cache) // we could have removed a new dependency of a garbage package, // so check if a reverse depends is broken and if so install it again. - if (tooMuch.empty() == false && Cache->BrokenCount() != 0) + if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0)) { bool Changed; do { @@ -1708,8 +1708,8 @@ bool DoAutomaticRemove(CacheFile &Cache) for (pkgCache::DepIterator R = P.RevDependsList(); R.end() == false; ++R) { - if (R->Type != pkgCache::Dep::Depends && - R->Type != pkgCache::Dep::PreDepends) + if (R.IsNegative() == true || + Cache->IsImportantDep(R) == false) continue; pkgCache::PkgIterator N = R.ParentPkg(); if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false)) diff --git a/debian/changelog b/debian/changelog index af7e792db..4b70eec55 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,8 +8,10 @@ apt (0.8.15.2) unstable; urgency=low - document available [options] for sources.list entries (Closes: 632441) * doc/apt.conf.5.xml: - document APT::Architectures list (Closes: #612102) + * cmdline/apt-get.cc: + - restore all important dependencies for garbage packages (LP: #806274) - -- David Kalnischkies Tue, 05 Jul 2011 15:31:55 +0200 + -- David Kalnischkies Wed, 06 Jul 2011 12:44:58 +0200 apt (0.8.15.1) unstable; urgency=low diff --git a/test/integration/test-ubuntu-bug-806274-install-suggests b/test/integration/test-ubuntu-bug-806274-install-suggests new file mode 100755 index 000000000..fb72f0999 --- /dev/null +++ b/test/integration/test-ubuntu-bug-806274-install-suggests @@ -0,0 +1,81 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture "i386" + +insertpackage 'unstable' 'apt' 'i386' '0.8.15' 'Depends: foo +Recommends: bar +Suggests: baz' +insertpackage 'unstable' 'foo' 'i386' '1.0' +insertpackage 'unstable' 'bar' 'i386' '1.0' +insertpackage 'unstable' 'baz' 'i386' '1.0' + +setupaptarchive + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + bar foo +Suggested packages: + baz +The following NEW packages will be installed: + apt bar foo +0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1.0 unstable [i386]) +Conf foo (1.0 unstable [i386]) +Inst apt (0.8.15 unstable [i386]) +Conf apt (0.8.15 unstable [i386]) +Inst bar (1.0 unstable [i386]) +Conf bar (1.0 unstable [i386])' aptget install apt -s --install-recommends --no-install-suggests + + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + bar baz foo +The following NEW packages will be installed: + apt bar baz foo +0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1.0 unstable [i386]) +Conf foo (1.0 unstable [i386]) +Inst apt (0.8.15 unstable [i386]) +Conf apt (0.8.15 unstable [i386]) +Inst bar (1.0 unstable [i386]) +Inst baz (1.0 unstable [i386]) +Conf bar (1.0 unstable [i386]) +Conf baz (1.0 unstable [i386])' aptget install apt -s --install-recommends --install-suggests + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo +Suggested packages: + baz +Recommended packages: + bar +The following NEW packages will be installed: + apt foo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1.0 unstable [i386]) +Conf foo (1.0 unstable [i386]) +Inst apt (0.8.15 unstable [i386]) +Conf apt (0.8.15 unstable [i386])' aptget install apt -s --no-install-recommends --no-install-suggests + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + baz foo +Recommended packages: + bar +The following NEW packages will be installed: + apt baz foo +0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1.0 unstable [i386]) +Conf foo (1.0 unstable [i386]) +Inst apt (0.8.15 unstable [i386]) +Conf apt (0.8.15 unstable [i386]) +Inst baz (1.0 unstable [i386]) +Conf baz (1.0 unstable [i386])' aptget install apt -s --no-install-recommends --install-suggests -- cgit v1.2.3-70-g09d2