From: Michael Vogt Date: Thu, 18 Nov 2010 09:32:41 +0000 (+0100) Subject: merged lp:~mvo/apt/apt-get-changelog X-Git-Tag: 0.8.11~6^2~12 X-Git-Url: https://git.saurik.com/apt.git/commitdiff_plain/2d555a8205eccc4cb17b93f7c92b71a854e8f82e?ds=inline;hp=-c merged lp:~mvo/apt/apt-get-changelog --- 2d555a8205eccc4cb17b93f7c92b71a854e8f82e diff --combined cmdline/apt-get.cc index 116f4a07e,8cb43be67..b645da878 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@@ -2165,60 -2165,6 +2165,60 @@@ bool DoAutoClean(CommandLine &CmdL Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache); } /*}}}*/ +// DoDownload - download a binary /*{{{*/ +// --------------------------------------------------------------------- +bool DoDownload(CommandLine &CmdL) +{ + CacheFile Cache; + if (Cache.ReadOnlyOpen() == false) + return false; + + APT::CacheSetHelper helper(c0out); + APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, + CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper); + pkgAcquire Fetcher; + AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0)); + Fetcher.Setup(&Stat); + + if (verset.empty() == true) + return false; + + bool result = true; + pkgRecords Recs(Cache); + pkgSourceList *SrcList = Cache.GetSourceList(); + for (APT::VersionSet::const_iterator Ver = verset.begin(); + Ver != verset.end(); + ++Ver) + { + string descr; + // get the right version + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); + pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList()); + pkgCache::VerFileIterator Vf = Ver.FileList(); + if (Vf.end() == true) + return _error->Error("Can not find VerFile"); + pkgCache::PkgFileIterator F = Vf.File(); + pkgIndexFile *index; + if(SrcList->FindIndex(F, index) == false) + return _error->Error("FindIndex failed"); + string uri = index->ArchiveURI(rec.FileName()); + strprintf(descr, _("Downloading %s %s"), Pkg.Name(), Ver.VerStr()); + // get the most appropriate hash + HashString hash; + if (rec.SHA256Hash() != "") + hash = HashString("sha256", rec.SHA256Hash()); + else if (rec.SHA1Hash() != "") + hash = HashString("sha1", rec.SHA1Hash()); + else if (rec.MD5Hash() != "") + hash = HashString("md5", rec.MD5Hash()); + // get the file + new pkgAcqFile(&Fetcher, uri, hash.toStr(), (*Ver)->Size, descr, Pkg.Name(), "."); + result &= (Fetcher.Run() == pkgAcquire::Continue); + } + + return result; +} + /*}}}*/ // DoCheck - Perform the check operation /*{{{*/ // --------------------------------------------------------------------- /* Opening automatically checks the system, this command is mostly used @@@ -2787,6 -2733,158 +2787,158 @@@ bool DoBuildDep(CommandLine &CmdL return true; } /*}}}*/ + // GuessThirdPartyChangelogUri - return url /*{{{*/ + // --------------------------------------------------------------------- + bool GuessThirdPartyChangelogUri(CacheFile &Cache, + pkgCache::PkgIterator Pkg, + pkgCache::VerIterator Ver, + string &out_uri) + { + pkgRecords Recs(Cache); + pkgSourceList *SrcList = Cache.GetSourceList(); + + // get the binary deb server path + pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList()); + string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg(); + // FIXME: deal with cases like gcc-defaults (srcver != binver) + string srcver = StripEpoch(Ver.VerStr()); + + pkgCache::VerFileIterator Vf = Ver.FileList(); + if (Vf.end() == true) + return false; + pkgCache::PkgFileIterator F = Vf.File(); + pkgIndexFile *index; + if(SrcList->FindIndex(F, index) == false) + return false; + // get archive uri for the binary deb + string deb_uri = index->ArchiveURI(rec.FileName()); + + // now strip away the filename and add srcpkg_srcver.changelog + out_uri = flNotFile(deb_uri); + out_uri += srcpkg + "_" + srcver + ".changelog"; + return true; + } + // DownloadChangelog - Download the changelog /*{{{*/ + // --------------------------------------------------------------------- + bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, pkgCache::VerIterator V, string targetfile) + { + string srcpkg; + string prefix; + string descr; + string src_section; + string verstr; + string server; + string path; + + // data structures we need + pkgRecords Recs(CacheFile); + pkgCache::PkgIterator Pkg = V.ParentPkg(); + pkgRecords::Parser &rec=Recs.Lookup(V.FileList()); + + // build uri + srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg(); + // FIXME: we actually need the source section here + src_section= Pkg.Section(); + if(src_section.find('/')!=src_section.npos) + src_section=string(src_section, 0, src_section.find('/')); + else + src_section="main"; + + prefix+=srcpkg[0]; + if(srcpkg.size()>3 && srcpkg[0]=='l' && srcpkg[1]=='i' && srcpkg[2]=='b') + prefix=std::string("lib")+srcpkg[3]; + + verstr = V.VerStr(); + if(verstr.find(':')!=verstr.npos) + verstr=string(verstr, verstr.find(':')+1); + + // make the server configurable + server = _config->Find("Apt::Changelogs::Server", + "http://packages.debian.org/"); + // ... but not the format string to avoid all possible attacks + strprintf(path, "/changelogs/pool/%s/%s/%s/%s_%s/changelog", src_section.c_str(), prefix.c_str(), srcpkg.c_str(), srcpkg.c_str(), verstr.c_str()); + // queue it + string changelog_uri = server+path; + strprintf(descr, _("Changelog for %s (%s)"), srcpkg.c_str(), changelog_uri.c_str()); + new pkgAcqFile(&Fetcher, uri, "", 0, descr, srcpkg, "ignored", targetfile); + + // try downloading it, if that fails, they third-party-changelogs location + // FIXME: res is "Continue" even if I get a 404?!? + int res = Fetcher.Run(); + if (!FileExists(targetfile)) + { + string third_party_uri; + if (GuessThirdPartyChangelogUri(CacheFile, Pkg, V, third_party_uri)) + { + strprintf(descr, _("Changelog for %s (%s)"), srcpkg.c_str(), third_party_uri.c_str()); + new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, srcpkg, "ignored", targetfile); + res = Fetcher.Run(); + } + } + + if (FileExists(targetfile)) + return true; + + // error + return _error->Error("changelog download failed"); + } + /*}}}*/ + // DisplayFileInPager - Display File with pager /*{{{*/ + void DisplayFileInPager(string filename) + { + pid_t Process = ExecFork(); + if (Process == 0) + { + const char *Args[3]; + Args[0] = "/usr/bin/sensible-pager"; + Args[1] = filename.c_str(); + Args[2] = 0; + execvp(Args[0],(char **)Args); + exit(100); + } + + // Wait for the subprocess + ExecWait(Process, "sensible-pager", false); + } + /*}}}*/ + // DoChangelog - Get changelog from the command line /*{{{*/ + // --------------------------------------------------------------------- + bool DoChangelog(CommandLine &CmdL) + { + CacheFile Cache; + if (Cache.ReadOnlyOpen() == false) + return false; + + APT::CacheSetHelper helper(c0out); + APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, + CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper); + pkgAcquire Fetcher; + AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0)); + Fetcher.Setup(&Stat); + + if (verset.empty() == true) + return false; + char *tmpdir = mkdtemp(strdup("/tmp/apt-changelog-XXXXXX")); + if (tmpdir == NULL) { + return _error->Errno("mkdtemp", "mkdtemp failed"); + } + + for (APT::VersionSet::const_iterator Ver = verset.begin(); + Ver != verset.end(); + ++Ver) + { + string changelogfile = string(tmpdir) + "changelog"; + if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile)) + DisplayFileInPager(changelogfile); + // cleanup temp file + unlink(changelogfile.c_str()); + } + // clenaup tmp dir + rmdir(tmpdir); + free(tmpdir); + return true; + } + /*}}}*/ // DoMoo - Never Ask, Never Tell /*{{{*/ // --------------------------------------------------------------------- /* */ @@@ -2977,7 -3075,7 +3129,8 @@@ int main(int argc,const char *argv[] {"autoclean",&DoAutoClean}, {"check",&DoCheck}, {"source",&DoSource}, + {"download",&DoDownload}, + {"changelog",&DoChangelog}, {"moo",&DoMoo}, {"help",&ShowHelp}, {0,0}};