]> git.ipfire.org Git - pakfire.git/commitdiff
packages: Add support for build arches
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 26 Aug 2023 18:39:41 +0000 (18:39 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 26 Aug 2023 18:39:41 +0000 (18:39 +0000)
This requires that we add a new data type to packages to store a string
array.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/archive.c
src/libpakfire/include/pakfire/package.h
src/libpakfire/include/pakfire/util.h
src/libpakfire/package.c
src/libpakfire/parser.c
src/libpakfire/util.c

index 089f34d1b7b1b175438e85d63fc2c2558653dc28..4f7eab53ac6dbe8cb5dd0700f4890cae612f6623 100644 (file)
@@ -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) {
index f584eac5400c3f86d15dfe1bf0611f4e5948f526..1536a09c964d83bbc4e13434b93621311a6cbca5 100644 (file)
@@ -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);
index e5d32acd0e124834ce610f97809274a584635249..a2e48af1ec04b173901f49eea9b27df4264bd1c8 100644 (file)
@@ -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
 
index 50540cbc54c9c90eaf1bd6f531e7a5eae96fb5c9..0edd67477cc79ad9953e7a2427d302ebc4eb07b6 100644 (file)
@@ -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) {
index 9ec3af6dd28d7fa06bbf1b1c84dadf162e11ab22..6d0a1aa8849c407711807d0e15796b89d7660ad8 100644 (file)
@@ -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;
 }
index 090be50e19ef3137efc0bd5cceb665b29b77e9f5..311d0e2d504d6b6a940da53b69d619c2a6f5bd3b 100644 (file)
@@ -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;