add: allow specifying a version for --virtual package

fixes #10835
cute-signatures
Timo Teräs 2022-05-02 11:22:43 +03:00
parent 44994a46d4
commit f8cf7a0a0d
2 changed files with 34 additions and 19 deletions

View File

@ -42,7 +42,9 @@ following options:
*-t, --virtual* _NAME_ *-t, --virtual* _NAME_
Create virtual package _NAME_ with given dependencies. This new package Create virtual package _NAME_ with given dependencies. This new package
will get the _packages_ as dependencies instead of _world_. Finally the 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, 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_ and later the temporary modification be undone with *apk-del*(8) _NAME_

View File

@ -81,32 +81,26 @@ static int non_repository_check(struct apk_database *db)
return 1; 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_package *virtpkg;
struct apk_digest_ctx dctx; struct apk_digest_ctx dctx;
struct apk_digest d; struct apk_digest d;
struct tm tm;
time_t now = time(NULL);
pid_t pid = getpid(); pid_t pid = getpid();
gmtime_r(&now, &tm);
strftime(ver, sizeof ver, "%Y%m%d.%H%M%S", &tm);
virtpkg = apk_pkg_new(); virtpkg = apk_pkg_new();
if (virtpkg == NULL) return 0; if (virtpkg == NULL) return 0;
virtpkg->name = name; virtpkg->name = dep->name;
virtpkg->version = apk_atomize_dup(&db->atoms, APK_BLOB_STR(ver)); virtpkg->version = dep->version;
virtpkg->description = strdup("virtual meta package"); virtpkg->description = strdup("virtual meta package");
virtpkg->arch = apk_atomize(&db->atoms, APK_BLOB_STR("noarch")); virtpkg->arch = apk_atomize(&db->atoms, APK_BLOB_STR("noarch"));
virtpkg->repos |= BIT(APK_REPOSITORY_CACHED); virtpkg->repos |= BIT(APK_REPOSITORY_CACHED);
apk_digest_ctx_init(&dctx, APK_DIGEST_SHA1); 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, &pid, sizeof pid);
apk_digest_ctx_update(&dctx, virtpkg->name->name, strlen(virtpkg->name->name) + 1); 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_final(&dctx, &d);
apk_digest_ctx_free(&dctx); apk_digest_ctx_free(&dctx);
apk_checksum_from_digest(&virtpkg->csum, &d); 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; 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) static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args)
{ {
struct apk_out *out = &ac->out; 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) { if (actx->virtpkg) {
apk_blob_t b = APK_BLOB_STR(actx->virtpkg); apk_blob_t b = APK_BLOB_STR(actx->virtpkg);
apk_blob_pull_dep(&b, db, &virtdep); apk_blob_pull_dep(&b, db, &virtdep);
if (APK_BLOB_IS_NULL(b) || virtdep.conflict || if (APK_BLOB_IS_NULL(b) || virtdep.conflict ||
virtdep.result_mask != APK_DEPMASK_ANY || (virtdep.name->name[0] != '.' && non_repository_check(db)))
virtdep.version != &apk_atom_null) { 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); apk_err(out, "%s: bad package specifier", actx->virtpkg);
return -1; 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) { if (!virtpkg) {
apk_err(out, "Failed to allocate virtual meta package"); apk_err(out, "Failed to allocate virtual meta package");
return -1; return -1;
} }
virtdep.result_mask = APK_VERSION_EQUAL;
virtdep.version = virtpkg->version;
if (!args->num) apk_warn(out, "creating empty virtual package"); if (!args->num) apk_warn(out, "creating empty virtual package");
} }