From: Michael Vogt Date: Wed, 9 Jun 2010 11:15:34 +0000 (+0200) Subject: merged from lp:~donkult/apt/sid X-Git-Tag: 0.8.0~9^2~39 X-Git-Url: https://git.saurik.com/apt.git/commitdiff_plain/189bb640d2443a5fcaade2ce169429c629ba3148?hp=-c merged from lp:~donkult/apt/sid --- 189bb640d2443a5fcaade2ce169429c629ba3148 diff --combined apt-pkg/acquire-item.cc index 8973eedde,629d572a4..4d9a152ab --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@@ -33,6 -33,7 +33,7 @@@ #include #include #include + #include /*}}}*/ using namespace std; @@@ -64,7 -65,6 +65,7 @@@ void pkgAcquire::Item::Failed(string Me { Status = StatIdle; ErrorText = LookupTag(Message,"Message"); + UsedMirror = LookupTag(Message,"UsedMirror"); if (QueueCounter <= 1) { /* This indicates that the file is not available right now but might @@@ -77,17 -77,10 +78,17 @@@ Dequeue(); return; } - + Status = StatError; Dequeue(); } + + // report mirror failure back to LP if we actually use a mirror + string FailReason = LookupTag(Message, "FailReason"); + if(FailReason.size() != 0) + ReportMirrorFailure(FailReason); + else + ReportMirrorFailure(ErrorText); } /*}}}*/ // Acquire::Item::Start - Item has begun to download /*{{{*/ @@@ -109,7 -102,7 +110,7 @@@ void pkgAcquire::Item::Done(string Mess { // We just downloaded something.. string FileName = LookupTag(Message,"Filename"); - // we only inform the Log class if it was actually not a local thing + UsedMirror = LookupTag(Message,"UsedMirror"); if (Complete == false && !Local && FileName == DestFile) { if (Owner->Log != 0) @@@ -118,6 -111,7 +119,6 @@@ if (FileSize == 0) FileSize= Size; - Status = StatDone; ErrorText = string(); Owner->Dequeue(this); @@@ -139,49 -133,6 +140,49 @@@ void pkgAcquire::Item::Rename(string Fr } } /*}}}*/ + +void pkgAcquire::Item::ReportMirrorFailure(string FailCode) +{ + // we only act if a mirror was used at all + if(UsedMirror.empty()) + return; +#if 0 + std::cerr << "\nReportMirrorFailure: " + << UsedMirror + << " Uri: " << DescURI() + << " FailCode: " + << FailCode << std::endl; +#endif + const char *Args[40]; + unsigned int i = 0; + string report = _config->Find("Methods::Mirror::ProblemReporting", + "/usr/lib/apt/apt-report-mirror-failure"); + if(!FileExists(report)) + return; + Args[i++] = report.c_str(); + Args[i++] = UsedMirror.c_str(); + Args[i++] = DescURI().c_str(); + Args[i++] = FailCode.c_str(); + Args[i++] = NULL; + pid_t pid = ExecFork(); + if(pid < 0) + { + _error->Error("ReportMirrorFailure Fork failed"); + return; + } + else if(pid == 0) + { + execvp(Args[0], (char**)Args); + std::cerr << "Could not exec " << Args[0] << std::endl; + _exit(100); + } + if(!ExecWait(pid, "report-mirror-failure")) + { + _error->Warning("Couldn't report problem to '%s'", + _config->Find("Methods::Mirror::ProblemReporting").c_str()); + } +} + // AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- /* Get the DiffIndex file first and see if there are patches availabe @@@ -674,6 -625,7 +675,6 @@@ string pkgAcqIndex::Custom600Headers( struct stat Buf; if (stat(Final.c_str(),&Buf) != 0) return "\nIndex-File: true"; - return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); } /*}}}*/ @@@ -741,7 -693,6 +742,7 @@@ void pkgAcqIndex::Done(string Message,u Status = StatAuthError; ErrorText = _("Hash Sum mismatch"); Rename(DestFile,DestFile + ".FAILED"); + ReportMirrorFailure("HashChecksumFailure"); return; } // Done, move it into position @@@ -828,13 -779,6 +829,13 @@@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgA string URI,string URIDesc,string ShortDesc) : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "") { +} + /*}}}*/ +// AcqIndexTrans::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +string pkgAcqIndexTrans::Custom600Headers() +{ + return "\nFail-Ignore: true"; } /*}}}*/ // AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/ @@@ -939,9 -883,8 +940,9 @@@ void pkgAcqMetaSig::Done(string Message Rename(LastGoodSig, DestFile); // queue a pkgAcqMetaIndex to be verified against the sig we just retrieved - new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc, - DestFile, IndexTargets, MetaIndexParser); + new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, + MetaIndexShortDesc, DestFile, IndexTargets, + MetaIndexParser); } /*}}}*/ @@@ -954,7 -897,7 +955,7 @@@ void pkgAcqMetaSig::Failed(string Messa { Item::Failed(Message,Cnf); // move the sigfile back on transient network failures - if(FileExists(DestFile)) + if(FileExists(LastGoodSig)) Rename(LastGoodSig,Final); // set the status back to , Item::Failed likes to reset it @@@ -1029,15 -972,6 +1030,15 @@@ void pkgAcqMetaIndex::Done(string Messa if (AuthPass == true) { AuthDone(Message); + + // all cool, move Release file into place + Complete = true; + + string FinalFile = _config->FindDir("Dir::State::lists"); + FinalFile += URItoFileName(RealURI); + Rename(DestFile,FinalFile); + chmod(FinalFile.c_str(),0644); + DestFile = FinalFile; } else { @@@ -1089,15 -1023,22 +1090,15 @@@ void pkgAcqMetaIndex::RetrievalDone(str return; } - // see if the download was a IMSHit + // make sure to verify against the right file on I-M-S hit IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false); + if(IMSHit) + { + string FinalFile = _config->FindDir("Dir::State::lists"); + FinalFile += URItoFileName(RealURI); + DestFile = FinalFile; + } Complete = true; - - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); - - // If we get a IMS hit we can remove the empty file in partial - // othersie we move the file in place - if (IMSHit) - unlink(DestFile.c_str()); - else - Rename(DestFile,FinalFile); - - chmod(FinalFile.c_str(),0644); - DestFile = FinalFile; } /*}}}*/ void pkgAcqMetaIndex::AuthDone(string Message) /*{{{*/ @@@ -1127,6 -1068,7 +1128,6 @@@ QueueIndexes(true); // Done, move signature file into position - string VerifiedSigFile = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI) + ".gpg"; Rename(SigFile,VerifiedSigFile); @@@ -1164,13 -1106,16 +1165,16 @@@ void pkgAcqMetaIndex::QueueIndexes(boo return; } } - - // Queue Packages file (either diff or full packages files, depending - // on the users option) - if(_config->FindB("Acquire::PDiffs", true) == true) + + /* Queue Packages file (either diff or full packages files, depending + on the users option) - we also check if the PDiff Index file is listed + in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this + instead, but passing the required info to it is to much hassle */ + if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false || + MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true)) new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description, (*Target)->ShortDesc, ExpectedIndexHash); - else + else new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, (*Target)->ShortDesc, ExpectedIndexHash); } @@@ -1236,6 -1181,17 +1240,17 @@@ bool pkgAcqMetaIndex::VerifyVendor(stri Transformed = ""; } + if (_config->FindB("Acquire::Check-Valid-Until", true) == true && + MetaIndexParser->GetValidUntil() > 0) { + time_t const invalid_since = time(NULL) - MetaIndexParser->GetValidUntil(); + if (invalid_since > 0) + // TRANSLATOR: The first %s is the URL of the bad Release file, the second is + // the time since then the file is invalid - formated in the same way as in + // the download progress display (e.g. 7d 3h 42min 1s) + return _error->Error(_("Release file expired, ignoring %s (invalid since %s)"), + RealURI.c_str(), TimeToStr(invalid_since).c_str()); + } + if (_config->FindB("Debug::pkgAcquire::Auth", false)) { std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl; @@@ -1253,7 -1209,7 +1268,7 @@@ // return false; if (!Transformed.empty()) { - _error->Warning("Conflicting distribution: %s (expected %s but got %s)", + _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"), Desc.Description.c_str(), Transformed.c_str(), MetaIndexParser->GetDist().c_str()); @@@ -1270,30 -1226,30 +1285,30 @@@ void pkgAcqMetaIndex::Failed(string Mes { if (AuthPass == true) { - // if we fail the authentication but got the file via a IMS-Hit - // this means that the file wasn't downloaded and that it might be - // just stale (server problem, proxy etc). we delete what we have - // queue it again without i-m-s - // alternatively we could just unlink the file and let the user try again - if (IMSHit) + // gpgv method failed, if we have a good signature + string LastGoodSigFile = _config->FindDir("Dir::State::lists") + + "partial/" + URItoFileName(RealURI) + ".gpg.reverify"; + if(FileExists(LastGoodSigFile)) { - Complete = false; - Local = false; - AuthPass = false; - unlink(DestFile.c_str()); - - DestFile = _config->FindDir("Dir::State::lists") + "partial/"; - DestFile += URItoFileName(RealURI); - Desc.URI = RealURI; - QueueURI(Desc); + string VerifiedSigFile = _config->FindDir("Dir::State::lists") + + URItoFileName(RealURI) + ".gpg"; + Rename(LastGoodSigFile,VerifiedSigFile); + Status = StatTransientNetworkError; + _error->Warning(_("A error occurred during the signature " + "verification. The repository is not updated " + "and the previous index files will be used." + "GPG error: %s: %s\n"), + Desc.Description.c_str(), + LookupTag(Message,"Message").c_str()); + RunScripts("APT::Update::Auth-Failure"); return; + } else { + _error->Warning(_("GPG error: %s: %s"), + Desc.Description.c_str(), + LookupTag(Message,"Message").c_str()); } - // gpgv method failed - _error->Warning("GPG error: %s: %s", - Desc.Description.c_str(), - LookupTag(Message,"Message").c_str()); - + ReportMirrorFailure("GPGFailure"); } // No Release file was present, or verification failed, so fall diff --combined apt-pkg/acquire-item.h index 8f35c0dbf,36fc53b92..943c61876 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@@ -112,10 -112,10 +112,10 @@@ class pkgAcquire::Item : public WeakPoi string ErrorText; /** \brief The size of the object to fetch. */ - unsigned long FileSize; + unsigned long long FileSize; /** \brief How much of the object was already fetched. */ - unsigned long PartialSize; + unsigned long long PartialSize; /** \brief If not \b NULL, contains the name of a subprocess that * is operating on this object (for instance, "gzip" or "gpgv"). @@@ -143,7 -143,6 +143,7 @@@ * download progress indicator's overall statistics. */ bool Local; + string UsedMirror; /** \brief The number of fetch queues into which this item has been * inserted. @@@ -244,17 -243,6 +244,17 @@@ /** \return \b true if this object is being fetched from a trusted source. */ virtual bool IsTrusted() {return false;}; + + // report mirror problems + /** \brief Report mirror problem + * + * This allows reporting mirror failures back to a centralized + * server. The apt-report-mirror-failure script is called for this + * + * \param FailCode A short failure string that is send + */ + void ReportMirrorFailure(string FailCode); + /** \brief Initialize an item. * @@@ -563,8 -551,7 +563,8 @@@ class pkgAcqIndex : public pkgAcquire:: * fallback is ".gz" or none. */ pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc, - string ShortDesc, HashString ExpectedHash, string compressExt=""); + string ShortDesc, HashString ExpectedHash, + string compressExt=""); }; /*}}}*/ /** \brief An acquire item that is responsible for fetching a {{{ @@@ -579,7 -566,6 +579,7 @@@ class pkgAcqIndexTrans : public pkgAcqI public: virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf); + virtual string Custom600Headers(); /** \brief Create a pkgAcqIndexTrans. * @@@ -628,6 -614,7 +628,6 @@@ class pkgAcqMetaSig : public pkgAcquire /** \brief The last good signature file */ string LastGoodSig; - /** \brief The fetch request that is currently being processed. */ pkgAcquire::ItemDesc Desc; diff --combined apt-pkg/acquire-method.cc index 6e021a445,b82dceecb..17d52cf51 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@@ -96,11 -96,12 +96,11 @@@ void pkgAcqMethod::Fail(string Err,boo } char S[1024]; + char *End = S; if (Queue != 0) { - snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n" - "Message: %s %s\n",Queue->Uri.c_str(),Err.c_str(), - FailExtra.c_str()); - + End += snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n" + "Message: %s %s\n",Queue->Uri.c_str(), Err.c_str(), IP.c_str()); // Dequeue FetchItem *Tmp = Queue; Queue = Queue->Next; @@@ -109,14 -110,10 +109,14 @@@ QueueBack = Queue; } else - snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: \n" - "Message: %s %s\n",Err.c_str(), - FailExtra.c_str()); - + { + End += snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: \n" + "Message: %s\n",Err.c_str()); + } + if(FailReason.empty() == false) + End += snprintf(End,sizeof(S)-50 - (End - S),"FailReason: %s\n",FailReason.c_str()); + if (UsedMirror.empty() == false) + End += snprintf(End,sizeof(S)-50 - (End - S),"UsedMirror: %s\n",UsedMirror.c_str()); // Set the transient flag if (Transient == true) strcat(S,"Transient-Failure: true\n\n"); @@@ -187,8 -184,6 +187,8 @@@ void pkgAcqMethod::URIDone(FetchResult End += snprintf(End,sizeof(S)-50 - (End - S),"SHA1-Hash: %s\n",Res.SHA1Sum.c_str()); if (Res.SHA256Sum.empty() == false) End += snprintf(End,sizeof(S)-50 - (End - S),"SHA256-Hash: %s\n",Res.SHA256Sum.c_str()); + if (UsedMirror.empty() == false) + End += snprintf(End,sizeof(S)-50 - (End - S),"UsedMirror: %s\n",UsedMirror.c_str()); if (Res.GPGVOutput.size() > 0) End += snprintf(End,sizeof(S)-50 - (End - S),"GPGVOutput:\n"); for (vector::iterator I = Res.GPGVOutput.begin(); @@@ -378,10 -373,9 +378,10 @@@ int pkgAcqMethod::Run(bool Single Tmp->Uri = LookupTag(Message,"URI"); Tmp->DestFile = LookupTag(Message,"FileName"); - if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false) + if (RFC1123StrToTime(LookupTag(Message,"Last-Modified").c_str(),Tmp->LastModified) == false) Tmp->LastModified = 0; Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false); + Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false); Tmp->Next = 0; // Append it to the list diff --combined apt-pkg/deb/debsystem.cc index ef5ec9703,31c26ab2f..7056d771d --- a/apt-pkg/deb/debsystem.cc +++ b/apt-pkg/deb/debsystem.cc @@@ -18,6 -18,7 +18,6 @@@ #include #include #include - #include #include #include @@@ -78,15 -79,8 +78,15 @@@ bool debSystem::Lock( { close(LockFD); LockFD = -1; + const char *cmd; + if (getenv("SUDO_USER") != NULL) + cmd = "sudo dpkg --configure -a"; + else + cmd = "dpkg --configure -a"; + // TRANSLATORS: the %s contains the recovery command, usually + // dpkg --configure -a return _error->Error(_("dpkg was interrupted, you must manually " - "run 'dpkg --configure -a' to correct the problem. ")); + "run '%s' to correct the problem. "), cmd); } LockCount++; @@@ -164,7 -158,7 +164,7 @@@ bool debSystem::Initialize(Configuratio /* These really should be jammed into a generic 'Local Database' engine which is yet to be determined. The functions in pkgcachegen should be the only users of these */ - Cnf.CndSet("Dir::State::userstatus","status.user"); // Defunct + Cnf.CndSet("Dir::State::extended_states", Cnf.FindDir("Dir::State").append("extended_states")); Cnf.CndSet("Dir::State::status","/var/lib/dpkg/status"); Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg"); diff --combined apt-pkg/deb/dpkgpm.cc index 95e3bafdc,0ac6ac168..9af7a0792 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@@ -12,7 -12,6 +12,7 @@@ #include #include #include +#include #include #include #include @@@ -21,12 -20,10 +21,12 @@@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@@ -357,6 -354,7 +357,6 @@@ bool pkgDPkgPM::RunScriptsWithPkgs(cons return true; } - /*}}}*/ // DPkgPM::DoStdin - Read stdin and pass to slave pty /*{{{*/ // --------------------------------------------------------------------- @@@ -427,7 -425,7 +427,7 @@@ void pkgDPkgPM::ProcessDpkgStatusLine(i 'processing: trigproc: trigger' */ - char* list[5]; + 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 @@@ -472,20 -470,12 +472,20 @@@ std::clog << "send: '" << status.str() << "'" << endl; if (strncmp(action, "disappear", strlen("disappear")) == 0) - disappearedPkgs.insert(string(pkg_or_trigger)); + handleDisappearAction(pkg_or_trigger); return; } 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] @@@ -494,8 -484,6 +494,8 @@@ write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; + pkgFailures++; + WriteApportReport(list[1], list[3]); return; } else if(strncmp(action,"conffile",strlen("conffile")) == 0) @@@ -542,6 -530,51 +542,51 @@@ << " action: " << action << endl; } /*}}}*/ + // 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; + // the disappeared package was auto-installed - nothing to do + if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) + return; + pkgCache::VerIterator PkgVer = Pkg.CurrentVer(); + if (unlikely(PkgVer.end() == true)) + return; + /* search in the list of dependencies for (Pre)Depends, + check if this dependency has a Replaces on our package + and if so transfer the manual installed flag to it */ + for (pkgCache::DepIterator Dep = PkgVer.DependsList(); Dep.end() != true; ++Dep) + { + if (Dep->Type != pkgCache::Dep::Depends && + Dep->Type != pkgCache::Dep::PreDepends) + continue; + pkgCache::PkgIterator Tar = Dep.TargetPkg(); + if (unlikely(Tar.end() == true)) + continue; + // the package is already marked as manual + if ((Cache[Tar].Flags & pkgCache::Flag::Auto) != pkgCache::Flag::Auto) + continue; + pkgCache::VerIterator TarVer = Tar.CurrentVer(); + for (pkgCache::DepIterator Rep = TarVer.DependsList(); Rep.end() != true; ++Rep) + { + if (Rep->Type != pkgCache::Dep::Replaces) + continue; + if (Pkg != Rep.TargetPkg()) + continue; + // okay, they are strongly connected - transfer manual-bit + if (Debug == true) + std::clog << "transfer manual-bit from disappeared »" << pkgname << "« to »" << Tar.FullName() << "«" << std::endl; + Cache[Tar].Flags &= ~Flag::Auto; + break; + } + } + } + /*}}}*/ // DPkgPM::DoDpkgStatusFd /*{{{*/ // --------------------------------------------------------------------- /* @@@ -580,15 -613,15 +625,15 @@@ void pkgDPkgPM::DoDpkgStatusFd(int stat } /*}}}*/ // DPkgPM::WriteHistoryTag /*{{{*/ - void pkgDPkgPM::WriteHistoryTag(string tag, string value) + void pkgDPkgPM::WriteHistoryTag(string const &tag, string value) { - if (value.size() > 0) - { - // poor mans rstrip(", ") - if (value[value.size()-2] == ',' && value[value.size()-1] == ' ') - value.erase(value.size() - 2, 2); - fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str()); - } + size_t const length = value.length(); + if (length == 0) + return; + // poor mans rstrip(", ") + if (value[length-2] == ',' && value[length-1] == ' ') + value.erase(length - 2, 2); + fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str()); } /*}}}*/ // DPkgPM::OpenLog /*{{{*/ bool pkgDPkgPM::OpenLog() @@@ -675,7 -708,22 +720,22 @@@ bool pkgDPkgPM::CloseLog( if(history_out) { - if (dpkg_error.size() > 0) + if (disappearedPkgs.empty() == false) + { + string disappear; + for (std::set::const_iterator d = disappearedPkgs.begin(); + d != disappearedPkgs.end(); ++d) + { + pkgCache::PkgIterator P = Cache.FindPkg(*d); + disappear.append(*d); + if (P.end() == true) + disappear.append(", "); + else + disappear.append(" (").append(Cache[P].CurVersion).append("), "); + } + WriteHistoryTag("Disappeared", disappear); + } + if (dpkg_error.empty() == false) fprintf(history_out, "Error: %s\n", dpkg_error.c_str()); fprintf(history_out, "End-Date: %s\n", timestr); fclose(history_out); @@@ -1187,186 -1235,3 +1247,186 @@@ void pkgDPkgPM::Reset( List.erase(List.begin(),List.end()); } /*}}}*/ +// pkgDpkgPM::WriteApportReport - write out error report pkg failure /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) +{ + string pkgname, reportfile, srcpkgname, pkgver, arch; + string::size_type pos; + FILE *report; + + if (_config->FindB("Dpkg::ApportFailureReport", false) == false) + { + std::clog << "configured to not write apport reports" << std::endl; + return; + } + + // only report the first errors + if(pkgFailures > _config->FindI("APT::Apport::MaxReports", 3)) + { + std::clog << _("No apport report written because MaxReports is reached already") << std::endl; + return; + } + + // check if its not a follow up error + const char *needle = dgettext("dpkg", "dependency problems - leaving unconfigured"); + if(strstr(errormsg, needle) != NULL) { + std::clog << _("No apport report written because the error message indicates its a followup error from a previous failure.") << std::endl; + return; + } + + // do not report disk-full failures + if(strstr(errormsg, strerror(ENOSPC)) != NULL) { + std::clog << _("No apport report written because the error message indicates a disk full error") << std::endl; + return; + } + + // do not report out-of-memory failures + if(strstr(errormsg, strerror(ENOMEM)) != NULL) { + std::clog << _("No apport report written because the error message indicates a out of memory error") << std::endl; + return; + } + + // do not report dpkg I/O errors + // XXX - this message is localized, but this only matches the English version. This is better than nothing. + if(strstr(errormsg, "short read in buffer_copy (")) { + std::clog << _("No apport report written because the error message indicates a dpkg I/O error") << std::endl; + return; + } + + // get the pkgname and reportfile + pkgname = flNotDir(pkgpath); + pos = pkgname.find('_'); + if(pos != string::npos) + pkgname = pkgname.substr(0, pos); + + // find the package versin and source package name + pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname); + if (Pkg.end() == true) + return; + pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg); + if (Ver.end() == true) + return; + pkgver = Ver.VerStr() == NULL ? "unknown" : Ver.VerStr(); + pkgRecords Recs(Cache); + pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList()); + srcpkgname = Parse.SourcePkg(); + if(srcpkgname.empty()) + srcpkgname = pkgname; + + // if the file exists already, we check: + // - if it was reported already (touched by apport). + // If not, we do nothing, otherwise + // we overwrite it. This is the same behaviour as apport + // - if we have a report with the same pkgversion already + // then we skip it + reportfile = flCombine("/var/crash",pkgname+".0.crash"); + if(FileExists(reportfile)) + { + struct stat buf; + char strbuf[255]; + + // check atime/mtime + stat(reportfile.c_str(), &buf); + if(buf.st_mtime > buf.st_atime) + return; + + // check if the existing report is the same version + report = fopen(reportfile.c_str(),"r"); + while(fgets(strbuf, sizeof(strbuf), report) != NULL) + { + if(strstr(strbuf,"Package:") == strbuf) + { + char pkgname[255], version[255]; + if(sscanf(strbuf, "Package: %s %s", pkgname, version) == 2) + if(strcmp(pkgver.c_str(), version) == 0) + { + fclose(report); + return; + } + } + } + fclose(report); + } + + // now write the report + arch = _config->Find("APT::Architecture"); + report = fopen(reportfile.c_str(),"w"); + if(report == NULL) + return; + if(_config->FindB("DPkgPM::InitialReportOnly",false) == true) + chmod(reportfile.c_str(), 0); + else + chmod(reportfile.c_str(), 0600); + fprintf(report, "ProblemType: Package\n"); + fprintf(report, "Architecture: %s\n", arch.c_str()); + time_t now = time(NULL); + fprintf(report, "Date: %s" , ctime(&now)); + fprintf(report, "Package: %s %s\n", pkgname.c_str(), pkgver.c_str()); + fprintf(report, "SourcePackage: %s\n", srcpkgname.c_str()); + fprintf(report, "ErrorMessage:\n %s\n", errormsg); + + // ensure that the log is flushed + if(term_out) + fflush(term_out); + + // attach terminal log it if we have it + string logfile_name = _config->FindFile("Dir::Log::Terminal"); + if (!logfile_name.empty()) + { + FILE *log = NULL; + char buf[1024]; + + fprintf(report, "DpkgTerminalLog:\n"); + log = fopen(logfile_name.c_str(),"r"); + if(log != NULL) + { + while( fgets(buf, sizeof(buf), log) != NULL) + fprintf(report, " %s", buf); + fclose(log); + } + } + + // log the ordering + const char *ops_str[] = {"Install", "Configure","Remove","Purge"}; + fprintf(report, "AptOrdering:\n"); + for (vector::iterator I = List.begin(); I != List.end(); I++) + fprintf(report, " %s: %s\n", (*I).Pkg.Name(), ops_str[(*I).Op]); + + // attach dmesg log (to learn about segfaults) + if (FileExists("/bin/dmesg")) + { + FILE *log = NULL; + char buf[1024]; + + fprintf(report, "Dmesg:\n"); + log = popen("/bin/dmesg","r"); + if(log != NULL) + { + while( fgets(buf, sizeof(buf), log) != NULL) + fprintf(report, " %s", buf); + fclose(log); + } + } + + // attach df -l log (to learn about filesystem status) + if (FileExists("/bin/df")) + { + FILE *log = NULL; + char buf[1024]; + + fprintf(report, "Df:\n"); + log = popen("/bin/df -l","r"); + if(log != NULL) + { + while( fgets(buf, sizeof(buf), log) != NULL) + fprintf(report, " %s", buf); + fclose(log); + } + } + + fclose(report); + +} + /*}}}*/ diff --combined apt-pkg/deb/dpkgpm.h index ce3e20f2e,9a4478f7c..b7b5a6def --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@@ -32,8 -32,22 +32,23 @@@ class pkgDPkgPM : public pkgPackageMana FILE *history_out; string dpkg_error; + /** \brief record the disappear action and handle accordingly + + dpkg let packages disappear then they have no files any longer and + nothing depends on them. We need to collect this as dpkg as well as + APT doesn't know beforehand that the package will disappear, so the + only possible option is to tell the user afterwards about it. + To enhance the experience we also try to forward the auto-install + flag so the disappear-causer(s) are not autoremoved next time - + for the transfer to happen the disappeared version needs to depend + on the package the flag should be forwarded to and this package + needs to declare a Replaces on the disappeared package. + \param pkgname Name of the package that disappeared + */ + void handleDisappearAction(string const &pkgname); + protected: + int pkgFailures; // progress reporting struct DpkgState @@@ -50,7 -64,6 +65,7 @@@ // the int is the state that is already done (e.g. a package that is // going to be install is already in state "half-installed") map PackageOpsDone; + // progress reporting unsigned int PackagesDone; unsigned int PackagesTotal; @@@ -70,11 -83,8 +85,11 @@@ // Helpers bool RunScriptsWithPkgs(const char *Cnf); bool SendV2Pkgs(FILE *F); - void WriteHistoryTag(string tag, string value); + void WriteHistoryTag(string const &tag, string value); + // apport integration + void WriteApportReport(const char *pkgpath, const char *errormsg); + // dpkg log bool OpenLog(); bool CloseLog(); diff --combined apt-pkg/tagfile.cc index e1f576875,1394d7e24..96a681bec --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@@ -365,6 -365,30 +365,30 @@@ signed int pkgTagSection::FindI(const c return Result; } /*}}}*/ + // TagSection::FindULL - Find an unsigned long long integer /*{{{*/ + // --------------------------------------------------------------------- + /* */ + unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long const &Default) const + { + const char *Start; + const char *Stop; + if (Find(Tag,Start,Stop) == false) + return Default; + + // Copy it into a temp buffer so we can use strtoull + char S[100]; + if ((unsigned)(Stop - Start) >= sizeof(S)) + return Default; + strncpy(S,Start,Stop-Start); + S[Stop - Start] = 0; + + char *End; + unsigned long long Result = strtoull(S,&End,10); + if (S == End) + return Default; + return Result; + } + /*}}}*/ // TagSection::FindFlag - Locate a yes/no type flag /*{{{*/ // --------------------------------------------------------------------- /* The bits marked in Flag are masked on/off in Flags */ @@@ -409,7 -433,6 +433,7 @@@ static const char *iTFRewritePackageOrd "Section", "Installed-Size", "Maintainer", + "Original-Maintainer", "Architecture", "Source", "Version", @@@ -439,7 -462,6 +463,7 @@@ static const char *iTFRewriteSourceOrde "Priority", "Section", "Maintainer", + "Original-Maintainer", "Build-Depends", "Build-Depends-Indep", "Build-Conflicts", diff --combined cmdline/apt-get.cc index eaf04eee7,2340a7e85..0ada46c73 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@@ -40,7 -40,8 +40,8 @@@ #include #include #include - + #include + #include #include @@@ -90,14 -91,14 +91,14 @@@ class CacheFile : public pkgCacheFil bool BuildCaches(bool WithLock = true) { OpTextProgress Prog(*_config); - if (pkgCacheFile::BuildCaches(Prog,WithLock) == false) + if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false) return false; return true; } bool Open(bool WithLock = true) { OpTextProgress Prog(*_config); - if (pkgCacheFile::Open(Prog,WithLock) == false) + if (pkgCacheFile::Open(&Prog,WithLock) == false) return false; Sort(); @@@ -837,9 -838,9 +838,9 @@@ bool InstallPackages(CacheFile &Cache,b return false; // Display statistics - double FetchBytes = Fetcher.FetchNeeded(); - double FetchPBytes = Fetcher.PartialPresent(); - double DebBytes = Fetcher.TotalNeeded(); + unsigned long long FetchBytes = Fetcher.FetchNeeded(); + unsigned long long FetchPBytes = Fetcher.PartialPresent(); + unsigned long long DebBytes = Fetcher.TotalNeeded(); if (DebBytes != Cache->DebSize()) { c0out << DebBytes << ',' << Cache->DebSize() << endl; @@@ -1780,51 -1781,24 +1781,24 @@@ bool DoInstall(CommandLine &CmdL Packages++; if (Pkg.end() == true) { - // Check if the name is a regex - const char *I; - for (I = S; *I != 0; I++) - if (*I == '?' || *I == '*' || *I == '|' || - *I == '[' || *I == '^' || *I == '$') - break; - if (*I == 0) + APT::PackageSet pkgset = APT::PackageSet::FromRegEx(Cache, S, c1out); + if (pkgset.empty() == true) return _error->Error(_("Couldn't find package %s"),S); // Regexs must always be confirmed ExpectedInst += 1000; - - // Compile the regex pattern - regex_t Pattern; - int Res; - if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE | - REG_NOSUB)) != 0) - { - char Error[300]; - regerror(Res,&Pattern,Error,sizeof(Error)); - return _error->Error(_("Regex compilation error - %s"),Error); - } - - // Run over the matches + bool Hit = false; - for (pkgCache::GrpIterator Grp = Cache->GrpBegin(); Grp.end() == false; ++Grp) + for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) { - if (regexec(&Pattern,Grp.Name(),0,0,0) != 0) - continue; - Pkg = Grp.FindPkg("native"); - if (unlikely(Pkg.end() == true)) - continue; - - ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"), - Pkg.Name(),S); - if (VerTag != 0) if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false) return false; - + Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix, ExpectedInst,false); } - regfree(&Pattern); - + if (Hit == false) return _error->Error(_("Couldn't find package %s"),S); } @@@ -2306,33 -2280,6 +2280,33 @@@ bool DoSource(CommandLine &CmdL if (Last == 0) return _error->Error(_("Unable to find a source package for %s"),Src.c_str()); + string srec = Last->AsStr(); + string::size_type pos = srec.find("\nVcs-"); + while (pos != string::npos) + { + pos += strlen("\nVcs-"); + string vcs = srec.substr(pos,srec.find(":",pos)-pos); + if(vcs == "Browser") + { + pos = srec.find("\nVcs-", pos); + continue; + } + pos += vcs.length()+2; + string::size_type epos = srec.find("\n", pos); + string uri = srec.substr(pos,epos-pos).c_str(); + ioprintf(c1out, _("NOTICE: '%s' packaging is maintained in " + "the '%s' version control system at:\n" + "%s\n"), + Src.c_str(), vcs.c_str(), uri.c_str()); + if(vcs == "Bzr") + ioprintf(c1out,_("Please use:\n" + "bzr get %s\n" + "to retrieve the latest (possibly unreleased) " + "updates to the package.\n"), + uri.c_str()); + break; + } + // Back track vector Lst; if (Last->Files(Lst) == false) @@@ -2389,9 -2336,9 +2363,9 @@@ } // Display statistics - double FetchBytes = Fetcher.FetchNeeded(); - double FetchPBytes = Fetcher.PartialPresent(); - double DebBytes = Fetcher.TotalNeeded(); + unsigned long long FetchBytes = Fetcher.FetchNeeded(); + unsigned long long FetchPBytes = Fetcher.PartialPresent(); + unsigned long long DebBytes = Fetcher.TotalNeeded(); // Check for enough free space struct statvfs Buf; @@@ -2995,6 -2942,7 +2969,6 @@@ int main(int argc,const char *argv[] {"remove",&DoInstall}, {"purge",&DoInstall}, {"autoremove",&DoInstall}, - {"purge",&DoInstall}, {"markauto",&DoMarkAuto}, {"unmarkauto",&DoMarkAuto}, {"dist-upgrade",&DoDistUpgrade}, diff --combined debian/changelog index 1740d196c,56a17eb38..9135d523b --- a/debian/changelog +++ b/debian/changelog @@@ -1,27 -1,67 +1,88 @@@ - apt (0.7.26~exp6) experimental; urgency=low + apt (0.7.26~exp6) UNRELEASED; urgency=low + [ Michael Vogt ] + * merge the remaining Ubuntu change: + - on gpg verification failure warn and restore the last known + good state + - on failure display the IP of the server (useful for servers + that use round robin DNS) + - support Original-Maintainer in RewritePackageOrder + - enable cdrom autodetection via libudev by default + - show messsage about Vcs in use when apt-get source is run for + packages maintained in a Vcs + - better support transitional packages with mark auto-installed. + when the transitional package is in "oldlibs" the new package + is not marked auto installed (same is true for section + metapackages) + - provide new "deb mirror://archive.foo/mirrors.list sid main" + method expects a list of mirrors (generated on the server e.g. + via geoip) and will use that, including cycle on failure + - write apport crash file on package failure (disabled by default + on debian until apport is available) + - support mirror failure reporting (disabled by default on debian) ++ + [ David Kalnischkies ] + * apt-pkg/deb/dpkgpm.cc: + - write Disappeared also to the history.log + - forward manual-installed bit on package disappearance + * apt-pkg/deb/debsystem.cc: + - add better config item for extended_states file + * apt-pkg/pkgcache.h: + - switch {,Install-}Size to unsigned long long + * apt-pkg/depcache.cc: + - do the autoremove mark process also for required packages to handle + these illegally depending on lower priority packages (Closes: #583517) + - try harder to find the other pseudo versions for autoremove multiarch + - correct "Dangerous iterator usage" pointed out by cppcheck + - deal with long long, not with int to remove 2GB Limit (LP: #250909) + - deprecate AddSize with Multiplier as it is unused and switch to + boolean instead to handle the sizes more gracefully. + - switch i{Download,Usr}Size from double to (un)signed long long + * apt-pkg/aptconfiguration.cc: + - remove duplicate architectures in getArchitectures() + * apt-pkg/indexrecords.{cc,h}: + - backport forgotten Valid-Until patch from the obsolete experimental + branch to prevent replay attacks better, thanks to Thomas Viehmann + for the initial patch! (Closes: #499897) + - add a constant Exists check for MetaKeys + * apt-pkg/acquire-item.cc: + - do not try PDiff if it is not listed in the Meta file + * apt-pkg/cacheiterator.h: + - let pkgCache::Iterator inherent std::iterator + * ftparchive/writer.h: + - add a virtual destructor to FTWScanner class (for cppcheck) + * apt-pkg/cacheset.{cc,h}: + - add simple wrapper around std::set for cache structures + - move regex magic from apt-get to new FromRegEx method + - move cmdline parsing from apt-cache to new FromCommandLine method + - support special release-modifier 'installed' and 'candidate' + * apt-pkg/contrib/cmdline.cc: + - fix segfault in SaveInConfig caused by writing over char[] sizes + * apt-pkg/pkgcache.cc: + - get the best matching arch package from a group with FindPreferredPkg + * cmdline/apt-cache.cc: + - make the search multiarch compatible by using GrpIterator instead + - use pkgCacheFile and the new CacheSets all over the place + - add --target-release option (Closes: #115520) + - accept pkg/release and pkg=version in show and co. (Closes: #236270) + - accept package versions in the unmet command + * cmdline/apt-get.cc: + - use unsigned long long instead of double to store values it gets + * apt-pkg/cachefile.{cc,h}: + - split Open() into submethods to be able to build only parts + - make the OpProgress optional in the Cache buildprocess + - store also the SourceList we use internally for export + * doc/apt.conf.5.xml: + - document the new Valid-Until related options + * apt-pkg/contrib/strutl.cc: + - split StrToTime() into HTTP1.1 and FTP date parser methods and + use strptime() instead of some self-made scanf mangling + - use the portable timegm shown in his manpage instead of a strange + looking code copycat from wget + * ftparchive/writer.cc: + - add ValidTime option to generate a Valid-Until header in Release file - -- Michael Vogt Wed, 09 Jun 2010 10:50:17 +0200 + -- David Kalnischkies Wed, 09 Jun 2010 10:52:31 +0200 apt (0.7.26~exp5) experimental; urgency=low diff --combined methods/http.cc index 3e2227f2b,5fdc62696..9fa74bffa --- a/methods/http.cc +++ b/methods/http.cc @@@ -631,7 -631,7 +631,7 @@@ bool ServerState::HeaderLine(string Lin if (stringcasecmp(Tag,"Last-Modified:") == 0) { - if (StrToTime(Val,Date) == false) + if (RFC1123StrToTime(Val.c_str(), Date) == false) return _error->Error(_("Unknown date format")); return true; } @@@ -953,9 -953,6 +953,9 @@@ HttpMethod::DealWithHeaders(FetchResul failure */ if (Srv->Result < 200 || Srv->Result >= 300) { + char err[255]; + snprintf(err,sizeof(err)-1,"HttpError%i",Srv->Result); + SetFailReason(err); _error->Error("%u %s",Srv->Result,Srv->Code); if (Srv->HaveContent == true) return ERROR_WITH_CONTENT_PAGE; @@@ -1369,4 -1366,15 +1369,4 @@@ bool HttpMethod::AutoDetectProxy( } /*}}}*/ -int main() -{ - setlocale(LC_ALL, ""); - // ignore SIGPIPE, this can happen on write() if the socket - // closes the connection (this is dealt with via ServerDie()) - signal(SIGPIPE, SIG_IGN); - - HttpMethod Mth; - return Mth.Loop(); -} - diff --combined test/pre-upload-check.py index 97a0ec4c4,e2dfecbd3..f9da8f941 --- a/test/pre-upload-check.py +++ b/test/pre-upload-check.py @@@ -4,8 -4,6 +4,8 @@@ import sy import os import glob import os.path +import shutil +import time from subprocess import call, PIPE import unittest @@@ -13,102 -11,7 +13,102 @@@ stdout = os.open("/dev/null",0) #sys.stdout stderr = os.open("/dev/null",0) # sys.stderr -apt_args = [] # ["-o","Debug::pkgAcquire::Auth=true"] +apt_args = [] +#apt_args = ["-o","Debug::pkgAcquire::Auth=true"] + +class testAptAuthenticationReliability(unittest.TestCase): + """ + test if the spec https://wiki.ubuntu.com/AptAuthenticationReliability + is properly implemented + """ + #apt = "../bin/apt-get" + apt = "apt-get" + + def setUp(self): + if os.path.exists("/tmp/autFailure"): + os.unlink("/tmp/authFailure"); + if os.path.exists("/tmp/autFailure2"): + os.unlink("/tmp/authFailure2"); + def testRepositorySigFailure(self): + """ + test if a repository that used to be authenticated and fails on + apt-get update refuses to update and uses the old state + """ + # copy valid signatures into lists (those are ok, even + # if the name is "-broken-" ... + for f in glob.glob("./authReliability/lists/*"): + shutil.copy(f,"/var/lib/apt/lists") + # ensure we do *not* get a I-M-S hit + os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (0,0)) + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure", + "-o",'APT::Update::Auth-Failure::=touch /tmp/authFailure', + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"), + "The gpg file disappeared, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"), + "The Packages file disappeared, this should not happen") + self.assert_(os.path.exists("/tmp/authFailure"), + "The APT::Update::Auth-Failure script did not run (1)") + # the same with i-m-s hit this time + for f in glob.glob("./authReliability/lists/*"): + shutil.copy(f,"/var/lib/apt/lists") + os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (time.time(),time.time())) + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.failure", + "-o",'APT::Update::Auth-Failure::=touch /tmp/authFailure2', + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Release.gpg"), + "The gpg file disappeared, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-broken_Packages"), + "The Packages file disappeared, this should not happen") + self.assert_(os.path.exists("/tmp/authFailure2"), + "The APT::Update::Auth-Failure script did not run (2)") + def testRepositorySigGood(self): + """ + test that a regular repository with good data stays good + """ + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good" + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"), + "The gpg file disappeared after a regular download, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"), + "The Packages file disappeared, this should not happen") + # test good is still good after non I-M-S hit and a previous files in lists/ + for f in glob.glob("./authReliability/lists/*"): + shutil.copy(f,"/var/lib/apt/lists") + # ensure we do *not* get a I-M-S hit + os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (0,0)) + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good" + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"), + "The gpg file disappeared after a I-M-S hit, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"), + "The Packages file disappeared, this should not happen") + # test good is still good after I-M-S hit + for f in glob.glob("./authReliability/lists/*"): + shutil.copy(f,"/var/lib/apt/lists") + # ensure we do get a I-M-S hit + os.utime("/var/lib/apt/lists/%s" % os.path.basename(f), (time.time(),time.time())) + res = call([self.apt, + "update", + "-o","Dir::Etc::sourcelist=./authReliability/sources.list.good" + ] + apt_args, + stdout=stdout, stderr=stderr) + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Release.gpg"), + "The gpg file disappeared, this should not happen") + self.assert_(os.path.exists("/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_auth-test-suit_gpg-package-ok_Packages"), + "The Packages file disappeared, this should not happen") class testAuthentication(unittest.TestCase): @@@ -192,6 -95,20 +192,20 @@@ self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0, "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*")) + def testValid(self): + for f in glob.glob("testsources.list/sources.list*validuntil*"): + self._cleanup() + (prefix, testtype, result) = f.split("-") + expected_res = self._expectedRes(result) + cmd = ["update"] + res = call([self.apt,"-o","Dir::Etc::sourcelist=./%s" % f]+cmd+apt_args, + stdout=stdout, stderr=stderr) + self.assert_(res == expected_res, + "test '%s' failed (got %s expected %s" % (f,res,expected_res)) + if expected_res == 0: + self.assert_(len(glob.glob("/var/lib/apt/lists/partial/*")) == 0, + "partial/ dir has leftover files: %s" % glob.glob("/var/lib/apt/lists/partial/*")) + class testLocalRepositories(unittest.TestCase): " test local repository regressions " @@@ -246,7 -163,6 +260,7 @@@ if __name__ == "__main__" if len(sys.argv) > 1 and sys.argv[1] == "-v": stdout = sys.stdout stderr = sys.stderr + + # run only one for now + #unittest.main(defaultTest="testAptAuthenticationReliability") unittest.main() - -