From: Michael Vogt Date: Sat, 7 May 2005 17:45:10 +0000 (+0000) Subject: * merge with matt, search for the right patch next instead of applying them in order X-Git-Tag: 0.7.21~334^2~22 X-Git-Url: https://git.saurik.com/apt.git/commitdiff_plain/94dc9d7d8bbf2f1351db26e4532327c6784ead96?ds=inline * merge with matt, search for the right patch next instead of applying them in order Patches applied: * apt@packages.debian.org/apt--main--0--patch-77 Merge apt--mvo--0 * apt@packages.debian.org/apt--main--0--patch-78 Update changelog * apt@packages.debian.org/apt--main--0--patch-79 Merge michael.vogt@ubuntu.com--2005/apt--mvo--0 * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-14 * changelog entry for 0.6.34ubuntu1 added, MinAge default is 2 days now * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-15 * merged with matts tree * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-16 * changelog updated * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-17 * whitespace change to add incomplete log for last patch * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-18 * honor "Acquire::gpgv::Options" in apt-cdrom too * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-19 * corrected a incorrect use of string().c_str() (thanks to mdz!) * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-20 * supress output when /var/cache/apt/archives is empty; break when min-age is reached * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-21 * changed distro to "experimental", changed version number to 0.6.36 --- 94dc9d7d8bbf2f1351db26e4532327c6784ead96 diff --cc apt-pkg/acquire-item.cc index 5d741af6f,b2f896627..81636902e --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@@ -134,281 -131,6 +134,301 @@@ void pkgAcquire::Item::Rename(string Fr } /*}}}*/ +// AcqIndexDiffs::AcqIndexDiffs - Constructor +// --------------------------------------------------------------------- +/* The package diff is added to the queue. one object is constructed + * for each diff and the index + */ +pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, + string URI,string URIDesc,string ShortDesc, + string ExpectedMD5, vector diffs) - : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), needed_files(diffs) ++ : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), available_patches(diffs) +{ + + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; + DestFile += URItoFileName(URI); + + Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); + + Desc.Description = URIDesc; + Desc.Owner = this; + Desc.ShortDesc = ShortDesc; + + CurrentPackagesFile = _config->FindDir("Dir::State::lists"); + CurrentPackagesFile += URItoFileName(RealURI); + + if(Debug) { + std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): " + << CurrentPackagesFile << std::endl; + } + + if(!FileExists(CurrentPackagesFile) || + !_config->FindB("Acquire::Diffs",true)) { + // we don't have a pkg file or we don't want to queue + if(Debug) + std::clog << "No index file or canceld by user" << std::endl; + Failed("", NULL); + return; + } + - if(needed_files.size() == 0) ++ if(available_patches.size() == 0) + QueueDiffIndex(URI); + else + QueueNextDiff(); +} + +void pkgAcqIndexDiffs::QueueDiffIndex(string URI) +{ + Desc.URI = URI + ".diff/Index"; + Desc.Description = Description + "IndexDiff"; + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; + DestFile += URItoFileName(URI) + string(".IndexDiff"); + + if(Debug) + std::clog << "QueueDiffIndex: " << Desc.URI << std::endl; + + QueueURI(Desc); +} + +// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +/* The only header we use is the last-modified header. */ +string pkgAcqIndexDiffs::Custom600Headers() +{ + if(DestFile.rfind(".IndexDiff") == string::npos) + return string(""); + + string Final = _config->FindDir("Dir::State::lists"); + Final += URItoFileName(RealURI) + string(".IndexDiff"); + + if(Debug) + std::clog << "Custom600Header-IMS: " << Final << std::endl; + + struct stat Buf; + if (stat(Final.c_str(),&Buf) != 0) + return "\nIndex-File: true"; + + return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); +} + +void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +{ + if(Debug) + std::clog << "Failed(): " << Desc.URI << std::endl + << "Falling back to big package file" << std::endl; + new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc, + ExpectedMD5); + Finish(); +} + + +// helper that cleans the item out of the fetcher queue +void pkgAcqIndexDiffs::Finish(bool allDone) +{ + // we restore the original name, this is required, otherwise + // the file will be cleaned + if(allDone) { + // this is for the "real" finish + DestFile = _config->FindDir("Dir::State::lists"); + DestFile += URItoFileName(RealURI); + Complete = true; + Dequeue(); + if(Debug) + std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl; + return; + + } + + if(Debug) + std::clog << "Finishing: " << Desc.URI << std::endl; + Complete = false; + Status = StatDone; + Dequeue(); + return; +} + + +// this needs to be rewriten to not depend on the external ed +bool pkgAcqIndexDiffs::ApplyDiff(string PatchFile) +{ + char *error; + int res=0; + + string FinalFile = _config->FindDir("Dir::State::lists"); + FinalFile += URItoFileName(RealURI); + + int Process = ExecFork(); + if (Process == 0) + { + chdir(_config->FindDir("Dir::State::lists").c_str()); - string cmd = "(zcat " + PatchFile + "; echo \"wq\" ) | red " + FinalFile + " >/dev/null 2>/dev/null"; ++ // for some reason "red" fails with the pdiffs from p.d.o/~aba ?!? ++ string cmd = "(zcat " + PatchFile + "; echo \"wq\" ) | /bin/ed " + FinalFile + " >/dev/null 2>/dev/null"; + if(Debug) + std::clog << "Runing: " << cmd << std::endl; + res = system(cmd.c_str()); + _exit(WEXITSTATUS(res)); + } + if(!ExecWait(Process, error, true)) { + //_error->Error("Patch failed: %s ", error); + return false; + } + + return true; +} + +bool pkgAcqIndexDiffs::QueueNextDiff() +{ - // FIXME: don't use the needed_files[0] but check sha1 and search - // for the right patch in needed_files - // -> and rename needed_files to "available_patches" ++ // calc sha1 of the just patched file ++ string FinalFile = _config->FindDir("Dir::State::lists"); ++ FinalFile += URItoFileName(RealURI); ++ ++ FileFd fd(FinalFile, FileFd::ReadOnly); ++ SHA1Summation SHA1; ++ SHA1.AddFD(fd.Fd(), fd.Size()); ++ string local_sha1 = string(SHA1.Result()); ++ ++ // see if we have a patch for it, the patch list must be ordered ++ for(vector::iterator I=available_patches.begin(); ++ I != available_patches.end(); I++) { ++ // if the patch does not fit, it's not interessting ++ if((*I).sha1 != local_sha1) ++ available_patches.erase(I); ++ } ++ ++ // error checking and falling back if no patch was found ++ if(available_patches.size() == 0) { ++ Failed("", NULL); ++ return false; ++ } + - // queue diff - Desc.URI = string(RealURI) + string(".diff/") + needed_files[0].file + string(".gz"); - Desc.Description = needed_files[0].file + string(".pdiff"); ++ // queue the right diff ++ Desc.URI = string(RealURI) + string(".diff/") + available_patches[0].file + string(".gz"); ++ Desc.Description = available_patches[0].file + string(".pdiff"); + + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; - DestFile += URItoFileName(RealURI + string(".diff/") + needed_files[0].file); ++ DestFile += URItoFileName(RealURI + string(".diff/") + available_patches[0].file); + + if(Debug) + std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; + + QueueURI(Desc); + + return true; +} + +bool pkgAcqIndexDiffs::ParseIndexDiff(string IndexDiffFile) +{ + if(Debug) + std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile + << std::endl; + + FileFd Fd(IndexDiffFile,FileFd::ReadOnly); + pkgTagFile TF(&Fd); + if (_error->PendingError() == true) + return false; + pkgTagSection Tags; + if(TF.Step(Tags) == true) + { + string local_sha1; + string tmp = Tags.FindS("SHA1-Current"); + std::stringstream ss(tmp); + ss >> ServerSha1; + + FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); + SHA1Summation SHA1; + SHA1.AddFD(fd.Fd(), fd.Size()); + local_sha1 = string(SHA1.Result()); + + if(local_sha1 == ServerSha1) { + if(Debug) + std::clog << "Package file is up-to-date" << std::endl; + Finish(true); + return true; + } + if(Debug) + std::clog << "SHA1-Current: " << ServerSha1 << std::endl; + + // check the historie and see what patches we need + string history = Tags.FindS("SHA1-History"); + std::stringstream hist(history); + DiffInfo d; + string size; + bool found = false; + while(hist >> d.sha1 >> size >> d.file) { + d.size = atoi(size.c_str()); + if(d.sha1 == local_sha1) + found=true; + if(found) { + if(Debug) + std::clog << "Need to get diff: " << d.file << std::endl; - needed_files.push_back(d); ++ available_patches.push_back(d); + } + } + // no information how to get the patches, bail out + if(!found) { + if(Debug) + std::clog << "Can't find a patch in the index file" << std::endl; + // Failed will queue a big package file + Failed("", NULL); + } else { + // queue the diffs + new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedMD5, needed_files); ++ ExpectedMD5, available_patches); + Finish(); + return true; + } + } + + return false; +} + + +void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash, + pkgAcquire::MethodConfig *Cnf) +{ + if(Debug) + std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl; + + Item::Done(Message,Size,Md5Hash,Cnf); + + int len = Desc.URI.size(); + // sucess in downloading the index + if(Desc.URI.substr(len-strlen("Index"),len-1) == "Index") { + + // rename + string FinalFile = _config->FindDir("Dir::State::lists"); + FinalFile += URItoFileName(RealURI) + string(".IndexDiff"); + if(Debug) + std::clog << "Renaming: " << DestFile << " -> " << FinalFile + << std::endl; + Rename(DestFile,FinalFile); + chmod(FinalFile.c_str(),0644); + DestFile = FinalFile; + + if(!ParseIndexDiff(DestFile)) + return Failed("", NULL); + else + return Finish(); + } + + // sucess in downloading a diff + if(Desc.URI.find(".diff") != string::npos) { + ApplyDiff(DestFile); - needed_files.erase(needed_files.begin()); ++ available_patches.erase(available_patches.begin()); + - if(needed_files.size() > 0) { ++ if(available_patches.size() > 0) { + new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedMD5, needed_files); ++ ExpectedMD5, available_patches); + } else { + Finish(true); + return; + } + } + + Finish(); +} + + // AcqIndex::AcqIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- /* The package file is added to the queue and a second class is diff --cc apt-pkg/acquire-item.h index 6c78f33ef,ea71153d5..8d58a39ba --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@@ -82,47 -82,6 +82,47 @@@ class pkgAcquire::Ite virtual ~Item(); }; +// item for index diffs +class pkgAcqIndexDiffs : public pkgAcquire::Item +{ + protected: + bool Debug; + pkgAcquire::ItemDesc Desc; + string RealURI; + string ExpectedMD5; + // this is the SHA-1 sum we expect after the patching + string ServerSha1; + string CurrentPackagesFile; + string Description; + struct DiffInfo { + string file; + string sha1; + unsigned long size; + }; - vector needed_files; ++ vector available_patches; + + + public: + + // Specialized action members + virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf); + virtual void Done(string Message,unsigned long Size,string Md5Hash, + pkgAcquire::MethodConfig *Cnf); + virtual string DescURI() {return RealURI + "Index";}; + virtual string Custom600Headers(); + + // various helpers + bool ParseIndexDiff(string IndexDiffFile); + void QueueDiffIndex(string URI); + bool QueueNextDiff(); + bool ApplyDiff(string PatchFile); + void Finish(bool allDone=false); + + pkgAcqIndexDiffs(pkgAcquire *Owner,string URI,string URIDesc, + string ShortDesct, string ExpectedMD5, + vector diffs=vector()); +}; + // Item class for index files class pkgAcqIndex : public pkgAcquire::Item { diff --cc configure.in index 3c5d6d69d,e17a126ba..12d3ecae7 --- a/configure.in +++ b/configure.in @@@ -18,7 -18,7 +18,7 @@@ AC_CONFIG_AUX_DIR(buildlib AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in include/apti18n.h:buildlib/apti18n.h.in) dnl -- SET THIS TO THE RELEASE VERSION -- - AC_DEFINE_UNQUOTED(VERSION,"0.6.35") -AC_DEFINE_UNQUOTED(VERSION,"0.6.35ubuntu1") ++AC_DEFINE_UNQUOTED(VERSION,"0.6.36") PACKAGE="apt" AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE") AC_SUBST(PACKAGE)