From f8cf7a0a0dfd6e84741d1bf28e575690cd376356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 2 May 2022 11:22:43 +0300 Subject: [PATCH] add: allow specifying a version for --virtual package fixes #10835 --- doc/apk-add.8.scd | 4 +++- src/app_add.c | 49 ++++++++++++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/doc/apk-add.8.scd b/doc/apk-add.8.scd index 3552095..7398946 100644 --- a/doc/apk-add.8.scd +++ b/doc/apk-add.8.scd @@ -42,7 +42,9 @@ following options: *-t, --virtual* _NAME_ Create virtual package _NAME_ with given dependencies. This new package will get the _packages_ as dependencies instead of _world_. Finally the - _NAME_ is added to _world_. + _NAME_ is added to _world_. An optional version specifier for the virtual + package can be given via syntax _NAME_=_VERSION_. The version defaults + to synthesized version based on time. One can use this to ensure that selected set of packages are installed, and later the temporary modification be undone with *apk-del*(8) _NAME_ diff --git a/src/app_add.c b/src/app_add.c index d12d2a3..d95cddd 100644 --- a/src/app_add.c +++ b/src/app_add.c @@ -81,32 +81,26 @@ static int non_repository_check(struct apk_database *db) return 1; } -static struct apk_package *create_virtual_package(struct apk_database *db, struct apk_name *name) +static struct apk_package *create_virtual_package(struct apk_database *db, struct apk_dependency *dep) { - char ver[32]; struct apk_package *virtpkg; struct apk_digest_ctx dctx; struct apk_digest d; - struct tm tm; - time_t now = time(NULL); pid_t pid = getpid(); - gmtime_r(&now, &tm); - strftime(ver, sizeof ver, "%Y%m%d.%H%M%S", &tm); - virtpkg = apk_pkg_new(); if (virtpkg == NULL) return 0; - virtpkg->name = name; - virtpkg->version = apk_atomize_dup(&db->atoms, APK_BLOB_STR(ver)); + virtpkg->name = dep->name; + virtpkg->version = dep->version; virtpkg->description = strdup("virtual meta package"); virtpkg->arch = apk_atomize(&db->atoms, APK_BLOB_STR("noarch")); virtpkg->repos |= BIT(APK_REPOSITORY_CACHED); apk_digest_ctx_init(&dctx, APK_DIGEST_SHA1); - apk_digest_ctx_update(&dctx, &tm, sizeof tm); apk_digest_ctx_update(&dctx, &pid, sizeof pid); apk_digest_ctx_update(&dctx, virtpkg->name->name, strlen(virtpkg->name->name) + 1); + apk_digest_ctx_update(&dctx, dep->version->ptr, dep->version->len); apk_digest_ctx_final(&dctx, &d); apk_digest_ctx_free(&dctx); apk_checksum_from_digest(&virtpkg->csum, &d); @@ -114,6 +108,17 @@ static struct apk_package *create_virtual_package(struct apk_database *db, struc return virtpkg; } +static apk_blob_t *generate_version(struct apk_database *db) +{ + char ver[32]; + struct tm tm; + time_t now = time(NULL); + + gmtime_r(&now, &tm); + strftime(ver, sizeof ver, "%Y%m%d.%H%M%S", &tm); + return apk_atomize_dup(&db->atoms, APK_BLOB_STR(ver)); +} + static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args) { struct apk_out *out = &ac->out; @@ -133,24 +138,32 @@ static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args if (actx->virtpkg) { apk_blob_t b = APK_BLOB_STR(actx->virtpkg); apk_blob_pull_dep(&b, db, &virtdep); + if (APK_BLOB_IS_NULL(b) || virtdep.conflict || - virtdep.result_mask != APK_DEPMASK_ANY || - virtdep.version != &apk_atom_null) { + (virtdep.name->name[0] != '.' && non_repository_check(db))) + goto bad_spec; + + switch (virtdep.result_mask) { + case APK_DEPMASK_ANY: + if (virtdep.version != &apk_atom_null) goto bad_spec; + virtdep.result_mask = APK_VERSION_EQUAL; + virtdep.version = generate_version(db); + break; + case APK_VERSION_EQUAL: + if (virtdep.version == &apk_atom_null) goto bad_spec; + break; + default: + bad_spec: apk_err(out, "%s: bad package specifier", actx->virtpkg); return -1; } - if (virtdep.name->name[0] != '.' && non_repository_check(db)) - return -1; - virtpkg = create_virtual_package(db, virtdep.name); + virtpkg = create_virtual_package(db, &virtdep); if (!virtpkg) { apk_err(out, "Failed to allocate virtual meta package"); return -1; } - virtdep.result_mask = APK_VERSION_EQUAL; - virtdep.version = virtpkg->version; - if (!args->num) apk_warn(out, "creating empty virtual package"); }