From facea693b2078327b59502e663c238c50118e96a Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 18 Sep 2013 17:55:44 +0200 Subject: improve the API for Upgrade() --- apt-pkg/algorithms.cc | 38 ++++++++++++++++++++++++++++++-------- apt-pkg/algorithms.h | 12 ++++++++++-- apt-private/private-upgrade.cc | 2 +- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 69d4acd83..68531f3ca 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -422,12 +422,8 @@ bool pkgDistUpgrade(pkgDepCache &Cache) return Fix.Resolve(); } /*}}}*/ -// AllUpgrade - Upgrade as many packages as possible /*{{{*/ -// --------------------------------------------------------------------- -/* Right now the system must be consistent before this can be called. - It also will not change packages marked for install, it only tries - to install packages not marked for install */ -bool pkgAllUpgrade(pkgDepCache &Cache) +// AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/ +bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache) { std::string const solver = _config->Find("APT::Solver", "internal"); if (solver != "internal") { @@ -459,13 +455,13 @@ bool pkgAllUpgrade(pkgDepCache &Cache) return Fix.ResolveByKeep(); } /*}}}*/ -// AllUpgradeNoDelete - Upgrade without removing packages /*{{{*/ +// AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/ // --------------------------------------------------------------------- /* Right now the system must be consistent before this can be called. * Upgrade as much as possible without deleting anything (useful for * stable systems) */ -bool pkgAllUpgradeNoDelete(pkgDepCache &Cache) +bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache) { pkgDepCache::ActionGroup group(Cache); @@ -502,6 +498,16 @@ bool pkgAllUpgradeNoDelete(pkgDepCache &Cache) return Fix.ResolveByKeep(); } /*}}}*/ +// AllUpgrade - Upgrade as many packages as possible /*{{{*/ +// --------------------------------------------------------------------- +/* Right now the system must be consistent before this can be called. + It also will not change packages marked for install, it only tries + to install packages not marked for install */ +bool pkgAllUpgrade(pkgDepCache &Cache) +{ + return pkgAllUpgradeNoNewPackages(Cache); +} + /*}}}*/ // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/ // --------------------------------------------------------------------- /* This simply goes over the entire set of packages and tries to keep @@ -547,6 +553,22 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache) return true; } /*}}}*/ +// APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/ +bool APT::Upgrade::Upgrade(pkgDepCache &Cache, APT::Upgrade::UpgradeMode mode) +{ + switch(mode) { + case APT::Upgrade::NO_INSTALL_OR_REMOVE: + return pkgAllUpgradeNoNewPackages(Cache); + case APT::Upgrade::ALLOW_NEW_INSTALLS: + return pkgAllUpgradeWithNewPackages(Cache); + case APT::Upgrade::ALLOW_REMOVAL_AND_NEW_INSTALLS: + return pkgDistUpgrade(Cache); + default: + _error->Error("pkgAllUpgrade called with unknwon mode %i", mode); + } + return false; +} + /*}}}*/ // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index a499db8ba..9ff84e3ff 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -45,6 +45,15 @@ using std::ostream; class pkgAcquireStatus; +namespace APT { + namespace Upgrade { + enum UpgradeMode {NO_INSTALL_OR_REMOVE, + ALLOW_NEW_INSTALLS, + ALLOW_REMOVAL_AND_NEW_INSTALLS}; + bool Upgrade(pkgDepCache &Cache, UpgradeMode mode); + } +} + class pkgSimulate : public pkgPackageManager /*{{{*/ { protected: @@ -85,6 +94,7 @@ private: /*}}}*/ class pkgProblemResolver /*{{{*/ { + private: /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -146,8 +156,6 @@ bool pkgFixBroken(pkgDepCache &Cache); bool pkgAllUpgrade(pkgDepCache &Cache); -bool pkgAllUpgradeNoDelete(pkgDepCache &Cache); - bool pkgMinimizeUpgrade(pkgDepCache &Cache); void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc index 9a5286b57..6ea7c19d6 100644 --- a/apt-private/private-upgrade.cc +++ b/apt-private/private-upgrade.cc @@ -39,7 +39,7 @@ bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL) return false; // Do the upgrade - if (pkgAllUpgradeNoDelete(Cache) == false) + if (APT::Upgrade::Upgrade(Cache, APT::Upgrade::ALLOW_NEW_INSTALLS) == false) { ShowBroken(c1out,Cache,false); return _error->Error(_("Internal error, AllUpgrade broke stuff")); -- cgit v1.2.3 From 5ca0cf51194422fb0f094bbf5e61e9f5eb57f013 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 5 Oct 2013 11:54:08 +0200 Subject: cleanup upgrade API some more (thanks for the feedback from David) --- apt-pkg/algorithms.cc | 25 +++++++++++-------- apt-pkg/algorithms.h | 10 +++++--- apt-private/private-upgrade.cc | 55 +++++++++++++++++++++++------------------- apt-private/private-upgrade.h | 1 + cmdline/apt-get.cc | 26 -------------------- 5 files changed, 52 insertions(+), 65 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 68531f3ca..b015ed20e 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -554,18 +554,23 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache) } /*}}}*/ // APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/ -bool APT::Upgrade::Upgrade(pkgDepCache &Cache, APT::Upgrade::UpgradeMode mode) +bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode) { - switch(mode) { - case APT::Upgrade::NO_INSTALL_OR_REMOVE: - return pkgAllUpgradeNoNewPackages(Cache); - case APT::Upgrade::ALLOW_NEW_INSTALLS: - return pkgAllUpgradeWithNewPackages(Cache); - case APT::Upgrade::ALLOW_REMOVAL_AND_NEW_INSTALLS: - return pkgDistUpgrade(Cache); - default: - _error->Error("pkgAllUpgrade called with unknwon mode %i", mode); + if (mode == 0) + { + return pkgDistUpgrade(Cache); + } + else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0) + { + return pkgAllUpgradeWithNewPackages(Cache); + } + else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_NEW_INSTALL_PACKAGES)) == 0) + { + return pkgAllUpgradeNoNewPackages(Cache); } + else + _error->Error("pkgAllUpgrade called with unsupported mode %i", mode); + return false; } /*}}}*/ diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 9ff84e3ff..d0de72462 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -47,10 +47,12 @@ class pkgAcquireStatus; namespace APT { namespace Upgrade { - enum UpgradeMode {NO_INSTALL_OR_REMOVE, - ALLOW_NEW_INSTALLS, - ALLOW_REMOVAL_AND_NEW_INSTALLS}; - bool Upgrade(pkgDepCache &Cache, UpgradeMode mode); + // FIXME: make this "enum class UpgradeMode {" once we enable c++11 + enum UpgradeMode { + FORBID_REMOVE_PACKAGES = 1, + FORBID_NEW_INSTALL_PACKAGES = 2, + }; + bool Upgrade(pkgDepCache &Cache, int UpgradeMode); } } diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc index 6ea7c19d6..00608866f 100644 --- a/apt-private/private-upgrade.cc +++ b/apt-private/private-upgrade.cc @@ -1,54 +1,59 @@ // Includes /*{{{*/ #include - +#include #include "private-install.h" #include "private-cachefile.h" #include "private-upgrade.h" #include "private-output.h" /*}}}*/ -// DoUpgradeNoNewPackages - Upgrade all packages /*{{{*/ -// --------------------------------------------------------------------- -/* Upgrade all packages without installing new packages or erasing old - packages */ -bool DoUpgradeNoNewPackages(CommandLine &CmdL) +// this is actually performing the various upgrade operations +static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags) { CacheFile Cache; if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; - // Do the upgrade - if (pkgAllUpgrade(Cache) == false) + //c0out << _("Calculating upgrade... ") << std::flush; + if (APT::Upgrade::Upgrade(Cache, UpgradeFlags) == false) { + c0out << _("Failed") << std::endl; ShowBroken(c1out,Cache,false); - return _error->Error(_("Internal error, AllUpgrade broke stuff")); + return _error->Error(_("Internal error, Upgrade broke stuff")); } // parse additional cmdline pkg manipulation switches if(!DoCacheManipulationFromCommandLine(CmdL, Cache)) return false; + + //c0out << _("Done") << std::endl; return InstallPackages(Cache,true); } + +// DoDistUpgrade - Automatic smart upgrader /*{{{*/ +// --------------------------------------------------------------------- +/* Intelligent upgrader that will install and remove packages at will */ +bool DoDistUpgrade(CommandLine &CmdL) +{ + return UpgradeHelper(CmdL, 0); +} + /*}}}*/ +// DoUpgradeNoNewPackages - Upgrade all packages /*{{{*/ +// --------------------------------------------------------------------- +/* Upgrade all packages without installing new packages or erasing old + packages */ +bool DoUpgradeNoNewPackages(CommandLine &CmdL) +{ + // Do the upgrade + return UpgradeHelper(CmdL, + APT::Upgrade::FORBID_REMOVE_PACKAGES| + APT::Upgrade::FORBID_NEW_INSTALL_PACKAGES); +} /*}}}*/ // DoSafeUpgrade - Upgrade all packages with install but not remove /*{{{*/ bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL) { - CacheFile Cache; - if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) - return false; - - // Do the upgrade - if (APT::Upgrade::Upgrade(Cache, APT::Upgrade::ALLOW_NEW_INSTALLS) == false) - { - ShowBroken(c1out,Cache,false); - return _error->Error(_("Internal error, AllUpgrade broke stuff")); - } - - // parse additional cmdline pkg manipulation switches - if(!DoCacheManipulationFromCommandLine(CmdL, Cache)) - return false; - - return InstallPackages(Cache,true); + return UpgradeHelper(CmdL, APT::Upgrade::FORBID_REMOVE_PACKAGES); } /*}}}*/ diff --git a/apt-private/private-upgrade.h b/apt-private/private-upgrade.h index 6ede6f96c..050d3a668 100644 --- a/apt-private/private-upgrade.h +++ b/apt-private/private-upgrade.h @@ -4,6 +4,7 @@ #include +bool DoDistUpgrade(CommandLine &CmdL); bool DoUpgradeNoNewPackages(CommandLine &CmdL); bool DoUpgradeWithAllowNewPackages(CommandLine &CmdL); diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 8a30ac38d..64c7506ae 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -342,32 +342,6 @@ bool DoMarkAuto(CommandLine &CmdL) return false; } /*}}}*/ -// DoDistUpgrade - Automatic smart upgrader /*{{{*/ -// --------------------------------------------------------------------- -/* Intelligent upgrader that will install and remove packages at will */ -bool DoDistUpgrade(CommandLine &CmdL) -{ - CacheFile Cache; - if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) - return false; - - c0out << _("Calculating upgrade... ") << flush; - if (pkgDistUpgrade(*Cache) == false) - { - c0out << _("Failed") << endl; - ShowBroken(c1out,Cache,false); - return false; - } - - // parse additional cmdline pkg manipulation switches - if(!DoCacheManipulationFromCommandLine(CmdL, Cache)) - return false; - - c0out << _("Done") << endl; - - return InstallPackages(Cache,true); -} - /*}}}*/ // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/ // --------------------------------------------------------------------- /* Follows dselect's selections */ -- cgit v1.2.3 From 7cf45682e5fcac541e495242bdc4885bbb8b2ef7 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 5 Oct 2013 11:55:08 +0200 Subject: re-add "Calculating upgrade..." message --- apt-private/private-upgrade.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc index 00608866f..df8fe8686 100644 --- a/apt-private/private-upgrade.cc +++ b/apt-private/private-upgrade.cc @@ -14,19 +14,18 @@ static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags) if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; - //c0out << _("Calculating upgrade... ") << std::flush; + c0out << _("Calculating upgrade... ") << std::flush; if (APT::Upgrade::Upgrade(Cache, UpgradeFlags) == false) { c0out << _("Failed") << std::endl; ShowBroken(c1out,Cache,false); return _error->Error(_("Internal error, Upgrade broke stuff")); } + c0out << _("Done") << std::endl; // parse additional cmdline pkg manipulation switches if(!DoCacheManipulationFromCommandLine(CmdL, Cache)) return false; - - //c0out << _("Done") << std::endl; return InstallPackages(Cache,true); } -- cgit v1.2.3 From 82e369c4b93b5b81db7988ab377a3c5bd388268e Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 5 Oct 2013 12:15:03 +0200 Subject: * move upgrade releated code into upgrade.{cc,h} The upgrade releated code is moved into upgrade.{cc,h} and all pkg*Upgrade* prototypes are included in algorihms.h to avoid breaking API (unless build with APT_9_CLEANER_HEADERS). --- apt-pkg/algorithms.cc | 238 ----------------------------------- apt-pkg/algorithms.h | 20 +-- apt-pkg/makefile | 5 +- apt-pkg/upgrade.cc | 263 +++++++++++++++++++++++++++++++++++++++ apt-pkg/upgrade.h | 29 +++++ apt-private/private-cachefile.cc | 1 + apt-private/private-upgrade.cc | 1 + buildlib/config.h.in | 1 + cmdline/apt-get.cc | 2 +- cmdline/apt-internal-solver.cc | 1 + 10 files changed, 305 insertions(+), 256 deletions(-) create mode 100644 apt-pkg/upgrade.cc create mode 100644 apt-pkg/upgrade.h diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index b015ed20e..22701f8a6 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -336,244 +336,6 @@ bool pkgFixBroken(pkgDepCache &Cache) return Fix.Resolve(true); } /*}}}*/ -// DistUpgrade - Distribution upgrade /*{{{*/ -// --------------------------------------------------------------------- -/* This autoinstalls every package and then force installs every - pre-existing package. This creates the initial set of conditions which - most likely contain problems because too many things were installed. - - The problem resolver is used to resolve the problems. - */ -bool pkgDistUpgrade(pkgDepCache &Cache) -{ - std::string const solver = _config->Find("APT::Solver", "internal"); - if (solver != "internal") { - OpTextProgress Prog(*_config); - return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog); - } - - pkgDepCache::ActionGroup group(Cache); - - /* Upgrade all installed packages first without autoinst to help the resolver - in versioned or-groups to upgrade the old solver instead of installing - a new one (if the old solver is not the first one [anymore]) */ - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if (I->CurrentVer != 0) - Cache.MarkInstall(I, false, 0, false); - - /* Auto upgrade all installed packages, this provides the basis - for the installation */ - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if (I->CurrentVer != 0) - Cache.MarkInstall(I, true, 0, false); - - /* Now, install each essential package which is not installed - (and not provided by another package in the same name group) */ - std::string essential = _config->Find("pkgCacheGen::Essential", "all"); - if (essential == "all") - { - for (pkgCache::GrpIterator G = Cache.GrpBegin(); G.end() == false; ++G) - { - bool isEssential = false; - bool instEssential = false; - for (pkgCache::PkgIterator P = G.PackageList(); P.end() == false; P = G.NextPkg(P)) - { - if ((P->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential) - continue; - isEssential = true; - if (Cache[P].Install() == true) - { - instEssential = true; - break; - } - } - if (isEssential == false || instEssential == true) - continue; - pkgCache::PkgIterator P = G.FindPreferredPkg(); - Cache.MarkInstall(P, true, 0, false); - } - } - else if (essential != "none") - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) - Cache.MarkInstall(I, true, 0, false); - - /* We do it again over all previously installed packages to force - conflict resolution on them all. */ - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if (I->CurrentVer != 0) - Cache.MarkInstall(I, false, 0, false); - - pkgProblemResolver Fix(&Cache); - - // Hold back held packages. - if (_config->FindB("APT::Ignore-Hold",false) == false) - { - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - { - if (I->SelectedState == pkgCache::State::Hold) - { - Fix.Protect(I); - Cache.MarkKeep(I, false, false); - } - } - } - - return Fix.Resolve(); -} - /*}}}*/ -// AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/ -bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache) -{ - std::string const solver = _config->Find("APT::Solver", "internal"); - if (solver != "internal") { - OpTextProgress Prog(*_config); - return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog); - } - - pkgDepCache::ActionGroup group(Cache); - - pkgProblemResolver Fix(&Cache); - - if (Cache.BrokenCount() != 0) - return false; - - // Upgrade all installed packages - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - { - if (Cache[I].Install() == true) - Fix.Protect(I); - - if (_config->FindB("APT::Ignore-Hold",false) == false) - if (I->SelectedState == pkgCache::State::Hold) - continue; - - if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) - Cache.MarkInstall(I, false, 0, false); - } - - return Fix.ResolveByKeep(); -} - /*}}}*/ -// AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/ -// --------------------------------------------------------------------- -/* Right now the system must be consistent before this can be called. - * Upgrade as much as possible without deleting anything (useful for - * stable systems) - */ -bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache) -{ - pkgDepCache::ActionGroup group(Cache); - - pkgProblemResolver Fix(&Cache); - - if (Cache.BrokenCount() != 0) - return false; - - // provide the initial set of stuff we want to upgrade by marking - // all upgradable packages for upgrade - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - { - if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) - { - if (_config->FindB("APT::Ignore-Hold",false) == false) - if (I->SelectedState == pkgCache::State::Hold) - continue; - - Cache.MarkInstall(I, false, 0, false); - } - } - - // then let auto-install loose - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if (Cache[I].Install()) - Cache.MarkInstall(I, true, 0, false); - - // ... but it may remove stuff, we we need to clean up afterwards again - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - if (Cache[I].Delete() == true) - Cache.MarkKeep(I, false, false); - - // resolve remaining issues via keep - return Fix.ResolveByKeep(); -} - /*}}}*/ -// AllUpgrade - Upgrade as many packages as possible /*{{{*/ -// --------------------------------------------------------------------- -/* Right now the system must be consistent before this can be called. - It also will not change packages marked for install, it only tries - to install packages not marked for install */ -bool pkgAllUpgrade(pkgDepCache &Cache) -{ - return pkgAllUpgradeNoNewPackages(Cache); -} - /*}}}*/ -// MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/ -// --------------------------------------------------------------------- -/* This simply goes over the entire set of packages and tries to keep - each package marked for upgrade. If a conflict is generated then - the package is restored. */ -bool pkgMinimizeUpgrade(pkgDepCache &Cache) -{ - pkgDepCache::ActionGroup group(Cache); - - if (Cache.BrokenCount() != 0) - return false; - - // We loop for 10 tries to get the minimal set size. - bool Change = false; - unsigned int Count = 0; - do - { - Change = false; - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) - { - // Not interesting - if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) - continue; - - // Keep it and see if that is OK - Cache.MarkKeep(I, false, false); - if (Cache.BrokenCount() != 0) - Cache.MarkInstall(I, false, 0, false); - else - { - // If keep didnt actually do anything then there was no change.. - if (Cache[I].Upgrade() == false) - Change = true; - } - } - ++Count; - } - while (Change == true && Count < 10); - - if (Cache.BrokenCount() != 0) - return _error->Error("Internal Error in pkgMinimizeUpgrade"); - - return true; -} - /*}}}*/ -// APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/ -bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode) -{ - if (mode == 0) - { - return pkgDistUpgrade(Cache); - } - else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0) - { - return pkgAllUpgradeWithNewPackages(Cache); - } - else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_NEW_INSTALL_PACKAGES)) == 0) - { - return pkgAllUpgradeNoNewPackages(Cache); - } - else - _error->Error("pkgAllUpgrade called with unsupported mode %i", mode); - - return false; -} - /*}}}*/ // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index d0de72462..9dfa1538a 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -40,21 +40,16 @@ #ifndef APT_8_CLEANER_HEADERS #include +// include pkg{DistUpgrade,AllUpgrade,MiniizeUpgrade} here for compatiblity using std::ostream; #endif +#ifndef APT_9_CLEANER_HEADERS +#include +#endif + class pkgAcquireStatus; -namespace APT { - namespace Upgrade { - // FIXME: make this "enum class UpgradeMode {" once we enable c++11 - enum UpgradeMode { - FORBID_REMOVE_PACKAGES = 1, - FORBID_NEW_INSTALL_PACKAGES = 2, - }; - bool Upgrade(pkgDepCache &Cache, int UpgradeMode); - } -} class pkgSimulate : public pkgPackageManager /*{{{*/ { @@ -152,14 +147,9 @@ class pkgProblemResolver /*{{{*/ ~pkgProblemResolver(); }; /*}}}*/ -bool pkgDistUpgrade(pkgDepCache &Cache); bool pkgApplyStatus(pkgDepCache &Cache); bool pkgFixBroken(pkgDepCache &Cache); -bool pkgAllUpgrade(pkgDepCache &Cache); - -bool pkgMinimizeUpgrade(pkgDepCache &Cache); - void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0); diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 59729faf5..262f8fd41 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -43,7 +43,8 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ srcrecords.cc cachefile.cc versionmatch.cc policy.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ - aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc + aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc \ + upgrade.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ @@ -51,7 +52,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cachefilter.h cacheset.h edsp.h + cachefilter.h cacheset.h edsp.h upgrade.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc new file mode 100644 index 000000000..84c781c61 --- /dev/null +++ b/apt-pkg/upgrade.cc @@ -0,0 +1,263 @@ + +// Include Files /*{{{*/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + /*}}}*/ + +// DistUpgrade - Distribution upgrade /*{{{*/ +// --------------------------------------------------------------------- +/* This autoinstalls every package and then force installs every + pre-existing package. This creates the initial set of conditions which + most likely contain problems because too many things were installed. + + The problem resolver is used to resolve the problems. + */ +bool pkgDistUpgrade(pkgDepCache &Cache) +{ + std::string const solver = _config->Find("APT::Solver", "internal"); + if (solver != "internal") { + OpTextProgress Prog(*_config); + return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog); + } + + pkgDepCache::ActionGroup group(Cache); + + /* Upgrade all installed packages first without autoinst to help the resolver + in versioned or-groups to upgrade the old solver instead of installing + a new one (if the old solver is not the first one [anymore]) */ + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (I->CurrentVer != 0) + Cache.MarkInstall(I, false, 0, false); + + /* Auto upgrade all installed packages, this provides the basis + for the installation */ + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (I->CurrentVer != 0) + Cache.MarkInstall(I, true, 0, false); + + /* Now, install each essential package which is not installed + (and not provided by another package in the same name group) */ + std::string essential = _config->Find("pkgCacheGen::Essential", "all"); + if (essential == "all") + { + for (pkgCache::GrpIterator G = Cache.GrpBegin(); G.end() == false; ++G) + { + bool isEssential = false; + bool instEssential = false; + for (pkgCache::PkgIterator P = G.PackageList(); P.end() == false; P = G.NextPkg(P)) + { + if ((P->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential) + continue; + isEssential = true; + if (Cache[P].Install() == true) + { + instEssential = true; + break; + } + } + if (isEssential == false || instEssential == true) + continue; + pkgCache::PkgIterator P = G.FindPreferredPkg(); + Cache.MarkInstall(P, true, 0, false); + } + } + else if (essential != "none") + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + Cache.MarkInstall(I, true, 0, false); + + /* We do it again over all previously installed packages to force + conflict resolution on them all. */ + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (I->CurrentVer != 0) + Cache.MarkInstall(I, false, 0, false); + + pkgProblemResolver Fix(&Cache); + + // Hold back held packages. + if (_config->FindB("APT::Ignore-Hold",false) == false) + { + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + { + if (I->SelectedState == pkgCache::State::Hold) + { + Fix.Protect(I); + Cache.MarkKeep(I, false, false); + } + } + } + + return Fix.Resolve(); +} + /*}}}*/ +// AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/ +static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache) +{ + std::string const solver = _config->Find("APT::Solver", "internal"); + if (solver != "internal") { + OpTextProgress Prog(*_config); + return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog); + } + + pkgDepCache::ActionGroup group(Cache); + + pkgProblemResolver Fix(&Cache); + + if (Cache.BrokenCount() != 0) + return false; + + // Upgrade all installed packages + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + { + if (Cache[I].Install() == true) + Fix.Protect(I); + + if (_config->FindB("APT::Ignore-Hold",false) == false) + if (I->SelectedState == pkgCache::State::Hold) + continue; + + if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) + Cache.MarkInstall(I, false, 0, false); + } + + return Fix.ResolveByKeep(); +} + /*}}}*/ +// AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/ +// --------------------------------------------------------------------- +/* Right now the system must be consistent before this can be called. + * Upgrade as much as possible without deleting anything (useful for + * stable systems) + */ +static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache) +{ + pkgDepCache::ActionGroup group(Cache); + + pkgProblemResolver Fix(&Cache); + + if (Cache.BrokenCount() != 0) + return false; + + // provide the initial set of stuff we want to upgrade by marking + // all upgradable packages for upgrade + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + { + if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) + { + if (_config->FindB("APT::Ignore-Hold",false) == false) + if (I->SelectedState == pkgCache::State::Hold) + continue; + + Cache.MarkInstall(I, false, 0, false); + } + } + + // then let auto-install loose + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (Cache[I].Install()) + Cache.MarkInstall(I, true, 0, false); + + // ... but it may remove stuff, we we need to clean up afterwards again + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (Cache[I].Delete() == true) + Cache.MarkKeep(I, false, false); + + // resolve remaining issues via keep + return Fix.ResolveByKeep(); +} + /*}}}*/ +// AllUpgrade - Upgrade as many packages as possible /*{{{*/ +// --------------------------------------------------------------------- +/* Right now the system must be consistent before this can be called. + It also will not change packages marked for install, it only tries + to install packages not marked for install */ +bool pkgAllUpgrade(pkgDepCache &Cache) +{ + return pkgAllUpgradeNoNewPackages(Cache); +} + /*}}}*/ +// MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/ +// --------------------------------------------------------------------- +/* This simply goes over the entire set of packages and tries to keep + each package marked for upgrade. If a conflict is generated then + the package is restored. */ +bool pkgMinimizeUpgrade(pkgDepCache &Cache) +{ + pkgDepCache::ActionGroup group(Cache); + + if (Cache.BrokenCount() != 0) + return false; + + // We loop for 10 tries to get the minimal set size. + bool Change = false; + unsigned int Count = 0; + do + { + Change = false; + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + { + // Not interesting + if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) + continue; + + // Keep it and see if that is OK + Cache.MarkKeep(I, false, false); + if (Cache.BrokenCount() != 0) + Cache.MarkInstall(I, false, 0, false); + else + { + // If keep didnt actually do anything then there was no change.. + if (Cache[I].Upgrade() == false) + Change = true; + } + } + ++Count; + } + while (Change == true && Count < 10); + + if (Cache.BrokenCount() != 0) + return _error->Error("Internal Error in pkgMinimizeUpgrade"); + + return true; +} + /*}}}*/ +// APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/ +bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode) +{ + if (mode == 0) + { + return pkgDistUpgrade(Cache); + } + else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0) + { + return pkgAllUpgradeWithNewPackages(Cache); + } + else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_NEW_INSTALL_PACKAGES)) == 0) + { + return pkgAllUpgradeNoNewPackages(Cache); + } + else + _error->Error("pkgAllUpgrade called with unsupported mode %i", mode); + + return false; +} + /*}}}*/ diff --git a/apt-pkg/upgrade.h b/apt-pkg/upgrade.h new file mode 100644 index 000000000..9fdfac2fd --- /dev/null +++ b/apt-pkg/upgrade.h @@ -0,0 +1,29 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Upgrade - Upgrade/DistUpgrade releated code + + ##################################################################### */ + /*}}}*/ + +#ifndef PKGLIB_UPGRADE_H +#define PKGLIB_UPGRADE_H + +namespace APT { + namespace Upgrade { + // FIXME: make this "enum class UpgradeMode {" once we enable c++11 + enum UpgradeMode { + FORBID_REMOVE_PACKAGES = 1, + FORBID_NEW_INSTALL_PACKAGES = 2, + }; + bool Upgrade(pkgDepCache &Cache, int UpgradeMode); + } +} + +bool pkgDistUpgrade(pkgDepCache &Cache); +bool pkgAllUpgrade(pkgDepCache &Cache); +bool pkgMinimizeUpgrade(pkgDepCache &Cache); + + +#endif diff --git a/apt-private/private-cachefile.cc b/apt-private/private-cachefile.cc index 25f65ef09..c822b9bad 100644 --- a/apt-private/private-cachefile.cc +++ b/apt-private/private-cachefile.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc index df8fe8686..456cbc0fa 100644 --- a/apt-private/private-upgrade.cc +++ b/apt-private/private-upgrade.cc @@ -1,5 +1,6 @@ // Includes /*{{{*/ #include +#include #include #include "private-install.h" #include "private-cachefile.h" diff --git a/buildlib/config.h.in b/buildlib/config.h.in index 85d3883fc..bd43a40b9 100644 --- a/buildlib/config.h.in +++ b/buildlib/config.h.in @@ -41,3 +41,4 @@ #undef PACKAGE_MAIL #define APT_8_CLEANER_HEADERS +#define APT_9_CLEANER_HEADERS diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 64c7506ae..1025005a2 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -49,7 +49,7 @@ #include #include #include - +#include #include #include diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc index aef7636e9..53b38ea43 100644 --- a/cmdline/apt-internal-solver.cc +++ b/cmdline/apt-internal-solver.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From d428d131a29a08fa7c1d95b98b684fb2ebb554c0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 5 Oct 2013 12:22:55 +0200 Subject: Move ListUpdate/AquireUpdate into update.{cc,h} This moves the ListUpdate/AquireUpdate out of the "catch-all" algorithm.{cc,h} file into its own update.{cc,h} --- apt-pkg/algorithms.cc | 99 --------------------------------- apt-pkg/algorithms.h | 6 +- apt-pkg/makefile | 4 +- apt-pkg/update.cc | 126 ++++++++++++++++++++++++++++++++++++++++++ apt-pkg/update.h | 21 +++++++ apt-private/private-update.cc | 1 + 6 files changed, 151 insertions(+), 106 deletions(-) create mode 100644 apt-pkg/update.cc create mode 100644 apt-pkg/update.h diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 22701f8a6..8644a8138 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1337,102 +1337,3 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List) qsort(List,Count,sizeof(*List),PrioComp); } /*}}}*/ -// ListUpdate - construct Fetcher and update the cache files /*{{{*/ -// --------------------------------------------------------------------- -/* This is a simple wrapper to update the cache. it will fetch stuff - * from the network (or any other sources defined in sources.list) - */ -bool ListUpdate(pkgAcquireStatus &Stat, - pkgSourceList &List, - int PulseInterval) -{ - pkgAcquire Fetcher; - if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false) - return false; - - // Populate it with the source selection - if (List.GetIndexes(&Fetcher) == false) - return false; - - return AcquireUpdate(Fetcher, PulseInterval, true); -} - /*}}}*/ -// AcquireUpdate - take Fetcher and update the cache files /*{{{*/ -// --------------------------------------------------------------------- -/* This is a simple wrapper to update the cache with a provided acquire - * If you only need control over Status and the used SourcesList use - * ListUpdate method instead. - */ -bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval, - bool const RunUpdateScripts, bool const ListCleanup) -{ - // Run scripts - if (RunUpdateScripts == true) - RunScripts("APT::Update::Pre-Invoke"); - - pkgAcquire::RunResult res; - if(PulseInterval > 0) - res = Fetcher.Run(PulseInterval); - else - res = Fetcher.Run(); - - if (res == pkgAcquire::Failed) - return false; - - bool Failed = false; - bool TransientNetworkFailure = false; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); - I != Fetcher.ItemsEnd(); ++I) - { - if ((*I)->Status == pkgAcquire::Item::StatDone) - continue; - - (*I)->Finished(); - - ::URI uri((*I)->DescURI()); - uri.User.clear(); - uri.Password.clear(); - string descUri = string(uri); - _error->Warning(_("Failed to fetch %s %s\n"), descUri.c_str(), - (*I)->ErrorText.c_str()); - - if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) - { - TransientNetworkFailure = true; - continue; - } - - Failed = true; - } - - // Clean out any old list files - // Keep "APT::Get::List-Cleanup" name for compatibility, but - // this is really a global option for the APT library now - if (!TransientNetworkFailure && !Failed && ListCleanup == true && - (_config->FindB("APT::Get::List-Cleanup",true) == true && - _config->FindB("APT::List-Cleanup",true) == true)) - { - if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false || - Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false) - // something went wrong with the clean - return false; - } - - if (TransientNetworkFailure == true) - _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead.")); - else if (Failed == true) - return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead.")); - - - // Run the success scripts if all was fine - if (RunUpdateScripts == true) - { - if(!TransientNetworkFailure && !Failed) - RunScripts("APT::Update::Post-Invoke-Success"); - - // Run the other scripts - RunScripts("APT::Update::Post-Invoke"); - } - return true; -} - /*}}}*/ diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 9dfa1538a..80f6578eb 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -46,10 +46,9 @@ using std::ostream; #ifndef APT_9_CLEANER_HEADERS #include +#include #endif -class pkgAcquireStatus; - class pkgSimulate : public pkgPackageManager /*{{{*/ { @@ -152,8 +151,5 @@ bool pkgFixBroken(pkgDepCache &Cache); void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); -bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0); -bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval = 0, - bool const RunUpdateScripts = true, bool const ListCleanup = true); #endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 262f8fd41..dc943aad4 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -44,7 +44,7 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc \ - upgrade.cc + upgrade.cc update.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ @@ -52,7 +52,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cachefilter.h cacheset.h edsp.h upgrade.h + cachefilter.h cacheset.h edsp.h upgrade.h update.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. diff --git a/apt-pkg/update.cc b/apt-pkg/update.cc new file mode 100644 index 000000000..97be5490b --- /dev/null +++ b/apt-pkg/update.cc @@ -0,0 +1,126 @@ + +// Include Files /*{{{*/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + /*}}}*/ + +using namespace std; + +// ListUpdate - construct Fetcher and update the cache files /*{{{*/ +// --------------------------------------------------------------------- +/* This is a simple wrapper to update the cache. it will fetch stuff + * from the network (or any other sources defined in sources.list) + */ +bool ListUpdate(pkgAcquireStatus &Stat, + pkgSourceList &List, + int PulseInterval) +{ + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false) + return false; + + // Populate it with the source selection + if (List.GetIndexes(&Fetcher) == false) + return false; + + return AcquireUpdate(Fetcher, PulseInterval, true); +} + /*}}}*/ +// AcquireUpdate - take Fetcher and update the cache files /*{{{*/ +// --------------------------------------------------------------------- +/* This is a simple wrapper to update the cache with a provided acquire + * If you only need control over Status and the used SourcesList use + * ListUpdate method instead. + */ +bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval, + bool const RunUpdateScripts, bool const ListCleanup) +{ + // Run scripts + if (RunUpdateScripts == true) + RunScripts("APT::Update::Pre-Invoke"); + + pkgAcquire::RunResult res; + if(PulseInterval > 0) + res = Fetcher.Run(PulseInterval); + else + res = Fetcher.Run(); + + if (res == pkgAcquire::Failed) + return false; + + bool Failed = false; + bool TransientNetworkFailure = false; + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); + I != Fetcher.ItemsEnd(); ++I) + { + if ((*I)->Status == pkgAcquire::Item::StatDone) + continue; + + (*I)->Finished(); + + ::URI uri((*I)->DescURI()); + uri.User.clear(); + uri.Password.clear(); + string descUri = string(uri); + _error->Warning(_("Failed to fetch %s %s\n"), descUri.c_str(), + (*I)->ErrorText.c_str()); + + if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) + { + TransientNetworkFailure = true; + continue; + } + + Failed = true; + } + + // Clean out any old list files + // Keep "APT::Get::List-Cleanup" name for compatibility, but + // this is really a global option for the APT library now + if (!TransientNetworkFailure && !Failed && ListCleanup == true && + (_config->FindB("APT::Get::List-Cleanup",true) == true && + _config->FindB("APT::List-Cleanup",true) == true)) + { + if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false || + Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false) + // something went wrong with the clean + return false; + } + + if (TransientNetworkFailure == true) + _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead.")); + else if (Failed == true) + return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead.")); + + + // Run the success scripts if all was fine + if (RunUpdateScripts == true) + { + if(!TransientNetworkFailure && !Failed) + RunScripts("APT::Update::Post-Invoke-Success"); + + // Run the other scripts + RunScripts("APT::Update::Post-Invoke"); + } + return true; +} + /*}}}*/ diff --git a/apt-pkg/update.h b/apt-pkg/update.h new file mode 100644 index 000000000..3835644de --- /dev/null +++ b/apt-pkg/update.h @@ -0,0 +1,21 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Update - ListUpdate releated code + + ##################################################################### */ + /*}}}*/ + +#ifndef PKGLIB_UPDATE_H +#define PKGLIB_UPDATE_H + +class pkgAcquireStatus; + + +bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0); +bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval = 0, + bool const RunUpdateScripts = true, bool const ListCleanup = true); + + +#endif diff --git a/apt-private/private-update.cc b/apt-private/private-update.cc index 61259748d..f6c12c26a 100644 --- a/apt-private/private-update.cc +++ b/apt-private/private-update.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 31f97d7b862ccf3de93b30a15f24d76e806031a3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 11 Oct 2013 19:27:23 +0200 Subject: first iteration of install progress refactor --- apt-pkg/deb/dpkgpm.cc | 111 +++++++++-------------------------------------- apt-pkg/deb/dpkgpm.h | 1 + apt-pkg/iprogress.cc | 111 +++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/iprogress.h | 59 +++++++++++++++++++++++++ apt-pkg/makefile | 4 +- apt-pkg/packagemanager.h | 1 + 6 files changed, 194 insertions(+), 93 deletions(-) create mode 100644 apt-pkg/iprogress.cc create mode 100644 apt-pkg/iprogress.h diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4d812d26..cd4f5c31e 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -54,16 +55,21 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - last_reported_progress(0.0), nr_terminal_rows(0), - fancy_progress_output(false) + last_reported_progress(0.0) { dpkgbuf[0] = '\0'; - if(_config->FindB("Dpkg::Progress-Fancy", false) == true) - { - fancy_progress_output = true; - _config->Set("DpkgPM::Progress", true); - } + if(_config->FindB("DpkgPM::Progress-Fancy", false) == true) + progress = new APT::Progress::PackageManagerFancy(); + else if (_config->FindB("DpkgPM::Progress", false) == true) + progress = new APT::Progress::PackageManagerText(); + else + progress = new APT::Progress::PackageManager(); } + ~pkgDPkgPMPrivate() + { + delete progress; + } + bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading char dpkgbuf[1024]; @@ -73,8 +79,7 @@ public: string dpkg_error; float last_reported_progress; - int nr_terminal_rows; - bool fancy_progress_output; + APT::Progress::PackageManager *progress; }; namespace @@ -644,8 +649,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) << ":" << (PackagesDone/float(PackagesTotal)*100.0) << ":" << s << endl; - if(_config->FindB("DPkgPM::Progress", false) == true) - SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); + d->progress->StatusChanged(pkg, PackagesDone, PackagesTotal); if(OutStatusFd > 0) FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); @@ -889,52 +893,6 @@ bool pkgDPkgPM::CloseLog() return true; } /*}}}*/ -// DPkgPM::SendTerminalProgress /*{{{*/ -// --------------------------------------------------------------------- -/* Send progress info to the terminal - */ -void pkgDPkgPM::SendTerminalProgress(float percentage) -{ - int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); - - if(percentage < (d->last_reported_progress + reporting_steps)) - return; - - std::string progress_str; - strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); - if (d->fancy_progress_output) - { - int row = d->nr_terminal_rows; - - static string save_cursor = "\033[s"; - static string restore_cursor = "\033[u"; - - static string set_bg_color = "\033[42m"; // green - static string set_fg_color = "\033[30m"; // black - - static string restore_bg = "\033[49m"; - static string restore_fg = "\033[39m"; - - std::cout << save_cursor - // move cursor position to last row - << "\033[" << row << ";0f" - << set_bg_color - << set_fg_color - << progress_str - << restore_cursor - << restore_bg - << restore_fg; - } - else - { - std::cout << progress_str << "\r\n"; - } - std::flush(std::cout); - - d->last_reported_progress = percentage; -} - /*}}}*/ -/*{{{*/ // This implements a racy version of pselect for those architectures // that don't have a working implementation. // FIXME: Probably can be removed on Lenny+1 @@ -956,27 +914,6 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, } /*}}}*/ -void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows) -{ - if(!d->fancy_progress_output) - return; - - // scroll down a bit to avoid visual glitch when the screen - // area shrinks by one row - std::cout << "\n"; - - // save cursor - std::cout << "\033[s"; - - // set scroll region (this will place the cursor in the top left) - std::cout << "\033[1;" << nr_rows - 1 << "r"; - - // restore cursor but ensure its inside the scrolling area - std::cout << "\033[u"; - static const char *move_cursor_up = "\033[1A"; - std::cout << move_cursor_up; - std::flush(std::cout); -} // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- @@ -1334,8 +1271,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) _error->PushToStack(); if (tcgetattr(STDOUT_FILENO, &tt) == 0) { - ioctl(1, TIOCGWINSZ, (char *)&win); - d->nr_terminal_rows = win.ws_row; + ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win); if (openpty(&master, &slave, NULL, &tt, &win) < 0) { _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); @@ -1415,7 +1351,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } - SetupTerminalScrollArea(d->nr_terminal_rows); /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ @@ -1424,6 +1359,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) cerr << "Could not exec dpkg!" << endl; _exit(100); } + d->progress->Started(); // apply ionice if (_config->FindB("DPkg::UseIoNice", false) == true) @@ -1510,14 +1446,8 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGHUP,old_SIGHUP); - // reset scroll area - SetupTerminalScrollArea(d->nr_terminal_rows + 1); - if(d->fancy_progress_output) - { - // override the progress line (sledgehammer) - static const char* clear_screen_below_cursor = "\033[J"; - std::cout << clear_screen_below_cursor; - } + // tell the progress + d->progress->Finished(); if(master >= 0) { @@ -1556,8 +1486,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) CloseLog(); // dpkg is done at this point - if(_config->FindB("DPkgPM::Progress", false) == true) - SendTerminalProgress(100); + d->progress->StatusChanged("", PackagesDone, PackagesTotal); if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 3b8d36623..53e352d4e 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -23,6 +23,7 @@ using std::map; class pkgDPkgPMPrivate; + class pkgDPkgPM : public pkgPackageManager { private: diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc new file mode 100644 index 000000000..4de8c0492 --- /dev/null +++ b/apt-pkg/iprogress.cc @@ -0,0 +1,111 @@ +#include +#include + +#include +#include + +namespace APT { +namespace Progress { + +static void SetupTerminalScrollArea(int nr_rows) +{ + // scroll down a bit to avoid visual glitch when the screen + // area shrinks by one row + std::cout << "\n"; + + // save cursor + std::cout << "\033[s"; + + // set scroll region (this will place the cursor in the top left) + std::cout << "\033[1;" << nr_rows - 1 << "r"; + + // restore cursor but ensure its inside the scrolling area + std::cout << "\033[u"; + static const char *move_cursor_up = "\033[1A"; + std::cout << move_cursor_up; + std::flush(std::cout); +} + +PackageManagerFancy::PackageManagerFancy() + : nr_terminal_rows(-1) +{ + struct winsize win; + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0) + { + nr_terminal_rows = win.ws_row; + } +} + +void PackageManagerFancy::Started() +{ + SetupTerminalScrollArea(nr_terminal_rows); +} + +void PackageManagerFancy::Finished() +{ + SetupTerminalScrollArea(nr_terminal_rows + 1); + + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; +} + +void PackageManagerFancy::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps) +{ + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + float percentage = StepsDone/(float)TotalSteps * 100.0; + + if(percentage < (last_reported_progress + reporting_steps)) + return; + + std::string progress_str; + strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + + int row = nr_terminal_rows; + + static string save_cursor = "\033[s"; + static string restore_cursor = "\033[u"; + + static string set_bg_color = "\033[42m"; // green + static string set_fg_color = "\033[30m"; // black + + static string restore_bg = "\033[49m"; + static string restore_fg = "\033[39m"; + + std::cout << save_cursor + // move cursor position to last row + << "\033[" << row << ";0f" + << set_bg_color + << set_fg_color + << progress_str + << restore_cursor + << restore_bg + << restore_fg; + std::flush(std::cout); + last_reported_progress = percentage; +} + +void PackageManagerText::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps) +{ + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + float percentage = StepsDone/(float)TotalSteps * 100.0; + + if(percentage < (last_reported_progress + reporting_steps)) + return; + + std::string progress_str; + strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + + std::cout << progress_str << "\r\n"; + std::flush(std::cout); + + last_reported_progress = percentage; +} + + +}; // namespace progress +}; // namespace apt diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h new file mode 100644 index 000000000..14fc89bff --- /dev/null +++ b/apt-pkg/iprogress.h @@ -0,0 +1,59 @@ +#ifndef PKGLIB_IPROGRESS_H +#define PKGLIB_IPROGRSS_H + + +#include + +namespace APT { +namespace Progress { + + + class PackageManager + { + private: + /** \brief dpointer placeholder */ + void *d; + + public: + virtual ~PackageManager() {}; + + virtual void Started() {}; + virtual void Finished() {}; + + virtual void StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps) {}; + }; + + class PackageManagerFancy : public PackageManager + { + protected: + int last_reported_progress; + int nr_terminal_rows; + public: + PackageManagerFancy(); + virtual void Started(); + virtual void Finished(); + virtual void StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps); + }; + + class PackageManagerText : public PackageManager + { + protected: + int last_reported_progress; + + public: + PackageManagerText() : last_reported_progress(0) {}; + virtual void StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps); + + }; + + +}; // namespace Progress +}; // namespace APT + +#endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 59729faf5..e69b5ce7f 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -43,7 +43,7 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ srcrecords.cc cachefile.cc versionmatch.cc policy.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ - aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc + aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc iprogress.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ @@ -51,7 +51,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cachefilter.h cacheset.h edsp.h + cachefilter.h cacheset.h edsp.h iprogress.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 1a6a9f01c..4956e816f 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -39,6 +39,7 @@ class pkgDepCache; class pkgSourceList; class pkgOrderList; class pkgRecords; + class pkgPackageManager : protected pkgCache::Namespace { public: -- cgit v1.2.3 From db78c60c6a726ed70fa8b0984090b80840444016 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 11 Oct 2013 22:16:55 +0200 Subject: deal with nr_terminal_rows unavailable --- apt-pkg/iprogress.cc | 17 +++++++++++------ apt-pkg/iprogress.h | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 4de8c0492..68a2c7207 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -7,7 +7,7 @@ namespace APT { namespace Progress { -static void SetupTerminalScrollArea(int nr_rows) +void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) { // scroll down a bit to avoid visual glitch when the screen // area shrinks by one row @@ -23,6 +23,7 @@ static void SetupTerminalScrollArea(int nr_rows) std::cout << "\033[u"; static const char *move_cursor_up = "\033[1A"; std::cout << move_cursor_up; + std::flush(std::cout); } @@ -38,16 +39,20 @@ PackageManagerFancy::PackageManagerFancy() void PackageManagerFancy::Started() { - SetupTerminalScrollArea(nr_terminal_rows); + if (nr_terminal_rows > 0) + SetupTerminalScrollArea(nr_terminal_rows); } void PackageManagerFancy::Finished() { - SetupTerminalScrollArea(nr_terminal_rows + 1); + if (nr_terminal_rows > 0) + { + SetupTerminalScrollArea(nr_terminal_rows + 1); - // override the progress line (sledgehammer) - static const char* clear_screen_below_cursor = "\033[J"; - std::cout << clear_screen_below_cursor; + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; + } } void PackageManagerFancy::StatusChanged(std::string PackageName, diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index 14fc89bff..f097e0943 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -30,6 +30,8 @@ namespace Progress { protected: int last_reported_progress; int nr_terminal_rows; + void SetupTerminalScrollArea(int nr_rows); + public: PackageManagerFancy(); virtual void Started(); -- cgit v1.2.3 From 6c5ae8ed079e01082f606614641b19b7c08893ad Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 11 Oct 2013 22:48:22 +0200 Subject: move common code into PackageManager::StatusChanged() --- apt-pkg/deb/dpkgpm.cc | 5 +++-- apt-pkg/iprogress.cc | 43 +++++++++++++++++++++++++------------------ apt-pkg/iprogress.h | 19 ++++++++++--------- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index cd4f5c31e..35adb91f6 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -58,9 +58,10 @@ public: last_reported_progress(0.0) { dpkgbuf[0] = '\0'; - if(_config->FindB("DpkgPM::Progress-Fancy", false) == true) + if(_config->FindB("Dpkg::Progress-Fancy", false) == true) progress = new APT::Progress::PackageManagerFancy(); - else if (_config->FindB("DpkgPM::Progress", false) == true) + else if (_config->FindB("Dpkg::Progress", + _config->FindB("DpkgPM::Progress", false)) == true) progress = new APT::Progress::PackageManagerText(); else progress = new APT::Progress::PackageManager(); diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 68a2c7207..398059051 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -7,6 +8,20 @@ namespace APT { namespace Progress { +bool PackageManager::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps) +{ + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + percentage = StepsDone/(float)TotalSteps * 100.0; + strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage); + + if(percentage < (last_reported_progress + reporting_steps)) + return false; + + return true; +} + void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) { // scroll down a bit to avoid visual glitch when the screen @@ -55,18 +70,12 @@ void PackageManagerFancy::Finished() } } -void PackageManagerFancy::StatusChanged(std::string PackageName, +bool PackageManagerFancy::StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps) { - int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); - float percentage = StepsDone/(float)TotalSteps * 100.0; - - if(percentage < (last_reported_progress + reporting_steps)) - return; - - std::string progress_str; - strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps)) + return false; int row = nr_terminal_rows; @@ -90,25 +99,23 @@ void PackageManagerFancy::StatusChanged(std::string PackageName, << restore_fg; std::flush(std::cout); last_reported_progress = percentage; + + return true; } -void PackageManagerText::StatusChanged(std::string PackageName, +bool PackageManagerText::StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps) { - int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); - float percentage = StepsDone/(float)TotalSteps * 100.0; - - if(percentage < (last_reported_progress + reporting_steps)) - return; - - std::string progress_str; - strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps)) + return false; std::cout << progress_str << "\r\n"; std::flush(std::cout); last_reported_progress = percentage; + + return true; } diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index f097e0943..5f1655ab9 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -14,21 +14,26 @@ namespace Progress { /** \brief dpointer placeholder */ void *d; + protected: + std::string progress_str; + float percentage; + int last_reported_progress; + public: + PackageManager() : percentage(0.0), last_reported_progress(0) {}; virtual ~PackageManager() {}; virtual void Started() {}; virtual void Finished() {}; - virtual void StatusChanged(std::string PackageName, + virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps) {}; + unsigned int TotalSteps); }; class PackageManagerFancy : public PackageManager { protected: - int last_reported_progress; int nr_terminal_rows; void SetupTerminalScrollArea(int nr_rows); @@ -36,19 +41,15 @@ namespace Progress { PackageManagerFancy(); virtual void Started(); virtual void Finished(); - virtual void StatusChanged(std::string PackageName, + virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps); }; class PackageManagerText : public PackageManager { - protected: - int last_reported_progress; - public: - PackageManagerText() : last_reported_progress(0) {}; - virtual void StatusChanged(std::string PackageName, + virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps); -- cgit v1.2.3 From e6ad8031b774af9bdd5d460d9983450bb5a03d0d Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 13 Oct 2013 15:05:04 +0200 Subject: move the status-fd progress reporting out of the pkgDPkgPM class, at this point, breaks ABI/API, lets see what we can do about this --- apt-pkg/deb/dpkgpm.cc | 99 ++++++++++-------------------------------- apt-pkg/deb/dpkgpm.h | 7 +-- apt-pkg/iprogress.cc | 95 +++++++++++++++++++++++++++++++++++++--- apt-pkg/iprogress.h | 56 ++++++++++++++++++++---- apt-pkg/packagemanager.cc | 14 +++--- apt-pkg/packagemanager.h | 18 ++++++-- apt-private/private-install.cc | 24 +++++++++- 7 files changed, 211 insertions(+), 102 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 35adb91f6..0c3be4ce5 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -55,20 +55,12 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - last_reported_progress(0.0) + last_reported_progress(0.0), progress(NULL) { dpkgbuf[0] = '\0'; - if(_config->FindB("Dpkg::Progress-Fancy", false) == true) - progress = new APT::Progress::PackageManagerFancy(); - else if (_config->FindB("Dpkg::Progress", - _config->FindB("DpkgPM::Progress", false)) == true) - progress = new APT::Progress::PackageManagerText(); - else - progress = new APT::Progress::PackageManager(); } ~pkgDPkgPMPrivate() { - delete progress; } bool stdin_is_dev_null; @@ -519,11 +511,9 @@ void pkgDPkgPM::DoTerminalPty(int master) // --------------------------------------------------------------------- /* */ -void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) +void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false); - // the status we output - ostringstream status; if (Debug == true) std::clog << "got from dpkg '" << line << "'" << std::endl; @@ -573,7 +563,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // 'processing: action: pkg' if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) { - char s[200]; const char* const pkg_or_trigger = list[2].c_str(); action = list[1].c_str(); const std::pair * const iter = @@ -586,17 +575,11 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::clog << "ignoring unknown action: " << action << std::endl; return; } - snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger); - - status << "pmstatus:" << pkg_or_trigger - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; + std::string pkg_action; + strprintf(pkg_action, _(iter->second), pkg_or_trigger); + d->progress->StatusChanged(pkg_or_trigger, PackagesDone, PackagesTotal, + pkg_action); if (strncmp(action, "disappear", strlen("disappear")) == 0) handleDisappearAction(pkg_or_trigger); return; @@ -604,28 +587,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if(strncmp(action,"error",strlen("error")) == 0) { - status << "pmerror:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; + d->progress->Error(list[1], PackagesDone, PackagesTotal, list[3]); pkgFailures++; WriteApportReport(list[1].c_str(), list[3].c_str()); return; } else if(strncmp(action,"conffile",strlen("conffile")) == 0) { - status << "pmconffile:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; + d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, + list[3]); return; } @@ -638,24 +608,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) { // only read the translation if there is actually a next // action - const char *translation = _(states[PackageOpsDone[pkg]].str); - char s[200]; - snprintf(s, sizeof(s), translation, pkg); + std::string translation; + strprintf(translation, _(states[PackageOpsDone[pkg]].str), pkg); // we moved from one dpkg state to a new one, report that PackageOpsDone[pkg]++; PackagesDone++; - // build the status str - status << "pmstatus:" << pkg - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s - << endl; - d->progress->StatusChanged(pkg, PackagesDone, PackagesTotal); - - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; + // and send to the progress + d->progress->StatusChanged(pkg, PackagesDone, PackagesTotal, + translation); } if (Debug == true) std::clog << "(parsed from dpkg) pkg: " << pkg @@ -713,7 +674,7 @@ void pkgDPkgPM::handleDisappearAction(string const &pkgname) // --------------------------------------------------------------------- /* */ -void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd) +void pkgDPkgPM::DoDpkgStatusFd(int statusfd) { char *p, *q; int len; @@ -728,7 +689,7 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd) while((q=(char*)memchr(p, '\n', d->dpkgbuf+d->dpkgbuf_pos-p)) != NULL) { *q = 0; - ProcessDpkgStatusLine(OutStatusFd, p); + ProcessDpkgStatusLine(p); p=q+1; // continue with next line } @@ -920,14 +881,15 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, // --------------------------------------------------------------------- /* This globs the operations and calls dpkg * - * If it is called with "OutStatusFd" set to a valid file descriptor - * apt will report the install progress over this fd. It maps the - * dpkg states a package goes through to human readable (and i10n-able) + * If it is called with a progress object apt will report the install + * progress to this object. It maps the dpkg states a package goes + * through to human readable (and i10n-able) * names and calculates a percentage for each step. */ -bool pkgDPkgPM::Go(int OutStatusFd) +bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { pkgPackageManager::SigINTStop = false; + d->progress = progress; // Generate the base argument list for dpkg std::vector Args; @@ -1304,16 +1266,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) // Fork dpkg pid_t Child; - _config->Set("APT::Keep-Fds::",fd[1]); - // send status information that we are about to fork dpkg - if(OutStatusFd > 0) { - ostringstream status; - status << "pmstatus:dpkg-exec:" - << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << _("Running dpkg") - << endl; - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - } + d->progress->Started(); Child = ExecFork(); // This is the child @@ -1360,15 +1313,11 @@ bool pkgDPkgPM::Go(int OutStatusFd) cerr << "Could not exec dpkg!" << endl; _exit(100); } - d->progress->Started(); // apply ionice if (_config->FindB("DPkg::UseIoNice", false) == true) ionice(Child); - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds",fd[1]); - // Wait for dpkg int Status = 0; @@ -1437,7 +1386,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if(master >= 0 && FD_ISSET(0, &rfds)) DoStdin(master); if(FD_ISSET(_dpkgin, &rfds)) - DoDpkgStatusFd(_dpkgin, OutStatusFd); + DoDpkgStatusFd(_dpkgin); } close(_dpkgin); @@ -1487,7 +1436,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) CloseLog(); // dpkg is done at this point - d->progress->StatusChanged("", PackagesDone, PackagesTotal); + d->progress->StatusChanged("", PackagesDone, PackagesTotal, ""); if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 53e352d4e..1f4bbafc7 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -99,14 +99,15 @@ class pkgDPkgPM : public pkgPackageManager // input processing void DoStdin(int master); void DoTerminalPty(int master); - void DoDpkgStatusFd(int statusfd, int OutStatusFd); - void ProcessDpkgStatusLine(int OutStatusFd, char *line); + void DoDpkgStatusFd(int statusfd); + void ProcessDpkgStatusLine(char *line); // The Actuall installation implementation virtual bool Install(PkgIterator Pkg,std::string File); virtual bool Configure(PkgIterator Pkg); virtual bool Remove(PkgIterator Pkg,bool Purge = false); - virtual bool Go(int StatusFd=-1); + + virtual bool Go(APT::Progress::PackageManager *progress); virtual void Reset(); public: diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 398059051..6c5d33d4a 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -1,16 +1,22 @@ +#include +#include #include #include + #include #include #include +#include + namespace APT { namespace Progress { bool PackageManager::StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps) + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) { int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); percentage = StepsDone/(float)TotalSteps * 100.0; @@ -22,6 +28,80 @@ bool PackageManager::StatusChanged(std::string PackageName, return true; } +PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) +{ + OutStatusFd = progress_fd; +} + +void PackageManagerProgressFd::Started() +{ + _config->Set("APT::Keep-Fds::", OutStatusFd); + + // send status information that we are about to fork dpkg + if(OutStatusFd > 0) { + std::ostringstream status; + status << "pmstatus:dpkg-exec:" + << (StepsDone/float(StepsTotal)*100.0) + << ":" << _("Running dpkg") + << std::endl; + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + } +} + +void PackageManagerProgressFd::Finished() +{ + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds", OutStatusFd); +} + +void PackageManagerProgressFd::Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) +{ + std::ostringstream status; + status << "pmerror:" << PackageName + << ":" << (StepsDone/float(TotalSteps)*100.0) + << ":" << ErrorMessage + << std::endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); +} + +void PackageManagerProgressFd::ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) +{ + std::ostringstream status; + status << "pmconffile:" << PackageName + << ":" << (StepsDone/float(TotalSteps)*100.0) + << ":" << ConfMessage + << std::endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); +} + + +bool PackageManagerProgressFd::StatusChanged(std::string PackageName, + unsigned int xStepsDone, + unsigned int xTotalSteps, + std::string pkg_action) +{ + StepsDone = xStepsDone; + StepsTotal = xTotalSteps; + + // build the status str + std::ostringstream status; + status << "pmstatus:" << PackageName + << ":" << (StepsDone/float(StepsTotal)*100.0) + << ":" << pkg_action + << std::endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + return true; +} + void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) { // scroll down a bit to avoid visual glitch when the screen @@ -72,9 +152,11 @@ void PackageManagerFancy::Finished() bool PackageManagerFancy::StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps) + unsigned int TotalSteps, + std::string HumanReadableAction) { - if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps)) + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, + HumanReadableAction)) return false; int row = nr_terminal_rows; @@ -105,9 +187,10 @@ bool PackageManagerFancy::StatusChanged(std::string PackageName, bool PackageManagerText::StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps) + unsigned int TotalSteps, + std::string HumanReadableAction) { - if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps)) + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction)) return false; std::cout << progress_str << "\r\n"; diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index 5f1655ab9..6519e9445 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -1,13 +1,13 @@ #ifndef PKGLIB_IPROGRESS_H -#define PKGLIB_IPROGRSS_H +#define PKGLIB_IPROGRESS_H +#include +#include -#include namespace APT { namespace Progress { - class PackageManager { private: @@ -20,15 +20,54 @@ namespace Progress { int last_reported_progress; public: - PackageManager() : percentage(0.0), last_reported_progress(0) {}; + PackageManager() + : percentage(0.0), last_reported_progress(0) {}; virtual ~PackageManager() {}; virtual void Started() {}; virtual void Finished() {}; + + virtual pid_t fork() {return fork(); }; virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps); + unsigned int TotalSteps, + std::string HumanReadableAction) ; + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) {}; + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) {}; + }; + + class PackageManagerProgressFd : public PackageManager + { + protected: + int OutStatusFd; + int StepsDone; + int StepsTotal; + + public: + PackageManagerProgressFd(int progress_fd); + virtual void Started(); + virtual void Finished(); + + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage); + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage); + }; class PackageManagerFancy : public PackageManager @@ -43,7 +82,8 @@ namespace Progress { virtual void Finished(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps); + unsigned int TotalSteps, + std::string HumanReadableAction); }; class PackageManagerText : public PackageManager @@ -51,8 +91,8 @@ namespace Progress { public: virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps); - + unsigned int TotalSteps, + std::string HumanReadableAction); }; diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 8c0d2e855..32bc5284e 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -1032,28 +1032,32 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() // PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/ // --------------------------------------------------------------------- pkgPackageManager::OrderResult -pkgPackageManager::DoInstallPostFork(int statusFd) +pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) { +// FIXME: port to new structure +#if 0 if(statusFd > 0) // FIXME: use SetCloseExec here once it taught about throwing // exceptions instead of doing _exit(100) on failure fcntl(statusFd,F_SETFD,FD_CLOEXEC); - bool goResult = Go(statusFd); +#endif + bool goResult = Go(progress); if(goResult == false) return Failed; return Res; }; - + /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ -pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) +pkgPackageManager::OrderResult +pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) { if(DoInstallPreFork() == Failed) return Failed; - return DoInstallPostFork(statusFd); + return DoInstallPostFork(progress); } /*}}}*/ diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 4956e816f..5c15ac0e4 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -24,6 +24,7 @@ #define PKGLIB_PACKAGEMANAGER_H #include +#include #include #include @@ -40,6 +41,7 @@ class pkgSourceList; class pkgOrderList; class pkgRecords; + class pkgPackageManager : protected pkgCache::Namespace { public: @@ -84,7 +86,7 @@ class pkgPackageManager : protected pkgCache::Namespace virtual bool Install(PkgIterator /*Pkg*/,std::string /*File*/) {return false;}; virtual bool Configure(PkgIterator /*Pkg*/) {return false;}; virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;}; - virtual bool Go(int statusFd=-1) {return true;}; + virtual bool Go(APT::Progress::PackageManager *progress) {return true;}; virtual void Reset() {}; // the result of the operation @@ -97,7 +99,17 @@ class pkgPackageManager : protected pkgCache::Namespace pkgRecords *Recs); // Do the installation - OrderResult DoInstall(int statusFd=-1); + OrderResult DoInstall(APT::Progress::PackageManager *progress); + + // compat + OrderResult DoInstall(int statusFd=-1) { + APT::Progress::PackageManager *progress = new + APT::Progress::PackageManagerProgressFd(statusFd); + OrderResult res = DoInstall(progress); + delete progress; + return res; + } + // stuff that needs to be done before the fork() of a library that // uses apt @@ -107,7 +119,7 @@ class pkgPackageManager : protected pkgCache::Namespace }; // stuff that needs to be done after the fork - OrderResult DoInstallPostFork(int statusFd=-1); + OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress); bool FixMissing(); /** \brief returns all packages dpkg let disappear */ diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 643a6b370..d1066c869 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -104,7 +105,11 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) { pkgSimulate PM(Cache); int status_fd = _config->FindI("APT::Status-Fd",-1); - pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd); + APT::Progress::PackageManager *progress = NULL; + if (status_fd > 0) + progress = new APT::Progress::PackageManagerProgressFd(status_fd); + pkgPackageManager::OrderResult Res = PM.DoInstall(progress); + delete progress; if (Res == pkgPackageManager::Failed) return false; if (Res != pkgPackageManager::Completed) @@ -332,8 +337,23 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) } _system->UnLock(); + + // FIXME: make this a factory + // select the right progress int status_fd = _config->FindI("APT::Status-Fd",-1); - pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd); + APT::Progress::PackageManager *progress = NULL; + if (status_fd > 0) + progress = new APT::Progress::PackageManagerProgressFd(status_fd); + else if(_config->FindB("Dpkg::Progress-Fancy", false) == true) + progress = new APT::Progress::PackageManagerFancy(); + else if (_config->FindB("Dpkg::Progress", + _config->FindB("DpkgPM::Progress", false)) == true) + progress = new APT::Progress::PackageManagerText(); + else + progress = new APT::Progress::PackageManager(); + pkgPackageManager::OrderResult Res = PM->DoInstall(progress); + delete progress; + if (Res == pkgPackageManager::Failed || _error->PendingError() == true) return false; if (Res == pkgPackageManager::Completed) -- cgit v1.2.3 From ca5b257835578d98145becbc3d97505394a7726c Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 13 Oct 2013 15:10:53 +0200 Subject: add APT::Progress::PackageManager::Pulse() --- apt-pkg/deb/dpkgpm.cc | 5 +++-- apt-pkg/iprogress.h | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 0c3be4ce5..d617a3c0c 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1364,13 +1364,14 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) FD_SET(_dpkgin, &rfds); if(master >= 0) FD_SET(master, &rfds); - tv.tv_sec = 1; - tv.tv_nsec = 0; + tv.tv_sec = 0; + tv.tv_nsec = d->progress->GetPulseInterval(); select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &original_sigmask); if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS)) select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &original_sigmask); + d->progress->Pulse(); if (select_ret == 0) continue; else if (select_ret < 0 && errno == EINTR) diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index 6519e9445..04520ffe8 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -28,7 +28,12 @@ namespace Progress { virtual void Finished() {}; virtual pid_t fork() {return fork(); }; - + + virtual void Pulse() {}; + virtual long GetPulseInterval() { + return 500000; + }; + virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, -- cgit v1.2.3 From f9935b1c33203b9e47ca0ff5cb441c7963b19fbc Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 14 Oct 2013 07:40:56 +0200 Subject: refactor writing to WriteToStatusFd() --- apt-pkg/iprogress.cc | 30 ++++++++++++++++-------------- apt-pkg/iprogress.h | 3 +++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 6c5d33d4a..7d1cc6341 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -33,19 +33,24 @@ PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) OutStatusFd = progress_fd; } +void PackageManagerProgressFd::WriteToStatusFd(std::string s) +{ + if(OutStatusFd <= 0) + return; + FileFd::Write(OutStatusFd, s.c_str(), s.size()); +} + void PackageManagerProgressFd::Started() { _config->Set("APT::Keep-Fds::", OutStatusFd); // send status information that we are about to fork dpkg - if(OutStatusFd > 0) { - std::ostringstream status; - status << "pmstatus:dpkg-exec:" - << (StepsDone/float(StepsTotal)*100.0) - << ":" << _("Running dpkg") - << std::endl; - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - } + std::ostringstream status; + status << "pmstatus:dpkg-exec:" + << (StepsDone/float(StepsTotal)*100.0) + << ":" << _("Running dpkg") + << std::endl; + WriteToStatusFd(status.str()); } void PackageManagerProgressFd::Finished() @@ -64,8 +69,7 @@ void PackageManagerProgressFd::Error(std::string PackageName, << ":" << (StepsDone/float(TotalSteps)*100.0) << ":" << ErrorMessage << std::endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + WriteToStatusFd(status.str()); } void PackageManagerProgressFd::ConffilePrompt(std::string PackageName, @@ -78,8 +82,7 @@ void PackageManagerProgressFd::ConffilePrompt(std::string PackageName, << ":" << (StepsDone/float(TotalSteps)*100.0) << ":" << ConfMessage << std::endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + WriteToStatusFd(status.str()); } @@ -97,8 +100,7 @@ bool PackageManagerProgressFd::StatusChanged(std::string PackageName, << ":" << (StepsDone/float(StepsTotal)*100.0) << ":" << pkg_action << std::endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + WriteToStatusFd(status.str()); return true; } diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index 04520ffe8..5584b3940 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -54,9 +54,12 @@ namespace Progress { int OutStatusFd; int StepsDone; int StepsTotal; + void WriteToStatusFd(std::string msg); public: PackageManagerProgressFd(int progress_fd); + + // FIXME: rename to Start/Stop to match the pkgAcquireStatus virtual void Started(); virtual void Finished(); -- cgit v1.2.3 From a22fdebf63a42026e4350ebd069512c797bc2a5b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 14 Oct 2013 07:52:21 +0200 Subject: rename APT::Progress::Packagemanager Started->Start, Finished->Stop to match pkgAcquireStatus --- apt-pkg/deb/dpkgpm.cc | 10 ++++------ apt-pkg/iprogress.cc | 8 ++++---- apt-pkg/iprogress.h | 13 ++++++------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d617a3c0c..36d8c829a 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1264,11 +1264,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) _error->DumpErrors(std::cerr); _error->RevertToStack(); - // Fork dpkg - pid_t Child; - d->progress->Started(); - - Child = ExecFork(); + // Tell the progress that its starting and fork dpkg + d->progress->Start(); + pid_t Child = ExecFork(); // This is the child if (Child == 0) { @@ -1398,7 +1396,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) signal(SIGHUP,old_SIGHUP); // tell the progress - d->progress->Finished(); + d->progress->Stop(); if(master >= 0) { diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 7d1cc6341..7de190da0 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -40,7 +40,7 @@ void PackageManagerProgressFd::WriteToStatusFd(std::string s) FileFd::Write(OutStatusFd, s.c_str(), s.size()); } -void PackageManagerProgressFd::Started() +void PackageManagerProgressFd::Start() { _config->Set("APT::Keep-Fds::", OutStatusFd); @@ -53,7 +53,7 @@ void PackageManagerProgressFd::Started() WriteToStatusFd(status.str()); } -void PackageManagerProgressFd::Finished() +void PackageManagerProgressFd::Stop() { // clear the Keep-Fd again _config->Clear("APT::Keep-Fds", OutStatusFd); @@ -134,13 +134,13 @@ PackageManagerFancy::PackageManagerFancy() } } -void PackageManagerFancy::Started() +void PackageManagerFancy::Start() { if (nr_terminal_rows > 0) SetupTerminalScrollArea(nr_terminal_rows); } -void PackageManagerFancy::Finished() +void PackageManagerFancy::Stop() { if (nr_terminal_rows > 0) { diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index 5584b3940..ccf154279 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -24,8 +24,8 @@ namespace Progress { : percentage(0.0), last_reported_progress(0) {}; virtual ~PackageManager() {}; - virtual void Started() {}; - virtual void Finished() {}; + virtual void Start() {}; + virtual void Stop() {}; virtual pid_t fork() {return fork(); }; @@ -59,9 +59,8 @@ namespace Progress { public: PackageManagerProgressFd(int progress_fd); - // FIXME: rename to Start/Stop to match the pkgAcquireStatus - virtual void Started(); - virtual void Finished(); + virtual void Start(); + virtual void Stop(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, @@ -86,8 +85,8 @@ namespace Progress { public: PackageManagerFancy(); - virtual void Started(); - virtual void Finished(); + virtual void Start(); + virtual void Stop(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, -- cgit v1.2.3 From 5e9458e285af11c7fa4308add10d250e3546c8bf Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 14 Oct 2013 08:42:48 +0200 Subject: re-add APT::Keep-Fds:: for the dpkg status-fd in dpkgpm.cc as we always need this --- apt-pkg/deb/dpkgpm.cc | 6 ++++++ apt-pkg/iprogress.cc | 9 +++++++-- apt-pkg/packagemanager.cc | 18 +++++------------- apt-private/private-install.cc | 3 +++ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 36d8c829a..fbb5e4c96 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1264,6 +1264,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) _error->DumpErrors(std::cerr); _error->RevertToStack(); + // this is the dpkg status-fd, we need to keep it + _config->Set("APT::Keep-Fds::",fd[1]); + // Tell the progress that its starting and fork dpkg d->progress->Start(); pid_t Child = ExecFork(); @@ -1316,6 +1319,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (_config->FindB("DPkg::UseIoNice", false) == true) ionice(Child); + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds",fd[1]); + // Wait for dpkg int Status = 0; diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 7de190da0..bed991d68 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -8,7 +8,7 @@ #include #include #include - +#include namespace APT { namespace Progress { @@ -42,7 +42,12 @@ void PackageManagerProgressFd::WriteToStatusFd(std::string s) void PackageManagerProgressFd::Start() { - _config->Set("APT::Keep-Fds::", OutStatusFd); + if(OutStatusFd <= 0) + return; + + // FIXME: use SetCloseExec here once it taught about throwing + // exceptions instead of doing _exit(100) on failure + fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); // send status information that we are about to fork dpkg std::ostringstream status; diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 32bc5284e..3690a64c3 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -26,7 +26,6 @@ #include #include -#include #include /*}}}*/ @@ -1034,18 +1033,11 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() pkgPackageManager::OrderResult pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) { -// FIXME: port to new structure -#if 0 - if(statusFd > 0) - // FIXME: use SetCloseExec here once it taught about throwing - // exceptions instead of doing _exit(100) on failure - fcntl(statusFd,F_SETFD,FD_CLOEXEC); -#endif - bool goResult = Go(progress); - if(goResult == false) - return Failed; - - return Res; + bool goResult = Go(progress); + if(goResult == false) + return Failed; + + return Res; }; /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index d1066c869..8d72faecc 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -104,12 +104,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) if (_config->FindB("APT::Get::Simulate") == true) { pkgSimulate PM(Cache); + int status_fd = _config->FindI("APT::Status-Fd",-1); APT::Progress::PackageManager *progress = NULL; if (status_fd > 0) progress = new APT::Progress::PackageManagerProgressFd(status_fd); pkgPackageManager::OrderResult Res = PM.DoInstall(progress); delete progress; + if (Res == pkgPackageManager::Failed) return false; if (Res != pkgPackageManager::Completed) @@ -341,6 +343,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) // FIXME: make this a factory // select the right progress int status_fd = _config->FindI("APT::Status-Fd",-1); + APT::Progress::PackageManager *progress = NULL; if (status_fd > 0) progress = new APT::Progress::PackageManagerProgressFd(status_fd); -- cgit v1.2.3 From 7c016f6e107ba55d7b55870166273ce63c4ecb65 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 17 Oct 2013 08:18:09 +0200 Subject: ensure that short-name -> long-name detection for dpkg-status works for reinstalls too --- apt-pkg/deb/dpkgpm.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 1b234c0ed..19de44001 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -561,7 +561,9 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) pkgCache::PkgIterator P = Grp.PackageList(); for (; P.end() != true; P = Grp.NextPkg(P)) { - if(Cache[P].Mode != pkgDepCache::ModeKeep) + if(Cache[P].Install() || Cache[P].ReInstall() || + Cache[P].Upgrade() || Cache[P].Downgrade() || + Cache[P].Delete() || Cache[P].Purge()) { pkgname = P.FullName(); break; @@ -569,6 +571,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) } } } + const char* const pkg = pkgname.c_str(); const char* action = list[2].c_str(); -- cgit v1.2.3 From dd640f3cece45693b57b49d90ba7cc4134577070 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 08:02:29 +0200 Subject: cleanup --- apt-pkg/deb/dpkgpm.cc | 104 +++++++++++++++++++++++----------- apt-pkg/deb/dpkgpm.h | 3 +- apt-pkg/iprogress.cc | 2 +- test/integration/test-apt-progress-fd | 46 +++++++-------- 4 files changed, 97 insertions(+), 58 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 19de44001..7fba04a30 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -507,6 +507,34 @@ void pkgDPkgPM::DoTerminalPty(int master) fwrite(term_buf, len, sizeof(char), d->term_out); } /*}}}*/ + +std::string pkgDPkgPM::ExpandShortPackageName(pkgDepCache &Cache, + const std::string &short_pkgname) +{ + if (short_pkgname.find(":") != string::npos) + return short_pkgname; + + std::string pkgname = short_pkgname; + // find the package in the group that is in a touched by dpkg + // if there are multiple dpkg will send us a full pkgname:arch + pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); + if (Grp.end() == false) + { + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if(Cache[P].Install() || Cache[P].ReInstall() || + Cache[P].Upgrade() || Cache[P].Downgrade() || + Cache[P].Delete() || Cache[P].Purge()) + { + pkgname = P.FullName(); + return pkgname; + } + } + } + return pkgname; +} + // DPkgPM::ProcessDpkgStatusBuf /*{{{*/ // --------------------------------------------------------------------- /* @@ -549,32 +577,35 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) std::clog << "ignoring line: not enough ':'" << std::endl; return; } - // dpkg does not send always send "pkgname:arch" so we add it here if needed - std::string pkgname = list[1]; - if (pkgname.find(":") == std::string::npos) + + if (list[0] != "processing" && list[0] != "status") { - // find the package in the group that is in a touched by dpkg - // if there are multiple dpkg will send us a full pkgname:arch - pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); - if (Grp.end() == false) - { - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { - if(Cache[P].Install() || Cache[P].ReInstall() || - Cache[P].Upgrade() || Cache[P].Downgrade() || - Cache[P].Delete() || Cache[P].Purge()) - { - pkgname = P.FullName(); - break; - } - } - } + if (Debug == true) + std::clog << "ignoring line: unknown prefix '" << list[0] << "'" + << std::endl; + return; + } + + std::string prefix = list[0]; + std::string pkgname; + std::string action; + if (prefix == "processing") + { + action = list[1]; + pkgname = list[2]; + if (action != "install" && action != "configure" && + action != "remove" && action != "purge" && + action != "disappear") + return; + } else if (prefix == "status") { + pkgname = list[1]; + action = list[2]; } + // dpkg does not always send out the architecture so we need to guess + // it here + pkgname = ExpandShortPackageName(Cache, pkgname); const char* const pkg = pkgname.c_str(); - const char* action = list[2].c_str(); - std::string short_pkgname = StringSplit(pkgname, ":")[0]; std::string i18n_pkgname = short_pkgname; if (pkgname.find(":") != string::npos) @@ -587,48 +618,52 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // 'processing: action: pkg' if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) { - const char* const pkg_or_trigger = list[2].c_str(); - action = list[1].c_str(); const std::pair * const iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, - MatchProcessingOp(action)); + MatchProcessingOp(action.c_str())); if(iter == PackageProcessingOpsEnd) { if (Debug == true) std::clog << "ignoring unknown action: " << action << std::endl; return; } + std::string pkg_action; - strprintf(pkg_action, _(iter->second), pkg_or_trigger); + strprintf(pkg_action, _(iter->second), short_pkgname.c_str()); - d->progress->StatusChanged(pkg_or_trigger, PackagesDone, PackagesTotal, + d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, pkg_action); - if (strncmp(action, "disappear", strlen("disappear")) == 0) - handleDisappearAction(pkg_or_trigger); + + if (strncmp(action.c_str(), "disappear", strlen("disappear")) == 0) + handleDisappearAction(pkgname); return; } - if(strncmp(action,"error",strlen("error")) == 0) + // FIXME: fix indent once this goes into debian/sid + if(strncmp(prefix.c_str(), "status", strlen("processing")) == 0) + { + + if(strncmp(action.c_str(),"error",strlen("error")) == 0) { d->progress->Error(list[1], PackagesDone, PackagesTotal, list[3]); pkgFailures++; WriteApportReport(list[1].c_str(), list[3].c_str()); return; } - else if(strncmp(action,"conffile",strlen("conffile")) == 0) + else if(strncmp(action.c_str(),"conffile",strlen("conffile")) == 0) { d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, list[3]); return; - } + } else { vector const &states = PackageOps[pkg]; const char *next_action = NULL; if(PackageOpsDone[pkg] < states.size()) next_action = states[PackageOpsDone[pkg]].state; // check if the package moved to the next dpkg state - if(next_action && (strcmp(action, next_action) == 0)) + if(next_action && (strcmp(action.c_str(), next_action) == 0)) { // only read the translation if there is actually a next // action @@ -644,9 +679,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, translation); } + if (Debug == true) std::clog << "(parsed from dpkg) pkg: " << pkgname << " action: " << action << endl; + } + } } /*}}}*/ // DPkgPM::handleDisappearAction /*{{{*/ diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 302507105..922631ba8 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -84,11 +84,12 @@ class pkgDPkgPM : public pkgPackageManager __deprecated bool SendV2Pkgs(FILE *F); bool SendPkgsInfo(FILE * const F, unsigned int const &Version); void WriteHistoryTag(std::string const &tag, std::string value); + std::string ExpandShortPackageName(pkgDepCache &Cache, + const std::string &short_pkgname); // Terminal progress void SetupTerminalScrollArea(int nr_scrolled_rows); void SendTerminalProgress(float percentage); - void CleanupTerminal(); // apport integration void WriteApportReport(const char *pkgpath, const char *errormsg); diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index bed991d68..318d626d4 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -101,7 +101,7 @@ bool PackageManagerProgressFd::StatusChanged(std::string PackageName, // build the status str std::ostringstream status; - status << "pmstatus:" << PackageName + status << "pmstatus:" << StringSplit(PackageName, ":")[0] << ":" << (StepsDone/float(StepsTotal)*100.0) << ":" << pkg_action << std::endl; diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd index 5f73c8f8c..cdf8d4a23 100755 --- a/test/integration/test-apt-progress-fd +++ b/test/integration/test-apt-progress-fd @@ -18,14 +18,14 @@ testsuccess aptget install testing=0.1 -y -o APT::Status-Fd=3 testequal "dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:0:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg -pmstatus:testing:0:Installing testing -pmstatus:testing:20:Preparing testing -pmstatus:testing:40:Unpacking testing +pmstatus:testing:0:Installing testing (amd64) +pmstatus:testing:20:Preparing testing (amd64) +pmstatus:testing:40:Unpacking testing (amd64) pmstatus:testing:60:Preparing to configure testing pmstatus:dpkg-exec:60:Running dpkg -pmstatus:testing:60:Configuring testing -pmstatus:testing:80:Configuring testing -pmstatus:testing:100:Installed testing" cat apt-progress.log +pmstatus:testing:60:Configuring testing (amd64) +pmstatus:testing:80:Configuring testing (amd64) +pmstatus:testing:100:Installed testing (amd64)" cat apt-progress.log # upgrade exec 3> apt-progress.log @@ -33,22 +33,22 @@ testsuccess aptget install testing=0.8.15 -y -o APT::Status-Fd=3 testequal "dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:0:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg -pmstatus:testing:20:Preparing testing -pmstatus:testing:40:Unpacking testing +pmstatus:testing:20:Preparing testing (amd64) +pmstatus:testing:40:Unpacking testing (amd64) pmstatus:testing:60:Preparing to configure testing pmstatus:dpkg-exec:60:Running dpkg -pmstatus:testing:60:Configuring testing -pmstatus:testing:80:Configuring testing -pmstatus:testing:100:Installed testing" cat apt-progress.log +pmstatus:testing:60:Configuring testing (amd64) +pmstatus:testing:80:Configuring testing (amd64) +pmstatus:testing:100:Installed testing (amd64)" cat apt-progress.log # and remove exec 3> apt-progress.log testsuccess aptget remove testing -y -o APT::Status-Fd=3 testequal "pmstatus:dpkg-exec:0:Running dpkg -pmstatus:testing:0:Removing testing -pmstatus:testing:33.3333:Preparing for removal of testing -pmstatus:testing:66.6667:Removing testing -pmstatus:testing:100:Removed testing" cat apt-progress.log +pmstatus:testing:0:Removing testing (amd64) +pmstatus:testing:33.3333:Preparing for removal of testing (amd64) +pmstatus:testing:66.6667:Removing testing (amd64) +pmstatus:testing:100:Removed testing (amd64)" cat apt-progress.log # install non-native and ensure we get proper progress info @@ -59,13 +59,13 @@ testsuccess aptget install testing2:i386 -y -o APT::Status-Fd=3 testequal "dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:0:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg -pmstatus:testing2:0:Installing testing2 -pmstatus:testing2:20:Preparing testing2 -pmstatus:testing2:40:Unpacking testing2 -pmstatus:testing2:60:Preparing to configure testing2 +pmstatus:testing2:0:Installing testing2 (i386) +pmstatus:testing2:20:Preparing testing2 (i386) +pmstatus:testing2:40:Unpacking testing2 (i386) +pmstatus:testing2:60:Preparing to configure testing2 (i386) pmstatus:dpkg-exec:60:Running dpkg -pmstatus:testing2:60:Configuring testing2 -pmstatus:testing2:80:Configuring testing2 -pmstatus:testing2:100:Installed testing2" cat apt-progress.log +pmstatus:testing2:60:Configuring testing2 (i386) +pmstatus:testing2:80:Configuring testing2 (i386) +pmstatus:testing2:100:Installed testing2 (i386)" cat apt-progress.log -rm -f apt-progress*.log \ No newline at end of file +rm -f apt-progress*.log -- cgit v1.2.3 From 34d6563ef47b455b69a7bc9ad0838902bb911dea Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 15:56:06 +0200 Subject: merged debian/sid --- apt-pkg/deb/dpkgpm.cc | 257 +++++++++++++++++++++++++------------------------- 1 file changed, 127 insertions(+), 130 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 7fba04a30..b5f858022 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -55,14 +55,13 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - last_reported_progress(0.0), progress(NULL) + progress(NULL) { dpkgbuf[0] = '\0'; } ~pkgDPkgPMPrivate() { } - bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading char dpkgbuf[1024]; @@ -70,8 +69,6 @@ public: FILE *term_out; FILE *history_out; string dpkg_error; - - float last_reported_progress; APT::Progress::PackageManager *progress; }; @@ -507,34 +504,6 @@ void pkgDPkgPM::DoTerminalPty(int master) fwrite(term_buf, len, sizeof(char), d->term_out); } /*}}}*/ - -std::string pkgDPkgPM::ExpandShortPackageName(pkgDepCache &Cache, - const std::string &short_pkgname) -{ - if (short_pkgname.find(":") != string::npos) - return short_pkgname; - - std::string pkgname = short_pkgname; - // find the package in the group that is in a touched by dpkg - // if there are multiple dpkg will send us a full pkgname:arch - pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); - if (Grp.end() == false) - { - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { - if(Cache[P].Install() || Cache[P].ReInstall() || - Cache[P].Upgrade() || Cache[P].Downgrade() || - Cache[P].Delete() || Cache[P].Purge()) - { - pkgname = P.FullName(); - return pkgname; - } - } - } - return pkgname; -} - // DPkgPM::ProcessDpkgStatusBuf /*{{{*/ // --------------------------------------------------------------------- /* @@ -542,28 +511,17 @@ std::string pkgDPkgPM::ExpandShortPackageName(pkgDepCache &Cache, void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false); - if (Debug == true) std::clog << "got from dpkg '" << line << "'" << std::endl; - /* dpkg sends strings like this: 'status: : ' 'status: :: ' - errors look like this: - 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data - and conffile-prompt like this - 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited - Newer versions of dpkg sent also: - 'processing: install: pkg' - 'processing: configure: pkg' - 'processing: remove: pkg' - 'processing: purge: pkg' - 'processing: disappear: pkg' - 'processing: trigproc: trigger' - + 'processing: {install,configure,remove,purge,disappear,trigproc}: pkg' + 'processing: {install,configure,remove,purge,disappear,trigproc}: trigger' */ + // we need to split on ": " (note the appended space) as the ':' is // part of the pkgname:arch information that dpkg sends // @@ -578,45 +536,106 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) return; } - if (list[0] != "processing" && list[0] != "status") + // build the (prefix, pkgname, action) tuple, position of this + // is different for "processing" or "status" messages + std::string prefix = APT::String::Strip(list[0]); + std::string pkgname; + std::string action; + ostringstream status; + + // "processing" has the form "processing: action: pkg or trigger" + // with action = ["install", "configure", "remove", "purge", "disappear", + // "trigproc"] + if (prefix == "processing") + { + pkgname = APT::String::Strip(list[2]); + action = APT::String::Strip(list[1]); + + // this is what we support in the processing stage + if(action != "install" && action != "configure" && + action != "remove" && action != "purge" && action != "purge") + { + if (Debug == true) + std::clog << "ignoring processing action: '" << action + << "'" << std::endl; + return; + } + } + // "status" has the form: "status: pkg: state" + // with state in ["half-installed", "unpacked", "half-configured", + // "installed", "config-files", "not-installed"] + else if (prefix == "status") { + pkgname = APT::String::Strip(list[1]); + action = APT::String::Strip(list[2]); + } else { if (Debug == true) - std::clog << "ignoring line: unknown prefix '" << list[0] << "'" - << std::endl; + std::clog << "unknown prefix '" << prefix << "'" << std::endl; return; } - std::string prefix = list[0]; - std::string pkgname; - std::string action; - if (prefix == "processing") + + /* handle the special cases first: + + errors look like this: + 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data + and conffile-prompt like this + 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited + */ + if (prefix == "status") { - action = list[1]; - pkgname = list[2]; - if (action != "install" && action != "configure" && - action != "remove" && action != "purge" && - action != "disappear") + if(action == "error") + { + d->progress->Error(list[1], PackagesDone, PackagesTotal, + list[3]); + pkgFailures++; + WriteApportReport(list[1].c_str(), list[3].c_str()); + return; + } + else if(action == "conffile") + { + d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, + list[3]); return; - } else if (prefix == "status") { - pkgname = list[1]; - action = list[2]; + } } - // dpkg does not always send out the architecture so we need to guess - // it here - pkgname = ExpandShortPackageName(Cache, pkgname); + // at this point we know that we should have a valid pkgname, so build all + // the info from it + + // dpkg does not send always send "pkgname:arch" so we add it here + // if needed + if (pkgname.find(":") == std::string::npos) + { + // find the package in the group that is in a touched by dpkg + // if there are multiple dpkg will send us a full pkgname:arch + pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); + if (Grp.end() == false) + { + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if(Cache[P].Mode != pkgDepCache::ModeKeep) + { + pkgname = P.FullName(); + break; + } + } + } + } + const char* const pkg = pkgname.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; - std::string i18n_pkgname = short_pkgname; + std::string arch = ""; if (pkgname.find(":") != string::npos) - { - strprintf(i18n_pkgname, "%s (%s)", short_pkgname.c_str(), - StringSplit(pkgname, ":")[1].c_str()); - } + arch = StringSplit(pkgname, ":")[1]; + std::string i18n_pkgname = pkgname; + if (arch.size() != 0) + strprintf(i18n_pkgname, "%s (%s)", short_pkgname.c_str(), arch.c_str()); // 'processing' from dpkg looks like // 'processing: action: pkg' - if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) + if(prefix == "processing") { const std::pair * const iter = std::find_if(PackageProcessingOpsBegin, @@ -628,62 +647,41 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) std::clog << "ignoring unknown action: " << action << std::endl; return; } - - std::string pkg_action; - strprintf(pkg_action, _(iter->second), short_pkgname.c_str()); - - d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, - pkg_action); - - if (strncmp(action.c_str(), "disappear", strlen("disappear")) == 0) + std::string msg; + strprintf(msg, _(iter->second), i18n_pkgname.c_str()); + d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); + + // FIXME: this needs a muliarch testcase + // FIXME2: is "pkgname" here reliable with dpkg only sending us + // short pkgnames? + if (action == "disappear") handleDisappearAction(pkgname); return; - } - - // FIXME: fix indent once this goes into debian/sid - if(strncmp(prefix.c_str(), "status", strlen("processing")) == 0) - { - - if(strncmp(action.c_str(),"error",strlen("error")) == 0) - { - d->progress->Error(list[1], PackagesDone, PackagesTotal, list[3]); - pkgFailures++; - WriteApportReport(list[1].c_str(), list[3].c_str()); - return; - } - else if(strncmp(action.c_str(),"conffile",strlen("conffile")) == 0) - { - d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, - list[3]); - return; - } else { + } - vector const &states = PackageOps[pkg]; - const char *next_action = NULL; - if(PackageOpsDone[pkg] < states.size()) - next_action = states[PackageOpsDone[pkg]].state; - // check if the package moved to the next dpkg state - if(next_action && (strcmp(action.c_str(), next_action) == 0)) + if (prefix == "status") { - // only read the translation if there is actually a next - // action - std::string translation; - strprintf(translation, _(states[PackageOpsDone[pkg]].str), - i18n_pkgname.c_str()); - - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; - - // and send to the progress - d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, - translation); - } - - if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << pkgname - << " action: " << action << endl; - } + vector const &states = PackageOps[pkg]; + const char *next_action = NULL; + if(PackageOpsDone[pkg] < states.size()) + next_action = states[PackageOpsDone[pkg]].state; + // check if the package moved to the next dpkg state + if(next_action && (action == next_action)) + { + // only read the translation if there is actually a next + // action + const char *translation = _(states[PackageOpsDone[pkg]].str); + std::string msg; + strprintf(msg, translation, i18n_pkgname.c_str()); + d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); + + // we moved from one dpkg state to a new one, report that + PackageOpsDone[pkg]++; + PackagesDone++; + } + if (Debug == true) + std::clog << "(parsed from dpkg) pkg: " << short_pkgname + << " action: " << action << endl; } } /*}}}*/ @@ -919,6 +917,8 @@ bool pkgDPkgPM::CloseLog() return true; } /*}}}*/ + /*}}}*/ +/*{{{*/ // This implements a racy version of pselect for those architectures // that don't have a working implementation. // FIXME: Probably can be removed on Lenny+1 @@ -938,18 +938,16 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, sigprocmask(SIG_SETMASK, &origmask, 0); return retval; } -/*}}}*/ - - + /*}}}*/ // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg - * + * * If it is called with a progress object apt will report the install * progress to this object. It maps the dpkg states a package goes * through to human readable (and i10n-able) * names and calculates a percentage for each step. -*/ + */ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { pkgPackageManager::SigINTStop = false; @@ -1331,7 +1329,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) // this is the dpkg status-fd, we need to keep it _config->Set("APT::Keep-Fds::",fd[1]); - // Tell the progress that its starting and fork dpkg + // Tell the progress that its starting and fork dpkg // FIXME: this is called once per dpkg run which is *too often* d->progress->Start(); @@ -1372,7 +1370,6 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } - /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ putenv((char *)"DPKG_NO_TSTP=yes"); @@ -1441,6 +1438,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS)) select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &original_sigmask); + d->progress->Pulse(); if (select_ret == 0) @@ -1509,7 +1507,6 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) d->progress->StatusChanged("", PackagesDone, PackagesTotal, ""); d->progress->Stop(); - if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); -- cgit v1.2.3 From 65dbd5a1a32f63dae81c8b5814cd246f1154c38d Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 18:26:56 +0200 Subject: re-add missing APT::String::Strip --- apt-pkg/contrib/strutl.cc | 17 ++++++++++++++++- apt-pkg/contrib/strutl.h | 7 +++++++ apt-pkg/deb/dpkgpm.cc | 7 ++++--- apt-pkg/iprogress.cc | 8 ++++++++ apt-pkg/iprogress.h | 2 +- test/integration/test-apt-progress-fd | 1 - 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 77e48962c..9f794927d 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -36,7 +36,22 @@ using namespace std; /*}}}*/ - +// Strip - Remove white space from the front and back of a string /*{{{*/ +// --------------------------------------------------------------------- +namespace APT { + namespace String { +std::string Strip(const std::string &s) +{ + size_t start = s.find_first_not_of(" \t\n"); + // only whitespace + if (start == string::npos) + return ""; + size_t end = s.find_last_not_of(" \t\n"); + return s.substr(start, end-start+1); +} +} +} + /*}}}*/ // UTF8ToCodeset - Convert some UTF-8 string for some codeset /*{{{*/ // --------------------------------------------------------------------- /* This is handy to use before display some information for enduser */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index b42e06491..c8fc317c0 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -33,6 +33,13 @@ using std::vector; using std::ostream; #endif +namespace APT { + namespace String { + std::string Strip(const std::string &s); + }; +}; + + bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest); char *_strstrip(char *String); char *_strrstrip(char *String); // right strip only diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b5f858022..5f1849b53 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -668,6 +668,10 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // check if the package moved to the next dpkg state if(next_action && (action == next_action)) { + // we moved from one dpkg state to a new one, report that + PackageOpsDone[pkg]++; + PackagesDone++; + // only read the translation if there is actually a next // action const char *translation = _(states[PackageOpsDone[pkg]].str); @@ -675,9 +679,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) strprintf(msg, translation, i18n_pkgname.c_str()); d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; } if (Debug == true) std::clog << "(parsed from dpkg) pkg: " << short_pkgname diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 318d626d4..daa7695e2 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -29,6 +29,7 @@ bool PackageManager::StatusChanged(std::string PackageName, } PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) + : StepsDone(0), StepsTotal(1) { OutStatusFd = progress_fd; } @@ -106,6 +107,13 @@ bool PackageManagerProgressFd::StatusChanged(std::string PackageName, << ":" << pkg_action << std::endl; WriteToStatusFd(status.str()); + + if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true) + std::cerr << "progress: " << PackageName << " " << xStepsDone + << " " << xTotalSteps << " " << pkg_action + << std::endl; + + return true; } diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index ccf154279..42fa89be4 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -21,7 +21,7 @@ namespace Progress { public: PackageManager() - : percentage(0.0), last_reported_progress(0) {}; + : percentage(0.0), last_reported_progress(-1) {}; virtual ~PackageManager() {}; virtual void Start() {}; diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd index cdf8d4a23..97bb25848 100755 --- a/test/integration/test-apt-progress-fd +++ b/test/integration/test-apt-progress-fd @@ -50,7 +50,6 @@ pmstatus:testing:33.3333:Preparing for removal of testing (amd64) pmstatus:testing:66.6667:Removing testing (amd64) pmstatus:testing:100:Removed testing (amd64)" cat apt-progress.log - # install non-native and ensure we get proper progress info exec 3> apt-progress.log testsuccess aptget install testing2:i386 -y -o APT::Status-Fd=3 -- cgit v1.2.3 From 1c6cedc489b5eaeed1b7fdb845eca06bc1fccd4f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 21 Oct 2013 21:23:07 +0200 Subject: move iprogress.{cc,h} to private-progress.{cc,h} until its fully stable --- apt-pkg/iprogress.cc | 221 ---------------------------------------- apt-pkg/iprogress.h | 109 -------------------- apt-pkg/makefile | 4 +- apt-private/makefile | 2 +- apt-private/private-progress.cc | 221 ++++++++++++++++++++++++++++++++++++++++ apt-private/private-progress.h | 109 ++++++++++++++++++++ 6 files changed, 333 insertions(+), 333 deletions(-) delete mode 100644 apt-pkg/iprogress.cc delete mode 100644 apt-pkg/iprogress.h create mode 100644 apt-private/private-progress.cc create mode 100644 apt-private/private-progress.h diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc deleted file mode 100644 index daa7695e2..000000000 --- a/apt-pkg/iprogress.cc +++ /dev/null @@ -1,221 +0,0 @@ -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -namespace APT { -namespace Progress { - -bool PackageManager::StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction) -{ - int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); - percentage = StepsDone/(float)TotalSteps * 100.0; - strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage); - - if(percentage < (last_reported_progress + reporting_steps)) - return false; - - return true; -} - -PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) - : StepsDone(0), StepsTotal(1) -{ - OutStatusFd = progress_fd; -} - -void PackageManagerProgressFd::WriteToStatusFd(std::string s) -{ - if(OutStatusFd <= 0) - return; - FileFd::Write(OutStatusFd, s.c_str(), s.size()); -} - -void PackageManagerProgressFd::Start() -{ - if(OutStatusFd <= 0) - return; - - // FIXME: use SetCloseExec here once it taught about throwing - // exceptions instead of doing _exit(100) on failure - fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); - - // send status information that we are about to fork dpkg - std::ostringstream status; - status << "pmstatus:dpkg-exec:" - << (StepsDone/float(StepsTotal)*100.0) - << ":" << _("Running dpkg") - << std::endl; - WriteToStatusFd(status.str()); -} - -void PackageManagerProgressFd::Stop() -{ - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); -} - -void PackageManagerProgressFd::Error(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ErrorMessage) -{ - std::ostringstream status; - status << "pmerror:" << PackageName - << ":" << (StepsDone/float(TotalSteps)*100.0) - << ":" << ErrorMessage - << std::endl; - WriteToStatusFd(status.str()); -} - -void PackageManagerProgressFd::ConffilePrompt(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ConfMessage) -{ - std::ostringstream status; - status << "pmconffile:" << PackageName - << ":" << (StepsDone/float(TotalSteps)*100.0) - << ":" << ConfMessage - << std::endl; - WriteToStatusFd(status.str()); -} - - -bool PackageManagerProgressFd::StatusChanged(std::string PackageName, - unsigned int xStepsDone, - unsigned int xTotalSteps, - std::string pkg_action) -{ - StepsDone = xStepsDone; - StepsTotal = xTotalSteps; - - // build the status str - std::ostringstream status; - status << "pmstatus:" << StringSplit(PackageName, ":")[0] - << ":" << (StepsDone/float(StepsTotal)*100.0) - << ":" << pkg_action - << std::endl; - WriteToStatusFd(status.str()); - - if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true) - std::cerr << "progress: " << PackageName << " " << xStepsDone - << " " << xTotalSteps << " " << pkg_action - << std::endl; - - - return true; -} - -void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) -{ - // scroll down a bit to avoid visual glitch when the screen - // area shrinks by one row - std::cout << "\n"; - - // save cursor - std::cout << "\033[s"; - - // set scroll region (this will place the cursor in the top left) - std::cout << "\033[1;" << nr_rows - 1 << "r"; - - // restore cursor but ensure its inside the scrolling area - std::cout << "\033[u"; - static const char *move_cursor_up = "\033[1A"; - std::cout << move_cursor_up; - - std::flush(std::cout); -} - -PackageManagerFancy::PackageManagerFancy() - : nr_terminal_rows(-1) -{ - struct winsize win; - if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0) - { - nr_terminal_rows = win.ws_row; - } -} - -void PackageManagerFancy::Start() -{ - if (nr_terminal_rows > 0) - SetupTerminalScrollArea(nr_terminal_rows); -} - -void PackageManagerFancy::Stop() -{ - if (nr_terminal_rows > 0) - { - SetupTerminalScrollArea(nr_terminal_rows + 1); - - // override the progress line (sledgehammer) - static const char* clear_screen_below_cursor = "\033[J"; - std::cout << clear_screen_below_cursor; - } -} - -bool PackageManagerFancy::StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction) -{ - if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, - HumanReadableAction)) - return false; - - int row = nr_terminal_rows; - - static string save_cursor = "\033[s"; - static string restore_cursor = "\033[u"; - - static string set_bg_color = "\033[42m"; // green - static string set_fg_color = "\033[30m"; // black - - static string restore_bg = "\033[49m"; - static string restore_fg = "\033[39m"; - - std::cout << save_cursor - // move cursor position to last row - << "\033[" << row << ";0f" - << set_bg_color - << set_fg_color - << progress_str - << restore_cursor - << restore_bg - << restore_fg; - std::flush(std::cout); - last_reported_progress = percentage; - - return true; -} - -bool PackageManagerText::StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction) -{ - if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction)) - return false; - - std::cout << progress_str << "\r\n"; - std::flush(std::cout); - - last_reported_progress = percentage; - - return true; -} - - -}; // namespace progress -}; // namespace apt diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h deleted file mode 100644 index 42fa89be4..000000000 --- a/apt-pkg/iprogress.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef PKGLIB_IPROGRESS_H -#define PKGLIB_IPROGRESS_H - -#include -#include - - -namespace APT { -namespace Progress { - - class PackageManager - { - private: - /** \brief dpointer placeholder */ - void *d; - - protected: - std::string progress_str; - float percentage; - int last_reported_progress; - - public: - PackageManager() - : percentage(0.0), last_reported_progress(-1) {}; - virtual ~PackageManager() {}; - - virtual void Start() {}; - virtual void Stop() {}; - - virtual pid_t fork() {return fork(); }; - - virtual void Pulse() {}; - virtual long GetPulseInterval() { - return 500000; - }; - - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction) ; - virtual void Error(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ErrorMessage) {}; - virtual void ConffilePrompt(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ConfMessage) {}; - }; - - class PackageManagerProgressFd : public PackageManager - { - protected: - int OutStatusFd; - int StepsDone; - int StepsTotal; - void WriteToStatusFd(std::string msg); - - public: - PackageManagerProgressFd(int progress_fd); - - virtual void Start(); - virtual void Stop(); - - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction); - virtual void Error(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ErrorMessage); - virtual void ConffilePrompt(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ConfMessage); - - }; - - class PackageManagerFancy : public PackageManager - { - protected: - int nr_terminal_rows; - void SetupTerminalScrollArea(int nr_rows); - - public: - PackageManagerFancy(); - virtual void Start(); - virtual void Stop(); - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction); - }; - - class PackageManagerText : public PackageManager - { - public: - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction); - }; - - -}; // namespace Progress -}; // namespace APT - -#endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index e69b5ce7f..abf701511 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -43,7 +43,7 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ srcrecords.cc cachefile.cc versionmatch.cc policy.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ - aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc iprogress.cc + aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ @@ -51,7 +51,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cachefilter.h cacheset.h edsp.h iprogress.h + cachefilter.h cacheset.h edsp.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. diff --git a/apt-private/makefile b/apt-private/makefile index 1d179f0b2..9b074f189 100644 --- a/apt-private/makefile +++ b/apt-private/makefile @@ -17,7 +17,7 @@ MAJOR=0.0 MINOR=0 SLIBS=$(PTHREADLIB) -lapt-pkg -PRIVATES=list install download output cachefile cacheset update upgrade cmndline moo search show main +PRIVATES=list install download output cachefile cacheset update upgrade cmndline moo search show main progress SOURCE += $(foreach private, $(PRIVATES), private-$(private).cc) HEADERS += $(foreach private, $(PRIVATES), private-$(private).h) diff --git a/apt-private/private-progress.cc b/apt-private/private-progress.cc new file mode 100644 index 000000000..daa7695e2 --- /dev/null +++ b/apt-private/private-progress.cc @@ -0,0 +1,221 @@ +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace APT { +namespace Progress { + +bool PackageManager::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) +{ + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + percentage = StepsDone/(float)TotalSteps * 100.0; + strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage); + + if(percentage < (last_reported_progress + reporting_steps)) + return false; + + return true; +} + +PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) + : StepsDone(0), StepsTotal(1) +{ + OutStatusFd = progress_fd; +} + +void PackageManagerProgressFd::WriteToStatusFd(std::string s) +{ + if(OutStatusFd <= 0) + return; + FileFd::Write(OutStatusFd, s.c_str(), s.size()); +} + +void PackageManagerProgressFd::Start() +{ + if(OutStatusFd <= 0) + return; + + // FIXME: use SetCloseExec here once it taught about throwing + // exceptions instead of doing _exit(100) on failure + fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); + + // send status information that we are about to fork dpkg + std::ostringstream status; + status << "pmstatus:dpkg-exec:" + << (StepsDone/float(StepsTotal)*100.0) + << ":" << _("Running dpkg") + << std::endl; + WriteToStatusFd(status.str()); +} + +void PackageManagerProgressFd::Stop() +{ + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds", OutStatusFd); +} + +void PackageManagerProgressFd::Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) +{ + std::ostringstream status; + status << "pmerror:" << PackageName + << ":" << (StepsDone/float(TotalSteps)*100.0) + << ":" << ErrorMessage + << std::endl; + WriteToStatusFd(status.str()); +} + +void PackageManagerProgressFd::ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) +{ + std::ostringstream status; + status << "pmconffile:" << PackageName + << ":" << (StepsDone/float(TotalSteps)*100.0) + << ":" << ConfMessage + << std::endl; + WriteToStatusFd(status.str()); +} + + +bool PackageManagerProgressFd::StatusChanged(std::string PackageName, + unsigned int xStepsDone, + unsigned int xTotalSteps, + std::string pkg_action) +{ + StepsDone = xStepsDone; + StepsTotal = xTotalSteps; + + // build the status str + std::ostringstream status; + status << "pmstatus:" << StringSplit(PackageName, ":")[0] + << ":" << (StepsDone/float(StepsTotal)*100.0) + << ":" << pkg_action + << std::endl; + WriteToStatusFd(status.str()); + + if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true) + std::cerr << "progress: " << PackageName << " " << xStepsDone + << " " << xTotalSteps << " " << pkg_action + << std::endl; + + + return true; +} + +void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) +{ + // scroll down a bit to avoid visual glitch when the screen + // area shrinks by one row + std::cout << "\n"; + + // save cursor + std::cout << "\033[s"; + + // set scroll region (this will place the cursor in the top left) + std::cout << "\033[1;" << nr_rows - 1 << "r"; + + // restore cursor but ensure its inside the scrolling area + std::cout << "\033[u"; + static const char *move_cursor_up = "\033[1A"; + std::cout << move_cursor_up; + + std::flush(std::cout); +} + +PackageManagerFancy::PackageManagerFancy() + : nr_terminal_rows(-1) +{ + struct winsize win; + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0) + { + nr_terminal_rows = win.ws_row; + } +} + +void PackageManagerFancy::Start() +{ + if (nr_terminal_rows > 0) + SetupTerminalScrollArea(nr_terminal_rows); +} + +void PackageManagerFancy::Stop() +{ + if (nr_terminal_rows > 0) + { + SetupTerminalScrollArea(nr_terminal_rows + 1); + + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; + } +} + +bool PackageManagerFancy::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) +{ + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, + HumanReadableAction)) + return false; + + int row = nr_terminal_rows; + + static string save_cursor = "\033[s"; + static string restore_cursor = "\033[u"; + + static string set_bg_color = "\033[42m"; // green + static string set_fg_color = "\033[30m"; // black + + static string restore_bg = "\033[49m"; + static string restore_fg = "\033[39m"; + + std::cout << save_cursor + // move cursor position to last row + << "\033[" << row << ";0f" + << set_bg_color + << set_fg_color + << progress_str + << restore_cursor + << restore_bg + << restore_fg; + std::flush(std::cout); + last_reported_progress = percentage; + + return true; +} + +bool PackageManagerText::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) +{ + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction)) + return false; + + std::cout << progress_str << "\r\n"; + std::flush(std::cout); + + last_reported_progress = percentage; + + return true; +} + + +}; // namespace progress +}; // namespace apt diff --git a/apt-private/private-progress.h b/apt-private/private-progress.h new file mode 100644 index 000000000..42fa89be4 --- /dev/null +++ b/apt-private/private-progress.h @@ -0,0 +1,109 @@ +#ifndef PKGLIB_IPROGRESS_H +#define PKGLIB_IPROGRESS_H + +#include +#include + + +namespace APT { +namespace Progress { + + class PackageManager + { + private: + /** \brief dpointer placeholder */ + void *d; + + protected: + std::string progress_str; + float percentage; + int last_reported_progress; + + public: + PackageManager() + : percentage(0.0), last_reported_progress(-1) {}; + virtual ~PackageManager() {}; + + virtual void Start() {}; + virtual void Stop() {}; + + virtual pid_t fork() {return fork(); }; + + virtual void Pulse() {}; + virtual long GetPulseInterval() { + return 500000; + }; + + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) ; + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) {}; + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) {}; + }; + + class PackageManagerProgressFd : public PackageManager + { + protected: + int OutStatusFd; + int StepsDone; + int StepsTotal; + void WriteToStatusFd(std::string msg); + + public: + PackageManagerProgressFd(int progress_fd); + + virtual void Start(); + virtual void Stop(); + + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage); + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage); + + }; + + class PackageManagerFancy : public PackageManager + { + protected: + int nr_terminal_rows; + void SetupTerminalScrollArea(int nr_rows); + + public: + PackageManagerFancy(); + virtual void Start(); + virtual void Stop(); + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + }; + + class PackageManagerText : public PackageManager + { + public: + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + }; + + +}; // namespace Progress +}; // namespace APT + +#endif -- cgit v1.2.3 From d274520ee8d174aa9f062f2fbb2c4d117a121dd8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 21 Oct 2013 21:24:32 +0200 Subject: fix apt output ordering and update test to match the new human friendly messages that include the architecture --- apt-pkg/deb/dpkgpm.cc | 10 +++++----- test/integration/test-apt-progress-fd | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 5f1849b53..a61f08d91 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -668,14 +668,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // check if the package moved to the next dpkg state if(next_action && (action == next_action)) { - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; - // only read the translation if there is actually a next // action const char *translation = _(states[PackageOpsDone[pkg]].str); std::string msg; + + // we moved from one dpkg state to a new one, report that + PackageOpsDone[pkg]++; + PackagesDone++; + strprintf(msg, translation, i18n_pkgname.c_str()); d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); @@ -1505,7 +1506,6 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) CloseLog(); // dpkg is done at this point - d->progress->StatusChanged("", PackagesDone, PackagesTotal, ""); d->progress->Stop(); if (pkgPackageManager::SigINTStop) diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd index 97bb25848..9d250e949 100755 --- a/test/integration/test-apt-progress-fd +++ b/test/integration/test-apt-progress-fd @@ -21,7 +21,7 @@ pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:0:Installing testing (amd64) pmstatus:testing:20:Preparing testing (amd64) pmstatus:testing:40:Unpacking testing (amd64) -pmstatus:testing:60:Preparing to configure testing +pmstatus:testing:60:Preparing to configure testing (amd64) pmstatus:dpkg-exec:60:Running dpkg pmstatus:testing:60:Configuring testing (amd64) pmstatus:testing:80:Configuring testing (amd64) @@ -35,7 +35,7 @@ dlstatus:1:0:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:20:Preparing testing (amd64) pmstatus:testing:40:Unpacking testing (amd64) -pmstatus:testing:60:Preparing to configure testing +pmstatus:testing:60:Preparing to configure testing (amd64) pmstatus:dpkg-exec:60:Running dpkg pmstatus:testing:60:Configuring testing (amd64) pmstatus:testing:80:Configuring testing (amd64) -- cgit v1.2.3 From 3b1b0f2900347ef2836c7ee4cc3ee20c6cdcb621 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 21 Oct 2013 21:42:16 +0200 Subject: restore binary compatiblity with the pkgPackageManager interface --- apt-pkg/deb/dpkgpm.cc | 3 +- apt-pkg/packagemanager.cc | 25 +++++++++++++ apt-pkg/packagemanager.h | 18 +++++----- test/integration/test-apt-progress-fd-deb822 | 54 ++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 test/integration/test-apt-progress-fd-deb822 diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a61f08d91..adc94f05c 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -19,7 +19,8 @@ #include #include #include -#include + +#include #include #include diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 3690a64c3..a2079a2e4 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -1027,6 +1027,18 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() return Completed; } +// PM::DoInstallPostFork - compat /*{{{*/ +// --------------------------------------------------------------------- + /*}}}*/ +pkgPackageManager::OrderResult +pkgPackageManager::DoInstallPostFork(int statusFd) +{ + APT::Progress::PackageManager *progress = new + APT::Progress::PackageManagerProgressFd(statusFd); + pkgPackageManager::OrderResult res = DoInstallPostFork(progress); + delete progress; + return res; + } /*}}}*/ // PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/ // --------------------------------------------------------------------- @@ -1042,6 +1054,19 @@ pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- +/* compat */ +pkgPackageManager::OrderResult +pkgPackageManager::DoInstall(int statusFd) +{ + APT::Progress::PackageManager *progress = new + APT::Progress::PackageManagerProgressFd(statusFd); + OrderResult res = DoInstall(progress); + delete progress; + return res; + } + /*}}}*/ +// PM::DoInstall - Does the installation /*{{{*/ +// --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ pkgPackageManager::OrderResult diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 5c15ac0e4..dcd12f979 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -23,8 +23,10 @@ #ifndef PKGLIB_PACKAGEMANAGER_H #define PKGLIB_PACKAGEMANAGER_H +#include #include -#include + +#include #include #include @@ -100,16 +102,8 @@ class pkgPackageManager : protected pkgCache::Namespace // Do the installation OrderResult DoInstall(APT::Progress::PackageManager *progress); - // compat - OrderResult DoInstall(int statusFd=-1) { - APT::Progress::PackageManager *progress = new - APT::Progress::PackageManagerProgressFd(statusFd); - OrderResult res = DoInstall(progress); - delete progress; - return res; - } - + __deprecated OrderResult DoInstall(int statusFd=-1); // stuff that needs to be done before the fork() of a library that // uses apt @@ -120,6 +114,10 @@ class pkgPackageManager : protected pkgCache::Namespace // stuff that needs to be done after the fork OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress); + // compat + __deprecated OrderResult DoInstallPostFork(int statusFd=-1); + + // ? bool FixMissing(); /** \brief returns all packages dpkg let disappear */ diff --git a/test/integration/test-apt-progress-fd-deb822 b/test/integration/test-apt-progress-fd-deb822 new file mode 100644 index 000000000..0a7be0cd8 --- /dev/null +++ b/test/integration/test-apt-progress-fd-deb822 @@ -0,0 +1,54 @@ + +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' 'i386' + +buildsimplenativepackage 'testing' 'amd64' '0.1' 'stable' +buildsimplenativepackage 'testing' 'all' '0.8.15' 'stable' +buildsimplenativepackage 'testing2' 'amd64,i386' '0.8.15' 'stable' +setupaptarchive + +# install native +exec 3> apt-progress.log +testsuccess aptget install testing=0.1 -y -o APT::Status-deb822-Fd=3 +testequal "# and compare +testequal "percent:0 +message: Running dpkg + +package: testing2 +percent: 0 +message: Installing testing2 (i386) + +package: testing2 +percent: 20 +message: Preparing testing2 (i386) + +package: testing2 +percent: 40 +message: Unpacking testing2 (i386) + +package: testing2 +percent: 60 +message: Preparing to configure testing2 (i386) + +percent: 60 +message: Running dpkg + +package: testing2 +percent: 60 +message: Configuring testing2 (i386) + +package: testing2 +percent: 80 +message: Configuring testing2 (i386) + +package: testing2 +percent: 100 +message: Installed testing2 (i386)" cat apt-progress.log + + +rm -f apt-progress*.log -- cgit v1.2.3 From c7ea1ebaef0edebfe41353f93a81ee2ada5870a8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 21 Oct 2013 22:11:40 +0200 Subject: add APT::Status-deb822-Fd --- apt-private/private-install.cc | 11 +++- apt-private/private-progress.cc | 87 +++++++++++++++++++++++++++- apt-private/private-progress.h | 28 +++++++++ test/integration/test-apt-progress-fd-deb822 | 64 +++++++++++--------- 4 files changed, 159 insertions(+), 31 deletions(-) mode change 100644 => 100755 test/integration/test-apt-progress-fd-deb822 diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 8d72faecc..1d2acee6c 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -23,7 +23,8 @@ #include #include #include -#include + +#include #include #include @@ -342,10 +343,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) // FIXME: make this a factory // select the right progress - int status_fd = _config->FindI("APT::Status-Fd",-1); + int status_fd = _config->FindI("APT::Status-Fd", -1); + int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1); APT::Progress::PackageManager *progress = NULL; - if (status_fd > 0) + if (status_deb822_fd > 0) + progress = new APT::Progress::PackageManagerProgressDeb822Fd( + status_deb822_fd); + else if (status_fd > 0) progress = new APT::Progress::PackageManagerProgressFd(status_fd); else if(_config->FindB("Dpkg::Progress-Fancy", false) == true) progress = new APT::Progress::PackageManagerFancy(); diff --git a/apt-private/private-progress.cc b/apt-private/private-progress.cc index daa7695e2..1d15228c2 100644 --- a/apt-private/private-progress.cc +++ b/apt-private/private-progress.cc @@ -1,8 +1,9 @@ #include #include -#include #include +#include + #include #include @@ -117,6 +118,89 @@ bool PackageManagerProgressFd::StatusChanged(std::string PackageName, return true; } + +PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd) + : StepsDone(0), StepsTotal(1) +{ + OutStatusFd = progress_fd; +} + +void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s) +{ + FileFd::Write(OutStatusFd, s.c_str(), s.size()); +} + +void PackageManagerProgressDeb822Fd::Start() +{ + // FIXME: use SetCloseExec here once it taught about throwing + // exceptions instead of doing _exit(100) on failure + fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); + + // send status information that we are about to fork dpkg + std::ostringstream status; + status << "Status: " << "progress" << std::endl + << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl + << "Message: " << _("Running dpkg") << std::endl + << std::endl; + WriteToStatusFd(status.str()); +} + +void PackageManagerProgressDeb822Fd::Stop() +{ + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds", OutStatusFd); +} + +void PackageManagerProgressDeb822Fd::Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) +{ + std::ostringstream status; + status << "Status: " << "Error" << std::endl + << "Package:" << PackageName << std::endl + << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl + << "Message: " << ErrorMessage << std::endl + << std::endl; + WriteToStatusFd(status.str()); +} + +void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) +{ + std::ostringstream status; + status << "Status: " << "ConfFile" << std::endl + << "Package:" << PackageName << std::endl + << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl + << "Message: " << ConfMessage << std::endl + << std::endl; + WriteToStatusFd(status.str()); +} + + +bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName, + unsigned int xStepsDone, + unsigned int xTotalSteps, + std::string message) +{ + StepsDone = xStepsDone; + StepsTotal = xTotalSteps; + + // build the status str + std::ostringstream status; + status << "Status: " << "progress" << std::endl + << "Package: " << PackageName << std::endl + << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl + << "Message: " << message << std::endl + << std::endl; + WriteToStatusFd(status.str()); + + return true; +} + + void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) { // scroll down a bit to avoid visual glitch when the screen @@ -217,5 +301,6 @@ bool PackageManagerText::StatusChanged(std::string PackageName, } + }; // namespace progress }; // namespace apt diff --git a/apt-private/private-progress.h b/apt-private/private-progress.h index 42fa89be4..9c31eac92 100644 --- a/apt-private/private-progress.h +++ b/apt-private/private-progress.h @@ -77,6 +77,34 @@ namespace Progress { }; + class PackageManagerProgressDeb822Fd : public PackageManager + { + protected: + int OutStatusFd; + int StepsDone; + int StepsTotal; + void WriteToStatusFd(std::string msg); + + public: + PackageManagerProgressDeb822Fd(int progress_fd); + + virtual void Start(); + virtual void Stop(); + + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage); + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage); + }; + class PackageManagerFancy : public PackageManager { protected: diff --git a/test/integration/test-apt-progress-fd-deb822 b/test/integration/test-apt-progress-fd-deb822 old mode 100644 new mode 100755 index 0a7be0cd8..9d227942d --- a/test/integration/test-apt-progress-fd-deb822 +++ b/test/integration/test-apt-progress-fd-deb822 @@ -1,4 +1,4 @@ - +#!/bin/sh set -e TESTDIR=$(readlink -f $(dirname $0)) @@ -15,40 +15,50 @@ setupaptarchive # install native exec 3> apt-progress.log testsuccess aptget install testing=0.1 -y -o APT::Status-deb822-Fd=3 -testequal "# and compare -testequal "percent:0 -message: Running dpkg -package: testing2 -percent: 0 -message: Installing testing2 (i386) +testequal "Status: progress +Percent: 0 +Message: Running dpkg + +Status: progress +Package: testing:amd64 +Percent: 0 +Message: Installing testing (amd64) -package: testing2 -percent: 20 -message: Preparing testing2 (i386) +Status: progress +Package: testing:amd64 +Percent: 20 +Message: Preparing testing (amd64) -package: testing2 -percent: 40 -message: Unpacking testing2 (i386) +Status: progress +Package: testing:amd64 +Percent: 40 +Message: Unpacking testing (amd64) -package: testing2 -percent: 60 -message: Preparing to configure testing2 (i386) +Status: progress +Package: testing:amd64 +Percent: 60 +Message: Preparing to configure testing (amd64) -percent: 60 -message: Running dpkg +Status: progress +Percent: 60 +Message: Running dpkg -package: testing2 -percent: 60 -message: Configuring testing2 (i386) +Status: progress +Package: testing:amd64 +Percent: 60 +Message: Configuring testing (amd64) -package: testing2 -percent: 80 -message: Configuring testing2 (i386) +Status: progress +Package: testing:amd64 +Percent: 80 +Message: Configuring testing (amd64) -package: testing2 -percent: 100 -message: Installed testing2 (i386)" cat apt-progress.log +Status: progress +Package: testing:amd64 +Percent: 100 +Message: Installed testing (amd64) +" cat apt-progress.log rm -f apt-progress*.log -- cgit v1.2.3 From 8336ae355b8a22877cd233063c715688155aa617 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 18:44:14 +0200 Subject: move install-progress.{cc,h} to apt-pkg --- apt-pkg/install-progress.cc | 306 ++++++++++++++++++++++++++++++++++++++++ apt-pkg/install-progress.h | 137 ++++++++++++++++++ apt-pkg/makefile | 5 +- apt-private/makefile | 2 +- apt-private/private-progress.cc | 306 ---------------------------------------- apt-private/private-progress.h | 137 ------------------ 6 files changed, 447 insertions(+), 446 deletions(-) create mode 100644 apt-pkg/install-progress.cc create mode 100644 apt-pkg/install-progress.h delete mode 100644 apt-private/private-progress.cc delete mode 100644 apt-private/private-progress.h diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc new file mode 100644 index 000000000..1d15228c2 --- /dev/null +++ b/apt-pkg/install-progress.cc @@ -0,0 +1,306 @@ +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +namespace APT { +namespace Progress { + +bool PackageManager::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) +{ + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + percentage = StepsDone/(float)TotalSteps * 100.0; + strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage); + + if(percentage < (last_reported_progress + reporting_steps)) + return false; + + return true; +} + +PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) + : StepsDone(0), StepsTotal(1) +{ + OutStatusFd = progress_fd; +} + +void PackageManagerProgressFd::WriteToStatusFd(std::string s) +{ + if(OutStatusFd <= 0) + return; + FileFd::Write(OutStatusFd, s.c_str(), s.size()); +} + +void PackageManagerProgressFd::Start() +{ + if(OutStatusFd <= 0) + return; + + // FIXME: use SetCloseExec here once it taught about throwing + // exceptions instead of doing _exit(100) on failure + fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); + + // send status information that we are about to fork dpkg + std::ostringstream status; + status << "pmstatus:dpkg-exec:" + << (StepsDone/float(StepsTotal)*100.0) + << ":" << _("Running dpkg") + << std::endl; + WriteToStatusFd(status.str()); +} + +void PackageManagerProgressFd::Stop() +{ + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds", OutStatusFd); +} + +void PackageManagerProgressFd::Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) +{ + std::ostringstream status; + status << "pmerror:" << PackageName + << ":" << (StepsDone/float(TotalSteps)*100.0) + << ":" << ErrorMessage + << std::endl; + WriteToStatusFd(status.str()); +} + +void PackageManagerProgressFd::ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) +{ + std::ostringstream status; + status << "pmconffile:" << PackageName + << ":" << (StepsDone/float(TotalSteps)*100.0) + << ":" << ConfMessage + << std::endl; + WriteToStatusFd(status.str()); +} + + +bool PackageManagerProgressFd::StatusChanged(std::string PackageName, + unsigned int xStepsDone, + unsigned int xTotalSteps, + std::string pkg_action) +{ + StepsDone = xStepsDone; + StepsTotal = xTotalSteps; + + // build the status str + std::ostringstream status; + status << "pmstatus:" << StringSplit(PackageName, ":")[0] + << ":" << (StepsDone/float(StepsTotal)*100.0) + << ":" << pkg_action + << std::endl; + WriteToStatusFd(status.str()); + + if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true) + std::cerr << "progress: " << PackageName << " " << xStepsDone + << " " << xTotalSteps << " " << pkg_action + << std::endl; + + + return true; +} + + +PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd) + : StepsDone(0), StepsTotal(1) +{ + OutStatusFd = progress_fd; +} + +void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s) +{ + FileFd::Write(OutStatusFd, s.c_str(), s.size()); +} + +void PackageManagerProgressDeb822Fd::Start() +{ + // FIXME: use SetCloseExec here once it taught about throwing + // exceptions instead of doing _exit(100) on failure + fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); + + // send status information that we are about to fork dpkg + std::ostringstream status; + status << "Status: " << "progress" << std::endl + << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl + << "Message: " << _("Running dpkg") << std::endl + << std::endl; + WriteToStatusFd(status.str()); +} + +void PackageManagerProgressDeb822Fd::Stop() +{ + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds", OutStatusFd); +} + +void PackageManagerProgressDeb822Fd::Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) +{ + std::ostringstream status; + status << "Status: " << "Error" << std::endl + << "Package:" << PackageName << std::endl + << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl + << "Message: " << ErrorMessage << std::endl + << std::endl; + WriteToStatusFd(status.str()); +} + +void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) +{ + std::ostringstream status; + status << "Status: " << "ConfFile" << std::endl + << "Package:" << PackageName << std::endl + << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl + << "Message: " << ConfMessage << std::endl + << std::endl; + WriteToStatusFd(status.str()); +} + + +bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName, + unsigned int xStepsDone, + unsigned int xTotalSteps, + std::string message) +{ + StepsDone = xStepsDone; + StepsTotal = xTotalSteps; + + // build the status str + std::ostringstream status; + status << "Status: " << "progress" << std::endl + << "Package: " << PackageName << std::endl + << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl + << "Message: " << message << std::endl + << std::endl; + WriteToStatusFd(status.str()); + + return true; +} + + +void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) +{ + // scroll down a bit to avoid visual glitch when the screen + // area shrinks by one row + std::cout << "\n"; + + // save cursor + std::cout << "\033[s"; + + // set scroll region (this will place the cursor in the top left) + std::cout << "\033[1;" << nr_rows - 1 << "r"; + + // restore cursor but ensure its inside the scrolling area + std::cout << "\033[u"; + static const char *move_cursor_up = "\033[1A"; + std::cout << move_cursor_up; + + std::flush(std::cout); +} + +PackageManagerFancy::PackageManagerFancy() + : nr_terminal_rows(-1) +{ + struct winsize win; + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0) + { + nr_terminal_rows = win.ws_row; + } +} + +void PackageManagerFancy::Start() +{ + if (nr_terminal_rows > 0) + SetupTerminalScrollArea(nr_terminal_rows); +} + +void PackageManagerFancy::Stop() +{ + if (nr_terminal_rows > 0) + { + SetupTerminalScrollArea(nr_terminal_rows + 1); + + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; + } +} + +bool PackageManagerFancy::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) +{ + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, + HumanReadableAction)) + return false; + + int row = nr_terminal_rows; + + static string save_cursor = "\033[s"; + static string restore_cursor = "\033[u"; + + static string set_bg_color = "\033[42m"; // green + static string set_fg_color = "\033[30m"; // black + + static string restore_bg = "\033[49m"; + static string restore_fg = "\033[39m"; + + std::cout << save_cursor + // move cursor position to last row + << "\033[" << row << ";0f" + << set_bg_color + << set_fg_color + << progress_str + << restore_cursor + << restore_bg + << restore_fg; + std::flush(std::cout); + last_reported_progress = percentage; + + return true; +} + +bool PackageManagerText::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) +{ + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction)) + return false; + + std::cout << progress_str << "\r\n"; + std::flush(std::cout); + + last_reported_progress = percentage; + + return true; +} + + + +}; // namespace progress +}; // namespace apt diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h new file mode 100644 index 000000000..9c31eac92 --- /dev/null +++ b/apt-pkg/install-progress.h @@ -0,0 +1,137 @@ +#ifndef PKGLIB_IPROGRESS_H +#define PKGLIB_IPROGRESS_H + +#include +#include + + +namespace APT { +namespace Progress { + + class PackageManager + { + private: + /** \brief dpointer placeholder */ + void *d; + + protected: + std::string progress_str; + float percentage; + int last_reported_progress; + + public: + PackageManager() + : percentage(0.0), last_reported_progress(-1) {}; + virtual ~PackageManager() {}; + + virtual void Start() {}; + virtual void Stop() {}; + + virtual pid_t fork() {return fork(); }; + + virtual void Pulse() {}; + virtual long GetPulseInterval() { + return 500000; + }; + + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) ; + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) {}; + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) {}; + }; + + class PackageManagerProgressFd : public PackageManager + { + protected: + int OutStatusFd; + int StepsDone; + int StepsTotal; + void WriteToStatusFd(std::string msg); + + public: + PackageManagerProgressFd(int progress_fd); + + virtual void Start(); + virtual void Stop(); + + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage); + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage); + + }; + + class PackageManagerProgressDeb822Fd : public PackageManager + { + protected: + int OutStatusFd; + int StepsDone; + int StepsTotal; + void WriteToStatusFd(std::string msg); + + public: + PackageManagerProgressDeb822Fd(int progress_fd); + + virtual void Start(); + virtual void Stop(); + + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage); + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage); + }; + + class PackageManagerFancy : public PackageManager + { + protected: + int nr_terminal_rows; + void SetupTerminalScrollArea(int nr_rows); + + public: + PackageManagerFancy(); + virtual void Start(); + virtual void Stop(); + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + }; + + class PackageManagerText : public PackageManager + { + public: + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + }; + + +}; // namespace Progress +}; // namespace APT + +#endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index abf701511..503bd7839 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -43,7 +43,8 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ srcrecords.cc cachefile.cc versionmatch.cc policy.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ - aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc + aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc \ + install-progress.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ @@ -51,7 +52,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cachefilter.h cacheset.h edsp.h + cachefilter.h cacheset.h edsp.h install-progress.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. diff --git a/apt-private/makefile b/apt-private/makefile index 9b074f189..1d179f0b2 100644 --- a/apt-private/makefile +++ b/apt-private/makefile @@ -17,7 +17,7 @@ MAJOR=0.0 MINOR=0 SLIBS=$(PTHREADLIB) -lapt-pkg -PRIVATES=list install download output cachefile cacheset update upgrade cmndline moo search show main progress +PRIVATES=list install download output cachefile cacheset update upgrade cmndline moo search show main SOURCE += $(foreach private, $(PRIVATES), private-$(private).cc) HEADERS += $(foreach private, $(PRIVATES), private-$(private).h) diff --git a/apt-private/private-progress.cc b/apt-private/private-progress.cc deleted file mode 100644 index 1d15228c2..000000000 --- a/apt-private/private-progress.cc +++ /dev/null @@ -1,306 +0,0 @@ -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include - -namespace APT { -namespace Progress { - -bool PackageManager::StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction) -{ - int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); - percentage = StepsDone/(float)TotalSteps * 100.0; - strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage); - - if(percentage < (last_reported_progress + reporting_steps)) - return false; - - return true; -} - -PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) - : StepsDone(0), StepsTotal(1) -{ - OutStatusFd = progress_fd; -} - -void PackageManagerProgressFd::WriteToStatusFd(std::string s) -{ - if(OutStatusFd <= 0) - return; - FileFd::Write(OutStatusFd, s.c_str(), s.size()); -} - -void PackageManagerProgressFd::Start() -{ - if(OutStatusFd <= 0) - return; - - // FIXME: use SetCloseExec here once it taught about throwing - // exceptions instead of doing _exit(100) on failure - fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); - - // send status information that we are about to fork dpkg - std::ostringstream status; - status << "pmstatus:dpkg-exec:" - << (StepsDone/float(StepsTotal)*100.0) - << ":" << _("Running dpkg") - << std::endl; - WriteToStatusFd(status.str()); -} - -void PackageManagerProgressFd::Stop() -{ - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); -} - -void PackageManagerProgressFd::Error(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ErrorMessage) -{ - std::ostringstream status; - status << "pmerror:" << PackageName - << ":" << (StepsDone/float(TotalSteps)*100.0) - << ":" << ErrorMessage - << std::endl; - WriteToStatusFd(status.str()); -} - -void PackageManagerProgressFd::ConffilePrompt(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ConfMessage) -{ - std::ostringstream status; - status << "pmconffile:" << PackageName - << ":" << (StepsDone/float(TotalSteps)*100.0) - << ":" << ConfMessage - << std::endl; - WriteToStatusFd(status.str()); -} - - -bool PackageManagerProgressFd::StatusChanged(std::string PackageName, - unsigned int xStepsDone, - unsigned int xTotalSteps, - std::string pkg_action) -{ - StepsDone = xStepsDone; - StepsTotal = xTotalSteps; - - // build the status str - std::ostringstream status; - status << "pmstatus:" << StringSplit(PackageName, ":")[0] - << ":" << (StepsDone/float(StepsTotal)*100.0) - << ":" << pkg_action - << std::endl; - WriteToStatusFd(status.str()); - - if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true) - std::cerr << "progress: " << PackageName << " " << xStepsDone - << " " << xTotalSteps << " " << pkg_action - << std::endl; - - - return true; -} - - -PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd) - : StepsDone(0), StepsTotal(1) -{ - OutStatusFd = progress_fd; -} - -void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s) -{ - FileFd::Write(OutStatusFd, s.c_str(), s.size()); -} - -void PackageManagerProgressDeb822Fd::Start() -{ - // FIXME: use SetCloseExec here once it taught about throwing - // exceptions instead of doing _exit(100) on failure - fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); - - // send status information that we are about to fork dpkg - std::ostringstream status; - status << "Status: " << "progress" << std::endl - << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl - << "Message: " << _("Running dpkg") << std::endl - << std::endl; - WriteToStatusFd(status.str()); -} - -void PackageManagerProgressDeb822Fd::Stop() -{ - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); -} - -void PackageManagerProgressDeb822Fd::Error(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ErrorMessage) -{ - std::ostringstream status; - status << "Status: " << "Error" << std::endl - << "Package:" << PackageName << std::endl - << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl - << "Message: " << ErrorMessage << std::endl - << std::endl; - WriteToStatusFd(status.str()); -} - -void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ConfMessage) -{ - std::ostringstream status; - status << "Status: " << "ConfFile" << std::endl - << "Package:" << PackageName << std::endl - << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl - << "Message: " << ConfMessage << std::endl - << std::endl; - WriteToStatusFd(status.str()); -} - - -bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName, - unsigned int xStepsDone, - unsigned int xTotalSteps, - std::string message) -{ - StepsDone = xStepsDone; - StepsTotal = xTotalSteps; - - // build the status str - std::ostringstream status; - status << "Status: " << "progress" << std::endl - << "Package: " << PackageName << std::endl - << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl - << "Message: " << message << std::endl - << std::endl; - WriteToStatusFd(status.str()); - - return true; -} - - -void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) -{ - // scroll down a bit to avoid visual glitch when the screen - // area shrinks by one row - std::cout << "\n"; - - // save cursor - std::cout << "\033[s"; - - // set scroll region (this will place the cursor in the top left) - std::cout << "\033[1;" << nr_rows - 1 << "r"; - - // restore cursor but ensure its inside the scrolling area - std::cout << "\033[u"; - static const char *move_cursor_up = "\033[1A"; - std::cout << move_cursor_up; - - std::flush(std::cout); -} - -PackageManagerFancy::PackageManagerFancy() - : nr_terminal_rows(-1) -{ - struct winsize win; - if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0) - { - nr_terminal_rows = win.ws_row; - } -} - -void PackageManagerFancy::Start() -{ - if (nr_terminal_rows > 0) - SetupTerminalScrollArea(nr_terminal_rows); -} - -void PackageManagerFancy::Stop() -{ - if (nr_terminal_rows > 0) - { - SetupTerminalScrollArea(nr_terminal_rows + 1); - - // override the progress line (sledgehammer) - static const char* clear_screen_below_cursor = "\033[J"; - std::cout << clear_screen_below_cursor; - } -} - -bool PackageManagerFancy::StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction) -{ - if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, - HumanReadableAction)) - return false; - - int row = nr_terminal_rows; - - static string save_cursor = "\033[s"; - static string restore_cursor = "\033[u"; - - static string set_bg_color = "\033[42m"; // green - static string set_fg_color = "\033[30m"; // black - - static string restore_bg = "\033[49m"; - static string restore_fg = "\033[39m"; - - std::cout << save_cursor - // move cursor position to last row - << "\033[" << row << ";0f" - << set_bg_color - << set_fg_color - << progress_str - << restore_cursor - << restore_bg - << restore_fg; - std::flush(std::cout); - last_reported_progress = percentage; - - return true; -} - -bool PackageManagerText::StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction) -{ - if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction)) - return false; - - std::cout << progress_str << "\r\n"; - std::flush(std::cout); - - last_reported_progress = percentage; - - return true; -} - - - -}; // namespace progress -}; // namespace apt diff --git a/apt-private/private-progress.h b/apt-private/private-progress.h deleted file mode 100644 index 9c31eac92..000000000 --- a/apt-private/private-progress.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef PKGLIB_IPROGRESS_H -#define PKGLIB_IPROGRESS_H - -#include -#include - - -namespace APT { -namespace Progress { - - class PackageManager - { - private: - /** \brief dpointer placeholder */ - void *d; - - protected: - std::string progress_str; - float percentage; - int last_reported_progress; - - public: - PackageManager() - : percentage(0.0), last_reported_progress(-1) {}; - virtual ~PackageManager() {}; - - virtual void Start() {}; - virtual void Stop() {}; - - virtual pid_t fork() {return fork(); }; - - virtual void Pulse() {}; - virtual long GetPulseInterval() { - return 500000; - }; - - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction) ; - virtual void Error(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ErrorMessage) {}; - virtual void ConffilePrompt(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ConfMessage) {}; - }; - - class PackageManagerProgressFd : public PackageManager - { - protected: - int OutStatusFd; - int StepsDone; - int StepsTotal; - void WriteToStatusFd(std::string msg); - - public: - PackageManagerProgressFd(int progress_fd); - - virtual void Start(); - virtual void Stop(); - - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction); - virtual void Error(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ErrorMessage); - virtual void ConffilePrompt(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ConfMessage); - - }; - - class PackageManagerProgressDeb822Fd : public PackageManager - { - protected: - int OutStatusFd; - int StepsDone; - int StepsTotal; - void WriteToStatusFd(std::string msg); - - public: - PackageManagerProgressDeb822Fd(int progress_fd); - - virtual void Start(); - virtual void Stop(); - - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction); - virtual void Error(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ErrorMessage); - virtual void ConffilePrompt(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string ConfMessage); - }; - - class PackageManagerFancy : public PackageManager - { - protected: - int nr_terminal_rows; - void SetupTerminalScrollArea(int nr_rows); - - public: - PackageManagerFancy(); - virtual void Start(); - virtual void Stop(); - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction); - }; - - class PackageManagerText : public PackageManager - { - public: - virtual bool StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps, - std::string HumanReadableAction); - }; - - -}; // namespace Progress -}; // namespace APT - -#endif -- cgit v1.2.3 From af36becc889122909d677c267bc5325fb73b6151 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 19:02:01 +0200 Subject: fix install-progress location --- apt-pkg/deb/dpkgpm.cc | 3 +-- apt-pkg/install-progress.cc | 3 +-- apt-pkg/packagemanager.h | 3 +-- apt-private/private-install.cc | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index adc94f05c..c98ff3e04 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -19,8 +19,7 @@ #include #include #include - -#include +#include #include #include diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 1d15228c2..9d0d4e3f1 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -1,8 +1,7 @@ #include #include #include - -#include +#include #include diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index dcd12f979..8ffac2f13 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -25,8 +25,7 @@ #include #include - -#include +#include #include #include diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 1d2acee6c..d9d46dba0 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -23,8 +23,7 @@ #include #include #include - -#include +#include #include #include -- cgit v1.2.3 From 1f467276115ddc43b766dbd1107eb2fb315dc747 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 21:15:55 +0200 Subject: use Pkg.FullName() in disappearedPkgs and remove duplicated check --- apt-pkg/deb/dpkgpm.cc | 13 ++----------- test/integration/test-disappearing-packages | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index c98ff3e04..889b62afa 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -550,16 +550,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { pkgname = APT::String::Strip(list[2]); action = APT::String::Strip(list[1]); - - // this is what we support in the processing stage - if(action != "install" && action != "configure" && - action != "remove" && action != "purge" && action != "purge") - { - if (Debug == true) - std::clog << "ignoring processing action: '" << action - << "'" << std::endl; - return; - } } // "status" has the form: "status: pkg: state" // with state in ["half-installed", "unpacked", "half-configured", @@ -696,6 +686,7 @@ void pkgDPkgPM::handleDisappearAction(string const &pkgname) pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname); if (unlikely(Pkg.end() == true)) return; + // the disappeared package was auto-installed - nothing to do if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) return; @@ -1218,7 +1209,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { if((*I).Pkg.end() == true) continue; - if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.Name()) != disappearedPkgs.end()) + if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.FullName()) != disappearedPkgs.end()) continue; // We keep this here to allow "smooth" transitions from e.g. multiarch dpkg/ubuntu to dpkg/debian if (dpkgMultiArch == false && (I->Pkg.Arch() == nativeArch || diff --git a/test/integration/test-disappearing-packages b/test/integration/test-disappearing-packages index 09dbf7014..3b1e1bd7c 100755 --- a/test/integration/test-disappearing-packages +++ b/test/integration/test-disappearing-packages @@ -40,7 +40,7 @@ echo "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 $COMPAREFILE - && msgpass || msgfail +$CMD 2>&1 | tail -n 4 | diff -u $COMPAREFILE - && msgpass || msgfail rm $COMPAREFILE sed -i rootdir/var/log/apt/history.log -e '/^Commandline: / d' -e '/^Start-Date: / d' -e '/^End-Date: / d' -e "s#:$(getarchitecture 'native') #:native #" -- cgit v1.2.3 From 2b4e2e839ad6031061ffb0c58b1065a744d5a300 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 21:38:45 +0200 Subject: test/integration/run-tests: output the failed test names --- test/integration/run-tests | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/integration/run-tests b/test/integration/run-tests index 18474b20f..7316016e2 100755 --- a/test/integration/run-tests +++ b/test/integration/run-tests @@ -2,6 +2,7 @@ set -e FAIL=0 +FAILED_TESTS="" DIR=$(readlink -f $(dirname $0)) if [ "$1" = "-q" ]; then export MSGLEVEL=2 @@ -29,6 +30,7 @@ for testcase in $(run-parts --list $DIR | grep '/test-'); do fi if ! ${testcase}; then FAIL=$((FAIL+1)) + FAILED_TESTS="$FAILED_TESTS $(basename $testcase)" echo "$(basename $testcase) ... FAIL" fi if [ "$MSGLEVEL" -le 2 ]; then @@ -37,5 +39,8 @@ for testcase in $(run-parts --list $DIR | grep '/test-'); do done echo "failures: $FAIL" +if [ -n "$FAILED_TESTS" ]; then + echo "Failed tests: $FAILED_TESTS"; +fi # ensure we don't overflow exit $((FAIL <= 255 ? FAIL : 255)) -- cgit v1.2.3 From b4017ba767e15dc06c73915efaf36409ee099bf2 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 21:53:49 +0200 Subject: fix failing ./test/integration/test-disappearing-packages (thanks Donkult!) --- apt-pkg/deb/dpkgpm.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 889b62afa..1a02115ba 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -680,13 +680,13 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // DPkgPM::handleDisappearAction /*{{{*/ void pkgDPkgPM::handleDisappearAction(string const &pkgname) { - // record the package name for display and stuff later - disappearedPkgs.insert(pkgname); - pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname); if (unlikely(Pkg.end() == true)) return; + // record the package name for display and stuff later + disappearedPkgs.insert(Pkg.FullName(true)); + // the disappeared package was auto-installed - nothing to do if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) return; @@ -1209,7 +1209,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { if((*I).Pkg.end() == true) continue; - if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.FullName()) != disappearedPkgs.end()) + if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.FullName(true)) != disappearedPkgs.end()) continue; // We keep this here to allow "smooth" transitions from e.g. multiarch dpkg/ubuntu to dpkg/debian if (dpkgMultiArch == false && (I->Pkg.Arch() == nativeArch || -- cgit v1.2.3 From 4b9969da40ff1dff2f5787feff5103c873c57f7f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 21:55:02 +0200 Subject: fix failing ./test/integration/test-disappearing-packages (thanks Donkult) - ported from the mvo/feature/install-progress-refactor branch --- apt-pkg/deb/dpkgpm.cc | 19 +++++-------------- test/integration/test-disappearing-packages | 2 +- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 0ebd9f28b..ae895c9e6 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -555,16 +555,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) { pkgname = APT::String::Strip(list[2]); action = APT::String::Strip(list[1]); - - // this is what we support in the processing stage - if(action != "install" && action != "configure" && - action != "remove" && action != "purge" && action != "purge") - { - if (Debug == true) - std::clog << "ignoring processing action: '" << action - << "'" << std::endl; - return; - } } // "status" has the form: "status: pkg: state" // with state in ["half-installed", "unpacked", "half-configured", @@ -724,12 +714,13 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // DPkgPM::handleDisappearAction /*{{{*/ void pkgDPkgPM::handleDisappearAction(string const &pkgname) { - // record the package name for display and stuff later - disappearedPkgs.insert(pkgname); - pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname); if (unlikely(Pkg.end() == true)) return; + + // record the package name for display and stuff later + disappearedPkgs.insert(Pkg.FullName(true)); + // the disappeared package was auto-installed - nothing to do if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) return; @@ -1332,7 +1323,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) { if((*I).Pkg.end() == true) continue; - if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.Name()) != disappearedPkgs.end()) + if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.FullName(true)) != disappearedPkgs.end()) continue; // We keep this here to allow "smooth" transitions from e.g. multiarch dpkg/ubuntu to dpkg/debian if (dpkgMultiArch == false && (I->Pkg.Arch() == nativeArch || diff --git a/test/integration/test-disappearing-packages b/test/integration/test-disappearing-packages index 09dbf7014..3b1e1bd7c 100755 --- a/test/integration/test-disappearing-packages +++ b/test/integration/test-disappearing-packages @@ -40,7 +40,7 @@ echo "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 $COMPAREFILE - && msgpass || msgfail +$CMD 2>&1 | tail -n 4 | diff -u $COMPAREFILE - && msgpass || msgfail rm $COMPAREFILE sed -i rootdir/var/log/apt/history.log -e '/^Commandline: / d' -e '/^Start-Date: / d' -e '/^End-Date: / d' -e "s#:$(getarchitecture 'native') #:native #" -- cgit v1.2.3 From a18456a58a9ad2fe33f7fbd202533a115712df96 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 24 Oct 2013 08:31:50 +0200 Subject: make the main loop a while() instead of a for() as I find this (much) easier to read this way) --- apt-pkg/deb/dpkgpm.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 1a02115ba..56358ae87 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1087,8 +1087,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) dpkgMultiArch = true; } - // this loop is runs once per operation - for (vector::const_iterator I = List.begin(); I != List.end();) + // go over each item + vector::const_iterator I = List.begin(); + while (I != List.end()) { // Do all actions with the same Op in one run vector::const_iterator J = I; -- cgit v1.2.3 From c57805f9d9295541840b5775573ba51d079a11cc Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 25 Oct 2013 12:23:11 +0200 Subject: improve documentation for Acquire::http::Proxy-Auto-Detect (thanks to Francesco Poli) --- doc/apt.conf.5.xml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index e8da666c7..428c0d2db 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -398,11 +398,17 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; only if the client uses a known identifier. Acquire::http::Proxy-Auto-Detect can be used to - specify a external command to discover the http proxy to use. Apt expects + specify an external command to discover the http proxy to use. Apt expects the command to output the proxy on stdout in the style - http://proxy:port/. See the - &squid-deb-proxy-client; package for a example implementation that - uses avahi. + http://proxy:port/. This will override the + generic Acquire::http::Proxy but not any specific + host proxy configuration set via + Acquire::http::Proxy::$HOST. + + See the &squid-deb-proxy-client; package for an example implementation that + uses avahi. This option takes precedence over the legacy option name + ProxyAutoDetect. + -- cgit v1.2.3 From 6fad3c240c18dff339d934f2e3bd41c93c417f89 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 25 Oct 2013 15:43:28 +0200 Subject: extract getDpkgExecutable() and DPkgPM::BuildPackagesProgressMap() out of the monster long pkgDPkgPM::Go() --- apt-pkg/deb/dpkgpm.cc | 136 +++++++++++++++++++++++++++----------------------- apt-pkg/deb/dpkgpm.h | 3 ++ 2 files changed, 77 insertions(+), 62 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 56358ae87..98fb7581a 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -132,6 +132,20 @@ ionice(int PID) return ExecWait(Process, "ionice"); } +static std::string getDpkgExecutable() +{ + string Tmp = _config->Find("Dir::Bin::dpkg","dpkg"); + string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/"); + size_t dpkgChrootLen = dpkgChrootDir.length(); + if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0) + { + if (dpkgChrootDir[dpkgChrootLen - 1] == '/') + --dpkgChrootLen; + Tmp = Tmp.substr(dpkgChrootLen); + } + return Tmp; +} + // dpkgChrootDirectory - chrooting for dpkg if needed /*{{{*/ static void dpkgChrootDirectory() { @@ -932,6 +946,60 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, return retval; } /*}}}*/ + +// DPkgPM::BuildPackagesProgressMap /*{{{*/ +void pkgDPkgPM::BuildPackagesProgressMap() +{ + // map the dpkg states to the operations that are performed + // (this is sorted in the same way as Item::Ops) + static const struct DpkgState DpkgStatesOpMap[][7] = { + // Install operation + { + {"half-installed", N_("Preparing %s")}, + {"unpacked", N_("Unpacking %s") }, + {NULL, NULL} + }, + // Configure operation + { + {"unpacked",N_("Preparing to configure %s") }, + {"half-configured", N_("Configuring %s") }, + { "installed", N_("Installed %s")}, + {NULL, NULL} + }, + // Remove operation + { + {"half-configured", N_("Preparing for removal of %s")}, + {"half-installed", N_("Removing %s")}, + {"config-files", N_("Removed %s")}, + {NULL, NULL} + }, + // Purge operation + { + {"config-files", N_("Preparing to completely remove %s")}, + {"not-installed", N_("Completely removed %s")}, + {NULL, NULL} + }, + }; + + // init the PackageOps map, go over the list of packages that + // that will be [installed|configured|removed|purged] and add + // them to the PackageOps map (the dpkg states it goes through) + // and the PackageOpsTranslations (human readable strings) + for (vector::const_iterator I = List.begin(); I != List.end(); ++I) + { + if((*I).Pkg.end() == true) + continue; + + string const name = (*I).Pkg.FullName(); + PackageOpsDone[name] = 0; + for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; ++i) + { + PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]); + PackagesTotal++; + } + } +} + /*}}}*/ // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg @@ -947,21 +1015,11 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) d->progress = progress; // Generate the base argument list for dpkg - std::vector Args; unsigned long StartSize = 0; - string Tmp = _config->Find("Dir::Bin::dpkg","dpkg"); - { - string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/"); - size_t dpkgChrootLen = dpkgChrootDir.length(); - if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0) - { - if (dpkgChrootDir[dpkgChrootLen - 1] == '/') - --dpkgChrootLen; - Tmp = Tmp.substr(dpkgChrootLen); - } - } - Args.push_back(Tmp.c_str()); - StartSize += Tmp.length(); + std::vector Args; + std::string DpkgExecutable = getDpkgExecutable(); + Args.push_back(DpkgExecutable.c_str()); + StartSize += DpkgExecutable.length(); // Stick in any custom dpkg options Configuration::Item const *Opts = _config->Tree("DPkg::Options"); @@ -1018,54 +1076,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (_config->FindB("DPkg::ConfigurePending", SmartConf) == true) List.push_back(Item(Item::ConfigurePending, PkgIterator())); - // map the dpkg states to the operations that are performed - // (this is sorted in the same way as Item::Ops) - static const struct DpkgState DpkgStatesOpMap[][7] = { - // Install operation - { - {"half-installed", N_("Preparing %s")}, - {"unpacked", N_("Unpacking %s") }, - {NULL, NULL} - }, - // Configure operation - { - {"unpacked",N_("Preparing to configure %s") }, - {"half-configured", N_("Configuring %s") }, - { "installed", N_("Installed %s")}, - {NULL, NULL} - }, - // Remove operation - { - {"half-configured", N_("Preparing for removal of %s")}, - {"half-installed", N_("Removing %s")}, - {"config-files", N_("Removed %s")}, - {NULL, NULL} - }, - // Purge operation - { - {"config-files", N_("Preparing to completely remove %s")}, - {"not-installed", N_("Completely removed %s")}, - {NULL, NULL} - }, - }; - - // init the PackageOps map, go over the list of packages that - // that will be [installed|configured|removed|purged] and add - // them to the PackageOps map (the dpkg states it goes through) - // and the PackageOpsTranslations (human readable strings) - for (vector::const_iterator I = List.begin(); I != List.end(); ++I) - { - if((*I).Pkg.end() == true) - continue; - - string const name = (*I).Pkg.FullName(); - PackageOpsDone[name] = 0; - for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; ++i) - { - PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]); - PackagesTotal++; - } - } + // for the progress + BuildPackagesProgressMap(); d->stdin_is_dev_null = false; diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 922631ba8..5f00eee5d 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -97,6 +97,9 @@ class pkgDPkgPM : public pkgPackageManager // dpkg log bool OpenLog(); bool CloseLog(); + + // helper + void BuildPackagesProgressMap(); // input processing void DoStdin(int master); -- cgit v1.2.3 From c3045b79796b611858e9f8b44127a70d6043cea0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 07:36:47 +0100 Subject: move pty stuff into its own function --- apt-pkg/deb/dpkgpm.cc | 173 +++++++++++++++++++++++++++----------------------- apt-pkg/deb/dpkgpm.h | 3 + 2 files changed, 97 insertions(+), 79 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 0ebd9f28b..ddfc7c04e 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -55,7 +55,7 @@ public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), last_reported_progress(0.0), nr_terminal_rows(0), - fancy_progress_output(false) + fancy_progress_output(false), master(-1), slave(-1) { dpkgbuf[0] = '\0'; if(_config->FindB("Dpkg::Progress-Fancy", false) == true) @@ -63,6 +63,7 @@ public: fancy_progress_output = true; _config->Set("DpkgPM::Progress", true); } + } bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading @@ -75,6 +76,16 @@ public: float last_reported_progress; int nr_terminal_rows; bool fancy_progress_output; + + // pty stuff + struct termios tt; + int master; + int slave; + + // signals + sigset_t sigmask; + sigset_t original_sigmask; + }; namespace @@ -1055,6 +1066,61 @@ void pkgDPkgPM::CleanupTerminal() } } +void pkgDPkgPM::StartPtyMagic() +{ + // setup the pty and stuff + struct winsize win; + + // if tcgetattr does not return zero there was a error + // and we do not do any pty magic + _error->PushToStack(); + if (tcgetattr(STDOUT_FILENO, &d->tt) == 0) + { + ioctl(1, TIOCGWINSZ, (char *)&win); + d->nr_terminal_rows = win.ws_row; + if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0) + { + _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); + d->master = d->slave = -1; + } else { + struct termios rtt; + rtt = d->tt; + cfmakeraw(&rtt); + rtt.c_lflag &= ~ECHO; + rtt.c_lflag |= ISIG; + // block SIGTTOU during tcsetattr to prevent a hang if + // the process is a member of the background process group + // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html + sigemptyset(&d->sigmask); + sigaddset(&d->sigmask, SIGTTOU); + sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask); + tcsetattr(0, TCSAFLUSH, &rtt); + sigprocmask(SIG_SETMASK, &d->original_sigmask, 0); + } + } + // complain only if stdout is either a terminal (but still failed) or is an invalid + // descriptor otherwise we would complain about redirection to e.g. /dev/null as well. + else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) + _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); + + if (_error->PendingError() == true) + _error->DumpErrors(std::cerr); + _error->RevertToStack(); + + // setup terminal + SetupTerminalScrollArea(d->nr_terminal_rows); +} + +void pkgDPkgPM::StopPtyMagic() +{ + if(d->slave > 0) + close(d->slave); + if(d->master >= 0) + { + tcsetattr(0, TCSAFLUSH, &d->tt); + close(d->master); + } +} // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- @@ -1121,8 +1187,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) fd_set rfds; struct timespec tv; - sigset_t sigmask; - sigset_t original_sigmask; unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024); unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024); @@ -1210,8 +1274,12 @@ bool pkgDPkgPM::Go(int OutStatusFd) dpkgMultiArch = true; } - // this loop is runs once per operation - for (vector::const_iterator I = List.begin(); I != List.end();) + // start pty magic before the loop + StartPtyMagic(); + + // this loop is runs once per dpkg operation + vector::const_iterator I = List.begin(); + while (I != List.end()) { // Do all actions with the same Op in one run vector::const_iterator J = I; @@ -1402,47 +1470,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) // ignore SIGHUP as well (debian #463030) sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN); - struct termios tt; - struct winsize win; - int master = -1; - int slave = -1; - - // if tcgetattr does not return zero there was a error - // and we do not do any pty magic - _error->PushToStack(); - if (tcgetattr(STDOUT_FILENO, &tt) == 0) - { - ioctl(1, TIOCGWINSZ, (char *)&win); - d->nr_terminal_rows = win.ws_row; - if (openpty(&master, &slave, NULL, &tt, &win) < 0) - { - _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); - master = slave = -1; - } else { - struct termios rtt; - rtt = tt; - cfmakeraw(&rtt); - rtt.c_lflag &= ~ECHO; - rtt.c_lflag |= ISIG; - // block SIGTTOU during tcsetattr to prevent a hang if - // the process is a member of the background process group - // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGTTOU); - sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask); - tcsetattr(0, TCSAFLUSH, &rtt); - sigprocmask(SIG_SETMASK, &original_sigmask, 0); - } - } - // complain only if stdout is either a terminal (but still failed) or is an invalid - // descriptor otherwise we would complain about redirection to e.g. /dev/null as well. - else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) - _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); - - if (_error->PendingError() == true) - _error->DumpErrors(std::cerr); - _error->RevertToStack(); - // Fork dpkg pid_t Child; _config->Set("APT::Keep-Fds::",fd[1]); @@ -1461,15 +1488,15 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (Child == 0) { - if(slave >= 0 && master >= 0) + if(d->slave >= 0 && d->master >= 0) { setsid(); - ioctl(slave, TIOCSCTTY, 0); - close(master); - dup2(slave, 0); - dup2(slave, 1); - dup2(slave, 2); - close(slave); + ioctl(d->slave, TIOCSCTTY, 0); + close(d->master); + dup2(d->slave, 0); + dup2(d->slave, 1); + dup2(d->slave, 2); + close(d->slave); } close(fd[0]); // close the read end of the pipe @@ -1493,9 +1520,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } - // setup terminal - SetupTerminalScrollArea(d->nr_terminal_rows); - SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ @@ -1519,12 +1543,9 @@ bool pkgDPkgPM::Go(int OutStatusFd) int const _dpkgin = fd[0]; close(fd[1]); // close the write end of the pipe - if(slave > 0) - close(slave); - // setups fds - sigemptyset(&sigmask); - sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask); + sigemptyset(&d->sigmask); + sigprocmask(SIG_BLOCK,&d->sigmask,&d->original_sigmask); /* free vectors (and therefore memory) as we don't need the included data anymore */ for (std::vector::const_iterator p = Packages.begin(); @@ -1553,18 +1574,18 @@ bool pkgDPkgPM::Go(int OutStatusFd) // wait for input or output here FD_ZERO(&rfds); - if (master >= 0 && !d->stdin_is_dev_null) + if (d->master >= 0 && !d->stdin_is_dev_null) FD_SET(0, &rfds); FD_SET(_dpkgin, &rfds); - if(master >= 0) - FD_SET(master, &rfds); + if(d->master >= 0) + FD_SET(d->master, &rfds); tv.tv_sec = 1; tv.tv_nsec = 0; - select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, - &tv, &original_sigmask); + select_ret = pselect(max(d->master, _dpkgin)+1, &rfds, NULL, NULL, + &tv, &d->original_sigmask); if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS)) - select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL, - NULL, &tv, &original_sigmask); + select_ret = racy_pselect(max(d->master, _dpkgin)+1, &rfds, NULL, + NULL, &tv, &d->original_sigmask); if (select_ret == 0) continue; else if (select_ret < 0 && errno == EINTR) @@ -1575,10 +1596,10 @@ bool pkgDPkgPM::Go(int OutStatusFd) continue; } - if(master >= 0 && FD_ISSET(master, &rfds)) - DoTerminalPty(master); - if(master >= 0 && FD_ISSET(0, &rfds)) - DoStdin(master); + if(d->master >= 0 && FD_ISSET(d->master, &rfds)) + DoTerminalPty(d->master); + if(d->master >= 0 && FD_ISSET(0, &rfds)) + DoStdin(d->master); if(FD_ISSET(_dpkgin, &rfds)) DoDpkgStatusFd(_dpkgin, OutStatusFd); } @@ -1589,13 +1610,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGINT,old_SIGINT); signal(SIGHUP,old_SIGHUP); - - if(master >= 0) - { - tcsetattr(0, TCSAFLUSH, &tt); - close(master); - } - // Check for an error code. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) { @@ -1632,6 +1646,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) SendTerminalProgress(100); CleanupTerminal(); + StopPtyMagic(); if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 1a58e1af5..5551b4383 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -95,6 +95,9 @@ class pkgDPkgPM : public pkgPackageManager // dpkg log bool OpenLog(); bool CloseLog(); + + void StartPtyMagic(); + void StopPtyMagic(); // input processing void DoStdin(int master); -- cgit v1.2.3 From bd5f39b34cc0e8cebbe9103f569d4d903e75bd2b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 08:23:12 +0100 Subject: restore ABI and prepare next ABI via #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) --- apt-pkg/deb/dpkgpm.cc | 17 +++++++++++++++++ apt-pkg/deb/dpkgpm.h | 7 +++++++ apt-pkg/install-progress.cc | 22 ++++++++++++++++++++++ apt-pkg/install-progress.h | 3 +++ apt-pkg/packagemanager.cc | 36 ++++++++++++++++++++++++++++++------ apt-pkg/packagemanager.h | 15 ++++++++++++++- apt-private/private-install.cc | 35 +++++++++++++---------------------- 7 files changed, 106 insertions(+), 29 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 98fb7581a..b252c02eb 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1000,6 +1000,19 @@ void pkgDPkgPM::BuildPackagesProgressMap() } } /*}}}*/ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) +bool pkgDPkgPM::Go(int StatusFd) +{ + APT::Progress::PackageManager *progress = NULL; + if (StatusFd == -1) + progress = APT::Progress::PackageManagerProgressFactory(); + else + progress = new APT::Progress::PackageManagerProgressFd(StatusFd); + + return GoNoABIBreak(progress); +} +#endif + // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg @@ -1009,7 +1022,11 @@ void pkgDPkgPM::BuildPackagesProgressMap() * through to human readable (and i10n-able) * names and calculates a percentage for each step. */ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) +#else +bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) +#endif { pkgPackageManager::SigINTStop = false; d->progress = progress; diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 5f00eee5d..4494bbae3 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -15,6 +15,7 @@ #include #include #include +#include #ifndef APT_8_CLEANER_HEADERS using std::vector; @@ -112,7 +113,13 @@ class pkgDPkgPM : public pkgPackageManager virtual bool Configure(PkgIterator Pkg); virtual bool Remove(PkgIterator Pkg,bool Purge = false); +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) virtual bool Go(APT::Progress::PackageManager *progress); +#else + virtual bool Go(int StatusFd=-1); + bool GoNoABIBreak(APT::Progress::PackageManager *progress); +#endif + virtual void Reset(); public: diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 9d0d4e3f1..a9146f27d 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -13,6 +13,28 @@ namespace APT { namespace Progress { +PackageManager* PackageManagerProgressFactory() +{ + // select the right progress + int status_fd = _config->FindI("APT::Status-Fd", -1); + int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1); + + APT::Progress::PackageManager *progress = NULL; + if (status_deb822_fd > 0) + progress = new APT::Progress::PackageManagerProgressDeb822Fd( + status_deb822_fd); + else if (status_fd > 0) + progress = new APT::Progress::PackageManagerProgressFd(status_fd); + else if(_config->FindB("Dpkg::Progress-Fancy", false) == true) + progress = new APT::Progress::PackageManagerFancy(); + else if (_config->FindB("Dpkg::Progress", + _config->FindB("DpkgPM::Progress", false)) == true) + progress = new APT::Progress::PackageManagerText(); + else + progress = new APT::Progress::PackageManager(); + return progress; +} + bool PackageManager::StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 9c31eac92..050954bb5 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -8,6 +8,9 @@ namespace APT { namespace Progress { + class PackageManager; + PackageManager* PackageManagerProgressFactory(); + class PackageManager { private: diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index a2079a2e4..3fdd9b637 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -1030,15 +1030,16 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() // PM::DoInstallPostFork - compat /*{{{*/ // --------------------------------------------------------------------- /*}}}*/ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) pkgPackageManager::OrderResult pkgPackageManager::DoInstallPostFork(int statusFd) { - APT::Progress::PackageManager *progress = new - APT::Progress::PackageManagerProgressFd(statusFd); - pkgPackageManager::OrderResult res = DoInstallPostFork(progress); - delete progress; - return res; - } + APT::Progress::PackageManager *progress = new + APT::Progress::PackageManagerProgressFd(statusFd); + pkgPackageManager::OrderResult res = DoInstallPostFork(progress); + delete progress; + return res; +} /*}}}*/ // PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/ // --------------------------------------------------------------------- @@ -1051,10 +1052,22 @@ pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) return Res; }; +#else +pkgPackageManager::OrderResult +pkgPackageManager::DoInstallPostFork(int statusFd) +{ + bool goResult = Go(statusFd); + if(goResult == false) + return Failed; + + return Res; +} +#endif /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* compat */ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) { @@ -1064,11 +1077,21 @@ pkgPackageManager::DoInstall(int statusFd) delete progress; return res; } +#else +pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) +{ + if(DoInstallPreFork() == Failed) + return Failed; + + return DoInstallPostFork(statusFd); +} +#endif /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) pkgPackageManager::OrderResult pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) { @@ -1077,4 +1100,5 @@ pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) return DoInstallPostFork(progress); } +#endif /*}}}*/ diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 8ffac2f13..a5c58e4a7 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -87,7 +88,12 @@ class pkgPackageManager : protected pkgCache::Namespace virtual bool Install(PkgIterator /*Pkg*/,std::string /*File*/) {return false;}; virtual bool Configure(PkgIterator /*Pkg*/) {return false;}; virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;}; +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) virtual bool Go(APT::Progress::PackageManager *progress) {return true;}; +#else + virtual bool Go(int StatusFd=-1) {return true;}; +#endif + virtual void Reset() {}; // the result of the operation @@ -100,9 +106,13 @@ class pkgPackageManager : protected pkgCache::Namespace pkgRecords *Recs); // Do the installation +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) OrderResult DoInstall(APT::Progress::PackageManager *progress); // compat __deprecated OrderResult DoInstall(int statusFd=-1); +#else + OrderResult DoInstall(int statusFd=-1); +#endif // stuff that needs to be done before the fork() of a library that // uses apt @@ -110,11 +120,14 @@ class pkgPackageManager : protected pkgCache::Namespace Res = OrderInstall(); return Res; }; - +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) // stuff that needs to be done after the fork OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress); // compat __deprecated OrderResult DoInstallPostFork(int statusFd=-1); +#else + OrderResult DoInstallPostFork(int statusFd=-1); +#endif // ? bool FixMissing(); diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index d9d46dba0..3adb00b23 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -105,12 +106,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) { pkgSimulate PM(Cache); - int status_fd = _config->FindI("APT::Status-Fd",-1); - APT::Progress::PackageManager *progress = NULL; - if (status_fd > 0) - progress = new APT::Progress::PackageManagerProgressFd(status_fd); +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) + APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory(); pkgPackageManager::OrderResult Res = PM.DoInstall(progress); delete progress; +#else + int status_fd = _config->FindI("APT::Status-Fd",-1); + pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd); +#endif if (Res == pkgPackageManager::Failed) return false; @@ -340,26 +343,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) _system->UnLock(); - // FIXME: make this a factory - // select the right progress - int status_fd = _config->FindI("APT::Status-Fd", -1); - int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1); - - APT::Progress::PackageManager *progress = NULL; - if (status_deb822_fd > 0) - progress = new APT::Progress::PackageManagerProgressDeb822Fd( - status_deb822_fd); - else if (status_fd > 0) - progress = new APT::Progress::PackageManagerProgressFd(status_fd); - else if(_config->FindB("Dpkg::Progress-Fancy", false) == true) - progress = new APT::Progress::PackageManagerFancy(); - else if (_config->FindB("Dpkg::Progress", - _config->FindB("DpkgPM::Progress", false)) == true) - progress = new APT::Progress::PackageManagerText(); - else - progress = new APT::Progress::PackageManager(); +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) + APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory(); pkgPackageManager::OrderResult Res = PM->DoInstall(progress); delete progress; +#else + int status_fd = _config->FindI("APT::Status-Fd", -1); + pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd); +#endif if (Res == pkgPackageManager::Failed || _error->PendingError() == true) return false; -- cgit v1.2.3 From c5f0d8e6f8d338727b2b6bc4be0e482082398014 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 17:08:20 +0100 Subject: fix some more ABI issues, abicheck is happy now --- abicheck/run_abi_test | 2 +- apt-pkg/deb/dpkgpm.h | 9 +++++++++ apt-pkg/packagemanager.h | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/abicheck/run_abi_test b/abicheck/run_abi_test index 9ee840ea0..8f2d7d203 100755 --- a/abicheck/run_abi_test +++ b/abicheck/run_abi_test @@ -16,4 +16,4 @@ sed s#@installed_libapt@#$LIBPATH# apt_installed.xml.in > apt_installed.xml BUILDPATH=$(readlink -f ../build) sed s#@build_path@#$BUILDPATH# apt_build.xml.in > apt_build.xml -abi-compliance-checker -l apt -d1 apt_installed.xml -d2 apt_build.xml +abi-compliance-checker -l apt -d1 apt_installed.xml -d2 apt_build.xml $@ diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 4494bbae3..50b5d609b 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -107,6 +107,15 @@ class pkgDPkgPM : public pkgPackageManager void DoTerminalPty(int master); void DoDpkgStatusFd(int statusfd); void ProcessDpkgStatusLine(char *line); +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) + void DoDpkgStatusFd(int statusfd, int unused) { + DoDpkgStatusFd(statusfd); + } + void ProcessDpkgStatusLine(int unused, char *line) { + ProcessDpkgStatusLine(line); + } +#endif + // The Actuall installation implementation virtual bool Install(PkgIterator Pkg,std::string File); diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index a5c58e4a7..853b9bac8 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -91,7 +91,7 @@ class pkgPackageManager : protected pkgCache::Namespace #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) virtual bool Go(APT::Progress::PackageManager *progress) {return true;}; #else - virtual bool Go(int StatusFd=-1) {return true;}; + virtual bool Go(int statusFd=-1) {return true;}; #endif virtual void Reset() {}; -- cgit v1.2.3 From e45c4617e496b49f8d7225546a751022f246a2f3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 22:55:38 +0100 Subject: add new pid_t ExecFork(std::set KeepFDs) to get rid of the super ugly APT::Keep-Fds hack and also add a new PackageManagerProgressFd::StartDpkg() progress state --- apt-pkg/contrib/fileutl.cc | 33 +++++++++++++++++++-------------- apt-pkg/contrib/fileutl.h | 2 ++ apt-pkg/deb/dpkgpm.cc | 26 ++++++++++++++------------ apt-pkg/install-progress.cc | 6 +----- apt-pkg/install-progress.h | 8 +++++++- 5 files changed, 43 insertions(+), 32 deletions(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 0261119ba..2347ef140 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -766,6 +766,25 @@ bool WaitFd(int Fd,bool write,unsigned long timeout) child, it fixes up the important signals and nukes all of the fds, otherwise acts like normal fork. */ pid_t ExecFork() +{ + set KeepFDs; + + Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds"); + if (Opts != 0 && Opts->Child != 0) + { + Opts = Opts->Child; + for (; Opts != 0; Opts = Opts->Next) + { + if (Opts->Value.empty() == true) + continue; + int fd = atoi(Opts->Value.c_str()); + KeepFDs.insert(fd); + } + } + return ExecFork(KeepFDs); +} + +pid_t ExecFork(std::set KeepFDs) { // Fork off the process pid_t Process = fork(); @@ -786,20 +805,6 @@ pid_t ExecFork() signal(SIGCONT,SIG_DFL); signal(SIGTSTP,SIG_DFL); - set KeepFDs; - Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds"); - if (Opts != 0 && Opts->Child != 0) - { - Opts = Opts->Child; - for (; Opts != 0; Opts = Opts->Next) - { - if (Opts->Value.empty() == true) - continue; - int fd = atoi(Opts->Value.c_str()); - KeepFDs.insert(fd); - } - } - // Close all of our FDs - just in case for (int K = 3; K != 40; K++) { diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index decd64d9d..63a999c30 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -26,6 +26,7 @@ #include #include +#include #include @@ -182,6 +183,7 @@ void SetCloseExec(int Fd,bool Close); void SetNonBlock(int Fd,bool Block); bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0); pid_t ExecFork(); +pid_t ExecFork(std::set keep_fds); bool ExecWait(pid_t Pid,const char *Name,bool Reap = false); // File string manipulators diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d1b11098c..26d79dbb1 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -416,17 +416,20 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) unsigned int InfoFD = _config->FindI(OptSec + "::InfoFD", STDIN_FILENO); // Create the pipes + std::set KeepFDs; int Pipes[2]; if (pipe(Pipes) != 0) return _error->Errno("pipe","Failed to create IPC pipe to subprocess"); if (InfoFD != (unsigned)Pipes[0]) SetCloseExec(Pipes[0],true); else - _config->Set("APT::Keep-Fds::", Pipes[0]); + KeepFDs.insert(Pipes[0]); + + SetCloseExec(Pipes[1],true); // Purified Fork for running the script - pid_t Process = ExecFork(); + pid_t Process = ExecFork(KeepFDs); if (Process == 0) { // Setup the FDs @@ -448,8 +451,6 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) execv(Args[0],(char **)Args); _exit(100); } - if (InfoFD == (unsigned)Pipes[0]) - _config->Clear("APT::Keep-Fds", Pipes[0]); close(Pipes[0]); FILE *F = fdopen(Pipes[1],"w"); if (F == 0) @@ -1375,11 +1376,14 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) // ignore SIGHUP as well (debian #463030) sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN); - pid_t Child = ExecFork(); - // This is the child + // now run dpkg + d->progress->StartDpkg(); + std::set KeepFDs; + KeepFDs.insert(fd[1]); + pid_t Child = ExecFork(KeepFDs); if (Child == 0) { - + // This is the child if(d->slave >= 0 && d->master >= 0) { setsid(); @@ -1425,9 +1429,6 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) if (_config->FindB("DPkg::UseIoNice", false) == true) ionice(Child); - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds",fd[1]); - // Wait for dpkg int Status = 0; @@ -1471,13 +1472,14 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) FD_SET(_dpkgin, &rfds); if(d->master >= 0) FD_SET(d->master, &rfds); - tv.tv_sec = 1; - tv.tv_nsec = 0; + tv.tv_sec = 0; + tv.tv_nsec = d->progress->GetPulseInterval(); select_ret = pselect(max(d->master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &d->original_sigmask); if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS)) select_ret = racy_pselect(max(d->master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &d->original_sigmask); + d->progress->Pulse(); if (select_ret == 0) continue; else if (select_ret < 0 && errno == EINTR) diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index a9146f27d..79660b29e 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -63,7 +63,7 @@ void PackageManagerProgressFd::WriteToStatusFd(std::string s) FileFd::Write(OutStatusFd, s.c_str(), s.size()); } -void PackageManagerProgressFd::Start() +void PackageManagerProgressFd::StartDpkg() { if(OutStatusFd <= 0) return; @@ -83,8 +83,6 @@ void PackageManagerProgressFd::Start() void PackageManagerProgressFd::Stop() { - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); } void PackageManagerProgressFd::Error(std::string PackageName, @@ -168,8 +166,6 @@ void PackageManagerProgressDeb822Fd::Start() void PackageManagerProgressDeb822Fd::Stop() { - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); } void PackageManagerProgressDeb822Fd::Error(std::string PackageName, diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 050954bb5..5291039d8 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -27,9 +27,15 @@ namespace Progress { : percentage(0.0), last_reported_progress(-1) {}; virtual ~PackageManager() {}; + /* Global Start/Stop */ virtual void Start() {}; virtual void Stop() {}; + /* When dpkg is invoked (may happen multiple times for each + * install/remove block + */ + virtual void StartDpkg() {}; + virtual pid_t fork() {return fork(); }; virtual void Pulse() {}; @@ -62,7 +68,7 @@ namespace Progress { public: PackageManagerProgressFd(int progress_fd); - virtual void Start(); + virtual void StartDpkg(); virtual void Stop(); virtual bool StatusChanged(std::string PackageName, -- cgit v1.2.3 From 790d41f6372871e527f3fc9da66d049937b4c780 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 23:00:11 +0100 Subject: use StartDpkg() in PackageManagerProgressDeb822Fd as well --- apt-pkg/install-progress.cc | 2 +- apt-pkg/install-progress.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 79660b29e..f76fc88c2 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -149,7 +149,7 @@ void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s) FileFd::Write(OutStatusFd, s.c_str(), s.size()); } -void PackageManagerProgressDeb822Fd::Start() +void PackageManagerProgressDeb822Fd::StartDpkg() { // FIXME: use SetCloseExec here once it taught about throwing // exceptions instead of doing _exit(100) on failure diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 5291039d8..d721c6373 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -97,7 +97,7 @@ namespace Progress { public: PackageManagerProgressDeb822Fd(int progress_fd); - virtual void Start(); + virtual void StartDpkg(); virtual void Stop(); virtual bool StatusChanged(std::string PackageName, -- cgit v1.2.3 From bc37330b76f56a556ab1ddcd4e6cfb72640f5764 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 23:24:41 +0100 Subject: setup LINES in apt-pkg/install-progress.cc --- apt-pkg/install-progress.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index f76fc88c2..b341fe686 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -235,6 +235,11 @@ void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) static const char *move_cursor_up = "\033[1A"; std::cout << move_cursor_up; + // setup env for (hopefully!) ncurses + string s; + strprintf(s, "%i", nr_rows); + setenv("LINES", s.c_str(), 1); + std::flush(std::cout); } -- cgit v1.2.3 From 123fa88a1a77da53c55adea7dfdb4334e58dedb4 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 23:37:10 +0100 Subject: prepare new upload --- debian/changelog | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/debian/changelog b/debian/changelog index 65269de95..20436d919 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,27 @@ +apt (0.9.13~exp1) UNRELEASED; urgency=low + + * Improve the API for APT::Upgrade::Upgrade() + * Re-add "Calculating upgrade..." message + * move upgrade releated code into upgrade.{cc,h} + * Move ListUpdate/AquireUpdate into update.{cc,h} + * Add new apt-pkg/install-progress.h with APT::Progress::PackageManager + progress reporting classes + * Move the status-fd progress reporting out of the pkgDPkgPM class + and into PackageManagerProgressFd + * Fix reading dpkg --status-fd on reinstalls + * Add new APT::Status-deb822-Fd progress output + * add Acquire::http::Proxy-Auto-Detect to the apt.conf.5 manpage + (closes: 726597) + * Fix detection when multiarch packages are reported by dpkg as + disappeared Packages + * test/integration/run-tests: output the failed test names + * Code Cleanup in pkgDPkgPM + * prepare next ABI via #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) + * add new pid_t ExecFork(std::set KeepFDs) + * Avoid flickering when "apt-get -o DpkgPM::Progress-Fancy=1" is use + + -- Michael Vogt Thu, 31 Oct 2013 23:25:59 +0100 + apt (0.9.12.1) unstable; urgency=low [ Michael Vogt ] -- cgit v1.2.3 From 213a00a43774ad41d1a59c82fe042390026ab048 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 1 Nov 2013 10:03:16 +0100 Subject: releasing package apt version 0.9.13~exp1 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 20436d919..5c31210aa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -apt (0.9.13~exp1) UNRELEASED; urgency=low +apt (0.9.13~exp1) experimental; urgency=low * Improve the API for APT::Upgrade::Upgrade() * Re-add "Calculating upgrade..." message @@ -20,7 +20,7 @@ apt (0.9.13~exp1) UNRELEASED; urgency=low * add new pid_t ExecFork(std::set KeepFDs) * Avoid flickering when "apt-get -o DpkgPM::Progress-Fancy=1" is use - -- Michael Vogt Thu, 31 Oct 2013 23:25:59 +0100 + -- Michael Vogt Fri, 01 Nov 2013 10:03:06 +0100 apt (0.9.12.1) unstable; urgency=low -- cgit v1.2.3 From 61f954bff040809e7ab57b3adec2fe95339ffb94 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 1 Nov 2013 10:42:49 +0100 Subject: small documentation updates --- apt-pkg/algorithms.h | 2 +- apt-pkg/contrib/fileutl.cc | 3 ++- apt-pkg/install-progress.cc | 4 ++++ debian/changelog | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 80f6578eb..5a9a77415 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -40,11 +40,11 @@ #ifndef APT_8_CLEANER_HEADERS #include -// include pkg{DistUpgrade,AllUpgrade,MiniizeUpgrade} here for compatiblity using std::ostream; #endif #ifndef APT_9_CLEANER_HEADERS +// include pkg{DistUpgrade,AllUpgrade,MiniizeUpgrade} here for compatiblity #include #include #endif diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 2347ef140..d2be276c7 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -769,6 +769,7 @@ pid_t ExecFork() { set KeepFDs; + // FIXME: remove looking at APT::Keep-Fds eventually, its a hack Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds"); if (Opts != 0 && Opts->Child != 0) { @@ -806,7 +807,7 @@ pid_t ExecFork(std::set KeepFDs) signal(SIGTSTP,SIG_DFL); // Close all of our FDs - just in case - for (int K = 3; K != 40; K++) + for (int K = 3; K != sysconf(_SC_OPEN_MAX); K++) { if(KeepFDs.find(K) == KeepFDs.end()) fcntl(K,F_SETFD,FD_CLOEXEC); diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index b341fe686..09b1bef9e 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -13,6 +13,10 @@ namespace APT { namespace Progress { + +/* Return a APT::Progress::PackageManager based on the global + * apt configuration (i.e. APT::Status-Fd and APT::Status-deb822-Fd) + */ PackageManager* PackageManagerProgressFactory() { // select the right progress diff --git a/debian/changelog b/debian/changelog index 5c31210aa..e6bdcb1fa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -19,6 +19,7 @@ apt (0.9.13~exp1) experimental; urgency=low * prepare next ABI via #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) * add new pid_t ExecFork(std::set KeepFDs) * Avoid flickering when "apt-get -o DpkgPM::Progress-Fancy=1" is use + * use sysconf(_SC_OPEN_MAX) in ExecFork() -- Michael Vogt Fri, 01 Nov 2013 10:03:06 +0100 -- cgit v1.2.3