diff options
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 217 | ||||
-rw-r--r-- | apt-pkg/deb/dpkgpm.h | 8 | ||||
-rw-r--r-- | apt-pkg/iprogress.cc | 213 | ||||
-rw-r--r-- | apt-pkg/iprogress.h | 109 | ||||
-rw-r--r-- | apt-pkg/makefile | 4 | ||||
-rw-r--r-- | apt-pkg/packagemanager.cc | 24 | ||||
-rw-r--r-- | apt-pkg/packagemanager.h | 19 | ||||
-rw-r--r-- | apt-private/private-install.cc | 27 |
8 files changed, 431 insertions, 190 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index f870fab93..1b234c0ed 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -19,6 +19,7 @@ #include <apt-pkg/fileutl.h> #include <apt-pkg/cachefile.h> #include <apt-pkg/packagemanager.h> +#include <apt-pkg/iprogress.h> #include <unistd.h> #include <stdlib.h> @@ -54,16 +55,14 @@ 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), progress(NULL) { dpkgbuf[0] = '\0'; - if(_config->FindB("Dpkg::Progress-Fancy", false) == true) - { - fancy_progress_output = true; - _config->Set("DpkgPM::Progress", true); - } } + ~pkgDPkgPMPrivate() + { + } + bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading char dpkgbuf[1024]; @@ -73,8 +72,7 @@ public: string dpkg_error; float last_reported_progress; - int nr_terminal_rows; - bool fancy_progress_output; + APT::Progress::PackageManager *progress; }; namespace @@ -513,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; @@ -577,12 +573,17 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) 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) + { + strprintf(i18n_pkgname, "%s (%s)", short_pkgname.c_str(), + StringSplit(pkgname, ":")[1].c_str()); + } // 'processing' from dpkg looks like // '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 = @@ -595,17 +596,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; @@ -613,28 +608,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; } @@ -647,28 +629,20 @@ 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, short_pkgname.c_str()); + 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++; - // build the status str - status << "pmstatus:" << short_pkgname - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s - << endl; - if(_config->FindB("DPkgPM::Progress", false) == true) - SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); - - 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(pkgname, PackagesDone, PackagesTotal, + translation); } if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << short_pkgname + std::clog << "(parsed from dpkg) pkg: " << pkgname << " action: " << action << endl; } /*}}}*/ @@ -723,7 +697,7 @@ void pkgDPkgPM::handleDisappearAction(string const &pkgname) // --------------------------------------------------------------------- /* */ -void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd) +void pkgDPkgPM::DoDpkgStatusFd(int statusfd) { char *p, *q; int len; @@ -738,7 +712,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 } @@ -904,52 +878,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 @@ -971,54 +899,20 @@ 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); -} - -void pkgDPkgPM::CleanupTerminal() -{ - // 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; - std::flush(std::cout); - } -} - // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* 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; @@ -1363,8 +1257,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?")); @@ -1394,20 +1287,14 @@ bool pkgDPkgPM::Go(int OutStatusFd) _error->DumpErrors(std::cerr); _error->RevertToStack(); - // Fork dpkg - pid_t Child; + // this is the dpkg status-fd, we need to keep it _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()); - } - Child = ExecFork(); + // Tell the progress that its starting and fork dpkg + // FIXME: this is called once per dpkg run which is *too often* + d->progress->Start(); + + pid_t Child = ExecFork(); // This is the child if (Child == 0) { @@ -1444,9 +1331,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 */ @@ -1509,13 +1393,15 @@ bool pkgDPkgPM::Go(int OutStatusFd) 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) @@ -1531,7 +1417,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); @@ -1571,7 +1457,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if(stopOnError) { CloseLog(); - CleanupTerminal(); + d->progress->Stop(); return false; } } @@ -1579,10 +1465,9 @@ 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, ""); + d->progress->Stop(); - CleanupTerminal(); 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..302507105 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: @@ -99,14 +100,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 new file mode 100644 index 000000000..bed991d68 --- /dev/null +++ b/apt-pkg/iprogress.cc @@ -0,0 +1,213 @@ +#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> +#include <fcntl.h> + +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) +{ + 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:" << PackageName + << ":" << (StepsDone/float(StepsTotal)*100.0) + << ":" << pkg_action + << 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/iprogress.h b/apt-pkg/iprogress.h new file mode 100644 index 000000000..ccf154279 --- /dev/null +++ b/apt-pkg/iprogress.h @@ -0,0 +1,109 @@ +#ifndef PKGLIB_IPROGRESS_H +#define PKGLIB_IPROGRESS_H + +#include <string> +#include <unistd.h> + + +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(0) {}; + 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 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.cc b/apt-pkg/packagemanager.cc index 8c0d2e855..3690a64c3 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -26,7 +26,6 @@ #include <apt-pkg/sptr.h> #include <iostream> -#include <fcntl.h> #include <apti18n.h> /*}}}*/ @@ -1032,28 +1031,25 @@ 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) { - 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); - if(goResult == false) - return Failed; - - return Res; + 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 1a6a9f01c..5c15ac0e4 100644 --- a/apt-pkg/packagemanager.h +++ b/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> @@ -39,6 +40,8 @@ class pkgDepCache; class pkgSourceList; class pkgOrderList; class pkgRecords; + + class pkgPackageManager : protected pkgCache::Namespace { public: @@ -83,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 @@ -96,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 @@ -106,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..8d72faecc 100644 --- a/apt-private/private-install.cc +++ b/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> @@ -103,8 +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); - 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 +339,24 @@ 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) |