app: support full offline operations with --cache-only
As Colin mentioned in #1035, the new `--cache-only` implemented only the rpmmd half of the story. Here we complete that story by also ensuring that when in cache-only mode, we don't download new ostree data nor new packages. We try to complete the requested operation with what we have. To do this, we add support for the same `SYNTHETIC` pull that was added in ostree[1] so that we don't actually pull, but still perform timestamp checking. On the pkgcache side, we disable all remote repos and instead insert all our cached RPMs into the `DnfSack`. Care is taken to still perform SHA256 verification for local pkg installs/replacements. [1] https://github.com/ostreedev/ostree/pull/642 Closes: #687 Closes: #1049 Approved by: cgwalters
This commit is contained in:
parent
cd3da57453
commit
b811eb61c0
@ -182,6 +182,12 @@ Boston, MA 02111-1307, USA.
|
||||
inspect the RPM diff, but do not actually create a new
|
||||
deployment.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<option>--cache-only</option> or <command>-C</command> to
|
||||
perform the operation without trying to download the target
|
||||
tree from the remote nor the latest packages.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -206,6 +212,12 @@ Boston, MA 02111-1307, USA.
|
||||
exit after printing the transaction rather than downloading
|
||||
the packages and creating a new deployment.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<option>--cache-only</option> or <command>-C</command> to
|
||||
perform the operation without trying to download the latest
|
||||
packages.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -265,6 +277,12 @@ Boston, MA 02111-1307, USA.
|
||||
to pick a remote name.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<option>--cache-only</option> or <command>-C</command> to
|
||||
perform the rebase without trying to download the target
|
||||
tree from the remote nor the latest packages.
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -350,6 +368,12 @@ Boston, MA 02111-1307, USA.
|
||||
available, without downloading it or performing a
|
||||
package-level diff.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<option>--cache-only</option> or <command>-C</command> to
|
||||
perform the upgrade without trying to download the latest
|
||||
tree from the remote nor the latest packages.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -40,7 +40,7 @@ static GOptionEntry option_entries[] = {
|
||||
* A --preview option would work for both commands if we wanted to
|
||||
* deprecate --check-diff. */
|
||||
{ "preview", 0, 0, G_OPTION_ARG_NONE, &opt_preview, "Just preview package differences", NULL },
|
||||
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not update repo metadata cache", NULL },
|
||||
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not download latest ostree and RPM data", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -43,7 +43,7 @@ static GOptionEntry option_entries[] = {
|
||||
{ "remote", 'm', 0, G_OPTION_ARG_STRING, &opt_remote, "Rebase to current branch name using REMOTE; may also be combined with --branch", "REMOTE" },
|
||||
{ "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Initiate a reboot after rebase is finished", NULL },
|
||||
{ "skip-purge", 0, 0, G_OPTION_ARG_NONE, &opt_skip_purge, "Keep previous refspec after rebase", NULL },
|
||||
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not update repo metadata cache", NULL },
|
||||
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not download latest ostree and RPM data", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -76,6 +76,7 @@ rpmostree_builtin_rollback (int argc,
|
||||
return EXIT_FAILURE;
|
||||
|
||||
g_autoptr(GVariant) previous_deployment = rpmostree_os_dup_default_deployment (os_proxy);
|
||||
/* really, rollback only supports the "reboot" option; all others are ignored */
|
||||
g_autoptr(GVariant) options =
|
||||
rpmostree_get_options_variant (opt_reboot,
|
||||
FALSE, /* allow-downgrade */
|
||||
|
@ -47,7 +47,7 @@ static GOptionEntry option_entries[] = {
|
||||
{ "check-diff", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_preview, "Check for upgrades and print package diff only", NULL },
|
||||
{ "preview", 0, 0, G_OPTION_ARG_NONE, &opt_preview, "Just preview package differences", NULL },
|
||||
{ "check", 0, 0, G_OPTION_ARG_NONE, &opt_check, "Just check if an upgrade is available", NULL },
|
||||
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not update repo metadata cache", NULL },
|
||||
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not download latest ostree and RPM data", NULL },
|
||||
{ "upgrade-unchanged-exit-77", 0, 0, G_OPTION_ARG_NONE, &opt_upgrade_unchanged_exit_77, "If no upgrade is available, exit 77", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
@ -1075,7 +1075,7 @@ rpmostree_get_options_variant (gboolean reboot,
|
||||
g_variant_dict_init (&dict, NULL);
|
||||
g_variant_dict_insert (&dict, "reboot", "b", reboot);
|
||||
g_variant_dict_insert (&dict, "allow-downgrade", "b", allow_downgrade);
|
||||
g_variant_dict_insert (&dict, "rpmmd-cache-only", "b", cache_only);
|
||||
g_variant_dict_insert (&dict, "cache-only", "b", cache_only);
|
||||
g_variant_dict_insert (&dict, "skip-purge", "b", skip_purge);
|
||||
g_variant_dict_insert (&dict, "no-pull-base", "b", no_pull_base);
|
||||
g_variant_dict_insert (&dict, "dry-run", "b", dry_run);
|
||||
|
@ -50,7 +50,7 @@ static GOptionEntry uninstall_option_entry[] = {
|
||||
|
||||
static GOptionEntry install_option_entry[] = {
|
||||
{ "uninstall", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_uninstall, "Uninstall a package", "PKG" },
|
||||
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not update repo metadata cache", NULL },
|
||||
{ "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Do not download latest ostree and RPM data", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -255,13 +255,14 @@
|
||||
Do not pull a base layer from the remote. Not valid if
|
||||
either "set-refspec" or "set-revision" is specified.
|
||||
"dry-run" (type 'b')
|
||||
Stop short of deploying the new tree. If
|
||||
layering packages, the pkg diff is printed.
|
||||
Stop short of deploying the new tree. If layering packages,
|
||||
the pkg diff is printed but packages are not downloaded or
|
||||
imported.
|
||||
"no-overrides" (type 'b')
|
||||
Remove all active overrides. Not valid if any override
|
||||
modifiers are specified.
|
||||
"rpmmd-cache-only" (type 'b')
|
||||
Do not update rpmmd repo metadata cache.
|
||||
"cache-only" (type 'b')
|
||||
Do not update rpmmd repo metadata cache or ostree refspec.
|
||||
-->
|
||||
<method name="UpdateDeployment">
|
||||
<arg type="a{sv}" name="modifiers" direction="in"/>
|
||||
|
@ -382,11 +382,13 @@ rpmostree_sysroot_upgrader_pull_base (RpmOstreeSysrootUpgrader *self,
|
||||
|
||||
const gboolean allow_older =
|
||||
(self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER) > 0;
|
||||
const gboolean synthetic =
|
||||
(self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_SYNTHETIC_PULL) > 0;
|
||||
|
||||
const char *override_commit = rpmostree_origin_get_override_commit (self->origin);
|
||||
|
||||
g_assert (self->origin_merge_deployment);
|
||||
if (origin_remote)
|
||||
if (origin_remote && !synthetic)
|
||||
{
|
||||
g_autoptr(GVariantBuilder) optbuilder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
||||
if (dir_to_pull && *dir_to_pull)
|
||||
@ -428,8 +430,8 @@ rpmostree_sysroot_upgrader_pull_base (RpmOstreeSysrootUpgrader *self,
|
||||
gboolean changed = !g_str_equal (new_base_rev, self->base_revision);
|
||||
if (changed)
|
||||
{
|
||||
/* check timestamps here too in case the commit was already pulled (or the
|
||||
* refspec is local) */
|
||||
/* check timestamps here too in case the commit was already pulled, or the pull was
|
||||
* synthetic, or the refspec is local */
|
||||
if (!allow_older)
|
||||
{
|
||||
if (!ostree_sysroot_upgrader_check_timestamps (self->repo, self->base_revision,
|
||||
@ -785,6 +787,10 @@ prepare_context_for_assembly (RpmOstreeSysrootUpgrader *self,
|
||||
return FALSE;
|
||||
|
||||
rpmostree_context_set_sepolicy (self->ctx, sepolicy);
|
||||
|
||||
if (self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGCACHE_ONLY)
|
||||
rpmostree_context_set_pkgcache_only (self->ctx, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -814,12 +820,6 @@ prep_local_assembly (RpmOstreeSysrootUpgrader *self,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_RPMMD_CACHE_ONLY)
|
||||
{
|
||||
DnfContext *hifctx = rpmostree_context_get_hif (self->ctx);
|
||||
dnf_context_set_cache_age (hifctx, G_MAXUINT);
|
||||
}
|
||||
|
||||
g_autoptr(OstreeRepo) pkgcache_repo = NULL;
|
||||
if (!rpmostree_get_pkgcache_repo (self->repo, &pkgcache_repo, cancellable, error))
|
||||
return FALSE;
|
||||
|
@ -41,7 +41,8 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (RpmOstreeSysrootUpgrader, g_object_unref)
|
||||
* @RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED: Do not error if the origin has an unconfigured-state key
|
||||
* @RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER: Do not error if the new deployment was composed earlier than the current deployment
|
||||
* @RPMOSTREE_SYSROOT_UPGRADER_FLAGS_DRY_RUN: Don't deploy new base. If layering packages, only print the transaction
|
||||
* @RPMOSTREE_SYSROOT_UPGRADER_FLAGS_DRY_RUN: Don't update rpmmd cache.
|
||||
* @RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGCACHE_ONLY: Don't try to update cached packages.
|
||||
* @RPMOSTREE_SYSROOT_UPGRADER_FLAGS_SYNTHETIC_PULL: Don't actually pull, just resolve ref and timestamp check
|
||||
*
|
||||
* Flags controlling operation of an #RpmOstreeSysrootUpgrader.
|
||||
*/
|
||||
@ -50,7 +51,8 @@ typedef enum {
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED = (1 << 1),
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER = (1 << 2),
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_DRY_RUN = (1 << 3),
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_RPMMD_CACHE_ONLY = (1 << 4)
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGCACHE_ONLY = (1 << 4),
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_SYNTHETIC_PULL = (1 << 5),
|
||||
} RpmOstreeSysrootUpgraderFlags;
|
||||
|
||||
/* _NONE means we're doing pure ostree, no client-side computation.
|
||||
|
@ -546,8 +546,8 @@ deploy_flags_from_options (GVariant *options,
|
||||
ret |= RPMOSTREE_TRANSACTION_DEPLOY_FLAG_DRY_RUN;
|
||||
if (vardict_lookup_bool (&dict, "no-overrides", FALSE))
|
||||
ret |= RPMOSTREE_TRANSACTION_DEPLOY_FLAG_NO_OVERRIDES;
|
||||
if (vardict_lookup_bool (&dict, "rpmmd-cache-only", FALSE))
|
||||
ret |= RPMOSTREE_TRANSACTION_DEPLOY_FLAG_RPMMD_CACHE_ONLY;
|
||||
if (vardict_lookup_bool (&dict, "cache-only", FALSE))
|
||||
ret |= RPMOSTREE_TRANSACTION_DEPLOY_FLAG_CACHE_ONLY;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -558,11 +558,20 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
|
||||
upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER;
|
||||
if (self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_DRY_RUN)
|
||||
upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_DRY_RUN;
|
||||
if (self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_RPMMD_CACHE_ONLY)
|
||||
upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_RPMMD_CACHE_ONLY;
|
||||
const gboolean no_overrides =
|
||||
((self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_NO_OVERRIDES) > 0);
|
||||
|
||||
if (self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_CACHE_ONLY)
|
||||
{
|
||||
/* practically, we could unite those two into a single flag, though it's nice to be
|
||||
* able to keep them separate as well */
|
||||
|
||||
/* don't pull, just resolve ref locally and timestamp check */
|
||||
upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_SYNTHETIC_PULL;
|
||||
/* turn on rpmmd cache only in the upgrader */
|
||||
upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGCACHE_ONLY;
|
||||
}
|
||||
|
||||
/* this should have been checked already */
|
||||
if (no_overrides)
|
||||
{
|
||||
@ -803,7 +812,10 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
|
||||
rpmostree_sysroot_upgrader_set_origin (upgrader, origin);
|
||||
|
||||
/* Mainly for the `install` and `override` commands */
|
||||
if (!(self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_NO_PULL_BASE))
|
||||
const gboolean no_pull_base =
|
||||
((self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_NO_PULL_BASE) > 0);
|
||||
|
||||
if (!no_pull_base)
|
||||
{
|
||||
gboolean base_changed;
|
||||
|
||||
|
@ -54,7 +54,7 @@ typedef enum {
|
||||
RPMOSTREE_TRANSACTION_DEPLOY_FLAG_NO_PULL_BASE = (1 << 4),
|
||||
RPMOSTREE_TRANSACTION_DEPLOY_FLAG_DRY_RUN = (1 << 5),
|
||||
RPMOSTREE_TRANSACTION_DEPLOY_FLAG_NO_OVERRIDES = (1 << 6),
|
||||
RPMOSTREE_TRANSACTION_DEPLOY_FLAG_RPMMD_CACHE_ONLY = (1 << 7),
|
||||
RPMOSTREE_TRANSACTION_DEPLOY_FLAG_CACHE_ONLY = (1 << 7),
|
||||
} RpmOstreeTransactionDeployFlags;
|
||||
|
||||
|
||||
|
@ -243,6 +243,7 @@ struct _RpmOstreeContext {
|
||||
|
||||
RpmOstreeTreespec *spec;
|
||||
gboolean empty;
|
||||
gboolean pkgcache_only;
|
||||
DnfContext *hifctx;
|
||||
OstreeRepo *ostreerepo;
|
||||
OstreeRepo *pkgcache_repo;
|
||||
@ -403,6 +404,15 @@ rpmostree_context_ensure_tmpdir (RpmOstreeContext *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
rpmostree_context_set_pkgcache_only (RpmOstreeContext *self,
|
||||
gboolean pkgcache_only)
|
||||
{
|
||||
/* if called, must always be before setup() */
|
||||
g_assert (!self->spec);
|
||||
self->pkgcache_only = pkgcache_only;
|
||||
}
|
||||
|
||||
/* Pick up repos dir and passwd from @cfg_deployment. */
|
||||
void
|
||||
rpmostree_context_configure_from_deployment (RpmOstreeContext *self,
|
||||
@ -600,13 +610,22 @@ rpmostree_context_setup (RpmOstreeContext *self,
|
||||
if (!dnf_context_setup (self->hifctx, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
/* NB: missing "repos" --> let hif figure it out for itself */
|
||||
if (g_variant_dict_lookup (self->spec->dict, "repos", "^a&s", &enabled_repos))
|
||||
if (!context_repos_enable_only (self, (const char *const*)enabled_repos, error))
|
||||
return FALSE;
|
||||
/* disable all repos in pkgcache-only mode, otherwise obey "repos" key */
|
||||
if (self->pkgcache_only)
|
||||
{
|
||||
if (!context_repos_enable_only (self, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NB: missing "repos" --> let hif figure it out for itself */
|
||||
if (g_variant_dict_lookup (self->spec->dict, "repos", "^a&s", &enabled_repos))
|
||||
if (!context_repos_enable_only (self, (const char *const*)enabled_repos, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_autoptr(GPtrArray) repos = get_enabled_rpmmd_repos (self->hifctx, DNF_REPO_ENABLED_PACKAGES);
|
||||
if (repos->len == 0)
|
||||
if (repos->len == 0 && !self->pkgcache_only)
|
||||
{
|
||||
/* To be nice, let's only make this fatal if "packages" is empty (e.g. if
|
||||
* we're only installing local RPMs. Missing deps will cause the regular
|
||||
@ -616,6 +635,7 @@ rpmostree_context_setup (RpmOstreeContext *self,
|
||||
g_strv_length (pkgs) > 0)
|
||||
return glnx_throw (error, "No enabled repositories");
|
||||
}
|
||||
|
||||
/* Ensure that each repo that's enabled is marked as required; this should be
|
||||
* the default, but we make sure. This is a bit of a messy topic, but for
|
||||
* rpm-ostree we're being more strict about requiring repos.
|
||||
@ -807,8 +827,7 @@ rpmostree_find_cache_branch_by_nevra (OstreeRepo *pkgcache,
|
||||
|
||||
g_autoptr(GHashTable) refs = NULL;
|
||||
if (!ostree_repo_list_refs_ext (pkgcache, "rpmostree/pkg", &refs,
|
||||
OSTREE_REPO_LIST_REFS_EXT_NONE, cancellable,
|
||||
error))
|
||||
OSTREE_REPO_LIST_REFS_EXT_NONE, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
GLNX_HASH_TABLE_FOREACH (refs, const char*, ref)
|
||||
@ -872,8 +891,7 @@ checkout_pkg_metadata_by_nevra (RpmOstreeContext *self,
|
||||
&header, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
return checkout_pkg_metadata (self, nevra, header,
|
||||
cancellable, error);
|
||||
return checkout_pkg_metadata (self, nevra, header, cancellable, error);
|
||||
}
|
||||
|
||||
/* Fetches decomposed NEVRA information from pkgcache for a given nevra string. Requires the
|
||||
@ -921,7 +939,21 @@ rpmostree_context_download_metadata (RpmOstreeContext *self,
|
||||
{
|
||||
g_assert (!self->empty);
|
||||
|
||||
g_autoptr(GPtrArray) rpmmd_repos = get_enabled_rpmmd_repos (self->hifctx, DNF_REPO_ENABLED_PACKAGES);
|
||||
g_autoptr(GPtrArray) rpmmd_repos =
|
||||
get_enabled_rpmmd_repos (self->hifctx, DNF_REPO_ENABLED_PACKAGES);
|
||||
|
||||
if (self->pkgcache_only)
|
||||
{
|
||||
g_assert_cmpint (rpmmd_repos->len, ==, 0);
|
||||
|
||||
/* this is essentially a no-op */
|
||||
g_autoptr(DnfState) hifstate = dnf_state_new ();
|
||||
if (!dnf_context_setup_sack (self->hifctx, hifstate, error))
|
||||
return FALSE;
|
||||
|
||||
/* Note early return; no repos to fetch. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_autoptr(GString) enabled_repos = g_string_new ("Enabled rpm-md repositories:");
|
||||
for (guint i = 0; i < rpmmd_repos->len; i++)
|
||||
@ -1507,7 +1539,8 @@ install_pkg_from_cache (RpmOstreeContext *self,
|
||||
/* This is the great lie: we make libdnf et al. think that they're dealing with a full
|
||||
* RPM, all while crossing our fingers that they don't try to look past the header.
|
||||
* Ideally, it would be best if libdnf could learn to treat the pkgcache repo as another
|
||||
* DnfRepo. */
|
||||
* DnfRepo. We could do this all in-memory though it doesn't seem like libsolv has an
|
||||
* appropriate API for this. */
|
||||
g_autofree char *rpm = g_strdup_printf ("%s/metarpm/%s.rpm", self->tmpdir.path, nevra);
|
||||
DnfPackage *pkg = dnf_sack_add_cmdline_package (dnf_context_get_sack (self->hifctx), rpm);
|
||||
if (!pkg)
|
||||
@ -1517,6 +1550,49 @@ install_pkg_from_cache (RpmOstreeContext *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This is a hacky way to bridge the gap between libdnf and our pkgcache. We extract the
|
||||
* metarpm for every RPM in our cache and present that as the cmdline repo to libdnf. But we
|
||||
* do still want all the niceties of the libdnf stack, e.g. HyGoal, libsolv depsolv, etc...
|
||||
*/
|
||||
static gboolean
|
||||
add_remaining_pkgcache_pkgs (RpmOstreeContext *self,
|
||||
GHashTable *already_added,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_assert (self->pkgcache_repo);
|
||||
g_assert (self->pkgcache_only);
|
||||
|
||||
DnfSack *sack = dnf_context_get_sack (self->hifctx);
|
||||
g_assert (sack);
|
||||
|
||||
g_autoptr(GHashTable) refs = NULL;
|
||||
if (!ostree_repo_list_refs_ext (self->pkgcache_repo, "rpmostree/pkg", &refs,
|
||||
OSTREE_REPO_LIST_REFS_EXT_NONE, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
GLNX_HASH_TABLE_FOREACH (refs, const char*, ref)
|
||||
{
|
||||
g_autofree char *nevra = rpmostree_cache_branch_to_nevra (ref);
|
||||
if (g_hash_table_contains (already_added, nevra))
|
||||
continue;
|
||||
|
||||
g_autoptr(GVariant) header = NULL;
|
||||
if (!get_header_variant (self->pkgcache_repo, ref, &header, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!checkout_pkg_metadata (self, nevra, header, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
g_autofree char *rpm = g_strdup_printf ("%s/metarpm/%s.rpm", self->tmpdir.path, nevra);
|
||||
DnfPackage *pkg = dnf_sack_add_cmdline_package (sack, rpm);
|
||||
if (!pkg)
|
||||
return glnx_throw (error, "Failed to add local pkg %s to sack", nevra);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check for/download new rpm-md, then depsolve */
|
||||
gboolean
|
||||
rpmostree_context_prepare (RpmOstreeContext *self,
|
||||
@ -1562,6 +1638,9 @@ rpmostree_context_prepare (RpmOstreeContext *self,
|
||||
g_ptr_array_add (removed_pkgnames, (gpointer)pkgname);
|
||||
}
|
||||
|
||||
/* track cached pkgs already added to the sack so far */
|
||||
g_autoptr(GHashTable) already_added = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
/* Handle packages to replace */
|
||||
g_autoptr(GPtrArray) replaced_nevras = g_ptr_array_new ();
|
||||
for (char **it = cached_replace_pkgs; it && *it; it++)
|
||||
@ -1575,6 +1654,7 @@ rpmostree_context_prepare (RpmOstreeContext *self,
|
||||
return FALSE;
|
||||
|
||||
g_ptr_array_add (replaced_nevras, (gpointer)nevra);
|
||||
g_hash_table_add (already_added, (gpointer)nevra);
|
||||
}
|
||||
|
||||
/* For each new local package, tell libdnf to add it to the goal */
|
||||
@ -1587,6 +1667,18 @@ rpmostree_context_prepare (RpmOstreeContext *self,
|
||||
|
||||
if (!install_pkg_from_cache (self, nevra, sha256, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_add (already_added, (gpointer)nevra);
|
||||
}
|
||||
|
||||
/* If we're in cache-only mode, add all the remaining pkgs now. We do this *after* the
|
||||
* replace & local pkgs since they already handle a subset of the cached pkgs and have
|
||||
* SHA256 checks. But we do it *before* dnf_context_install() since those subjects are not
|
||||
* directly linked to a cached pkg, so we need to teach libdnf about them beforehand. */
|
||||
if (self->pkgcache_only)
|
||||
{
|
||||
if (!add_remaining_pkgcache_pkgs (self, already_added, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Loop over each named package, and tell libdnf to add it to the goal */
|
||||
|
@ -44,6 +44,9 @@ RpmOstreeContext *rpmostree_context_new_tree (int basedir_dfd,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
void rpmostree_context_set_pkgcache_only (RpmOstreeContext *self,
|
||||
gboolean pkgcache_only);
|
||||
|
||||
DnfContext * rpmostree_context_get_hif (RpmOstreeContext *self);
|
||||
|
||||
RpmOstreeTreespec *rpmostree_treespec_new_from_keyfile (GKeyFile *keyfile, GError **error);
|
||||
|
@ -173,15 +173,12 @@ vm_build_rpm_repo_mode skip refresh-md-old-pkg
|
||||
vm_rpmostree refresh-md
|
||||
vm_build_rpm_repo_mode skip refresh-md-new-pkg
|
||||
vm_rpmostree refresh-md # shouldn't do anything since it hasn't expired yet
|
||||
if ! vm_rpmostree install -C refresh-md-old-pkg --dry-run; then
|
||||
assert_not_reached "failed to dry-run install old pkg from cached rpmmd"
|
||||
fi
|
||||
if vm_rpmostree install -C refresh-md-new-pkg --dry-run; then
|
||||
if vm_rpmostree install refresh-md-new-pkg --dry-run; then
|
||||
assert_not_reached "successfully dry-run installed new pkg from cached rpmmd?"
|
||||
fi
|
||||
vm_rpmostree refresh-md -f
|
||||
if ! vm_rpmostree install -C refresh-md-new-pkg --dry-run; then
|
||||
if ! vm_rpmostree install refresh-md-new-pkg --dry-run; then
|
||||
assert_not_reached "failed to dry-run install new pkg from cached rpmmd?"
|
||||
fi
|
||||
vm_stop_httpd vmcheck
|
||||
echo "ok refresh-md and --cache-only"
|
||||
echo "ok refresh-md"
|
||||
|
Loading…
Reference in New Issue
Block a user