From 314e2310ac1c219f772a114ce2cad085d37eca76 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 26 Aug 2023 18:39:41 +0000 Subject: [PATCH] packages: Add support for build arches This requires that we add a new data type to packages to store a string array. Signed-off-by: Michael Tremer --- src/libpakfire/archive.c | 20 ++ src/libpakfire/include/pakfire/package.h | 15 ++ src/libpakfire/include/pakfire/util.h | 2 +- src/libpakfire/package.c | 299 ++++++++++++++++++++++- src/libpakfire/parser.c | 13 + src/libpakfire/util.c | 4 +- 6 files changed, 349 insertions(+), 4 deletions(-) diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index 089f34d1b..4f7eab53a 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -1140,6 +1140,26 @@ static int pakfire_archive_make_package_from_json(struct pakfire_archive* archiv goto ERROR; } + // Build arches + struct json_object* build_arches = pakfire_archive_metadata_get_object(archive, "build", "arches"); + if (build_arches) { + const size_t length = json_object_array_length(build_arches); + + for (unsigned int i = 0; i < length; i++) { + struct json_object* item = json_object_array_get_idx(build_arches, i); + if (!item) + continue; + + const char* build_arch = json_object_get_string(item); + if (!build_arch) + continue; + + r = pakfire_package_add_string(pkg, PAKFIRE_PKG_BUILD_ARCHES, build_arch); + if (r) + goto ERROR; + } + } + // Source package const char* source_name = pakfire_archive_metadata_get(archive, "build", "source-name"); if (source_name) { diff --git a/src/libpakfire/include/pakfire/package.h b/src/libpakfire/include/pakfire/package.h index f584eac54..1536a09c9 100644 --- a/src/libpakfire/include/pakfire/package.h +++ b/src/libpakfire/include/pakfire/package.h @@ -57,6 +57,7 @@ enum pakfire_package_key { PAKFIRE_PKG_BUILD_HOST, PAKFIRE_PKG_BUILD_ID, PAKFIRE_PKG_BUILD_TIME, + PAKFIRE_PKG_BUILD_ARCHES, PAKFIRE_PKG_SOURCE_PKG, PAKFIRE_PKG_SOURCE_NAME, PAKFIRE_PKG_SOURCE_EVR, @@ -87,12 +88,23 @@ int pakfire_package_evr_cmp(struct pakfire_package* pkg1, struct pakfire_package unsigned int pakfire_package_id(struct pakfire_package* pkg); +void pakfire_package_unset(struct pakfire_package* pkg, + const enum pakfire_package_key key); + // String const char* pakfire_package_get_string(struct pakfire_package* pkg, const enum pakfire_package_key key); int pakfire_package_set_string(struct pakfire_package* pkg, const enum pakfire_package_key key, const char* value); +// String Arrays +const char** pakfire_package_get_strings(struct pakfire_package* pkg, + const enum pakfire_package_key key); +int pakfire_package_set_strings(struct pakfire_package* pkg, + const enum pakfire_package_key key, const char** values); +int pakfire_package_add_string(struct pakfire_package* pkg, + const enum pakfire_package_key key, const char* value); + // UUID int pakfire_package_get_uuid(struct pakfire_package* pkg, const enum pakfire_package_key key, uuid_t uuid); @@ -147,6 +159,9 @@ int pakfire_package_installcheck(struct pakfire_package* pkg, char** problem); int pakfire_package_create_from_solvable(struct pakfire_package** package, struct pakfire* pakfire, Id id); +int pakfire_package_set_strings_from_string(struct pakfire_package* pkg, + const enum pakfire_package_key key, const char* value); + int pakfire_package_is_source(struct pakfire_package* pkg); char* pakfire_package_join_evr(const char* e, const char* v, const char* r); diff --git a/src/libpakfire/include/pakfire/util.h b/src/libpakfire/include/pakfire/util.h index e5d32acd0..a2e48af1e 100644 --- a/src/libpakfire/include/pakfire/util.h +++ b/src/libpakfire/include/pakfire/util.h @@ -110,7 +110,7 @@ int pakfire_json_add_string(struct pakfire* pakfire, int pakfire_json_add_integer(struct pakfire* pakfire, struct json_object* json, const char* name, int value); int pakfire_json_add_string_array(struct pakfire* pakfire, - struct json_object* json, const char* name, char** array); + struct json_object* json, const char* name, const char** array); // Resource Limits diff --git a/src/libpakfire/package.c b/src/libpakfire/package.c index 50540cbc5..0edd67477 100644 --- a/src/libpakfire/package.c +++ b/src/libpakfire/package.c @@ -435,6 +435,251 @@ static int pakfire_package_make_cache_path(struct pakfire_package* pkg) { return pakfire_cache_path(pkg->pakfire, pkg->cache_path, "%s/%s", uuid, filename); } +PAKFIRE_EXPORT void pakfire_package_unset(struct pakfire_package* pkg, + const enum pakfire_package_key key) { + Id id = ID_NULL; + + Solvable* s = get_solvable(pkg); + + switch (key) { + // Some keys cannot be unset + case PAKFIRE_PKG_NAME: + case PAKFIRE_PKG_EVR: + case PAKFIRE_PKG_ARCH: + return; + + case PAKFIRE_PKG_NEVRA: + break; + + case PAKFIRE_PKG_UUID: + id = SOLVABLE_PKGID; + break; + + case PAKFIRE_PKG_SUMMARY: + id = SOLVABLE_SUMMARY; + break; + + case PAKFIRE_PKG_DESCRIPTION: + id = SOLVABLE_DESCRIPTION; + break; + + case PAKFIRE_PKG_LICENSE: + id = SOLVABLE_LICENSE; + break; + + case PAKFIRE_PKG_URL: + id = SOLVABLE_URL; + break; + + case PAKFIRE_PKG_GROUPS: + id = SOLVABLE_GROUP; + break; + + case PAKFIRE_PKG_VENDOR: + id = SOLVABLE_VENDOR; + break; + + case PAKFIRE_PKG_DISTRO: + id = SOLVABLE_DISTRIBUTION; + break; + + case PAKFIRE_PKG_PACKAGER: + id = SOLVABLE_PACKAGER; + break; + + case PAKFIRE_PKG_PATH: + id = SOLVABLE_MEDIADIR; + + // Unset the filename, too + pakfire_package_unset(pkg, PAKFIRE_PKG_FILENAME); + + // Invalidate the cache + *pkg->path = '\0'; + break; + + case PAKFIRE_PKG_FILENAME: + id = SOLVABLE_MEDIAFILE; + break; + + case PAKFIRE_PKG_CACHE_PATH: + *pkg->cache_path = '\0'; + break; + + case PAKFIRE_PKG_BUILD_HOST: + id = SOLVABLE_BUILDHOST; + break; + + case PAKFIRE_PKG_BUILD_ID: + id = SOLVABLE_BUILDVERSION; + break; + + case PAKFIRE_PKG_BUILD_TIME: + id = SOLVABLE_BUILDTIME; + break; + + case PAKFIRE_PKG_BUILD_ARCHES: + id = SOLVABLE_BUILDFLAVOR; + break; + + case PAKFIRE_PKG_SOURCE_PKG: + pakfire_package_unset(pkg, PAKFIRE_PKG_SOURCE_NAME); + pakfire_package_unset(pkg, PAKFIRE_PKG_SOURCE_EVR); + pakfire_package_unset(pkg, PAKFIRE_PKG_SOURCE_ARCH); + + // Invalidate cache + *pkg->source_nevra = '\0'; + break; + + case PAKFIRE_PKG_SOURCE_NAME: + id = SOLVABLE_SOURCENAME; + break; + + case PAKFIRE_PKG_SOURCE_EVR: + id = SOLVABLE_SOURCEEVR; + break; + + case PAKFIRE_PKG_SOURCE_ARCH: + id = SOLVABLE_SOURCEARCH; + break; + + case PAKFIRE_PKG_DOWNLOADSIZE: + id = SOLVABLE_DOWNLOADSIZE; + break; + + case PAKFIRE_PKG_INSTALLSIZE: + id = SOLVABLE_INSTALLSIZE; + break; + + case PAKFIRE_PKG_INSTALLTIME: + id = SOLVABLE_INSTALLTIME; + break; + + // Cannot unset dependencies here + case PAKFIRE_PKG_PROVIDES: + case PAKFIRE_PKG_PREREQUIRES: + case PAKFIRE_PKG_REQUIRES: + case PAKFIRE_PKG_CONFLICTS: + case PAKFIRE_PKG_OBSOLETES: + case PAKFIRE_PKG_RECOMMENDS: + case PAKFIRE_PKG_SUGGESTS: + case PAKFIRE_PKG_SUPPLEMENTS: + case PAKFIRE_PKG_ENHANCES: + return; + + case PAKFIRE_PKG_DBID: + return; + } + + // Unset any values + solvable_unset(s, id); +} + +PAKFIRE_EXPORT const char** pakfire_package_get_strings( + struct pakfire_package* pkg, const enum pakfire_package_key key) { + const char** ret = NULL; + Queue strings; + Id id = ID_NULL; + + pakfire_package_internalize_repo(pkg); + + Pool* pool = pakfire_get_solv_pool(pkg->pakfire); + Solvable* s = get_solvable(pkg); + + switch (key) { + case PAKFIRE_PKG_BUILD_ARCHES: + id = SOLVABLE_BUILDFLAVOR; + break; + + default: + errno = EINVAL; + return NULL; + } + + // Setup a queue + queue_init(&strings); + + // Fetch the strings + solvable_lookup_idarray(s, id, &strings); + + if (strings.count) { + // Allocate an array + ret = calloc(strings.count + 1, sizeof(*ret)); + if (!ret) + goto ERROR; + + // Fetch the strings + for (int i = 0; i < strings.count; i++) + ret[i] = pool_id2str(pool, strings.elements[i]); + } + +ERROR: + // Free the queue + queue_free(&strings); + + return ret; +} + +PAKFIRE_EXPORT int pakfire_package_set_strings(struct pakfire_package* pkg, + const enum pakfire_package_key key, const char** values) { + int r; + + // Drop any previous values + pakfire_package_unset(pkg, key); + + // End without error if values is empty + if (!values) + return 0; + + // Add all new values + for (const char** value = values; *value; value++) { + r = pakfire_package_add_string(pkg, key, *value); + if (r) + return r; + } + + return 0; +} + +int pakfire_package_set_strings_from_string(struct pakfire_package* pkg, + const enum pakfire_package_key key, const char* value) { + char* buffer = NULL; + char* p = NULL; + int r; + + // Drop any previous values + pakfire_package_unset(pkg, key); + + // End without error if value is empty + if (!value || !*value) + return 0; + + // Copy the string to the heap to change it + buffer = strdup(value); + if (!buffer) { + r = -errno; + goto ERROR; + } + + // Split the string + char* s = strtok_r(buffer, " ", &p); + + // Add each part individually + while (s) { + r = pakfire_package_add_string(pkg, key, s); + if (r) + goto ERROR; + + // Move on to the next part + s = strtok_r(NULL, " ", &p); + } + +ERROR: + if (buffer) + free(buffer); + + return r; +} + PAKFIRE_EXPORT const char* pakfire_package_get_string( struct pakfire_package* pkg, const enum pakfire_package_key key) { const char* ret = NULL; @@ -732,6 +977,10 @@ PAKFIRE_EXPORT int pakfire_package_set_string( id = SOLVABLE_SOURCEARCH; break; + // Compat which splits a string and stores it as an array + case PAKFIRE_PKG_BUILD_ARCHES: + return pakfire_package_set_strings_from_string(pkg, key, value); + default: break; } @@ -756,6 +1005,34 @@ PAKFIRE_EXPORT int pakfire_package_set_string( return 0; } +PAKFIRE_EXPORT int pakfire_package_add_string(struct pakfire_package* pkg, + const enum pakfire_package_key key, const char* value) { + Id key_id = ID_NULL; + Id value_id = ID_NULL; + + Pool* pool = pakfire_get_solv_pool(pkg->pakfire); + Solvable* s = get_solvable(pkg); + + switch (key) { + case PAKFIRE_PKG_BUILD_ARCHES: + key_id = SOLVABLE_BUILDFLAVOR; + value_id = pool_str2id(pool, value, 1); + break; + + default: + errno = EINVAL; + return 1; + } + + // Append the string to the ID array + solvable_add_idarray(s, key_id, value_id); + + // Mark the package as changed + pakfire_package_has_changed(pkg); + + return 0; +} + PAKFIRE_EXPORT int pakfire_package_get_uuid(struct pakfire_package* pkg, const enum pakfire_package_key key, uuid_t uuid) { const char* buffer = NULL; @@ -1316,6 +1593,15 @@ PAKFIRE_EXPORT char* pakfire_package_dump(struct pakfire_package* pkg, int flags if (build_id) pakfire_package_dump_add_line(&string, _("Build ID"), build_id); + // Build Arches + const char** build_arches = pakfire_package_get_strings(pkg, PAKFIRE_PKG_BUILD_ARCHES); + if (build_arches) { + for (const char** build_arch = build_arches; *build_arch; build_arch++) + pakfire_package_dump_add_line(&string, _("Build Arch"), *build_arch); + + free(build_arches); + } + enum pakfire_digest_types digest_type = PAKFIRE_DIGEST_UNDEFINED; size_t digest_length = 0; @@ -1662,7 +1948,8 @@ static int _pakfire_package_add_json_dependencies( return 1; // Add dependencies - int r = pakfire_json_add_string_array(pkg->pakfire, json, name, dependencies); + int r = pakfire_json_add_string_array(pkg->pakfire, json, + name, (const char**)dependencies); if (r) goto ERROR; @@ -1938,6 +2225,16 @@ static int pakfire_package_add_build_metadata(struct pakfire_package* pkg, goto ERROR; } + // Write build arches + const char** build_arches = pakfire_package_get_strings(pkg, PAKFIRE_PKG_BUILD_ARCHES); + if (build_arches) { + r = pakfire_json_add_string_array(pkg->pakfire, object, "arches", build_arches); + free(build_arches); + + if (r) + goto ERROR; + } + // Source package name const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_NAME); if (name) { diff --git a/src/libpakfire/parser.c b/src/libpakfire/parser.c index 9ec3af6dd..6d0a1aa88 100644 --- a/src/libpakfire/parser.c +++ b/src/libpakfire/parser.c @@ -995,6 +995,7 @@ int pakfire_parser_create_package(struct pakfire_parser* parser, char* evr = NULL; char* arch = NULL; char* deps = NULL; + char* build_arches = NULL; DEBUG(parser->pakfire, "Building package from namespace '%s'\n", namespace); @@ -1098,6 +1099,16 @@ int pakfire_parser_create_package(struct pakfire_parser* parser, } } + // Add supported architectures + if (is_source) { + build_arches = pakfire_parser_get(parser, "build", "arches"); + if (build_arches) { + r = pakfire_package_set_strings_from_string(*pkg, PAKFIRE_PKG_BUILD_ARCHES, build_arches); + if (r) + goto CLEANUP; + } + } + // All okay r = 0; @@ -1113,6 +1124,8 @@ CLEANUP: free(arch); if (deps) free(deps); + if (build_arches) + free(build_arches); return r; } diff --git a/src/libpakfire/util.c b/src/libpakfire/util.c index 090be50e1..311d0e2d5 100644 --- a/src/libpakfire/util.c +++ b/src/libpakfire/util.c @@ -847,7 +847,7 @@ int pakfire_json_add_string(struct pakfire* pakfire, struct json_object* json, } int pakfire_json_add_string_array(struct pakfire* pakfire, struct json_object* json, - const char* name, char** array) { + const char* name, const char** array) { int r = 1; // Allocate a new array @@ -856,7 +856,7 @@ int pakfire_json_add_string_array(struct pakfire* pakfire, struct json_object* j goto ERROR; // Add all items on list to the array - for (char** item = array; *item; item++) { + for (const char** item = array; *item; item++) { r = json_object_array_add(object, json_object_new_string(*item)); if (r) goto ERROR; -- 2.39.5