summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/deb/dpkgpm.cc93
1 files changed, 58 insertions, 35 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 7c41e02b4..70e7592a7 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -143,6 +143,8 @@ namespace
// 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")),
@@ -615,9 +617,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
{
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",
@@ -690,10 +689,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
// '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)
@@ -709,6 +705,37 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
// 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;
}
@@ -752,34 +779,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
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")
@@ -803,6 +802,12 @@ void pkgDPkgPM::handleDisappearAction(string const &pkgname)
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));
@@ -1994,6 +1999,24 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
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))