Add a cleanup command and DBus API

We sometimes talk about using `ostree admin undeploy`, but that
doesn't know about the pkgcache, and hence space there leaks
until the next rpm-ostree operation.

Just for this, we need to expose a cleanup command (and API).  But
we also need to support cleaning:

 - repomd
 - downloads (repo/tmp)

So let's start implementing that.

Closes: #614
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-02-08 17:38:49 -05:00 committed by Atomic Bot
parent 3c77b6e0a9
commit a66d27230d
14 changed files with 512 additions and 27 deletions

View File

@ -27,6 +27,7 @@ rpm_ostree_SOURCES = src/app/main.c \
src/app/rpmostree-builtin-rollback.c \
src/app/rpmostree-builtin-deploy.c \
src/app/rpmostree-builtin-rebase.c \
src/app/rpmostree-builtin-cleanup.c \
src/app/rpmostree-builtin-initramfs.c \
src/app/rpmostree-pkg-builtins.c \
src/app/rpmostree-builtin-status.c \

View File

@ -334,6 +334,35 @@ Boston, MA 02111-1307, USA.
</listitem>
</varlistentry>
<varlistentry>
<term><command>cleanup</command></term>
<listitem>
<para>
Commands such as <command>upgrade</command> create new deployments,
which affect the next boot, and take up additional storage space. In
some cases, you may want to undo and clean up these operations. This
command supports both removing additional deployments such as the
"pending" deployment (the next boot) as well as the default rollback
deployment. Use <option>-p/--pending</option> to remove the pending
deployment, and <option>-r/--rollback</option> to remove the
rollback.
</para>
<para>
The <option>-b/--base</option> option does not affect finished
deployments, but will clean up any transient allocated space that
may result from interrupted operations. If you want to free up disk
space safely, use this option first.
</para>
<para>
The <option>-m/--repomd</option> option cleans up cached RPM
repodata and any partially downloaded (but not imported) packages.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>initramfs</command></term>

View File

@ -37,6 +37,7 @@ static RpmOstreeCommand supported_commands[] = {
#ifdef HAVE_COMPOSE_TOOLING
{ "compose", rpmostree_builtin_compose },
#endif
{ "cleanup", rpmostree_builtin_cleanup },
{ "db", rpmostree_builtin_db },
{ "deploy", rpmostree_builtin_deploy },
{ "rebase", rpmostree_builtin_rebase },

View File

@ -0,0 +1,113 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2017 Colin Walters <walters@verbum.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the licence or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <glib-unix.h>
#include "rpmostree-builtins.h"
#include "rpmostree-util.h"
#include "rpmostree-libbuiltin.h"
#include "rpmostree-dbus-helpers.h"
#include <libglnx.h>
static char *opt_osname;
static gboolean opt_base;
static gboolean opt_pending;
static gboolean opt_rollback;
static gboolean opt_repomd;
static GOptionEntry option_entries[] = {
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" },
{ "base", 'b', 0, G_OPTION_ARG_NONE, &opt_base, "Clear temporary files; will leave deployments unchanged", NULL },
{ "pending", 'p', 0, G_OPTION_ARG_NONE, &opt_pending, "Remove pending deployment", NULL },
{ "rollback", 'r', 0, G_OPTION_ARG_NONE, &opt_rollback, "Remove rollback deployment", NULL },
{ "repomd", 'm', 0, G_OPTION_ARG_NONE, &opt_repomd, "Delete cached rpm repo metadata", NULL },
{ NULL }
};
int
rpmostree_builtin_cleanup (int argc,
char **argv,
GCancellable *cancellable,
GError **error)
{
int exit_status = EXIT_FAILURE;
g_autoptr(GOptionContext) context = g_option_context_new ("- Clear cached/pending data");
g_autoptr(GPtrArray) cleanup_types = g_ptr_array_new ();
glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL;
g_autofree char *transaction_address = NULL;
if (!rpmostree_option_context_parse (context,
option_entries,
&argc, &argv,
RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT,
cancellable,
&sysroot_proxy,
error))
goto out;
if (argc < 1 || argc > 2)
{
rpmostree_usage_error (context, "Too few or too many arguments", error);
goto out;
}
if (opt_base)
g_ptr_array_add (cleanup_types, "base");
if (opt_pending)
g_ptr_array_add (cleanup_types, "pending-deploy");
if (opt_rollback)
g_ptr_array_add (cleanup_types, "rollback-deploy");
if (opt_repomd)
g_ptr_array_add (cleanup_types, "repomd");
if (cleanup_types->len == 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "At least one cleanup option must be specified");
goto out;
}
g_ptr_array_add (cleanup_types, NULL);
if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname,
cancellable, &os_proxy, error))
goto out;
if (!rpmostree_os_call_cleanup_sync (os_proxy,
(const char *const*)cleanup_types->pdata,
&transaction_address,
cancellable,
error))
goto out;
if (!rpmostree_transaction_get_response_sync (sysroot_proxy,
transaction_address,
cancellable,
error))
goto out;
exit_status = EXIT_SUCCESS;
out:
/* Does nothing if using the message bus. */
rpmostree_cleanup_peer ();
return exit_status;
}

