Commit b91f9406 authored by Natanael Copa's avatar Natanael Copa

add: support for virtual meta packages

implements 'apk add --virutal metaname dep1 dep2...' where metaname will
be an empy meta package with dep1 and dep2 as dependencies.

This is useful to prevent abuild to add each makedepend to world which
causes some headache when it comes to unintalling them after sucessful build.
parent 6db3bbd7
......@@ -17,6 +17,7 @@
struct add_ctx {
unsigned int open_flags;
const char *virtpkg;
};
static int add_parse(void *ctx, int optch, int optindex, const char *optarg)
......@@ -30,6 +31,9 @@ static int add_parse(void *ctx, int optch, int optindex, const char *optarg)
case 'u':
apk_flags |= APK_UPGRADE;
break;
case 't':
actx->virtpkg = optarg;
break;
default:
return -1;
}
......@@ -41,12 +45,33 @@ static int add_main(void *ctx, int argc, char **argv)
struct add_ctx *actx = (struct add_ctx *) ctx;
struct apk_database db;
struct apk_state *state = NULL;
struct apk_dependency_array *pkgs = NULL; /* list of pkgs to install */
struct apk_dependency_array *pkgs = NULL;
struct apk_package *virtpkg = NULL;
int i, r;
r = apk_db_open(&db, apk_root, actx->open_flags | APK_OPENF_WRITE);
if (r != 0)
return r;
if (actx->virtpkg) {
struct apk_dependency dep;
virtpkg = apk_pkg_new();
if (virtpkg == NULL) {
apk_error("Failed to allocate virtual meta package");
goto err;
}
virtpkg->name = apk_db_get_name(&db, APK_BLOB_STR(actx->virtpkg));
virtpkg->version = strdup("0");
virtpkg->description = strdup("virtual meta package");
dep = (struct apk_dependency) {
.name = virtpkg->name,
.version = virtpkg->version,
.result_mask = APK_VERSION_EQUAL,
};
dep.name->flags |= APK_NAME_TOPLEVEL | APK_NAME_VIRTUAL;
virtpkg = apk_db_pkg_add(&db, virtpkg);
apk_deps_add(&pkgs, &dep);
}
for (i = 0; i < argc; i++) {
struct apk_dependency dep;
......@@ -71,8 +96,12 @@ static int add_main(void *ctx, int argc, char **argv)
.result_mask = APK_DEPMASK_REQUIRE,
};
}
dep.name->flags |= APK_NAME_TOPLEVEL;
apk_deps_add(&pkgs, &dep);
if (virtpkg) {
apk_deps_add(&virtpkg->depends, &dep);
} else {
dep.name->flags |= APK_NAME_TOPLEVEL;
apk_deps_add(&pkgs, &dep);
}
}
state = apk_state_new(&db);
......@@ -95,11 +124,12 @@ err:
static struct option add_options[] = {
{ "initdb", no_argument, NULL, 0x10000 },
{ "upgrade", no_argument, NULL, 'u' },
{ "virtual", required_argument, NULL, 't' },
};
static struct apk_applet apk_add = {
.name = "add",
.usage = "[--initdb] [--upgrade|-u] apkname...",
.usage = "[--initdb] [--upgrade|-u] [--virtual metaname] apkname...",
.context_size = sizeof(struct add_ctx),
.num_options = ARRAY_SIZE(add_options),
.options = add_options,
......
......@@ -55,6 +55,7 @@ struct apk_db_dir_instance {
};
#define APK_NAME_TOPLEVEL 0x0001
#define APK_NAME_VIRTUAL 0x0002
struct apk_name {
apk_hash_node hash_node;
......@@ -120,6 +121,7 @@ int apk_db_write_config(struct apk_database *db);
void apk_db_close(struct apk_database *db);
struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *file);
struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg);
struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum);
struct apk_package *apk_db_get_file_owner(struct apk_database *db, apk_blob_t filename);
......
......@@ -349,7 +349,7 @@ static void apk_db_pkg_rdepends(struct apk_database *db, struct apk_package *pkg
}
}
static struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg)
struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg)
{
struct apk_package *idb;
......@@ -1229,35 +1229,16 @@ static void apk_db_purge_pkg(struct apk_database *db,
apk_pkg_set_state(db, pkg, APK_PKG_NOT_INSTALLED);
}
int apk_db_install_pkg(struct apk_database *db,
struct apk_package *oldpkg,
struct apk_package *newpkg,
apk_progress_cb cb, void *cb_ctx)
static int apk_db_unpack_pkg(struct apk_database *db,
struct apk_package *newpkg,
int upgrade, csum_t csum,
apk_progress_cb cb, void *cb_ctx)
{
struct apk_bstream *bs;
struct install_ctx ctx;
csum_t csum;
struct apk_bstream *bs;
char file[256];
int r, i;
if (fchdir(db->root_fd) < 0)
return errno;
/* Just purging? */
if (oldpkg != NULL && newpkg == NULL) {
r = apk_pkg_run_script(oldpkg, db->root_fd,
APK_SCRIPT_PRE_DEINSTALL);
if (r != 0)
return r;
apk_db_purge_pkg(db, oldpkg);
r = apk_pkg_run_script(oldpkg, db->root_fd,
APK_SCRIPT_POST_DEINSTALL);
return r;
}
int i;
/* Install the new stuff */
if (newpkg->filename == NULL) {
for (i = 0; i < APK_MAX_REPOS; i++)
if (newpkg->repos & BIT(i))
......@@ -1285,8 +1266,8 @@ int apk_db_install_pkg(struct apk_database *db,
ctx = (struct install_ctx) {
.db = db,
.pkg = newpkg,
.script = (oldpkg == NULL) ?
APK_SCRIPT_PRE_INSTALL : APK_SCRIPT_PRE_UPGRADE,
.script = upgrade ?
APK_SCRIPT_PRE_UPGRADE : APK_SCRIPT_PRE_INSTALL,
.cb = cb,
.cb_ctx = cb_ctx,
};
......@@ -1294,10 +1275,49 @@ int apk_db_install_pkg(struct apk_database *db,
goto err_close;
bs->close(bs, csum, NULL);
return 0;
err_close:
bs->close(bs, NULL, NULL);
return -1;
}
int apk_db_install_pkg(struct apk_database *db,
struct apk_package *oldpkg,
struct apk_package *newpkg,
apk_progress_cb cb, void *cb_ctx)
{
csum_t csum;
int r;
if (fchdir(db->root_fd) < 0)
return errno;
/* Just purging? */
if (oldpkg != NULL && newpkg == NULL) {
r = apk_pkg_run_script(oldpkg, db->root_fd,
APK_SCRIPT_PRE_DEINSTALL);
if (r != 0)
return r;
apk_db_purge_pkg(db, oldpkg);
r = apk_pkg_run_script(oldpkg, db->root_fd,
APK_SCRIPT_POST_DEINSTALL);
return r;
}
/* Install the new stuff */
if (!(newpkg->name->flags & APK_NAME_VIRTUAL)) {
r = apk_db_unpack_pkg(db, newpkg, (oldpkg == NULL), csum,
cb, cb_ctx);
if (r != 0)
return r;
}
apk_pkg_set_state(db, newpkg, APK_PKG_INSTALLED);
if (memcmp(csum, newpkg->csum, sizeof(csum)) != 0)
if (!(newpkg->name->flags & APK_NAME_VIRTUAL) &&
memcmp(csum, newpkg->csum, sizeof(csum)) != 0)
apk_warning("%s-%s: checksum does not match",
newpkg->name->name, newpkg->version);
......@@ -1312,7 +1332,4 @@ int apk_db_install_pkg(struct apk_database *db,
newpkg->name->name, newpkg->version);
}
return r;
err_close:
bs->close(bs, NULL, NULL);
return -1;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment