Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support repo's Appstream data download and install #1844

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ option(WITH_COMPS "Build with comps groups and environments support" ON)
option(WITH_MODULEMD "Build with modulemd modules support" ON)
option(WITH_ZCHUNK "Build with zchunk delta compression support" ON)
option(WITH_SYSTEMD "Build with systemd and D-Bus features" ON)
option(WITH_APPSTREAM "Build with appstream support" ON)
option(ENABLE_SOLV_URPMREORDER "Build with support for URPM-like solution reordering?" OFF)
option(ENABLE_SOLV_FOCUSNEW "Build with SOLVER_FLAG_FOCUS_NEW libsolv flag enabled to ensure new dependencies are installed in latests versions?" ON)

Expand Down Expand Up @@ -129,6 +130,10 @@ if (WITH_MODULEMD)
add_definitions(-DWITH_MODULEMD)
endif()

if (WITH_APPSTREAM)
add_definitions(-DWITH_APPSTREAM)
endif()

include_directories("${PROJECT_SOURCE_DIR}/include")
include_directories("${PROJECT_SOURCE_DIR}/common")

Expand Down
4 changes: 4 additions & 0 deletions include/libdnf5/repo/repo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ class LIBDNF_API Repo {
// @replaces libdnf:repo/Repo.hpp:method:Repo.loadCache(bool throwExcept)
void read_metadata_cache();

/// install downloaded appstream data for the repo, if available and
/// if built with the appstream support
void install_appstream();

/// Checks whether the locally downloaded metadata are in sync with the origin.
/// @return `true` if metadata are in sync with the origin, `false` otherwise.
bool is_in_sync();
Expand Down
7 changes: 7 additions & 0 deletions libdnf5/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ if (WITH_MODULEMD)
target_link_libraries(libdnf5_static PRIVATE ${LIBMODULEMD_LIBRARIES})
endif()

if (WITH_APPSTREAM)
pkg_check_modules(APPSTREAM REQUIRED appstream>=1.0)
include_directories(${APPSTREAM_INCLUDE_DIRS})
target_link_libraries(libdnf5 PRIVATE ${APPSTREAM_LIBRARIES})
target_link_libraries(libdnf5_static PRIVATE ${APPSTREAM_LIBRARIES})
endif()

if (ENABLE_SOLV_FOCUSNEW)
pkg_check_modules(LIBSOLV REQUIRED libsolv>=0.7.30)
else()
Expand Down
47 changes: 47 additions & 0 deletions libdnf5/repo/repo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ constexpr const char * REPOID_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmno
#include "repo_downloader.hpp"
#include "rpm/package_sack_impl.hpp"
#include "solv_repo.hpp"
#include "utils/string.hpp"

#include "libdnf5/common/exception.hpp"
#include "libdnf5/conf/const.hpp"
Expand Down Expand Up @@ -52,6 +53,9 @@ extern "C" {
#include <filesystem>
#include <set>

#ifdef WITH_APPSTREAM
#include <appstream.h>
#endif

namespace libdnf5::repo {

Expand Down Expand Up @@ -203,6 +207,45 @@ void Repo::read_metadata_cache() {
p_impl->downloader->load_local();
}

void Repo::install_appstream() {
#ifdef WITH_APPSTREAM
std::string repo_id = p_impl->config.get_id();
const std::map<std::string, std::string> & metadata_paths = p_impl->downloader->get_metadata_paths();
std::vector<std::string> basenames;
/* Let every type starting with any of the basenames be considered as the Appstream
data and pass it to the "appstream" library for installation; example type names
are "appstream", "appstream-icons", "appstream-icons_64x64", "appdata", "appdata-icons".
The list of the variants can be long, thus do not hard code the it, but use
the "starts_with" comparison instead. */
/* TODO: make the list configurable with this default */
basenames.push_back("appstream");
basenames.push_back("appdata");

for (size_t i = 0; i < basenames.size(); i++) {
std::string basename = basenames[i];
for (std::map<std::string, std::string>::const_iterator it = metadata_paths.begin(); it != metadata_paths.end();
it++) {
const std::string type = it->first;
const std::string path = it->second;
GError * local_error = NULL;

if (!utils::string::starts_with(type, basename))
continue;

if (!as_utils_install_metadata_file(
AS_METADATA_LOCATION_CACHE, path.c_str(), repo_id.c_str(), NULL, &local_error)) {
p_impl->base->get_logger()->debug(
"Failed to install Appstream metadata file '{}' for repo '{}': {}",
path,
repo_id,
local_error ? local_error->message : "Unknown error");
}

g_clear_error(&local_error);
}
}
#endif
}

bool Repo::is_in_sync() {
if (!p_impl->config.get_metalink_option().empty() && !p_impl->config.get_metalink_option().get_value().empty()) {
Expand Down Expand Up @@ -409,6 +452,10 @@ void Repo::load_available_repo() {
}

p_impl->solv_repo->load_repo_main(p_impl->downloader->repomd_filename, primary_fn);
#ifdef WITH_APPSTREAM
p_impl->solv_repo->load_repo_ext(RepodataType::APPSTREAM, *p_impl->downloader.get());
p_impl->solv_repo->load_repo_ext(RepodataType::APPSTREAM_ICONS, *p_impl->downloader.get());
#endif

auto optional_metadata = p_impl->config.get_main_config().get_optional_metadata_types_option().get_value();

Expand Down
7 changes: 7 additions & 0 deletions libdnf5/repo/repo_downloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,9 @@ const std::string & RepoDownloader::get_metadata_path(const std::string & metada
return it != metadata_paths.end() ? it->second : empty;
}

const std::map<std::string, std::string> & RepoDownloader::get_metadata_paths() const {
return metadata_paths;
}

LibrepoHandle RepoDownloader::init_local_handle() {
LibrepoHandle h;
Expand Down Expand Up @@ -477,6 +480,10 @@ void RepoDownloader::common_handle_setup(LibrepoHandle & h) {
dlist.push_back(MD_FILENAME_PRIMARY);
#ifdef WITH_MODULEMD
dlist.push_back(MD_FILENAME_MODULES);
#endif
#ifdef WITH_APPSTREAM
dlist.push_back(MD_FILENAME_APPSTREAM);
dlist.push_back(MD_FILENAME_APPSTREAM_ICONS);
#endif
if (optional_metadata.extract(libdnf5::METADATA_TYPE_FILELISTS)) {
dlist.push_back(MD_FILENAME_FILELISTS);
Expand Down
3 changes: 3 additions & 0 deletions libdnf5/repo/repo_downloader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class RepoDownloader {
static constexpr const char * MD_FILENAME_GROUP_GZ = "group_gz";
static constexpr const char * MD_FILENAME_GROUP = "group";
static constexpr const char * MD_FILENAME_MODULES = "modules";
static constexpr const char * MD_FILENAME_APPSTREAM = "appstream";
static constexpr const char * MD_FILENAME_APPSTREAM_ICONS = "appstream-icons";

RepoDownloader(const libdnf5::BaseWeakPtr & base, const ConfigRepo & config, Repo::Type repo_type);

Expand All @@ -74,6 +76,7 @@ class RepoDownloader {
void * get_user_data() const noexcept;

const std::string & get_metadata_path(const std::string & metadata_type) const;
const std::map<std::string, std::string> & get_metadata_paths() const;


private:
Expand Down
1 change: 1 addition & 0 deletions libdnf5/repo/repo_sack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ void RepoSack::Impl::update_and_load_repos(libdnf5::repo::RepoQuery & repos, boo
RepoCache(base, cache_dir).remove_attribute(RepoCache::ATTRIBUTE_EXPIRED);
repo->mark_fresh();
repo->read_metadata_cache();
repo->install_appstream();

repos_for_processing.erase(repos_for_processing.begin() + static_cast<ssize_t>(idx));
send_to_sack_loader(repo);
Expand Down
15 changes: 15 additions & 0 deletions libdnf5/repo/solv_repo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ static const char * repodata_type_to_name(RepodataType type) {
return RepoDownloader::MD_FILENAME_GROUP;
case RepodataType::OTHER:
return RepoDownloader::MD_FILENAME_OTHER;
case RepodataType::APPSTREAM:
return RepoDownloader::MD_FILENAME_APPSTREAM;
case RepodataType::APPSTREAM_ICONS:
return RepoDownloader::MD_FILENAME_APPSTREAM_ICONS;
}

libdnf_throw_assertion("Unknown RepodataType: {}", utils::to_underlying(type));
Expand All @@ -197,6 +201,9 @@ static int repodata_type_to_flags(RepodataType type) {
return 0;
case RepodataType::OTHER:
return REPO_EXTEND_SOLVABLES | REPO_LOCALPOOL;
case RepodataType::APPSTREAM:
case RepodataType::APPSTREAM_ICONS:
return 0;
}

libdnf_throw_assertion("Unknown RepodataType: {}", utils::to_underlying(type));
Expand Down Expand Up @@ -313,6 +320,8 @@ void SolvRepo::load_system_repo_ext(RepodataType type) {
case RepodataType::OTHER:
case RepodataType::PRESTO:
case RepodataType::UPDATEINFO:
case RepodataType::APPSTREAM:
case RepodataType::APPSTREAM_ICONS:
throw SolvError(M_("Unsupported extended repodata type for the system repo: \"{}\"."), type_name);
}
}
Expand Down Expand Up @@ -375,6 +384,12 @@ void SolvRepo::load_repo_ext(RepodataType type, const RepoDownloader & downloade
case RepodataType::OTHER:
res = repo_add_rpmmd(repo, ext_file.get(), 0, REPO_EXTEND_SOLVABLES);
break;
case RepodataType::APPSTREAM:
res = repo_add_rpmmd(repo, ext_file.get(), 0, REPO_EXTEND_SOLVABLES);
break;
case RepodataType::APPSTREAM_ICONS:
res = repo_add_rpmmd(repo, ext_file.get(), 0, REPO_EXTEND_SOLVABLES);
break;
}

if (res != 0) {
Expand Down
2 changes: 1 addition & 1 deletion libdnf5/repo/solv_repo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct SolvUserdata {
namespace libdnf5::repo {

using LibsolvRepo = ::Repo;
enum class RepodataType { FILELISTS, PRESTO, UPDATEINFO, COMPS, OTHER };
enum class RepodataType { FILELISTS, PRESTO, UPDATEINFO, COMPS, OTHER, APPSTREAM, APPSTREAM_ICONS };


class SolvError : public Error {
Expand Down
Loading