// of each array is the key, entry 1 is the value.
const std::pair<const char *, const char *> PackageProcessingOps[] = {
std::make_pair("install", N_("Installing %s")),
+ // we don't care for the difference
+ std::make_pair("upgrade", N_("Installing %s")),
std::make_pair("configure", N_("Configuring %s")),
std::make_pair("remove", N_("Removing %s")),
std::make_pair("purge", N_("Completely removing %s")),
{
pkgname = APT::String::Strip(list[2]);
action = APT::String::Strip(list[1]);
- // we don't care for the difference (as dpkg doesn't really either)
- if (action == "upgrade")
- action = "install";
}
// "status" has the form: "status: pkg: state"
// with state in ["half-installed", "unpacked", "half-configured",
// 'processing: action: pkg'
if(prefix == "processing")
{
- const std::pair<const char *, const char *> * const iter =
- std::find_if(PackageProcessingOpsBegin,
- PackageProcessingOpsEnd,
- MatchProcessingOp(action.c_str()));
+ auto const iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, MatchProcessingOp(action.c_str()));
if(iter == PackageProcessingOpsEnd)
{
if (Debug == true)
// short pkgnames?
if (action == "disappear")
handleDisappearAction(pkgname);
+ else if (action == "upgrade")
+ {
+ // in a crossgrade what looked like a remove first is really an unpack over it
+ auto const Pkg = Cache.FindPkg(pkgname);
+ if (likely(Pkg.end() == false) && Cache[Pkg].Delete())
+ {
+ auto const Grp = Pkg.Group();
+ if (likely(Grp.end() == false))
+ {
+ for (auto P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P))
+ if(Cache[P].Install())
+ {
+ auto && Ops = PackageOps[P.FullName()];
+ auto const unpackOp = std::find_if(Ops.cbegin(), Ops.cend(), [](DpkgState const &s) { return strcmp(s.state, "unpacked") == 0; });
+ if (unpackOp != Ops.cend())
+ {
+ // skip ahead in the crossgraded packages
+ auto const skipped = std::distance(Ops.cbegin(), unpackOp);
+ PackagesDone += skipped;
+ PackageOpsDone[P.FullName()] += skipped;
+ // finish the crossremoved package
+ auto const ROps = PackageOps[Pkg.FullName()].size();
+ auto && ROpsDone = PackageOpsDone[Pkg.FullName()];
+ PackagesDone += ROps - ROpsDone;
+ ROpsDone = ROps;
+ break;
+ }
+ }
+ }
+ }
+ }
return;
}
strprintf(msg, translation, i18n_pkgname.c_str());
d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg);
}
- else if (action == "unpacked" && strcmp(next_action, "config-files") == 0)
- {
- // in a crossgrade what looked like a remove first is really an unpack over it
- ++PackageOpsDone[pkgname];
- ++PackagesDone;
-
- auto const Pkg = Cache.FindPkg(pkgname);
- if (likely(Pkg.end() == false))
- {
- auto const Grp = Pkg.Group();
- if (likely(Grp.end() == false))
- {
- for (auto P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P))
- if(Cache[P].Install())
- {
- auto && Ops = PackageOps[P.FullName()];
- auto const unpackOp = std::find_if(Ops.cbegin(), Ops.cend(), [](DpkgState const &s) { return strcmp(s.state, "unpacked") == 0; });
- if (unpackOp != Ops.cend())
- {
- auto const skipped = std::distance(Ops.cbegin(), unpackOp);
- PackagesDone += skipped;
- PackageOpsDone[P.FullName()] += skipped;
- break;
- }
- }
- }
- }
- }
}
}
else if (action == "triggers-pending")
if (unlikely(Pkg.end() == true))
return;
+ // a disappeared package has no further actions
+ auto const ROps = PackageOps[Pkg.FullName()].size();
+ auto && ROpsDone = PackageOpsDone[Pkg.FullName()];
+ PackagesDone += ROps - ROpsDone;
+ ROpsDone = ROps;
+
// record the package name for display and stuff later
disappearedPkgs.insert(Pkg.FullName(true));
if (noopDPkgInvocation == false)
{
+ if (d->dpkg_error.empty() && (PackagesDone + 1) != PackagesTotal)
+ {
+ std::string pkglist;
+ for (auto const &PO: PackageOps)
+ if (PO.second.size() != PackageOpsDone[PO.first])
+ {
+ if (pkglist.empty() == false)
+ pkglist.append(" ");
+ pkglist.append(PO.first);
+ }
+ /* who cares about correct progress? As we depend on it for skipping actions
+ our parsing should be correct. People will no doubt be confused if they see
+ this message, but the dpkg warning about unknown packages isn't much better
+ from a user POV and combined we might have a chance to figure out what is wrong */
+ _error->Warning("APT had planned for dpkg to do more than it reported back (%u vs %u).\n"
+ "Affected packages: %s", PackagesDone, PackagesTotal, pkglist.c_str());
+ }
+
std::string const oldpkgcache = _config->FindFile("Dir::cache::pkgcache");
if (oldpkgcache.empty() == false && RealFileExists(oldpkgcache) == true &&
RemoveFile("pkgDPkgPM::Go", oldpkgcache))
TESTDIR="$(readlink -f "$(dirname "$0")")"
. "$TESTDIR/framework"
setupenvironment
-configarchitecture 'native'
+configarchitecture 'amd64' 'i386'
-buildsimplenativepackage 'old-pkg' 'native' '1.0' 'stable'
-buildsimplenativepackage 'unrelated' 'all' '0.5' 'unstable'
+buildsimplenativepackage 'old-pkg' 'amd64' '1' 'stable'
-setupsimplenativepackage 'new-pkg' 'native' '2.0' 'unstable' 'Provides: old-pkg
+setupsimplenativepackage 'new-pkg' 'amd64' '2' 'unstable' 'Provides: old-pkg
Replaces: old-pkg
-Conflicts: old-pkg (<< 2.0)'
-BUILDDIR='incoming/new-pkg-2.0'
+Conflicts: old-pkg (<< 2)'
+BUILDDIR='incoming/new-pkg-2'
echo '/usr/share/doc/new-pkg /usr/share/doc/old-pkg' > "${BUILDDIR}/debian/new-pkg.links"
buildpackage "$BUILDDIR" 'unstable' 'main'
rm -rf "$BUILDDIR"
-setupsimplenativepackage 'old-pkg' 'all' '2.0' 'unstable' 'Depends: new-pkg'
-BUILDDIR='incoming/old-pkg-2.0'
+setupsimplenativepackage 'old-pkg' 'all' '2' 'unstable' 'Depends: new-pkg'
+BUILDDIR='incoming/old-pkg-2'
echo '/usr/share/doc/new-pkg /usr/share/doc/old-pkg' > "${BUILDDIR}/debian/old-pkg.links"
echo "
override_dh_link:
buildpackage "$BUILDDIR" 'unstable' 'main'
rm -rf "$BUILDDIR"
-setupaptarchive
+setupsimplenativepackage 'super-new-pkg' 'i386' '3' 'experimental' 'Provides: new-pkg
+Replaces: new-pkg
+Conflicts: new-pkg (<< 3)'
+BUILDDIR='incoming/super-new-pkg-3'
+echo '/usr/share/doc/super-new-pkg /usr/share/doc/old-pkg' > "${BUILDDIR}/debian/super-new-pkg.links"
+echo '/usr/share/doc/super-new-pkg /usr/share/doc/new-pkg' >> "${BUILDDIR}/debian/super-new-pkg.links"
+buildpackage "$BUILDDIR" 'experimental' 'main'
+rm -rf "$BUILDDIR"
+
+setupsimplenativepackage 'new-pkg' 'all' '3' 'experimental' 'Depends: super-new-pkg'
+BUILDDIR='incoming/new-pkg-3'
+echo '/usr/share/doc/super-new-pkg /usr/share/doc/old-pkg' > "${BUILDDIR}/debian/new-pkg.links"
+echo '/usr/share/doc/super-new-pkg /usr/share/doc/new-pkg' >> "${BUILDDIR}/debian/new-pkg.links"
+echo "
+override_dh_link:
+ rm -rf debian/new-pkg/usr/share/doc/new-pkg/
+ dh_link" >> "${BUILDDIR}/debian/rules"
+buildpackage "$BUILDDIR" 'experimental' 'main'
+rm -rf "$BUILDDIR"
-testsuccess aptget install old-pkg=1.0 --trivial-only
+setupaptarchive
+msgmsg 'Let a package disappear' 'old-pkg'
+testsuccess aptget install old-pkg=1 --trivial-only
testmarkedauto # old-pkg is manual installed
-
-CMD='aptget dist-upgrade -y'
-msgtest 'Test for equality of' "$CMD"
-COMPAREFILE="$(mktemp)"
-echo 'The following package disappeared from your system as
+testsuccess aptget dist-upgrade -y
+testdpkgnotinstalled old-pkg
+cp rootdir/tmp/testsuccess.output disappear.output
+testsuccessequal 'The following package disappeared from your system as
all files have been overwritten by other packages:
old-pkg
-Note: This is done automatically and on purpose by dpkg.' > "$COMPAREFILE"
-$CMD 2>&1 | tail -n 4 | diff -u "$COMPAREFILE" - && msgpass || msgfail
-rm "$COMPAREFILE"
+Note: This is done automatically and on purpose by dpkg.' tail -n 4 disappear.output
sed -i rootdir/var/log/apt/history.log -e '/^Commandline: / d' -e '/^Start-Date: / d' -e '/^End-Date: / d' -e "s#:$(getarchitecture 'native') #:native #"
if [ -n "$SUDO_USER" ]; then
testfileequal 'rootdir/var/log/apt/history.log' "
Requested-By: $SUDO_USER ($(id -u "$SUDO_USER"))
-Install: old-pkg:native (1.0)
+Install: old-pkg:native (1)
Requested-By: $SUDO_USER ($(id -u "$SUDO_USER"))
-Install: new-pkg:native (2.0, automatic)
-Upgrade: old-pkg:native (1.0, 2.0)
-Disappeared: old-pkg (1.0)"
+Install: new-pkg:native (2, automatic)
+Upgrade: old-pkg:native (1, 2)
+Disappeared: old-pkg (1)"
else
testfileequal 'rootdir/var/log/apt/history.log' '
-Install: old-pkg:native (1.0)
+Install: old-pkg:native (1)
-Install: new-pkg:native (2.0, automatic)
-Upgrade: old-pkg:native (1.0, 2.0)
-Disappeared: old-pkg (1.0)'
+Install: new-pkg:native (2, automatic)
+Upgrade: old-pkg:native (1, 2)
+Disappeared: old-pkg (1)'
fi
testmarkedauto # new-pkg should have get the manual flag from old-pkg
+
+msgmsg 'Let a package disappear which let the previous disappear' 'new-pkg'
+testsuccess aptget dist-upgrade -y -t experimental
+testdpkgnotinstalled new-pkg
+cp rootdir/tmp/testsuccess.output disappear.output
+testsuccessequal 'The following package disappeared from your system as
+all files have been overwritten by other packages:
+ new-pkg
+Note: This is done automatically and on purpose by dpkg.' tail -n 4 disappear.output
+
+testmarkedauto