diff options
author | Michael Vogt <mvo@debian.org> | 2013-10-05 10:49:26 +0200 |
---|---|---|
committer | Michael Vogt <mvo@debian.org> | 2013-10-05 10:49:26 +0200 |
commit | b821e492d6dc4e1e8fd1f83590e12e3fbccad717 (patch) | |
tree | ac6d28f28fe13078aa578e1fb0fdd956a7e6ae84 /apt-pkg/deb/dpkgpm.cc | |
parent | 318289bb17b827611fea6570f71df525b60a0e97 (diff) | |
parent | 75cd2506ce7ea411f7a0e888310d622ad330828c (diff) |
Merge remote-tracking branch 'mvo/bugfix/dpkg-progress-multiarch' into debian/sid
Diffstat (limited to 'apt-pkg/deb/dpkgpm.cc')
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 68 |
1 files changed, 41 insertions, 27 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 3c1013761..a5097a04f 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -37,6 +37,7 @@ #include <map> #include <pwd.h> #include <grp.h> +#include <iomanip> #include <termios.h> #include <unistd.h> @@ -52,7 +53,8 @@ class pkgDPkgPMPrivate { public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), - term_out(NULL), history_out(NULL) + term_out(NULL), history_out(NULL), + last_reported_progress(0.0) { dpkgbuf[0] = '\0'; } @@ -63,6 +65,8 @@ public: FILE *term_out; FILE *history_out; string dpkg_error; + + float last_reported_progress; }; namespace @@ -512,7 +516,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) /* dpkg sends strings like this: - 'status: <pkg>: <pkg qstate>' + 'status: <pkg>: <pkg qstate>' + 'status: <pkg>:<arch>: <pkg qstate>' 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 @@ -527,29 +532,36 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) 'processing: trigproc: trigger' */ - char* list[6]; - // dpkg sends multiline error messages sometimes (see - // #374195 for a example. we should support this by - // either patching dpkg to not send multiline over the - // statusfd or by rewriting the code here to deal with - // it. for now we just ignore it and not crash - TokSplitString(':', line, list, sizeof(list)/sizeof(list[0])); - if( list[0] == NULL || list[1] == NULL || list[2] == NULL) + // we need to split on ": " (note the appended space) as the ':' is + // part of the pkgname:arch information that dpkg sends + // + // A dpkg error message may contain additional ":" (like + // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..." + // so we need to ensure to not split too much + std::vector<std::string> list = StringSplit(line, ": ", 3); + if(list.size() != 3) { if (Debug == true) std::clog << "ignoring line: not enough ':'" << std::endl; return; } - const char* const pkg = list[1]; - const char* action = _strstrip(list[2]); + // 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) + { + string const nativeArch = _config->Find("APT::Architecture"); + pkgname = pkgname + ":" + nativeArch; + } + const char* const pkg = pkgname.c_str(); + const char* action = list[2].c_str(); // 'processing' from dpkg looks like // 'processing: action: pkg' - if(strncmp(list[0], "processing", strlen("processing")) == 0) + if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) { char s[200]; - const char* const pkg_or_trigger = _strstrip(list[2]); - action = _strstrip( list[1]); + const char* const pkg_or_trigger = list[2].c_str(); + action = list[1].c_str(); const std::pair<const char *, const char *> * const iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, @@ -578,14 +590,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if(strncmp(action,"error",strlen("error")) == 0) { - // urgs, sometime has ":" in its error string so that we - // end up with the error message split between list[3] - // and list[4], e.g. the message: - // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..." - // concat them again - if( list[4] != NULL ) - list[3][strlen(list[3])] = ':'; - status << "pmerror:" << list[1] << ":" << (PackagesDone/float(PackagesTotal)*100.0) << ":" << list[3] @@ -595,7 +599,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; pkgFailures++; - WriteApportReport(list[1], list[3]); + WriteApportReport(list[1].c_str(), list[3].c_str()); return; } else if(strncmp(action,"conffile",strlen("conffile")) == 0) @@ -883,10 +887,16 @@ bool pkgDPkgPM::CloseLog() */ void pkgDPkgPM::SendTerminalProgress(float percentage) { + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + + if(percentage < (d->last_reported_progress + reporting_steps)) + return; + // FIXME: use colors too std::cout << "\r\n" - << "Progress: [" << percentage << "%]" + << "Progress: [" << std::setw(3) << int(percentage) << "%]" << "\r\n"; + d->last_reported_progress = percentage; } /*}}}*/ /*{{{*/ @@ -1035,7 +1045,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if((*I).Pkg.end() == true) continue; - string const name = (*I).Pkg.Name(); + string const name = (*I).Pkg.FullName(); PackageOpsDone[name] = 0; for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; ++i) { @@ -1444,7 +1454,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) tcsetattr(0, TCSAFLUSH, &tt); close(master); } - + // Check for an error code. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) { @@ -1474,6 +1484,10 @@ bool pkgDPkgPM::Go(int OutStatusFd) } } CloseLog(); + + // dpkg is done at this point + if(_config->FindB("DPkgPM::Progress", false) == true) + SendTerminalProgress(100); if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); |