From 10d00430636266d7bb70caacbd3e0642b3f70ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 21 Jan 2022 14:29:46 +0200 Subject: [PATCH] cache: allow various flags, and addition of dependencies Allow controlling 'cache download' more closely to 'upgrade' so it can be used to pre-download packages for ugprade. --- doc/apk-cache.8.scd | 28 ++++++++++++++++++----- src/app_cache.c | 54 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/doc/apk-cache.8.scd b/doc/apk-cache.8.scd index 1381d81..e5a9b6f 100644 --- a/doc/apk-cache.8.scd +++ b/doc/apk-cache.8.scd @@ -8,9 +8,9 @@ apk cache - manage a local cache of package files *apk cache* [<_options_>...] clean -*apk cache* [<_options_>...] download +*apk cache* [<_options_>...] download [_dependency_...] -*apk cache* [<_options_>...] sync +*apk cache* [<_options_>...] sync [_dependency_...] # DESCRIPTION @@ -18,16 +18,29 @@ Manage local package cache by removing obsolete packages, or downloading missing or newer packages from the repositories. *apk cache download* will fetch package files from the repositories and store -them in the cache, which must be enabled upfront (see *apk-cache*(5)). +them in the cache, which must be enabled upfront (see *apk-cache*(5)). By +default _world_ dependencies are used to determine what to download. If +_dependency_ arguments are given, they will by default replace the _world_. -*apk cache clean* will remove package files which are no longer necessary, -having been made obsolete by new versions or no longer being transitively -depended on by packages in _world_. +*apk cache clean* will remove package files which no longer exist in any +repository index. *apk cache sync* performs both operations. # OPTIONS +*--add-dependencies* + Add the argument dependencies to _world_ dependencies when determining + which packages to download. + +*-a, --available* + Selected packages to be downloaded from active repositories even if + it means replacing or downgrading the installed package. + +*--ignore-conflict* + Ignore conflicts when resolving dependencies. This can be useful when + pre-populating cache for creation of multiple images in one go. + *-l, --latest* Always choose the latest package by version. However, the versions considered are based on the package pinning. Primarily this overrides @@ -39,3 +52,6 @@ depended on by packages in _world_. avoid changing installed package unless it is required by the newly added _packages_ or their dependencies. This changes the default preference to upgrading the package to the latest installable version. + +*-s, --simulate* + Simulate the requested operation without making any changes. diff --git a/src/app_cache.c b/src/app_cache.c index 95eae7a..9f526cc 100644 --- a/src/app_cache.c +++ b/src/app_cache.c @@ -26,11 +26,16 @@ struct cache_ctx { unsigned short solver_flags; + int add_dependencies : 1; }; #define CACHE_OPTIONS(OPT) \ + OPT(OPT_CACHE_add_dependencies, "add-dependencies") \ + OPT(OPT_CACHE_available, APK_OPT_SH("a") "available") \ + OPT(OPT_CACHE_ignore_conflict, "ignore-conflict") \ OPT(OPT_CACHE_latest, APK_OPT_SH("l") "latest") \ - OPT(OPT_CACHE_upgrade, APK_OPT_SH("u") "upgrade") + OPT(OPT_CACHE_upgrade, APK_OPT_SH("u") "upgrade") \ + OPT(OPT_CACHE_simulate, APK_OPT_SH("s") "simulate") \ APK_OPT_APPLET(option_desc, CACHE_OPTIONS); @@ -39,12 +44,24 @@ static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const cha struct cache_ctx *cctx = (struct cache_ctx *) ctx; switch (opt) { - case OPT_CACHE_upgrade: - cctx->solver_flags |= APK_SOLVERF_UPGRADE; + case OPT_CACHE_add_dependencies: + cctx->add_dependencies = 1; + break; + case OPT_CACHE_available: + cctx->solver_flags |= APK_SOLVERF_AVAILABLE; + break; + case OPT_CACHE_ignore_conflict: + cctx->solver_flags |= APK_SOLVERF_IGNORE_CONFLICT; break; case OPT_CACHE_latest: cctx->solver_flags |= APK_SOLVERF_LATEST; break; + case OPT_CACHE_upgrade: + cctx->solver_flags |= APK_SOLVERF_UPGRADE; + break; + case OPT_CACHE_simulate: + ac->flags |= APK_SIMULATE; + break; default: return -ENOTSUP; } @@ -67,17 +84,32 @@ static void progress_cb(void *ctx, size_t bytes_done) apk_print_progress(&prog->prog, prog->done + bytes_done, prog->total); } -static int cache_download(struct cache_ctx *cctx, struct apk_database *db) +static int cache_download(struct cache_ctx *cctx, struct apk_database *db, struct apk_string_array *args) { struct apk_out *out = &db->ctx->out; struct apk_changeset changeset = {}; struct apk_change *change; struct apk_package *pkg; struct apk_repository *repo; + struct apk_dependency_array *deps; + struct apk_dependency dep; struct progress prog = { .prog = db->ctx->progress }; - int r, ret = 0; + int i, r, ret = 0; - r = apk_solver_solve(db, cctx->solver_flags, db->world, &changeset); + apk_dependency_array_init(&deps); + if (args->num == 1 || cctx->add_dependencies) + apk_dependency_array_copy(&deps, db->world); + for (i = 1; i < args->num; i++) { + apk_blob_t b = APK_BLOB_STR(args->item[i]); + apk_blob_pull_dep(&b, db, &dep); + if (APK_BLOB_IS_NULL(b)) { + apk_err(out, "bad dependency: %s", args->item[i]); + return -EINVAL; + } + *apk_dependency_array_add(&deps) = dep; + } + r = apk_solver_solve(db, cctx->solver_flags, deps, &changeset); + apk_dependency_array_free(&deps); if (r < 0) { apk_err(out, "Unable to select packages. Run apk fix."); return r; @@ -85,8 +117,10 @@ static int cache_download(struct cache_ctx *cctx, struct apk_database *db) foreach_array_item(change, changeset.changes) { pkg = change->new_pkg; - if ((pkg != NULL) && !(pkg->repos & db->local_repos)) - prog.total += pkg->size; + if (!pkg || (pkg->repos & db->local_repos) || !pkg->installed_size) + continue; + if (!apk_db_select_repo(db, pkg)) continue; + prog.total += pkg->size; } foreach_array_item(change, changeset.changes) { @@ -153,7 +187,7 @@ static int cache_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *ar char *arg; int r = 0, actions = 0; - if (args->num != 1) + if (args->num < 1) return -EINVAL; arg = args->item[0]; @@ -175,7 +209,7 @@ static int cache_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *ar if (r == 0 && (actions & CACHE_CLEAN)) r = cache_clean(db); if (r == 0 && (actions & CACHE_DOWNLOAD)) - r = cache_download(cctx, db); + r = cache_download(cctx, db, args); err: return r; }