From a7f3cf73edc9bae4208a4ea9d61dd25b753dced5 Mon Sep 17 00:00:00 2001 From: Daniel Hartwig Date: Thu, 28 Jun 2012 20:07:38 +0800 Subject: Guess changelog URI for third-party sites Contruct a changelog file path for third party sites that do not use packages.debian.org/changelogs This simply uses the ArchiveURI() of the source pkg and looks for a .changelog file there. LP: #563155 --- NEWS | 3 ++ src/cmdline/cmdline_changelog.cc | 18 +------ src/generic/apt/pkg_changelog.cc | 114 +++++++++++++++++++++++++++++++++------ src/generic/apt/pkg_changelog.h | 18 ++++--- src/view_changelog.cc | 14 ----- 5 files changed, 114 insertions(+), 53 deletions(-) diff --git a/NEWS b/NEWS index 9362657b..9af97aa6 100644 --- a/NEWS +++ b/NEWS @@ -126,6 +126,9 @@ behaviour is desirable for two reasons: in Debian Policy § 11.1 “Architecture specification strings”. + * [all]: Support downloading changelogs for packages on + third-party sites by guessing the URI. (LP: #563155) + - Minor bugs: * handle "-qq" like other apt-utils diff --git a/src/cmdline/cmdline_changelog.cc b/src/cmdline/cmdline_changelog.cc index 966b9273..370301af 100644 --- a/src/cmdline/cmdline_changelog.cc +++ b/src/cmdline/cmdline_changelog.cc @@ -230,7 +230,7 @@ void set_name(temp::name n, temp::name *target) term_metrics); boost::shared_ptr - info = aptitude::apt::changelog_info::create(srcpkg, ver, section, name); + info = aptitude::apt::changelog_info::guess(srcpkg, ver, section, name); get_changelog(info, callbacks, @@ -316,22 +316,6 @@ void do_cmdline_changelog(const vector &packages, if(!ver.end()) { - // Move this to a central location and just display an - // apt error? - bool in_debian=false; - - for(pkgCache::VerFileIterator vf=ver.FileList(); - !vf.end() && !in_debian; ++vf) - if(!vf.File().end() && vf.File().Origin()!=NULL && - strcmp(vf.File().Origin(), "Debian")==0) - in_debian=true; - - if(!in_debian) - { - _error->Error(_("%s is not an official Debian package, cannot display its changelog."), input.c_str()); - continue; - } - get_changelog(ver, filename, term_metrics); } } diff --git a/src/generic/apt/pkg_changelog.cc b/src/generic/apt/pkg_changelog.cc index d425a260..192d3e56 100644 --- a/src/generic/apt/pkg_changelog.cc +++ b/src/generic/apt/pkg_changelog.cc @@ -85,15 +85,89 @@ namespace aptitude } } + std::string get_changelog_uri(const std::string &path) + { + string server = _config->Find("APT::Changelogs::Server", + "http://packages.debian.org/changelogs"); + + return cw::util::ssprintf("%s/%s/changelog", + server.c_str(), + path.c_str()); + } + + /* Construct a changelog file path for third party sites that do + * not use packages.debian.org/changelogs + * This simply uses the ArchiveURI() of the source pkg and looks for + * a .changelog file there. + */ + bool guess_third_party_changelog_uri(pkgCache::VerIterator ver, + const std::string &path, + std::string &out_uri) + { + // guess uri for third-party packages + pkgCache::VerFileIterator vf = ver.FileList(); + pkgCache::PkgFileIterator pf = vf.File(); + pkgIndexFile *index; + if(apt_source_list->FindIndex(pf, index) == false) + return false; + + out_uri = index->ArchiveURI(path + ".changelog"); + return true; + } + boost::shared_ptr changelog_info::create(const std::string &source_package, const std::string &source_version, - const std::string &path, + const std::vector &uri_list, const std::string &display_name) { return boost::make_shared(source_package, source_version, - path, + uri_list, + display_name); + } + + boost::shared_ptr + changelog_info::guess(const std::string &source_package, + const std::string &source_version, + const std::string §ion, + const std::string &display_name) + { + string realsection; + const string::size_type slashfound = section.find('/'); + if(slashfound != section.npos) + realsection.assign(section, 0, slashfound); + else + realsection.assign("main"); + + string prefix; + if(source_package.size() > 3 + && source_package.compare(0, 3, "lib") == 0) + prefix.assign(source_package, 0, 4); + else + prefix.assign(source_package, 0, 1); + + string realver = StripEpoch(source_version); + + vector uri_list; + + string path; + path = cw::util::ssprintf("pool/%s/%s/%s/%s_%s", + realsection.c_str(), + prefix.c_str(), + source_package.c_str(), + source_package.c_str(), + realver.c_str()); + + uri_list.push_back(get_changelog_uri(path)); + + LOG_TRACE(Loggers::getAptitudeChangelog(), + "Getting the changelog of the source package " + << source_package << " " << source_version); + + return boost::make_shared(source_package, + source_version, + uri_list, display_name); } @@ -123,14 +197,22 @@ namespace aptitude path = flNotFile(rec.FileName()); path += source_package + "_" + StripEpoch(source_version); + vector uri_list; + + uri_list.push_back(get_changelog_uri(path)); + + string third_party_uri; + if(guess_third_party_changelog_uri(ver, path, third_party_uri)) + uri_list.push_back(third_party_uri); + LOG_TRACE(Loggers::getAptitudeChangelog(), "For " << ver.ParentPkg().Name() << " " << ver.VerStr() << ", getting the changelog of the source package " - << source_package << " " << source_version << " from " << path); + << source_package << " " << source_version); return boost::make_shared(source_package, source_version, - path, + uri_list, ver.ParentPkg().Name()); } @@ -391,8 +473,6 @@ namespace aptitude << req.get_info()->get_source_package() << ", source_version = " << req.get_info()->get_source_version() - << ", path = " - << req.get_info()->get_path() << ", display_name = " << req.get_info()->get_display_name() << ", download = 0x" @@ -442,7 +522,7 @@ namespace aptitude const string source_package(info.get_source_package()); const string source_version(info.get_source_version()); - const string path(info.get_path()); + const vector uri_list(info.get_uri_list()); const string name(info.get_display_name()); const string short_description = cw::util::ssprintf(_("Changelog of %s"), name.c_str()); @@ -526,15 +606,17 @@ namespace aptitude } } - string server = _config->Find("APT::Changelogs::Server", - "http://packages.debian.org/changelogs"); - string uri = cw::util::ssprintf("%s/%s/changelog", server.c_str(), path.c_str()); - LOG_TRACE(logger, - "Adding " << uri - << " as a URI for the changelog of " << source_package << " " << source_version); - - download.push_back(uri); - + for(vector::const_iterator uri = uri_list.begin(); + uri != uri_list.end(); + ++uri) + { + LOG_TRACE(logger, + "Adding " << (*uri) + << " as a URI for the changelog of " << source_package + << " " << source_version); + + download.push_back(*uri); + } LOG_TRACE(logger, "Starting to download " << short_description); diff --git a/src/generic/apt/pkg_changelog.h b/src/generic/apt/pkg_changelog.h index a0748177..cf4ffa55 100644 --- a/src/generic/apt/pkg_changelog.h +++ b/src/generic/apt/pkg_changelog.h @@ -56,7 +56,7 @@ namespace aptitude { const std::string source_package; const std::string source_version; - const std::string path; + const std::vector uri_list; const std::string display_name; public: @@ -66,11 +66,11 @@ namespace aptitude */ changelog_info(const std::string &_source_package, const std::string &_source_version, - const std::string &_path, + const std::vector &_uri_list, const std::string &_display_name) : source_package(_source_package), source_version(_source_version), - path(_path), + uri_list(_uri_list), display_name(_display_name) { } @@ -78,9 +78,15 @@ namespace aptitude static boost::shared_ptr create(const std::string &source_package, const std::string &source_version, - const std::string &path, + const std::vector &uri_list, const std::string &display_name); + static boost::shared_ptr + guess(const std::string &source_package, + const std::string &source_version, + const std::string §ion, + const std::string &display_name); + /** \brief Create a changelog_info structure that describes the * changelog of the given package version. * @@ -94,8 +100,8 @@ namespace aptitude const std::string &get_source_package() const { return source_package; } /** \brief Retrieve the name of the changelog's source version. */ const std::string &get_source_version() const { return source_version; } - /** \brief Retrieve the path string for changelog url construction. */ - const std::string &get_path() const { return path; } + /** \brief Retrieve the list of URIs to try, in order. */ + const std::vector &get_uri_list() const { return uri_list; } /** \brief Retrieve the display name of the changelog's package. * * This is the name that should be displayed to the user when, diff --git a/src/view_changelog.cc b/src/view_changelog.cc index ae7ed465..0a3d7498 100644 --- a/src/view_changelog.cc +++ b/src/view_changelog.cc @@ -385,8 +385,6 @@ public: void view_changelog(pkgCache::VerIterator ver) { - bool in_debian=false; - string pkgname = ver.ParentPkg().Name(); @@ -404,18 +402,6 @@ void view_changelog(pkgCache::VerIterator ver) } // TODO: add a configurable association between origins and changelog URLs. - for(pkgCache::VerFileIterator vf=ver.FileList(); - !vf.end() && !in_debian; ++vf) - if(!vf.File().end() && vf.File().Origin()!=NULL && - strcmp(vf.File().Origin(), "Debian")==0) - in_debian=true; - - if(!in_debian) - { - show_message(_("You can only view changelogs of official Debian packages."), - NULL, cw::get_style("Error")); - return; - } boost::shared_ptr callbacks = boost::make_shared(ver.ParentPkg().Name(), -- cgit v1.2.3