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_
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_

View File

@ -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");
}