Browse Source

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

debian/1.8.y
Michael Vogt 9 years ago
parent
commit
e6ad8031b7
  1. 99
      apt-pkg/deb/dpkgpm.cc
  2. 7
      apt-pkg/deb/dpkgpm.h
  3. 95
      apt-pkg/iprogress.cc
  4. 56
      apt-pkg/iprogress.h
  5. 14
      apt-pkg/packagemanager.cc
  6. 18
      apt-pkg/packagemanager.h
  7. 24
      apt-private/private-install.cc

99
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 char *, const char *> * 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<const char *> 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"));

7
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:

95
apt-pkg/iprogress.cc

@ -1,16 +1,22 @@
#include <apt-pkg/configuration.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/iprogress.h>
#include <apt-pkg/strutl.h>
#include <apti18n.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sstream>
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";

56
apt-pkg/iprogress.h

@ -1,13 +1,13 @@
#ifndef PKGLIB_IPROGRESS_H
#define PKGLIB_IPROGRSS_H
#define PKGLIB_IPROGRESS_H
#include <string>
#include <unistd.h>
#include <apt-pkg/packagemanager.h>
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);
};

14
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);
}
/*}}}*/

18
apt-pkg/packagemanager.h

@ -24,6 +24,7 @@
#define PKGLIB_PACKAGEMANAGER_H
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/iprogress.h>
#include <string>
#include <iostream>
@ -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 */

24
apt-private/private-install.cc

@ -23,6 +23,7 @@
#include <apt-pkg/pkgsystem.h>
#include <apt-pkg/pkgrecords.h>
#include <apt-pkg/indexfile.h>
#include <apt-pkg/iprogress.h>
#include <set>
#include <locale.h>
@ -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)

Loading…
Cancel
Save