View File

@ -46,6 +46,7 @@ BUILTINPROTO(compose);
BUILTINPROTO(upgrade);
BUILTINPROTO(deploy);
BUILTINPROTO(rebase);
BUILTINPROTO(cleanup);
BUILTINPROTO(rollback);
BUILTINPROTO(initramfs);
BUILTINPROTO(status);

View File

@ -188,6 +188,11 @@
<arg type="s" name="transaction_address" direction="out"/>
</method>
<method name="Cleanup">
<arg type="as" name="elements" direction="in"/>
<arg type="s" name="transaction_address" direction="out"/>
</method>
</interface>
<interface name="org.projectatomic.rpmostree1.Transaction">

View File

@ -1162,7 +1162,7 @@ overlay_packages (RpmOstreeSysrootUpgrader *self,
* deployment, to ensure that upgrades work.
*/
static gboolean
get_base_commit_for_deployment (RpmOstreeSysrootUpgrader *self,
get_base_commit_for_deployment (OstreeRepo *repo,
OstreeDeployment *deployment,
char **out_base,
GError **error)
@ -1178,7 +1178,7 @@ get_base_commit_for_deployment (RpmOstreeSysrootUpgrader *self,
const char *csum = ostree_deployment_get_csum (deployment);
g_autofree char *base_rev = NULL;
if (!commit_get_parent_csum (self->repo, csum, &base_rev, error))
if (!commit_get_parent_csum (repo, csum, &base_rev, error))
return FALSE;
g_assert (base_rev);
@ -1197,7 +1197,8 @@ get_base_commit_for_deployment (RpmOstreeSysrootUpgrader *self,
* can always just re-pull it, but let's try to be nice).
**/
static gboolean
generate_baselayer_refs (RpmOstreeSysrootUpgrader *self,
generate_baselayer_refs (OstreeSysroot *sysroot,
OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
@ -1206,12 +1207,12 @@ generate_baselayer_refs (RpmOstreeSysrootUpgrader *self,
g_autoptr(GHashTable) bases =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
if (!ostree_repo_list_refs_ext (self->repo, "rpmostree/base", &refs,
if (!ostree_repo_list_refs_ext (repo, "rpmostree/base", &refs,
OSTREE_REPO_LIST_REFS_EXT_NONE,
cancellable, error))
goto out;
if (!ostree_repo_prepare_transaction (self->repo, NULL, cancellable, error))
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
goto out;
/* delete all the refs */
@ -1223,7 +1224,7 @@ generate_baselayer_refs (RpmOstreeSysrootUpgrader *self,
while (g_hash_table_iter_next (&it, &key, NULL))
{
const char *ref = key;
ostree_repo_transaction_set_refspec (self->repo, ref, NULL);
ostree_repo_transaction_set_refspec (repo, ref, NULL);
}
}
@ -1231,7 +1232,7 @@ generate_baselayer_refs (RpmOstreeSysrootUpgrader *self,
{
guint i = 0;
g_autoptr(GPtrArray) deployments =
ostree_sysroot_get_deployments (self->sysroot);
ostree_sysroot_get_deployments (sysroot);
/* existing deployments */
for (; i < deployments->len; i++)
@ -1239,7 +1240,7 @@ generate_baselayer_refs (RpmOstreeSysrootUpgrader *self,
OstreeDeployment *deployment = deployments->pdata[i];
g_autofree char *base_rev = NULL;
if (!get_base_commit_for_deployment (self, deployment,
if (!get_base_commit_for_deployment (repo, deployment,
&base_rev, error))
goto out;
if (base_rev)
@ -1258,16 +1259,16 @@ generate_baselayer_refs (RpmOstreeSysrootUpgrader *self,
{
const char *base = key;
g_autofree char *ref = g_strdup_printf ("rpmostree/base/%u", i++);
ostree_repo_transaction_set_refspec (self->repo, ref, base);
ostree_repo_transaction_set_refspec (repo, ref, base);
}
}
if (!ostree_repo_commit_transaction (self->repo, NULL, cancellable, error))
if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
goto out;
ret = TRUE;
out:
ostree_repo_abort_transaction (self->repo, cancellable, NULL);
ostree_repo_abort_transaction (repo, cancellable, NULL);
return ret;
}
@ -1308,13 +1309,14 @@ add_package_refs_to_set (RpmOstreeRefSack *rsack,
* that set.
*/
static gboolean
clean_pkgcache_orphans (RpmOstreeSysrootUpgrader *self,
clean_pkgcache_orphans (OstreeSysroot *sysroot,
OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
glnx_unref_object OstreeRepo *pkgcache_repo = NULL;
g_autoptr(GPtrArray) deployments =
ostree_sysroot_get_deployments (self->sysroot);
ostree_sysroot_get_deployments (sysroot);
g_autoptr(GHashTable) current_refs = NULL;
g_autoptr(GHashTable) referenced_pkgs = /* cache refs of packages we want to keep */
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@ -1325,7 +1327,7 @@ clean_pkgcache_orphans (RpmOstreeSysrootUpgrader *self,
guint64 freed_space;
guint n_freed = 0;
if (!get_pkgcache_repo (self->repo, &pkgcache_repo, cancellable, error))
if (!get_pkgcache_repo (repo, &pkgcache_repo, cancellable, error))
return FALSE;
for (guint i = 0; i < deployments->len; i++)
@ -1342,12 +1344,12 @@ clean_pkgcache_orphans (RpmOstreeSysrootUpgrader *self,
g_autoptr(RpmOstreeRefSack) rsack = NULL;
g_autofree char *deployment_dirpath = NULL;
deployment_dirpath = ostree_sysroot_get_deployment_dirpath (self->sysroot, deployment);
deployment_dirpath = ostree_sysroot_get_deployment_dirpath (sysroot, deployment);
/* We could do this via the commit object, but it's faster
* to reuse the existing rpmdb checkout.
*/
rsack = rpmostree_get_refsack_for_root (ostree_sysroot_get_fd (self->sysroot),
rsack = rpmostree_get_refsack_for_root (ostree_sysroot_get_fd (sysroot),
deployment_dirpath,
cancellable, error);
if (rsack == NULL)
@ -1392,26 +1394,38 @@ clean_pkgcache_orphans (RpmOstreeSysrootUpgrader *self,
return TRUE;
}
static gboolean
sysroot_upgrader_cleanup (RpmOstreeSysrootUpgrader *self,
GCancellable *cancellable,
GError **error)
/* Clean up to match the current deployments. This used to be a private static,
* but is now used by the cleanup txn.
*/
gboolean
rpmostree_sysroot_upgrader_cleanup (OstreeSysroot *sysroot,
OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
int repo_dfd = ostree_repo_get_dfd (repo); /* borrowed */
/* regenerate the baselayer refs in case we just kicked out an ancient layered
* deployment whose base layer is not needed anymore */
if (!generate_baselayer_refs (self, cancellable, error))
if (!generate_baselayer_refs (sysroot, repo, cancellable, error))
return FALSE;
/* Delete our temporary ref */
if (!ostree_repo_set_ref_immediate (self->repo, NULL, RPMOSTREE_TMP_BASE_REF,
if (!ostree_repo_set_ref_immediate (repo, NULL, RPMOSTREE_TMP_BASE_REF,
NULL, cancellable, error))
return FALSE;
/* and shake it loose */
if (!ostree_sysroot_cleanup (self->sysroot, cancellable, error))
if (!ostree_sysroot_cleanup (sysroot, cancellable, error))
return FALSE;
if (!clean_pkgcache_orphans (self, cancellable, error))
if (!clean_pkgcache_orphans (sysroot, repo, cancellable, error))
return FALSE;
/* delete our checkout dir in case a previous run didn't finish
successfully */
if (!glnx_shutil_rm_rf_at (repo_dfd, RPMOSTREE_TMP_ROOTFS_DIR,
cancellable, error))
return FALSE;
return TRUE;
@ -1483,7 +1497,7 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
cancellable, error))
goto out;
if (!sysroot_upgrader_cleanup (self, cancellable, error))
if (!rpmostree_sysroot_upgrader_cleanup (self->sysroot, self->repo, cancellable, error))
goto out;
ret = TRUE;

View File

@ -106,4 +106,11 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
GCancellable *cancellable,
GError **error);
gboolean
rpmostree_sysroot_upgrader_cleanup (OstreeSysroot *sysroot,
OstreeRepo *repo,
GCancellable *cancellable,
GError **error);
G_END_DECLS

View File

@ -806,6 +806,78 @@ out:
return TRUE;
}
static gboolean
os_handle_cleanup (RPMOSTreeOS *interface,
GDBusMethodInvocation *invocation,
const char *const*args)
{
RpmostreedOS *self = RPMOSTREED_OS (interface);
glnx_unref_object RpmostreedTransaction *transaction = NULL;
glnx_unref_object OstreeSysroot *ot_sysroot = NULL;
g_autoptr(GCancellable) cancellable = g_cancellable_new ();
RpmOstreeTransactionCleanupFlags flags = 0;
const char *osname;
GError *local_error = NULL;
transaction = merge_compatible_txn (self, invocation);
if (transaction)
goto out;
if (!rpmostreed_sysroot_load_state (rpmostreed_sysroot_get (),
cancellable,
&ot_sysroot,
NULL,
&local_error))
goto out;
osname = rpmostree_os_get_name (interface);
for (char **iter = (char**) args; iter && *iter; iter++)
{
const char *v = *iter;
if (strcmp (v, "base") == 0)
flags |= RPMOSTREE_TRANSACTION_CLEANUP_BASE;
else if (strcmp (v, "pending-deploy") == 0)
flags |= RPMOSTREE_TRANSACTION_CLEANUP_PENDING_DEPLOY;
else if (strcmp (v, "rollback-deploy") == 0)
flags |= RPMOSTREE_TRANSACTION_CLEANUP_ROLLBACK_DEPLOY;
else if (strcmp (v, "repomd") == 0)
flags |= RPMOSTREE_TRANSACTION_CLEANUP_REPOMD;
else
{
g_set_error (&local_error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid cleanup type: %s", v);
goto out;
}
}
transaction = rpmostreed_transaction_new_cleanup (invocation,
ot_sysroot,
osname,
flags,
cancellable,
&local_error);
if (transaction == NULL)
goto out;
rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction);
out:
if (local_error != NULL)
{
g_dbus_method_invocation_take_error (invocation, local_error);
}
else
{
const char *client_address;
client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_pkg_change (interface, invocation, client_address);
}
return TRUE;
}
static gboolean
os_handle_get_cached_rebase_rpm_diff (RPMOSTreeOS *interface,
GDBusMethodInvocation *invocation,
@ -1191,6 +1263,7 @@ rpmostreed_os_iface_init (RPMOSTreeOSIface *iface)
iface->handle_rebase = os_handle_rebase;
iface->handle_pkg_change = os_handle_pkg_change;
iface->handle_set_initramfs_state = os_handle_set_initramfs_state;
iface->handle_cleanup = os_handle_cleanup;
iface->handle_get_cached_rebase_rpm_diff = os_handle_get_cached_rebase_rpm_diff;
iface->handle_download_rebase_rpm_diff = os_handle_download_rebase_rpm_diff;
iface->handle_get_cached_deploy_rpm_diff = os_handle_get_cached_deploy_rpm_diff;

View File

@ -27,6 +27,7 @@
#include "rpmostreed-sysroot.h"
#include "rpmostree-sysroot-upgrader.h"
#include "rpmostree-util.h"
#include "rpmostree-core.h"
#include "rpmostreed-utils.h"
static gboolean
@ -954,3 +955,213 @@ rpmostreed_transaction_new_initramfs_state (GDBusMethodInvocation *invocation,
return (RpmostreedTransaction *) self;
}
/* ================================ Cleanup ================================ */
typedef struct {
RpmostreedTransaction parent;
char *osname;
RpmOstreeTransactionCleanupFlags flags;
} CleanupTransaction;
typedef RpmostreedTransactionClass CleanupTransactionClass;
GType cleanup_transaction_get_type (void);
G_DEFINE_TYPE (CleanupTransaction,
cleanup_transaction,
RPMOSTREED_TYPE_TRANSACTION)
static void
cleanup_transaction_finalize (GObject *object)
{
CleanupTransaction *self;
self = (CleanupTransaction *) object;
g_free (self->osname);
G_OBJECT_CLASS (cleanup_transaction_parent_class)->finalize (object);
}
static gboolean
remove_directory_content_if_exists (int dfd,
const char *path,
GCancellable *cancellable,
GError **error)
{
glnx_fd_close int fd = -1;
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
fd = glnx_opendirat_with_errno (dfd, path, TRUE);
if (fd < 0)
{
if (errno != ENOENT)
{
glnx_set_error_from_errno (error);
return FALSE;
}
}
else
{
if (!glnx_dirfd_iterator_init_take_fd (fd, &dfd_iter, error))
return FALSE;
fd = -1;
while (TRUE)
{
struct dirent *dent = NULL;
if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
return FALSE;
if (dent == NULL)
break;
if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error))
return FALSE;
}
}
return TRUE;
}
/* This is a bit like ostree_sysroot_simple_write_deployment() */
static GPtrArray *
get_filtered_deployments (OstreeSysroot *sysroot,
const char *osname,
gboolean cleanup_pending,
gboolean cleanup_rollback)
{
g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot);
g_autoptr(GPtrArray) new_deployments = g_ptr_array_new_with_free_func (g_object_unref);
OstreeDeployment *booted_deployment = NULL;
gboolean found_booted = FALSE;
booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
for (guint i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
/* Is this deployment booted? If so, note we're past the booted,
* and ensure it's added. */
if (booted_deployment != NULL &&
ostree_deployment_equal (deployment, booted_deployment))
{
found_booted = TRUE;
g_ptr_array_add (new_deployments, g_object_ref (deployment));
continue;
}
/* Is this deployment for a different osname? Keep it. */
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
{
g_ptr_array_add (new_deployments, g_object_ref (deployment));
continue;
}
/* Now, we may skip this deployment, i.e. GC it. */
if (!found_booted && cleanup_pending)
continue;
if (found_booted && cleanup_rollback)
continue;
/* Otherwise, add it */
g_ptr_array_add (new_deployments, g_object_ref (deployment));
}
if (new_deployments->len == deployments->len)
return NULL;
return g_steal_pointer (&new_deployments);
}
static gboolean
cleanup_transaction_execute (RpmostreedTransaction *transaction,
GCancellable *cancellable,
GError **error)
{
CleanupTransaction *self = (CleanupTransaction *) transaction;
OstreeSysroot *sysroot;
glnx_unref_object OstreeRepo *repo = NULL;
const gboolean cleanup_pending = (self->flags & RPMOSTREE_TRANSACTION_CLEANUP_PENDING_DEPLOY) > 0;
const gboolean cleanup_rollback = (self->flags & RPMOSTREE_TRANSACTION_CLEANUP_ROLLBACK_DEPLOY) > 0;
sysroot = rpmostreed_transaction_get_sysroot (transaction);
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
return FALSE;
if (cleanup_pending || cleanup_rollback)
{
g_autoptr(GPtrArray) new_deployments = get_filtered_deployments (sysroot, self->osname,
cleanup_pending,
cleanup_rollback);
if (new_deployments)
{
/* TODO - expose the skip cleanup flag in libostree, use it here */
if (!ostree_sysroot_write_deployments (sysroot, new_deployments, cancellable, error))
return FALSE;
/* And ensure we fall through to base cleanup */
self->flags |= RPMOSTREE_TRANSACTION_CLEANUP_BASE;
}
else
{
g_print ("Deployments unchanged.\n");
}
}
if (self->flags & RPMOSTREE_TRANSACTION_CLEANUP_BASE)
{
if (!rpmostree_sysroot_upgrader_cleanup (sysroot, repo, cancellable, error))
return FALSE;
}
if (self->flags & RPMOSTREE_TRANSACTION_CLEANUP_REPOMD)
{
if (!remove_directory_content_if_exists (AT_FDCWD, RPMOSTREE_CORE_CACHEDIR, cancellable, error))
return FALSE;
}
return TRUE;
}
static void
cleanup_transaction_class_init (CleanupTransactionClass *class)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (class);
object_class->finalize = cleanup_transaction_finalize;
class->execute = cleanup_transaction_execute;
}
static void
cleanup_transaction_init (CleanupTransaction *self)
{
}
RpmostreedTransaction *
rpmostreed_transaction_new_cleanup (GDBusMethodInvocation *invocation,
OstreeSysroot *sysroot,
const char *osname,
RpmOstreeTransactionCleanupFlags flags,
GCancellable *cancellable,
GError **error)
{
CleanupTransaction *self;
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
g_return_val_if_fail (OSTREE_IS_SYSROOT (sysroot), NULL);
self = g_initable_new (cleanup_transaction_get_type (),
cancellable, error,
"invocation", invocation,
"sysroot-path", gs_file_get_path_cached (ostree_sysroot_get_path (sysroot)),
NULL);
if (self != NULL)
{
self->osname = g_strdup (osname);
self->flags = flags;
}
return (RpmostreedTransaction *) self;
}

View File

@ -76,3 +76,18 @@ rpmostreed_transaction_new_initramfs_state (GDBusMethodInvocation *invocat
gboolean reboot,
GCancellable *cancellable,
GError **error);
typedef enum {
RPMOSTREE_TRANSACTION_CLEANUP_BASE = (1 << 0),
RPMOSTREE_TRANSACTION_CLEANUP_PENDING_DEPLOY = (1 << 1),
RPMOSTREE_TRANSACTION_CLEANUP_ROLLBACK_DEPLOY = (1 << 2),
RPMOSTREE_TRANSACTION_CLEANUP_REPOMD = (1 << 3),
} RpmOstreeTransactionCleanupFlags;
RpmostreedTransaction *
rpmostreed_transaction_new_cleanup (GDBusMethodInvocation *invocation,
OstreeSysroot *sysroot,
const char *osname,
RpmOstreeTransactionCleanupFlags flags,
GCancellable *cancellable,
GError **error);

View File

@ -340,8 +340,8 @@ rpmostree_context_new_system (GCancellable *cancellable,
* override this for testing. */
if (g_getenv("RPMOSTREE_USE_CACHED_METADATA") == NULL)
dnf_context_set_cache_age (self->hifctx, 0);
dnf_context_set_cache_dir (self->hifctx, "/var/cache/rpm-ostree/" RPMOSTREE_DIR_CACHE_REPOMD);
dnf_context_set_solv_dir (self->hifctx, "/var/cache/rpm-ostree/" RPMOSTREE_DIR_CACHE_SOLV);
dnf_context_set_cache_dir (self->hifctx, RPMOSTREE_CORE_CACHEDIR RPMOSTREE_DIR_CACHE_REPOMD);
dnf_context_set_solv_dir (self->hifctx, RPMOSTREE_CORE_CACHEDIR RPMOSTREE_DIR_CACHE_SOLV);
dnf_context_set_lock_dir (self->hifctx, "/run/rpm-ostree/" RPMOSTREE_DIR_LOCK);
dnf_context_set_user_agent (self->hifctx, PACKAGE_NAME "/" PACKAGE_VERSION);

View File

@ -26,6 +26,8 @@
#include "libglnx.h"
#define RPMOSTREE_CORE_CACHEDIR "/var/cache/rpm-ostree/"
#define RPMOSTREE_TYPE_CONTEXT (rpmostree_context_get_type ())
G_DECLARE_FINAL_TYPE (RpmOstreeContext, rpmostree_context, RPMOSTREE, CONTEXT, GObject)

View File

@ -77,3 +77,16 @@ vm_reboot
vm_assert_layered_pkg foo absent
echo "ok pkg foo removed"
vm_rpmostree cleanup -b
vm_assert_status_jq '.deployments|length == 2'
echo "ok baseline cleanup"
vm_rpmostree cleanup -r
vm_assert_status_jq '.deployments|length == 1'
vm_rpmostree cleanup -pr
vm_assert_status_jq '.deployments|length == 1'
vm_rpmostree pkg-add foo-1.0
vm_assert_status_jq '.deployments|length == 2'
vm_rpmostree cleanup -pr
vm_assert_status_jq '.deployments|length == 1'
echo "ok cleanup"