pkglayering: Commit in base repo, not pkgcache
Currently, we do the final commit into the pkgcache repo, then pull it to the base. The problem with this is that, combined with the fact that we're not presently pruning the pkgcache repo, we leak space. In preparation for a cleaner fix for this, rework things so that the core infra can know about *both* a base repo and a pkgcache repo. If they're separate (as is the case for rpm-ostree-on-host), whenever we are doing layering, explicitly pull just the `.file` objects that are referenced into the parent repo. We do the final commit in the base repo. Closes: #437 Approved by: jlebon
This commit is contained in:
parent
accd2b9f6f
commit
35d84f7507
@ -1119,7 +1119,7 @@ overlay_final_pkgset (RpmOstreeSysrootUpgrader *self,
|
||||
if (!get_pkgcache_repo (repo, &pkgcache_repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
rpmostree_context_set_repo (ctx, pkgcache_repo);
|
||||
rpmostree_context_set_repos (ctx, repo, pkgcache_repo);
|
||||
|
||||
/* --- Downloading metadata --- */
|
||||
if (!rpmostree_context_download_metadata (ctx, cancellable, error))
|
||||
@ -1152,23 +1152,6 @@ overlay_final_pkgset (RpmOstreeSysrootUpgrader *self,
|
||||
if (!final_assembly (self, ctx, repo, base_rev, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* Send the final commit to the parent repo */
|
||||
{
|
||||
GFile *repo_path = ostree_repo_get_path (pkgcache_repo);
|
||||
g_autofree char *uri =
|
||||
g_strdup_printf ("file://%s", gs_file_get_path_cached (repo_path));
|
||||
|
||||
GVariantBuilder builder;
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&builder, "{s@v}", "refs", g_variant_new_variant
|
||||
(g_variant_new_strv ((const char * const*)&self->new_revision, 1)));
|
||||
|
||||
if (!ostree_repo_pull_with_options (repo, uri,
|
||||
g_variant_builder_end (&builder),
|
||||
NULL, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
|
@ -43,6 +43,8 @@
|
||||
#define RPMOSTREE_DIR_CACHE_SOLV "solv"
|
||||
#define RPMOSTREE_DIR_LOCK "lock"
|
||||
|
||||
static OstreeRepo * get_pkgcache_repo (RpmOstreeContext *self);
|
||||
|
||||
/***********************************************************
|
||||
* RpmOstreeTreespec *
|
||||
***********************************************************
|
||||
@ -281,6 +283,7 @@ struct _RpmOstreeContext {
|
||||
DnfContext *hifctx;
|
||||
GHashTable *ignore_scripts;
|
||||
OstreeRepo *ostreerepo;
|
||||
OstreeRepo *pkgcache_repo;
|
||||
gboolean unprivileged;
|
||||
char *dummy_instroot_path;
|
||||
OstreeSePolicy *sepolicy;
|
||||
@ -437,10 +440,18 @@ rpmostree_context_new_unprivileged (int basedir_dfd,
|
||||
|
||||
/* XXX: or put this in new_system() instead? */
|
||||
void
|
||||
rpmostree_context_set_repo (RpmOstreeContext *self,
|
||||
OstreeRepo *repo)
|
||||
rpmostree_context_set_repos (RpmOstreeContext *self,
|
||||
OstreeRepo *base_repo,
|
||||
OstreeRepo *pkgcache_repo)
|
||||
{
|
||||
g_set_object (&self->ostreerepo, repo);
|
||||
g_set_object (&self->ostreerepo, base_repo);
|
||||
g_set_object (&self->pkgcache_repo, pkgcache_repo);
|
||||
}
|
||||
|
||||
static OstreeRepo *
|
||||
get_pkgcache_repo (RpmOstreeContext *self)
|
||||
{
|
||||
return self->pkgcache_repo ? self->pkgcache_repo : self->ostreerepo;
|
||||
}
|
||||
|
||||
/* I debated making this part of the treespec. Overall, I think it makes more
|
||||
@ -996,7 +1007,7 @@ rpmostree_context_prepare_install (RpmOstreeContext *self,
|
||||
|
||||
rpmostree_output_task_end ("done");
|
||||
|
||||
if (!sort_packages (hifctx, self->ostreerepo, self->sepolicy,
|
||||
if (!sort_packages (hifctx, get_pkgcache_repo (self), self->sepolicy,
|
||||
ret_install, error))
|
||||
goto out;
|
||||
|
||||
@ -1159,7 +1170,7 @@ import_one_package (RpmOstreeContext *self,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
OstreeRepo *ostreerepo = self->ostreerepo;
|
||||
OstreeRepo *ostreerepo = get_pkgcache_repo (self);
|
||||
g_autofree char *ostree_commit = NULL;
|
||||
glnx_unref_object RpmOstreeUnpacker *unpacker = NULL;
|
||||
g_autofree char *pkg_path;
|
||||
@ -1229,7 +1240,7 @@ rpmostree_context_import (RpmOstreeContext *self,
|
||||
if (n == 0)
|
||||
return TRUE;
|
||||
|
||||
g_return_val_if_fail (self->ostreerepo != NULL, FALSE);
|
||||
g_return_val_if_fail (get_pkgcache_repo (self) != NULL, FALSE);
|
||||
|
||||
{
|
||||
glnx_unref_object DnfState *hifstate = dnf_state_new ();
|
||||
@ -1257,14 +1268,14 @@ rpmostree_context_import (RpmOstreeContext *self,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ostree_checkout_package (OstreeRepo *repo,
|
||||
DnfPackage *pkg,
|
||||
int dfd,
|
||||
const char *path,
|
||||
OstreeRepoDevInoCache *devino_cache,
|
||||
const char *pkg_commit,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
checkout_package (OstreeRepo *repo,
|
||||
DnfPackage *pkg,
|
||||
int dfd,
|
||||
const char *path,
|
||||
OstreeRepoDevInoCache *devino_cache,
|
||||
const char *pkg_commit,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
OstreeRepoCheckoutAtOptions opts = { OSTREE_REPO_CHECKOUT_MODE_USER,
|
||||
@ -1293,6 +1304,36 @@ ostree_checkout_package (OstreeRepo *repo,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
checkout_package_into_root (RpmOstreeContext *self,
|
||||
DnfPackage *pkg,
|
||||
int dfd,
|
||||
const char *path,
|
||||
OstreeRepoDevInoCache *devino_cache,
|
||||
const char *pkg_commit,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
OstreeRepo *pkgcache_repo = get_pkgcache_repo (self);
|
||||
|
||||
if (pkgcache_repo != self->ostreerepo)
|
||||
{
|
||||
if (!rpmostree_pull_content_only (self->ostreerepo, pkgcache_repo, pkg_commit,
|
||||
cancellable, error))
|
||||
{
|
||||
g_prefix_error (error, "Linking cached content for %s: ", dnf_package_get_nevra (pkg));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkout_package (pkgcache_repo, pkg, dfd, path,
|
||||
devino_cache, pkg_commit,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Given a path to a file/symlink, make a copy (reflink if possible)
|
||||
* of it if it's a hard link. We need this for two places right now:
|
||||
* - The RPM database
|
||||
@ -1577,8 +1618,8 @@ relabel_one_package (OstreeRepo *repo,
|
||||
|
||||
cache = ostree_repo_devino_cache_new ();
|
||||
|
||||
if (!ostree_checkout_package (repo, pkg, tmprootfs_dfd, ".", cache,
|
||||
commit_csum, cancellable, error))
|
||||
if (!checkout_package (repo, pkg, tmprootfs_dfd, ".", cache,
|
||||
commit_csum, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* This is where the magic happens. We traverse the tree and relabel stuff,
|
||||
@ -1675,13 +1716,14 @@ rpmostree_context_relabel (RpmOstreeContext *self,
|
||||
gboolean ret = FALSE;
|
||||
guint progress_sigid;
|
||||
int n = install->packages_to_relabel->len;
|
||||
OstreeRepo *ostreerepo = get_pkgcache_repo (self);
|
||||
|
||||
if (n == 0)
|
||||
return TRUE;
|
||||
|
||||
g_assert (self->sepolicy);
|
||||
|
||||
g_return_val_if_fail (self->ostreerepo != NULL, FALSE);
|
||||
g_return_val_if_fail (ostreerepo != NULL, FALSE);
|
||||
|
||||
{
|
||||
glnx_unref_object DnfState *hifstate = dnf_state_new ();
|
||||
@ -1696,7 +1738,7 @@ rpmostree_context_relabel (RpmOstreeContext *self,
|
||||
for (guint i = 0; i < install->packages_to_relabel->len; i++)
|
||||
{
|
||||
DnfPackage *pkg = install->packages_to_relabel->pdata[i];
|
||||
if (!relabel_one_package (self->ostreerepo, pkg, self->sepolicy,
|
||||
if (!relabel_one_package (ostreerepo, pkg, self->sepolicy,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
dnf_state_assert_done (hifstate);
|
||||
@ -1864,6 +1906,7 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
OstreeRepo *pkgcache_repo = get_pkgcache_repo (self);
|
||||
DnfContext *hifctx = self->hifctx;
|
||||
TransactionData tdata = { 0, -1 };
|
||||
rpmts ordering_ts = NULL;
|
||||
@ -1919,19 +1962,19 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
|
||||
{
|
||||
g_autofree char *branch_head_rev = NULL;
|
||||
|
||||
if (!ostree_repo_resolve_rev (self->ostreerepo, cachebranch, FALSE,
|
||||
if (!ostree_repo_resolve_rev (pkgcache_repo, cachebranch, FALSE,
|
||||
&branch_head_rev, error))
|
||||
goto out;
|
||||
|
||||
if (self->sepolicy == NULL)
|
||||
cached_rev = g_steal_pointer (&branch_head_rev);
|
||||
else if (!find_rev_with_sepolicy (self->ostreerepo, branch_head_rev,
|
||||
else if (!find_rev_with_sepolicy (pkgcache_repo, branch_head_rev,
|
||||
self->sepolicy, FALSE, &cached_rev,
|
||||
error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_repo_load_variant (self->ostreerepo, OSTREE_OBJECT_TYPE_COMMIT, cached_rev,
|
||||
if (!ostree_repo_load_variant (pkgcache_repo, OSTREE_OBJECT_TYPE_COMMIT, cached_rev,
|
||||
&pkg_commit, error))
|
||||
goto out;
|
||||
|
||||
@ -1990,11 +2033,11 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
|
||||
*/
|
||||
if (filesystem_package)
|
||||
{
|
||||
if (!ostree_checkout_package (self->ostreerepo, filesystem_package,
|
||||
tmprootfs_dfd, ".", devino_cache,
|
||||
g_hash_table_lookup (pkg_to_ostree_commit,
|
||||
filesystem_package),
|
||||
cancellable, error))
|
||||
if (!checkout_package_into_root (self, filesystem_package,
|
||||
tmprootfs_dfd, ".", devino_cache,
|
||||
g_hash_table_lookup (pkg_to_ostree_commit,
|
||||
filesystem_package),
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
@ -2007,11 +2050,11 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
|
||||
|
||||
g_assert (pkg);
|
||||
|
||||
if (!ostree_checkout_package (self->ostreerepo, pkg,
|
||||
tmprootfs_dfd, ".", devino_cache,
|
||||
g_hash_table_lookup (pkg_to_ostree_commit,
|
||||
pkg),
|
||||
cancellable, error))
|
||||
if (!checkout_package_into_root (self, pkg,
|
||||
tmprootfs_dfd, ".", devino_cache,
|
||||
g_hash_table_lookup (pkg_to_ostree_commit,
|
||||
pkg),
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2030,11 +2073,11 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
|
||||
if (pkg == filesystem_package)
|
||||
continue;
|
||||
|
||||
if (!ostree_checkout_package (self->ostreerepo, pkg,
|
||||
tmprootfs_dfd, ".", devino_cache,
|
||||
g_hash_table_lookup (pkg_to_ostree_commit,
|
||||
pkg),
|
||||
cancellable, error))
|
||||
if (!checkout_package_into_root (self, pkg,
|
||||
tmprootfs_dfd, ".", devino_cache,
|
||||
g_hash_table_lookup (pkg_to_ostree_commit,
|
||||
pkg),
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,9 @@ gboolean rpmostree_context_setup (RpmOstreeContext *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
void rpmostree_context_set_repo (RpmOstreeContext *self,
|
||||
OstreeRepo *repo);
|
||||
void rpmostree_context_set_repos (RpmOstreeContext *self,
|
||||
OstreeRepo *base_repo,
|
||||
OstreeRepo *pkgcache_repo);
|
||||
void rpmostree_context_set_sepolicy (RpmOstreeContext *self,
|
||||
OstreeSePolicy *sepolicy);
|
||||
void rpmostree_context_set_ignore_scripts (RpmOstreeContext *self,
|
||||
|
@ -530,3 +530,95 @@ rpmostree_str_replace (const char *buf,
|
||||
|
||||
return g_regex_replace_literal (regex, buf, -1, 0, new, 0, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pull_content_only_recurse (OstreeRepo *dest,
|
||||
OstreeRepo *src,
|
||||
OstreeRepoCommitTraverseIter *iter,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean done = FALSE;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
OstreeRepoCommitIterResult iterres =
|
||||
ostree_repo_commit_traverse_iter_next (iter, cancellable, error);
|
||||
|
||||
switch (iterres)
|
||||
{
|
||||
case OSTREE_REPO_COMMIT_ITER_RESULT_ERROR:
|
||||
return FALSE;
|
||||
case OSTREE_REPO_COMMIT_ITER_RESULT_END:
|
||||
done = TRUE;
|
||||
break;
|
||||
case OSTREE_REPO_COMMIT_ITER_RESULT_FILE:
|
||||
{
|
||||
char *name;
|
||||
char *checksum;
|
||||
|
||||
ostree_repo_commit_traverse_iter_get_file (iter, &name, &checksum);
|
||||
|
||||
if (!ostree_repo_import_object_from (dest, src, OSTREE_OBJECT_TYPE_FILE,
|
||||
checksum, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case OSTREE_REPO_COMMIT_ITER_RESULT_DIR:
|
||||
{
|
||||
char *name;
|
||||
char *content_checksum;
|
||||
char *meta_checksum;
|
||||
g_autoptr(GVariant) dirtree = NULL;
|
||||
ostree_cleanup_repo_commit_traverse_iter
|
||||
OstreeRepoCommitTraverseIter subiter = { 0, };
|
||||
|
||||
ostree_repo_commit_traverse_iter_get_dir (iter, &name, &content_checksum, &meta_checksum);
|
||||
|
||||
if (!ostree_repo_load_variant (src, OSTREE_OBJECT_TYPE_DIR_TREE,
|
||||
content_checksum, &dirtree,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (!ostree_repo_commit_traverse_iter_init_dirtree (&subiter, src, dirtree,
|
||||
OSTREE_REPO_COMMIT_TRAVERSE_FLAG_NONE,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (!pull_content_only_recurse (dest, src, &subiter, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Migrate only the content (.file) objects from src+src_commit into dest.
|
||||
* Used for package layering.
|
||||
*/
|
||||
gboolean
|
||||
rpmostree_pull_content_only (OstreeRepo *dest,
|
||||
OstreeRepo *src,
|
||||
const char *src_commit,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GVariant) commitdata = NULL;
|
||||
ostree_cleanup_repo_commit_traverse_iter
|
||||
OstreeRepoCommitTraverseIter iter = { 0, };
|
||||
|
||||
if (!ostree_repo_load_commit (src, src_commit, &commitdata, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
if (!ostree_repo_commit_traverse_iter_init_commit (&iter, src, commitdata,
|
||||
OSTREE_REPO_COMMIT_TRAVERSE_FLAG_NONE,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (!pull_content_only_recurse (dest, src, &iter, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -106,3 +106,11 @@ rpmostree_str_replace (const char *buf,
|
||||
const char *old,
|
||||
const char *new,
|
||||
GError **error);
|
||||
|
||||
|
||||
gboolean
|
||||
rpmostree_pull_content_only (OstreeRepo *dest,
|
||||
OstreeRepo *src,
|
||||
const char *src_commit,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
Loading…
Reference in New Issue
Block a user