pkg-add: New builtin to layer additional packages
This builds upon the earlier prototype in https://github.com/cgwalters/atomic-pkglayer The `.origin` file says for a replicated installation: [origin] refspec=local:rhel-atomic-host/7/x86_64/standard If you then run `rpm-ostree pkg-add strace`, it will result in a new tree with: [origin] baserefspec=local:rhel-atomic-host/7/x86_64/standard [packages] requested=strace; Work still remaining here is to teach `rpm-ostree status` and `rpm-ostree upgrade` about this. Closes: #289 Approved by: cgwalters
This commit is contained in:
parent
d9e8535bcf
commit
beb026f701
@ -29,6 +29,8 @@ librpmostreed_la_SOURCES = \
|
||||
src/daemon/rpmostreed-utils.c \
|
||||
src/daemon/rpmostreed-sysroot.h \
|
||||
src/daemon/rpmostreed-sysroot.c \
|
||||
src/daemon/rpmostree-sysroot-upgrader.h \
|
||||
src/daemon/rpmostree-sysroot-upgrader.c \
|
||||
src/daemon/rpmostreed-errors.h \
|
||||
src/daemon/rpmostreed-errors.c \
|
||||
src/daemon/rpmostreed-deployment-utils.h \
|
||||
@ -39,6 +41,7 @@ librpmostreed_la_SOURCES = \
|
||||
src/daemon/rpmostreed-transaction-monitor.c \
|
||||
src/daemon/rpmostreed-transaction-types.h \
|
||||
src/daemon/rpmostreed-transaction-types.c \
|
||||
src/daemon/rpmostreed-transaction-pkg-add.c \
|
||||
src/daemon/rpmostree-package-variants.h \
|
||||
src/daemon/rpmostree-package-variants.c \
|
||||
src/daemon/rpmostreed-os.h \
|
||||
|
@ -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-pkgadd.c \
|
||||
src/app/rpmostree-builtin-status.c \
|
||||
src/app/rpmostree-builtin-internals.c \
|
||||
src/app/rpmostree-builtin-container.c \
|
||||
|
@ -39,6 +39,7 @@ static RpmOstreeCommand commands[] = {
|
||||
#endif
|
||||
{ "db", rpmostree_builtin_db },
|
||||
{ "deploy", rpmostree_builtin_deploy },
|
||||
{ "pkg-add", rpmostree_builtin_pkg_add },
|
||||
{ "rebase", rpmostree_builtin_rebase },
|
||||
{ "rollback", rpmostree_builtin_rollback },
|
||||
{ "status", rpmostree_builtin_status },
|
||||
|
123
src/app/rpmostree-builtin-pkgadd.c
Normal file
123
src/app/rpmostree-builtin-pkgadd.c
Normal file
@ -0,0 +1,123 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2015 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 "rpmostree-builtins.h"
|
||||
#include "rpmostree-libbuiltin.h"
|
||||
#include "rpmostree-rpm-util.h"
|
||||
#include "rpmostree-dbus-helpers.h"
|
||||
|
||||
#include <libglnx.h>
|
||||
|
||||
static char *opt_osname;
|
||||
static gboolean opt_reboot;
|
||||
|
||||
static GOptionEntry option_entries[] = {
|
||||
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" },
|
||||
{ "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Initiate a reboot after upgrade is prepared", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static GVariant *
|
||||
new_floating_empty_gvariant_dict (void)
|
||||
{
|
||||
GVariantDict dict;
|
||||
g_variant_dict_init (&dict, NULL);
|
||||
return g_variant_dict_end (&dict);
|
||||
}
|
||||
|
||||
int
|
||||
rpmostree_builtin_pkg_add (int argc,
|
||||
char **argv,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
int exit_status = EXIT_FAILURE;
|
||||
GOptionContext *context;
|
||||
glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
|
||||
glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL;
|
||||
g_autoptr(GVariant) default_deployment = NULL;
|
||||
g_autofree char *transaction_address = NULL;
|
||||
int i;
|
||||
g_autoptr(GPtrArray) argv_and_null = g_ptr_array_new ();
|
||||
|
||||
context = g_option_context_new ("PACKAGE [PACKAGE...] - Download and install layered RPM packages");
|
||||
|
||||
if (!rpmostree_option_context_parse (context,
|
||||
option_entries,
|
||||
&argc, &argv,
|
||||
RPM_OSTREE_BUILTIN_FLAG_NONE,
|
||||
cancellable,
|
||||
&sysroot_proxy,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
rpmostree_usage_error (context, "At least one PACKAGE must be specified", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
g_ptr_array_add (argv_and_null, argv[i]);
|
||||
g_ptr_array_add (argv_and_null, NULL);
|
||||
|
||||
if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname,
|
||||
cancellable, &os_proxy, error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_os_call_pkg_add_sync (os_proxy,
|
||||
new_floating_empty_gvariant_dict (),
|
||||
(const char * const*)argv_and_null->pdata,
|
||||
&transaction_address,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_transaction_get_response_sync (sysroot_proxy,
|
||||
transaction_address,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (!opt_reboot)
|
||||
{
|
||||
const char *sysroot_path;
|
||||
|
||||
|
||||
sysroot_path = rpmostree_sysroot_get_path (sysroot_proxy);
|
||||
|
||||
if (!rpmostree_print_treepkg_diff_from_sysroot_path (sysroot_path,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
g_print ("Run \"systemctl reboot\" to start a reboot\n");
|
||||
}
|
||||
|
||||
exit_status = EXIT_SUCCESS;
|
||||
|
||||
out:
|
||||
/* Does nothing if using the message bus. */
|
||||
rpmostree_cleanup_peer ();
|
||||
|
||||
return exit_status;
|
||||
}
|
@ -50,6 +50,16 @@ printchar (char *s, int n)
|
||||
g_print ("\n");
|
||||
}
|
||||
|
||||
static char *
|
||||
format_layered_packages_plus (char **packages)
|
||||
{
|
||||
guint len = g_strv_length (packages);
|
||||
if (len > 0)
|
||||
return g_strdup_printf (" (+%u)", len);
|
||||
else
|
||||
return g_strdup ("");
|
||||
}
|
||||
|
||||
int
|
||||
rpmostree_builtin_status (int argc,
|
||||
char **argv,
|
||||
@ -126,6 +136,7 @@ rpmostree_builtin_status (int argc,
|
||||
if (!opt_pretty)
|
||||
{
|
||||
gchar *origin_refspec = NULL; /* borrowed */
|
||||
gchar **origin_packages = NULL; /* borrowed */
|
||||
gchar *os_name = NULL; /* borrowed */
|
||||
gchar *version_string = NULL; /* borrowed */
|
||||
|
||||
@ -143,7 +154,17 @@ rpmostree_builtin_status (int argc,
|
||||
max_version_len = MAX (max_version_len, strlen (version_string));
|
||||
|
||||
if (g_variant_dict_lookup (dict, "origin", "&s", &origin_refspec))
|
||||
max_refspec_len = MAX (max_refspec_len, strlen (origin_refspec));
|
||||
{
|
||||
if (g_variant_dict_lookup (dict, "packages", "^a&s", &origin_packages))
|
||||
{
|
||||
g_autofree gchar *origin_packages_plus =
|
||||
format_layered_packages_plus (origin_packages);
|
||||
|
||||
max_refspec_len = MAX (max_refspec_len, strlen (origin_refspec) + strlen (origin_packages_plus));
|
||||
}
|
||||
else
|
||||
max_refspec_len = MAX (max_refspec_len, strlen (origin_refspec));
|
||||
}
|
||||
}
|
||||
|
||||
g_variant_unref (child);
|
||||
@ -177,9 +198,11 @@ rpmostree_builtin_status (int argc,
|
||||
|
||||
gchar *id = NULL; /* borrowed */
|
||||
gchar *origin_refspec = NULL; /* borrowed */
|
||||
gchar **origin_packages = NULL; /* borrowed */
|
||||
gchar *os_name = NULL; /* borrowed */
|
||||
gchar *version_string = NULL; /* borrowed */
|
||||
gchar *checksum = NULL; /* borrowed */
|
||||
g_autofree gchar *origin_refspec_description = NULL;
|
||||
|
||||
guint64 t = 0;
|
||||
gint serial;
|
||||
@ -194,9 +217,21 @@ rpmostree_builtin_status (int argc,
|
||||
g_variant_dict_lookup (dict, "version", "s", &version_string);
|
||||
g_variant_dict_lookup (dict, "timestamp", "t", &t);
|
||||
g_variant_dict_lookup (dict, "origin", "s", &origin_refspec);
|
||||
g_variant_dict_lookup (dict, "packages", "^a&s", &origin_packages);
|
||||
signatures = g_variant_dict_lookup_value (dict, "signatures",
|
||||
G_VARIANT_TYPE ("av"));
|
||||
|
||||
if (origin_packages)
|
||||
{
|
||||
g_autofree gchar *origin_packages_plus =
|
||||
format_layered_packages_plus (origin_packages);
|
||||
origin_refspec_description = g_strconcat (origin_refspec, origin_packages_plus, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
origin_refspec_description = g_strdup (origin_refspec);
|
||||
}
|
||||
|
||||
is_booted = g_strcmp0 (booted_id, id) == 0;
|
||||
|
||||
timestamp = g_date_time_new_from_unix_utc (t);
|
||||
@ -221,7 +256,7 @@ rpmostree_builtin_status (int argc,
|
||||
g_print ("%-*s%-*s%-*s\n",
|
||||
max_id_len+buffer, truncated_csum,
|
||||
max_osname_len+buffer, os_name,
|
||||
max_refspec_len, origin_refspec);
|
||||
max_refspec_len, origin_refspec_description);
|
||||
}
|
||||
|
||||
/* print "pretty" row info */
|
||||
@ -229,6 +264,8 @@ rpmostree_builtin_status (int argc,
|
||||
{
|
||||
guint tab = 11;
|
||||
char *title = NULL;
|
||||
g_autofree char *packages_joined = g_strjoinv (" ", origin_packages);
|
||||
|
||||
if (i==0)
|
||||
title = "DEFAULT ON BOOT";
|
||||
else if (is_booted || n <= 2)
|
||||
@ -243,11 +280,12 @@ rpmostree_builtin_status (int argc,
|
||||
if (version_string)
|
||||
g_print (" %-*s%-*s\n", tab, "version", tab, version_string);
|
||||
|
||||
g_print (" %-*s%-*s\n %-*s%-*s.%d\n %-*s%-*s\n %-*s%-*s\n",
|
||||
g_print (" %-*s%-*s\n %-*s%-*s.%d\n %-*s%-*s\n %-*s%-*s\n %-*s%-*s\n",
|
||||
tab, "timestamp", tab, timestamp_string,
|
||||
tab, "id", tab, checksum, serial,
|
||||
tab, "osname", tab, os_name,
|
||||
tab, "refspec", tab, origin_refspec);
|
||||
tab, "refspec", tab, origin_refspec,
|
||||
tab, "packages", tab, packages_joined);
|
||||
|
||||
if (signatures != NULL)
|
||||
rpmostree_print_signatures (signatures, " GPG: ");
|
||||
|
@ -50,6 +50,7 @@ BUILTINPROTO(status);
|
||||
BUILTINPROTO(db);
|
||||
BUILTINPROTO(internals);
|
||||
BUILTINPROTO(container);
|
||||
BUILTINPROTO(pkg_add);
|
||||
|
||||
#undef BUILTINPROTO
|
||||
|
||||
|
@ -883,9 +883,27 @@ rpmostree_compose_builtin_tree (int argc,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_commit (yumroot, repo, self->ref, metadata, gpgkey, selinux,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
{ g_autofree char *new_revision = NULL;
|
||||
glnx_fd_close int rootfs_fd = -1;
|
||||
|
||||
if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (yumroot), TRUE,
|
||||
&rootfs_fd, error))
|
||||
goto out;
|
||||
|
||||
g_print ("Committing...\n");
|
||||
|
||||
if (!rpmostree_commit (rootfs_fd, repo, self->ref, metadata, gpgkey, selinux, NULL,
|
||||
&new_revision,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
g_print ("%s => %s\n", ref, new_revision);
|
||||
|
||||
if (!g_getenv ("RPM_OSTREE_PRESERVE_ROOTFS"))
|
||||
(void) glnx_shutil_rm_rf_at (AT_FDCWD, gs_file_get_path_cached (yumroot), cancellable, NULL);
|
||||
else
|
||||
g_print ("Preserved %s\n", gs_file_get_path_cached (yumroot));
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_touch_if_changed)
|
||||
|
@ -12,6 +12,7 @@
|
||||
'timestamp' (type 't')
|
||||
'origin' (type 's')
|
||||
'signatures' (type 'av')
|
||||
'packages' (type 'as')
|
||||
-->
|
||||
|
||||
<interface name="org.projectatomic.rpmostree1.Sysroot">
|
||||
@ -171,6 +172,12 @@
|
||||
<arg type="s" name="transaction_address" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="PkgAdd">
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<arg type="as" name="packages"/>
|
||||
<arg type="s" name="transaction_address" direction="out"/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name="org.projectatomic.rpmostree1.Transaction">
|
||||
|
564
src/daemon/rpmostree-sysroot-upgrader.c
Normal file
564
src/daemon/rpmostree-sysroot-upgrader.c
Normal file
@ -0,0 +1,564 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2015 Colin Walters <walters@verbum.org>
|
||||
*
|
||||
* This library 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 License, 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 <libglnx.h>
|
||||
#include "rpmostreed-utils.h"
|
||||
#include "rpmostree-util.h"
|
||||
|
||||
#include "rpmostree-sysroot-upgrader.h"
|
||||
|
||||
/**
|
||||
* SECTION:rpmostree-sysroot-upgrader
|
||||
* @title: Simple upgrade class
|
||||
* @short_description: Upgrade RPM+OSTree systems
|
||||
*
|
||||
* The #RpmOstreeSysrootUpgrader class models a `baserefspec` OSTree branch
|
||||
* in an origin file, along with a set of layered RPM packages.
|
||||
*
|
||||
* It also supports the plain-ostree "refspec" model.
|
||||
*/
|
||||
typedef struct {
|
||||
GObjectClass parent_class;
|
||||
} RpmOstreeSysrootUpgraderClass;
|
||||
|
||||
struct RpmOstreeSysrootUpgrader {
|
||||
GObject parent;
|
||||
|
||||
OstreeSysroot *sysroot;
|
||||
char *osname;
|
||||
RpmOstreeSysrootUpgraderFlags flags;
|
||||
|
||||
OstreeDeployment *merge_deployment;
|
||||
GKeyFile *origin;
|
||||
char *origin_refspec;
|
||||
char **requested_packages;
|
||||
char *override_csum;
|
||||
|
||||
char *new_revision;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
PROP_SYSROOT,
|
||||
PROP_OSNAME,
|
||||
PROP_FLAGS
|
||||
};
|
||||
|
||||
static void rpmostree_sysroot_upgrader_initable_iface_init (GInitableIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (RpmOstreeSysrootUpgrader, ostree_sysroot_upgrader, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, rpmostree_sysroot_upgrader_initable_iface_init))
|
||||
|
||||
static gboolean
|
||||
parse_refspec (RpmOstreeSysrootUpgrader *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autofree char *unconfigured_state = NULL;
|
||||
g_autofree char *csum = NULL;
|
||||
|
||||
if ((self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED) == 0)
|
||||
{
|
||||
/* If explicit action by the OS creator is requried to upgrade, print their text as an error */
|
||||
unconfigured_state = g_key_file_get_string (self->origin, "origin", "unconfigured-state", NULL);
|
||||
if (unconfigured_state)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"origin unconfigured-state: %s", unconfigured_state);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_rpmostree_util_parse_origin (self->origin, &self->origin_refspec, &self->requested_packages, error))
|
||||
goto out;
|
||||
|
||||
csum = g_key_file_get_string (self->origin, "origin", "override-commit", NULL);
|
||||
if (csum != NULL && !ostree_validate_checksum_string (csum, error))
|
||||
goto out;
|
||||
self->override_csum = g_steal_pointer (&csum);
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rpmostree_sysroot_upgrader_initable_init (GInitable *initable,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
RpmOstreeSysrootUpgrader *self = (RpmOstreeSysrootUpgrader*)initable;
|
||||
OstreeDeployment *booted_deployment =
|
||||
ostree_sysroot_get_booted_deployment (self->sysroot);
|
||||
|
||||
if (booted_deployment == NULL && self->osname == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Not currently booted into an OSTree system and no OS specified");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (self->osname == NULL)
|
||||
{
|
||||
g_assert (booted_deployment);
|
||||
self->osname = g_strdup (ostree_deployment_get_osname (booted_deployment));
|
||||
}
|
||||
else if (self->osname[0] == '\0')
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid empty osname");
|
||||
goto out;
|
||||
}
|
||||
|
||||
self->merge_deployment = ostree_sysroot_get_merge_deployment (self->sysroot, self->osname);
|
||||
if (self->merge_deployment == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No previous deployment for OS '%s'", self->osname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
self->origin = ostree_deployment_get_origin (self->merge_deployment);
|
||||
if (!self->origin)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No origin known for deployment %s.%d",
|
||||
ostree_deployment_get_csum (self->merge_deployment),
|
||||
ostree_deployment_get_deployserial (self->merge_deployment));
|
||||
goto out;
|
||||
}
|
||||
g_key_file_ref (self->origin);
|
||||
|
||||
if (!parse_refspec (self, cancellable, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
rpmostree_sysroot_upgrader_initable_iface_init (GInitableIface *iface)
|
||||
{
|
||||
iface->init = rpmostree_sysroot_upgrader_initable_init;
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_sysroot_upgrader_finalize (GObject *object)
|
||||
{
|
||||
RpmOstreeSysrootUpgrader *self = RPMOSTREE_SYSROOT_UPGRADER (object);
|
||||
|
||||
g_clear_object (&self->sysroot);
|
||||
g_free (self->osname);
|
||||
|
||||
g_clear_object (&self->merge_deployment);
|
||||
if (self->origin)
|
||||
g_key_file_unref (self->origin);
|
||||
g_free (self->origin_refspec);
|
||||
g_strfreev (self->requested_packages);
|
||||
g_free (self->override_csum);
|
||||
|
||||
G_OBJECT_CLASS (ostree_sysroot_upgrader_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_sysroot_upgrader_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
RpmOstreeSysrootUpgrader *self = RPMOSTREE_SYSROOT_UPGRADER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SYSROOT:
|
||||
self->sysroot = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_OSNAME:
|
||||
self->osname = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
self->flags = g_value_get_flags (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_sysroot_upgrader_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
RpmOstreeSysrootUpgrader *self = RPMOSTREE_SYSROOT_UPGRADER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SYSROOT:
|
||||
g_value_set_object (value, self->sysroot);
|
||||
break;
|
||||
case PROP_OSNAME:
|
||||
g_value_set_string (value, self->osname);
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
g_value_set_flags (value, self->flags);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_sysroot_upgrader_constructed (GObject *object)
|
||||
{
|
||||
RpmOstreeSysrootUpgrader *self = RPMOSTREE_SYSROOT_UPGRADER (object);
|
||||
|
||||
g_assert (self->sysroot != NULL);
|
||||
|
||||
G_OBJECT_CLASS (ostree_sysroot_upgrader_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_sysroot_upgrader_class_init (RpmOstreeSysrootUpgraderClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = ostree_sysroot_upgrader_constructed;
|
||||
object_class->get_property = ostree_sysroot_upgrader_get_property;
|
||||
object_class->set_property = ostree_sysroot_upgrader_set_property;
|
||||
object_class->finalize = ostree_sysroot_upgrader_finalize;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_SYSROOT,
|
||||
g_param_spec_object ("sysroot", "", "",
|
||||
OSTREE_TYPE_SYSROOT,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_OSNAME,
|
||||
g_param_spec_string ("osname", "", "", NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FLAGS,
|
||||
g_param_spec_flags ("flags", "", "",
|
||||
rpmostree_sysroot_upgrader_flags_get_type (),
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_sysroot_upgrader_init (RpmOstreeSysrootUpgrader *self)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rpmostree_sysroot_upgrader_new_for_os_with_flags:
|
||||
* @sysroot: An #OstreeSysroot
|
||||
* @osname: (allow-none): Operating system name
|
||||
* @flags: Flags
|
||||
*
|
||||
* Returns: (transfer full): An upgrader
|
||||
*/
|
||||
RpmOstreeSysrootUpgrader *
|
||||
rpmostree_sysroot_upgrader_new (OstreeSysroot *sysroot,
|
||||
const char *osname,
|
||||
RpmOstreeSysrootUpgraderFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return g_initable_new (RPMOSTREE_TYPE_SYSROOT_UPGRADER, cancellable, error,
|
||||
"sysroot", sysroot, "osname", osname, "flags", flags, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmostree_sysroot_upgrader_get_origin:
|
||||
* @self: Sysroot
|
||||
*
|
||||
* Returns: (transfer none): The origin file, or %NULL if unknown
|
||||
*/
|
||||
GKeyFile *
|
||||
rpmostree_sysroot_upgrader_get_origin (RpmOstreeSysrootUpgrader *self)
|
||||
{
|
||||
return self->origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_sysroot_upgrader_dup_origin:
|
||||
* @self: Sysroot
|
||||
*
|
||||
* Returns: (transfer full): A copy of the origin file, or %NULL if unknown
|
||||
*/
|
||||
GKeyFile *
|
||||
rpmostree_sysroot_upgrader_dup_origin (RpmOstreeSysrootUpgrader *self)
|
||||
{
|
||||
GKeyFile *copy = NULL;
|
||||
|
||||
g_return_val_if_fail (OSTREE_IS_SYSROOT_UPGRADER (self), NULL);
|
||||
|
||||
if (self->origin != NULL)
|
||||
{
|
||||
g_autofree char *data = NULL;
|
||||
gsize length = 0;
|
||||
|
||||
copy = g_key_file_new ();
|
||||
data = g_key_file_to_data (self->origin, &length, NULL);
|
||||
g_key_file_load_from_data (copy, data, length,
|
||||
G_KEY_FILE_KEEP_COMMENTS, NULL);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_sysroot_upgrader_set_origin:
|
||||
* @self: Sysroot
|
||||
* @origin: (allow-none): The new origin
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Replace the origin with @origin.
|
||||
*/
|
||||
gboolean
|
||||
rpmostree_sysroot_upgrader_set_origin (RpmOstreeSysrootUpgrader *self,
|
||||
GKeyFile *origin,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_clear_pointer (&self->origin, g_key_file_unref);
|
||||
if (origin)
|
||||
{
|
||||
self->origin = g_key_file_ref (origin);
|
||||
if (!parse_refspec (self, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
rpmostree_sysroot_upgrader_set_origin_rebase (RpmOstreeSysrootUpgrader *self, const char *new_refspec, GError **error)
|
||||
{
|
||||
g_free (self->origin_refspec);
|
||||
self->origin_refspec = g_strdup (new_refspec);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
rpmostree_sysroot_upgrader_set_origin_override (RpmOstreeSysrootUpgrader *self, const char *override_commit)
|
||||
{
|
||||
if (override_commit != NULL)
|
||||
g_key_file_set_string (self->origin, "origin", "override-commit", override_commit);
|
||||
else
|
||||
g_key_file_remove_key (self->origin, "origin", "override_commit", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
rpmostree_sysroot_upgrader_set_origin_baseref_local (RpmOstreeSysrootUpgrader *self, const char *local_commit)
|
||||
{
|
||||
self->new_revision = g_strdup (local_commit);
|
||||
}
|
||||
|
||||
const char *
|
||||
rpmostree_sysroot_upgrader_get_refspec (RpmOstreeSysrootUpgrader *self)
|
||||
{
|
||||
return self->origin_refspec;
|
||||
}
|
||||
|
||||
const char *const*
|
||||
rpmostree_sysroot_upgrader_get_packages (RpmOstreeSysrootUpgrader *self)
|
||||
{
|
||||
return (const char * const *)self->requested_packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmostree_sysroot_upgrader_get_origin_description:
|
||||
* @self: Upgrader
|
||||
*
|
||||
* Returns: A one-line descriptive summary of the origin, or %NULL if unknown
|
||||
*/
|
||||
char *
|
||||
rpmostree_sysroot_upgrader_get_origin_description (RpmOstreeSysrootUpgrader *self)
|
||||
{
|
||||
return g_strdup (rpmostree_sysroot_upgrader_get_refspec (self));
|
||||
}
|
||||
|
||||
/*
|
||||
* Like ostree_sysroot_upgrader_pull(), but will modify to include
|
||||
* layered packages.
|
||||
*/
|
||||
gboolean
|
||||
rpmostree_sysroot_upgrader_pull (RpmOstreeSysrootUpgrader *self,
|
||||
const char *dir_to_pull,
|
||||
OstreeRepoPullFlags flags,
|
||||
OstreeAsyncProgress *progress,
|
||||
gboolean *out_changed,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
char *refs_to_fetch[] = { NULL, NULL };
|
||||
const char *from_revision = NULL;
|
||||
g_autofree char *new_revision = NULL;
|
||||
g_autofree char *origin_remote = NULL;
|
||||
g_autofree char *origin_ref = NULL;
|
||||
|
||||
if (!ostree_parse_refspec (self->origin_refspec,
|
||||
&origin_remote,
|
||||
&origin_ref,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (self->override_csum != NULL)
|
||||
refs_to_fetch[0] = self->override_csum;
|
||||
else
|
||||
refs_to_fetch[0] = origin_ref;
|
||||
|
||||
if (!ostree_sysroot_get_repo (self->sysroot, &repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
g_assert (self->merge_deployment);
|
||||
from_revision = ostree_deployment_get_csum (self->merge_deployment);
|
||||
|
||||
if (origin_remote)
|
||||
{
|
||||
if (!ostree_repo_pull_one_dir (repo, origin_remote, dir_to_pull, refs_to_fetch,
|
||||
flags, progress,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (progress)
|
||||
ostree_async_progress_finish (progress);
|
||||
}
|
||||
|
||||
if (self->override_csum != NULL)
|
||||
{
|
||||
if (!ostree_repo_set_ref_immediate (repo,
|
||||
origin_remote,
|
||||
origin_ref,
|
||||
self->override_csum,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
self->new_revision = g_strdup (self->override_csum);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ostree_repo_resolve_rev (repo, self->origin_refspec, FALSE,
|
||||
&self->new_revision, error))
|
||||
goto out;
|
||||
|
||||
}
|
||||
|
||||
if (g_strcmp0 (from_revision, self->new_revision) == 0)
|
||||
{
|
||||
*out_changed = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gboolean allow_older = (self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER) > 0;
|
||||
|
||||
*out_changed = TRUE;
|
||||
|
||||
if (from_revision && !allow_older)
|
||||
{
|
||||
if (!ostree_sysroot_upgrader_check_timestamps (repo, from_revision,
|
||||
self->new_revision,
|
||||
error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmostree_sysroot_upgrader_deploy:
|
||||
* @self: Self
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Write the new deployment to disk, perform a configuration merge
|
||||
* with /etc, and update the bootloader configuration.
|
||||
*/
|
||||
gboolean
|
||||
rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
glnx_unref_object OstreeDeployment *new_deployment = NULL;
|
||||
|
||||
if (!ostree_sysroot_deploy_tree (self->sysroot, self->osname,
|
||||
self->new_revision,
|
||||
self->origin,
|
||||
self->merge_deployment,
|
||||
NULL,
|
||||
&new_deployment,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!ostree_sysroot_simple_write_deployment (self->sysroot, self->osname,
|
||||
new_deployment,
|
||||
self->merge_deployment,
|
||||
0,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
GType
|
||||
rpmostree_sysroot_upgrader_flags_get_type (void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&g_define_type_id__volatile))
|
||||
{
|
||||
static const GFlagsValue values[] = {
|
||||
{ RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED, "RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED", "ignore-unconfigured" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
GType g_define_type_id =
|
||||
g_flags_register_static (g_intern_static_string ("RpmOstreeSysrootUpgraderFlags"), values);
|
||||
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
|
||||
}
|
||||
|
||||
return g_define_type_id__volatile;
|
||||
}
|
92
src/daemon/rpmostree-sysroot-upgrader.h
Normal file
92
src/daemon/rpmostree-sysroot-upgrader.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2014 Colin Walters <walters@verbum.org>
|
||||
*
|
||||
* This library 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 License, 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostree.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define RPMOSTREE_TYPE_SYSROOT_UPGRADER ostree_sysroot_upgrader_get_type()
|
||||
#define RPMOSTREE_SYSROOT_UPGRADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), RPMOSTREE_TYPE_SYSROOT_UPGRADER, RpmOstreeSysrootUpgrader))
|
||||
#define RPMOSTREE_IS_SYSROOT_UPGRADER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), RPMOSTREE_TYPE_SYSROOT_UPGRADER))
|
||||
|
||||
typedef struct RpmOstreeSysrootUpgrader RpmOstreeSysrootUpgrader;
|
||||
|
||||
/**
|
||||
* RpmOstreeSysrootUpgraderPullFlags:
|
||||
* @RPMOSTREE_SYSROOT_UPGRADER_PULL_FLAGS_NONE: No options
|
||||
* @RPMOSTREE_SYSROOT_UPGRADER_PULL_FLAGS_IGNORE_UNCONFIGURED: Do not error if the origin has an unconfigured-state key
|
||||
*
|
||||
* Flags controlling operation of an #RpmOstreeSysrootUpgrader.
|
||||
*/
|
||||
typedef enum {
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_NONE = (1 << 0),
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED = (1 << 1),
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER = (1 << 2)
|
||||
} RpmOstreeSysrootUpgraderFlags;
|
||||
|
||||
GType rpmostree_sysroot_upgrader_get_type (void);
|
||||
|
||||
GType rpmostree_sysroot_upgrader_flags_get_type (void);
|
||||
|
||||
RpmOstreeSysrootUpgrader *rpmostree_sysroot_upgrader_new (OstreeSysroot *sysroot,
|
||||
const char *osname,
|
||||
RpmOstreeSysrootUpgraderFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
const char *rpmostree_sysroot_upgrader_get_refspec (RpmOstreeSysrootUpgrader *self);
|
||||
const char *const*rpmostree_sysroot_upgrader_get_packages (RpmOstreeSysrootUpgrader *self);
|
||||
|
||||
char * rpmostree_sysroot_upgrader_get_origin_description (RpmOstreeSysrootUpgrader *self);
|
||||
|
||||
GKeyFile *rpmostree_sysroot_upgrader_get_origin (RpmOstreeSysrootUpgrader *self);
|
||||
GKeyFile *rpmostree_sysroot_upgrader_dup_origin (RpmOstreeSysrootUpgrader *self);
|
||||
gboolean rpmostree_sysroot_upgrader_set_origin (RpmOstreeSysrootUpgrader *self, GKeyFile *origin,
|
||||
GCancellable *cancellable, GError **error);
|
||||
|
||||
gboolean
|
||||
rpmostree_sysroot_upgrader_pull (RpmOstreeSysrootUpgrader *self,
|
||||
const char *dir_to_pull,
|
||||
OstreeRepoPullFlags flags,
|
||||
OstreeAsyncProgress *progress,
|
||||
gboolean *out_changed,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean rpmostree_sysroot_upgrader_set_origin_rebase (RpmOstreeSysrootUpgrader *self, const char *new_refspec, GError **error);
|
||||
void rpmostree_sysroot_upgrader_set_origin_override (RpmOstreeSysrootUpgrader *self, const char *override_commit);
|
||||
void rpmostree_sysroot_upgrader_set_origin_baseref_local (RpmOstreeSysrootUpgrader *self, const char *local_commit);
|
||||
|
||||
|
||||
G_END_DECLS
|
@ -125,17 +125,36 @@ out:
|
||||
char *
|
||||
rpmostreed_deployment_get_refspec (OstreeDeployment *deployment)
|
||||
{
|
||||
GKeyFile *origin = NULL; /* owned by deployment */
|
||||
char *origin_refspec = NULL;
|
||||
rpmostreed_deployment_get_refspec_packages (deployment, &origin_refspec, NULL);
|
||||
return origin_refspec;
|
||||
}
|
||||
|
||||
void
|
||||
rpmostreed_deployment_get_refspec_packages (OstreeDeployment *deployment,
|
||||
char **out_refspec,
|
||||
char ***out_packages)
|
||||
{
|
||||
GKeyFile *origin = NULL; /* owned by deployment */
|
||||
gsize len;
|
||||
|
||||
g_return_if_fail (out_refspec != NULL);
|
||||
|
||||
origin = ostree_deployment_get_origin (deployment);
|
||||
|
||||
if (!origin)
|
||||
goto out;
|
||||
{
|
||||
*out_refspec = NULL;
|
||||
*out_packages = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
|
||||
*out_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
|
||||
if (!*out_refspec)
|
||||
*out_refspec = g_key_file_get_string (origin, "origin", "baserefspec", NULL);
|
||||
|
||||
out:
|
||||
return origin_refspec;
|
||||
if (out_packages)
|
||||
*out_packages = g_key_file_get_string_list (origin, "packages", "requested", &len, NULL);
|
||||
}
|
||||
|
||||
GVariant *
|
||||
@ -192,6 +211,7 @@ rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
|
||||
g_autoptr(GVariant) commit = NULL;
|
||||
|
||||
g_autofree gchar *origin_refspec = NULL;
|
||||
g_auto(GStrv) origin_packages = NULL;
|
||||
g_autofree gchar *id = NULL;
|
||||
|
||||
GVariant *sigs = NULL; /* floating variant */
|
||||
@ -203,7 +223,7 @@ rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
|
||||
gint serial = ostree_deployment_get_deployserial (deployment);
|
||||
id = rpmostreed_deployment_generate_id (deployment);
|
||||
|
||||
origin_refspec = rpmostreed_deployment_get_refspec (deployment);
|
||||
rpmostreed_deployment_get_refspec_packages (deployment, &origin_refspec, &origin_packages);
|
||||
if (origin_refspec)
|
||||
sigs = rpmostreed_deployment_gpg_results (repo, origin_refspec, csum);
|
||||
|
||||
@ -218,6 +238,8 @@ rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
|
||||
variant_add_commit_details (&dict, repo, csum);
|
||||
if (origin_refspec != NULL)
|
||||
g_variant_dict_insert (&dict, "origin", "s", origin_refspec);
|
||||
if (origin_packages != NULL)
|
||||
g_variant_dict_insert (&dict, "packages", "^as", origin_packages);
|
||||
if (sigs != NULL)
|
||||
g_variant_dict_insert_value (&dict, "signatures", sigs);
|
||||
|
||||
|
@ -30,6 +30,10 @@ OstreeDeployment *
|
||||
|
||||
char * rpmostreed_deployment_get_refspec (OstreeDeployment *deployment);
|
||||
|
||||
void rpmostreed_deployment_get_refspec_packages (OstreeDeployment *deployment,
|
||||
char **out_refspec,
|
||||
char ***out_packages);
|
||||
|
||||
GVariant * rpmostreed_deployment_generate_blank_variant (void);
|
||||
|
||||
GVariant * rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
|
||||
|
@ -705,6 +705,79 @@ out:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
os_handle_pkg_add (RPMOSTreeOS *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GVariant *arg_options,
|
||||
const char * const *arg_packages)
|
||||
{
|
||||
/* TODO: Totally ignoring arg_packages for now */
|
||||
RpmostreedOS *self = RPMOSTREED_OS (interface);
|
||||
glnx_unref_object RpmostreedTransaction *transaction = NULL;
|
||||
glnx_unref_object OstreeSysroot *ot_sysroot = NULL;
|
||||
glnx_unref_object GCancellable *cancellable = NULL;
|
||||
GVariantDict options_dict;
|
||||
const char *osname;
|
||||
gboolean opt_reboot = FALSE;
|
||||
GError *local_error = NULL;
|
||||
|
||||
/* If a compatible transaction is in progress, share its bus address. */
|
||||
transaction = rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor);
|
||||
if (transaction != NULL)
|
||||
{
|
||||
if (rpmostreed_transaction_is_compatible (transaction, invocation))
|
||||
goto out;
|
||||
|
||||
g_clear_object (&transaction);
|
||||
}
|
||||
|
||||
cancellable = g_cancellable_new ();
|
||||
|
||||
if (!rpmostreed_sysroot_load_state (rpmostreed_sysroot_get (),
|
||||
cancellable,
|
||||
&ot_sysroot,
|
||||
NULL,
|
||||
&local_error))
|
||||
goto out;
|
||||
|
||||
osname = rpmostree_os_get_name (interface);
|
||||
|
||||
/* XXX Fail if option type is wrong? */
|
||||
|
||||
g_variant_dict_init (&options_dict, arg_options);
|
||||
g_variant_dict_lookup (&options_dict,
|
||||
"reboot", "b",
|
||||
&opt_reboot);
|
||||
g_variant_dict_clear (&options_dict);
|
||||
|
||||
transaction = rpmostreed_transaction_new_pkg_add (invocation,
|
||||
ot_sysroot,
|
||||
osname,
|
||||
arg_packages,
|
||||
opt_reboot,
|
||||
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_add (interface, invocation, client_address);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
os_handle_get_cached_rebase_rpm_diff (RPMOSTreeOS *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
@ -1078,6 +1151,7 @@ rpmostreed_os_iface_init (RPMOSTreeOSIface *iface)
|
||||
iface->handle_rollback = os_handle_rollback;
|
||||
iface->handle_clear_rollback_target = os_handle_clear_rollback_target;
|
||||
iface->handle_rebase = os_handle_rebase;
|
||||
iface->handle_pkg_add = os_handle_pkg_add;
|
||||
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;
|
||||
|
525
src/daemon/rpmostreed-transaction-pkg-add.c
Normal file
525
src/daemon/rpmostreed-transaction-pkg-add.c
Normal file
@ -0,0 +1,525 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "ostree.h"
|
||||
|
||||
#include <libglnx.h>
|
||||
#include <rpm/rpmlib.h>
|
||||
#include <rpm/rpmlog.h>
|
||||
#include <rpm/rpmdb.h>
|
||||
#include <libhif.h>
|
||||
#include <libhif/hif-utils.h>
|
||||
#include <libgsystem.h>
|
||||
|
||||
#include "rpmostreed-transaction-types.h"
|
||||
#include "rpmostreed-transaction-types.h"
|
||||
#include "rpmostreed-transaction.h"
|
||||
#include "rpmostreed-deployment-utils.h"
|
||||
#include "rpmostreed-sysroot.h"
|
||||
#include "rpmostree-sysroot-upgrader.h"
|
||||
#include "rpmostreed-utils.h"
|
||||
#include "rpmostree-hif.h"
|
||||
#include "rpmostree-postprocess.h"
|
||||
#include "rpmostree-rpm-util.h"
|
||||
|
||||
typedef struct {
|
||||
RpmostreedTransaction parent;
|
||||
char *osname;
|
||||
char **packages;
|
||||
gboolean reboot;
|
||||
} PkgAddTransaction;
|
||||
|
||||
typedef RpmostreedTransactionClass PkgAddTransactionClass;
|
||||
|
||||
GType pkg_add_transaction_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (PkgAddTransaction,
|
||||
pkg_add_transaction,
|
||||
RPMOSTREED_TYPE_TRANSACTION)
|
||||
|
||||
static void
|
||||
pkg_add_transaction_finalize (GObject *object)
|
||||
{
|
||||
PkgAddTransaction *self;
|
||||
|
||||
self = (PkgAddTransaction *) object;
|
||||
g_free (self->osname);
|
||||
g_strfreev (self->packages);
|
||||
|
||||
G_OBJECT_CLASS (pkg_add_transaction_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
copy_dir_contents_nonrecurse_at (int src_dfd,
|
||||
const char *srcpath,
|
||||
int dest_dfd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { FALSE, };
|
||||
struct dirent *dent = NULL;
|
||||
|
||||
if (!glnx_dirfd_iterator_init_at (src_dfd, srcpath, TRUE,
|
||||
&dfd_iter, error))
|
||||
goto out;
|
||||
|
||||
while (glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
|
||||
{
|
||||
if (dent == NULL)
|
||||
break;
|
||||
if (!glnx_file_copy_at (dfd_iter.fd, dent->d_name, NULL, dest_dfd, dent->d_name, 0,
|
||||
cancellable, error))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Given a directory referred to by @dfd and @dirpath, ensure that
|
||||
* physical (or reflink'd) copies of all files are done.
|
||||
*/
|
||||
static gboolean
|
||||
break_hardlinks_at (int dfd,
|
||||
const char *dirpath,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
glnx_fd_close int dest_dfd = -1;
|
||||
g_autofree char *dirpath_tmp = g_strconcat (dirpath, ".tmp", NULL);
|
||||
|
||||
if (TEMP_FAILURE_RETRY (renameat (dfd, dirpath, dfd, dirpath_tmp)) != 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We're not accurately copying the mode, but in reality modes don't
|
||||
* matter since it's all immutable anyways.
|
||||
*/
|
||||
if (TEMP_FAILURE_RETRY (mkdirat (dfd, dirpath, 0755)) != 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!glnx_opendirat (dfd, dirpath, TRUE, &dest_dfd, error))
|
||||
goto out;
|
||||
|
||||
if (!copy_dir_contents_nonrecurse_at (dfd, dirpath_tmp, dest_dfd, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!glnx_shutil_rm_rf_at (dfd, dirpath_tmp, cancellable, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
on_hifstate_percentage_changed (HifState *hifstate,
|
||||
guint percentage,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *text = user_data;
|
||||
glnx_console_progress_text_percent (text, percentage);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
overlay_packages_in_deploydir (HifContext *hifctx,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
/* --- Run transaction --- */
|
||||
{ g_auto(GLnxConsoleRef) console = { 0, };
|
||||
glnx_unref_object HifState *hifstate = hif_state_new ();
|
||||
guint progress_sigid;
|
||||
|
||||
progress_sigid = g_signal_connect (hifstate, "percentage-changed",
|
||||
G_CALLBACK (on_hifstate_percentage_changed),
|
||||
"Installing: ");
|
||||
|
||||
glnx_console_lock (&console);
|
||||
|
||||
if (!hif_context_commit (hifctx, hifstate, error))
|
||||
goto out;
|
||||
|
||||
g_signal_handler_disconnect (hifstate, progress_sigid);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pkg_add_transaction_execute (RpmostreedTransaction *transaction,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
PkgAddTransaction *self;
|
||||
OstreeSysroot *sysroot;
|
||||
int sysroot_fd; /* Borrowed */
|
||||
OstreeRepoCheckoutOptions checkout_options = { 0, };
|
||||
|
||||
glnx_unref_object RpmOstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
glnx_unref_object OstreeDeployment *merge_deployment = NULL;
|
||||
glnx_unref_object OstreeDeployment *new_deployment = NULL;
|
||||
g_autofree char *merge_deployment_dirpath = NULL;
|
||||
g_autofree char *tmp_deploy_workdir_name = NULL;
|
||||
gboolean tmp_deploy_workdir_created = FALSE;
|
||||
g_autofree char *tmp_deploy_root_path = NULL;
|
||||
g_autofree char *new_revision = NULL;
|
||||
glnx_fd_close int merge_deployment_dirfd = -1;
|
||||
glnx_fd_close int ostree_repo_tmp_dirfd = -1;
|
||||
glnx_fd_close int deploy_tmp_dirfd = -1;
|
||||
g_autoptr(GKeyFile) origin = NULL;
|
||||
gs_unref_object HifContext *hifctx = NULL;
|
||||
g_autoptr(GHashTable) cur_origin_pkgrequests = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
g_autoptr(GHashTable) new_pkgrequests = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
g_autoptr(GHashTable) layer_new_packages = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
self = (PkgAddTransaction *) transaction;
|
||||
|
||||
sysroot = rpmostreed_transaction_get_sysroot (transaction);
|
||||
sysroot_fd = ostree_sysroot_get_fd (sysroot);
|
||||
|
||||
merge_deployment = ostree_sysroot_get_merge_deployment (sysroot, self->osname);
|
||||
if (merge_deployment == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No deployments found for osname %s", self->osname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
merge_deployment_dirpath = ostree_sysroot_get_deployment_dirpath (sysroot, merge_deployment);
|
||||
|
||||
if (!glnx_opendirat (sysroot_fd, merge_deployment_dirpath, TRUE,
|
||||
&merge_deployment_dirfd, error))
|
||||
goto out;
|
||||
|
||||
if (!glnx_opendirat (sysroot_fd, "ostree/repo/tmp", TRUE,
|
||||
&ostree_repo_tmp_dirfd, error))
|
||||
goto out;
|
||||
|
||||
upgrader = rpmostree_sysroot_upgrader_new (sysroot, self->osname, 0,
|
||||
cancellable, error);
|
||||
if (upgrader == NULL)
|
||||
goto out;
|
||||
|
||||
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
origin = rpmostree_sysroot_upgrader_dup_origin (upgrader);
|
||||
if (origin == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Booted deployment has no origin");
|
||||
goto out;
|
||||
}
|
||||
|
||||
{
|
||||
const char *cur_origin_refspec =
|
||||
rpmostree_sysroot_upgrader_get_refspec (upgrader);
|
||||
const char *const *cur_origin_packages =
|
||||
rpmostree_sysroot_upgrader_get_packages (upgrader);
|
||||
const char *const*strviter;
|
||||
|
||||
g_assert (cur_origin_refspec);
|
||||
|
||||
for (strviter = cur_origin_packages; strviter && *strviter; strviter++)
|
||||
{
|
||||
const char *pkg = *strviter;
|
||||
g_hash_table_add (cur_origin_pkgrequests, (char*)pkg);
|
||||
g_hash_table_add (new_pkgrequests, (char*)pkg);
|
||||
}
|
||||
|
||||
(void) g_key_file_remove_key (origin, "origin", "refspec", NULL);
|
||||
g_key_file_set_value (origin, "origin", "baserefspec", cur_origin_refspec);
|
||||
}
|
||||
|
||||
if (!rpmostree_sysroot_upgrader_set_origin (upgrader, origin, cancellable, error))
|
||||
goto out;
|
||||
|
||||
{
|
||||
char **iter = self->packages;
|
||||
g_autoptr(RpmOstreeRefSack) rsack = NULL;
|
||||
|
||||
rsack = rpmostree_get_refsack_for_root (sysroot_fd,
|
||||
merge_deployment_dirpath,
|
||||
cancellable, error);
|
||||
if (!rsack)
|
||||
goto out;
|
||||
|
||||
for (; iter && *iter; iter++)
|
||||
{
|
||||
const char *desired_pkg = *iter;
|
||||
_cleanup_hyquery_ HyQuery query = NULL;
|
||||
_cleanup_hypackagelist_ HyPackageList pkglist = NULL;
|
||||
|
||||
if (g_hash_table_contains (cur_origin_pkgrequests, desired_pkg))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Package '%s' is already requested", desired_pkg);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* It's now requested */
|
||||
g_hash_table_add (new_pkgrequests, (char*)desired_pkg);
|
||||
|
||||
query = hy_query_create (rsack->sack);
|
||||
hy_query_filter (query, HY_PKG_NAME, HY_EQ, desired_pkg);
|
||||
hy_query_filter (query, HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME);
|
||||
pkglist = hy_query_run (query);
|
||||
|
||||
/* This one tracks whether it actually needs to be installed */
|
||||
if (hy_packagelist_count (pkglist) == 0)
|
||||
g_hash_table_add (layer_new_packages, (char*)desired_pkg);
|
||||
}
|
||||
}
|
||||
|
||||
hifctx = _rpmostree_libhif_new_default ();
|
||||
{
|
||||
g_autofree char *reposdir =
|
||||
g_build_filename (merge_deployment_dirpath, "etc/yum.repos.d", NULL);
|
||||
hif_context_set_repo_dir (hifctx, reposdir);
|
||||
}
|
||||
|
||||
tmp_deploy_workdir_name = g_strdup ("rpmostree-deploy-XXXXXX");
|
||||
if (!glnx_mkdtempat (ostree_repo_tmp_dirfd, tmp_deploy_workdir_name, 0755, error))
|
||||
goto out;
|
||||
tmp_deploy_workdir_created = TRUE;
|
||||
|
||||
tmp_deploy_root_path = g_strconcat (tmp_deploy_workdir_name, "root", NULL);
|
||||
|
||||
checkout_options.devino_to_csum_cache = ostree_repo_devino_cache_new ();
|
||||
|
||||
if (!ostree_repo_checkout_tree_at (repo, &checkout_options, ostree_repo_tmp_dirfd, tmp_deploy_root_path,
|
||||
ostree_deployment_get_csum (merge_deployment),
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!glnx_opendirat (ostree_repo_tmp_dirfd, tmp_deploy_root_path, TRUE,
|
||||
&deploy_tmp_dirfd, error))
|
||||
goto out;
|
||||
|
||||
/* Convert usr/share/rpm into physical copies, as librpm mutates it in place */
|
||||
if (!break_hardlinks_at (deploy_tmp_dirfd, "usr/share/rpm", cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* Temporarily rename /usr/etc to /etc so that RPMs can drop new files there */
|
||||
if (TEMP_FAILURE_RETRY (renameat (deploy_tmp_dirfd, "usr/etc",
|
||||
deploy_tmp_dirfd, "etc")) != 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
{ g_autofree char *tmp_deploy_abspath = glnx_fdrel_abspath (deploy_tmp_dirfd, ".");
|
||||
hif_context_set_install_root (hifctx, tmp_deploy_abspath);
|
||||
}
|
||||
|
||||
/* Note this path is relative to the install root */
|
||||
hif_context_set_rpm_macro (hifctx, "_dbpath", "/usr/share/rpm");
|
||||
|
||||
if (!_rpmostree_libhif_setup (hifctx, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (g_hash_table_size (layer_new_packages) > 0)
|
||||
{
|
||||
HifTransaction *hiftx;
|
||||
HyGoal goal;
|
||||
GHashTableIter hashiter;
|
||||
gpointer hkey, hvalue;
|
||||
|
||||
/* --- Downloading metadata --- */
|
||||
{ g_auto(GLnxConsoleRef) console = { 0, };
|
||||
glnx_unref_object HifState *hifstate = hif_state_new ();
|
||||
guint progress_sigid;
|
||||
|
||||
progress_sigid = g_signal_connect (hifstate, "percentage-changed",
|
||||
G_CALLBACK (on_hifstate_percentage_changed),
|
||||
"Downloading: ");
|
||||
|
||||
glnx_console_lock (&console);
|
||||
|
||||
if (!hif_context_setup_sack (hifctx, hifstate, error))
|
||||
goto out;
|
||||
|
||||
g_signal_handler_disconnect (hifstate, progress_sigid);
|
||||
}
|
||||
|
||||
hiftx = hif_context_get_transaction (hifctx);
|
||||
|
||||
g_hash_table_iter_init (&hashiter, layer_new_packages);
|
||||
while (g_hash_table_iter_next (&hashiter, &hkey, &hvalue))
|
||||
{
|
||||
const char *pkg = hkey;
|
||||
|
||||
if (!hif_context_install (hifctx, pkg, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
goal = hif_context_get_goal (hifctx);
|
||||
|
||||
if (!hif_transaction_depsolve (hiftx, goal, NULL, error))
|
||||
goto out;
|
||||
|
||||
/* --- Downloading packages --- */
|
||||
{ g_auto(GLnxConsoleRef) console = { 0, };
|
||||
glnx_unref_object HifState *hifstate = hif_state_new ();
|
||||
guint progress_sigid;
|
||||
|
||||
progress_sigid = g_signal_connect (hifstate, "percentage-changed",
|
||||
G_CALLBACK (on_hifstate_percentage_changed),
|
||||
"Downloading: ");
|
||||
|
||||
glnx_console_lock (&console);
|
||||
|
||||
if (!hif_transaction_download (hiftx, hifstate, error))
|
||||
goto out;
|
||||
|
||||
g_signal_handler_disconnect (hifstate, progress_sigid);
|
||||
}
|
||||
|
||||
/* find any packages without valid GPG signatures */
|
||||
#if 0
|
||||
if (!hif_transaction_check_untrusted (hiftx, goal, error))
|
||||
goto out;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Add previous package requests with newly requested packages */
|
||||
{ gs_unref_ptrarray GPtrArray *new_requested_pkglist = g_ptr_array_new ();
|
||||
GHashTableIter hashiter;
|
||||
gpointer hkey, hvalue;
|
||||
|
||||
g_hash_table_iter_init (&hashiter, cur_origin_pkgrequests);
|
||||
while (g_hash_table_iter_next (&hashiter, &hkey, &hvalue))
|
||||
g_ptr_array_add (new_requested_pkglist, hkey);
|
||||
|
||||
g_hash_table_iter_init (&hashiter, layer_new_packages);
|
||||
while (g_hash_table_iter_next (&hashiter, &hkey, &hvalue))
|
||||
g_ptr_array_add (new_requested_pkglist, hkey);
|
||||
|
||||
g_key_file_set_string_list (origin, "packages", "requested",
|
||||
(const char*const*)new_requested_pkglist->pdata,
|
||||
new_requested_pkglist->len);
|
||||
}
|
||||
|
||||
if (!overlay_packages_in_deploydir (hifctx, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* Clear out any references to the rpmdb, etc. */
|
||||
g_clear_object (&hifctx);
|
||||
|
||||
/* Rename /usr/etc back to /etc */
|
||||
if (TEMP_FAILURE_RETRY (renameat (deploy_tmp_dirfd, "etc", deploy_tmp_dirfd, "usr/etc")) != 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!rpmostree_commit (deploy_tmp_dirfd, repo, NULL, NULL, NULL, TRUE,
|
||||
checkout_options.devino_to_csum_cache,
|
||||
&new_revision, cancellable, error))
|
||||
goto out;
|
||||
|
||||
(void) close (deploy_tmp_dirfd);
|
||||
deploy_tmp_dirfd = -1;
|
||||
|
||||
if (!glnx_shutil_rm_rf_at (ostree_repo_tmp_dirfd, tmp_deploy_workdir_name, cancellable, error))
|
||||
goto out;
|
||||
tmp_deploy_workdir_created = FALSE;
|
||||
|
||||
rpmostree_sysroot_upgrader_set_origin_baseref_local (upgrader, new_revision);
|
||||
|
||||
if (!rpmostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (self->reboot)
|
||||
rpmostreed_reboot (cancellable, error);
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (tmp_deploy_workdir_created)
|
||||
(void) glnx_shutil_rm_rf_at (ostree_repo_tmp_dirfd, tmp_deploy_workdir_name, NULL, NULL);
|
||||
if (checkout_options.devino_to_csum_cache)
|
||||
ostree_repo_devino_cache_unref (checkout_options.devino_to_csum_cache);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
pkg_add_transaction_class_init (PkgAddTransactionClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
object_class->finalize = pkg_add_transaction_finalize;
|
||||
|
||||
class->execute = pkg_add_transaction_execute;
|
||||
}
|
||||
|
||||
static void
|
||||
pkg_add_transaction_init (PkgAddTransaction *self)
|
||||
{
|
||||
}
|
||||
|
||||
RpmostreedTransaction *
|
||||
rpmostreed_transaction_new_pkg_add (GDBusMethodInvocation *invocation,
|
||||
OstreeSysroot *sysroot,
|
||||
const char *osname,
|
||||
const char * const *packages,
|
||||
gboolean reboot,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
PkgAddTransaction *self;
|
||||
|
||||
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
||||
g_return_val_if_fail (OSTREE_IS_SYSROOT (sysroot), NULL);
|
||||
g_return_val_if_fail (osname != NULL, NULL);
|
||||
g_return_val_if_fail (packages != NULL, NULL);
|
||||
|
||||
self = g_initable_new (pkg_add_transaction_get_type (),
|
||||
cancellable, error,
|
||||
"invocation", invocation,
|
||||
"sysroot", sysroot,
|
||||
NULL);
|
||||
|
||||
if (self != NULL)
|
||||
{
|
||||
self->osname = g_strdup (osname);
|
||||
self->packages = g_strdupv ((char**)packages);
|
||||
self->reboot = reboot;
|
||||
}
|
||||
|
||||
return (RpmostreedTransaction *) self;
|
||||
}
|
@ -26,11 +26,12 @@
|
||||
#include "rpmostreed-transaction.h"
|
||||
#include "rpmostreed-deployment-utils.h"
|
||||
#include "rpmostreed-sysroot.h"
|
||||
#include "rpmostree-sysroot-upgrader.h"
|
||||
#include "rpmostreed-utils.h"
|
||||
|
||||
static gboolean
|
||||
change_upgrader_refspec (OstreeSysroot *sysroot,
|
||||
OstreeSysrootUpgrader *upgrader,
|
||||
RpmOstreeSysrootUpgrader *upgrader,
|
||||
const gchar *refspec,
|
||||
GCancellable *cancellable,
|
||||
gchar **out_old_refspec,
|
||||
@ -38,40 +39,30 @@ change_upgrader_refspec (OstreeSysroot *sysroot,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_autofree gchar *old_refspec = NULL;
|
||||
const char *current_refspec = rpmostree_sysroot_upgrader_get_refspec (upgrader);
|
||||
g_autofree gchar *new_refspec = NULL;
|
||||
g_autoptr(GKeyFile) new_origin = NULL;
|
||||
GKeyFile *old_origin = NULL; /* owned by deployment */
|
||||
|
||||
old_origin = ostree_sysroot_upgrader_get_origin (upgrader);
|
||||
old_refspec = g_key_file_get_string (old_origin, "origin",
|
||||
"refspec", NULL);
|
||||
|
||||
if (!rpmostreed_refspec_parse_partial (refspec,
|
||||
old_refspec,
|
||||
current_refspec,
|
||||
&new_refspec,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (strcmp (old_refspec, new_refspec) == 0)
|
||||
if (strcmp (current_refspec, new_refspec) == 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Old and new refs are equal: %s", new_refspec);
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_origin = ostree_sysroot_origin_new_from_refspec (sysroot,
|
||||
new_refspec);
|
||||
if (!ostree_sysroot_upgrader_set_origin (upgrader, new_origin,
|
||||
cancellable, error))
|
||||
if (!rpmostree_sysroot_upgrader_set_origin_rebase (upgrader, new_refspec, error))
|
||||
goto out;
|
||||
|
||||
if (out_new_refspec != NULL)
|
||||
*out_new_refspec = g_steal_pointer (&new_refspec);
|
||||
|
||||
if (out_old_refspec != NULL)
|
||||
*out_old_refspec = g_steal_pointer (&old_refspec);
|
||||
*out_old_refspec = g_strdup (current_refspec);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
@ -117,30 +108,37 @@ package_diff_transaction_execute (RpmostreedTransaction *transaction,
|
||||
PackageDiffTransaction *self;
|
||||
OstreeSysroot *sysroot;
|
||||
|
||||
glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object RpmOstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
g_autoptr(GKeyFile) origin = NULL;
|
||||
glnx_unref_object OstreeDeployment *merge_deployment = NULL;
|
||||
g_autofree gchar *origin_description = NULL;
|
||||
|
||||
OstreeSysrootUpgraderPullFlags upgrader_flags = 0;
|
||||
RpmOstreeSysrootUpgraderFlags upgrader_flags = 0;
|
||||
gboolean upgrading = FALSE;
|
||||
gboolean changed = FALSE;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
self = (PackageDiffTransaction *) transaction;
|
||||
|
||||
if (self->revision != NULL)
|
||||
upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER;
|
||||
|
||||
sysroot = rpmostreed_transaction_get_sysroot (transaction);
|
||||
upgrader = ostree_sysroot_upgrader_new_for_os (sysroot,
|
||||
self->osname,
|
||||
cancellable,
|
||||
error);
|
||||
upgrader = rpmostree_sysroot_upgrader_new (sysroot,
|
||||
self->osname,
|
||||
upgrader_flags,
|
||||
cancellable,
|
||||
error);
|
||||
if (upgrader == NULL)
|
||||
goto out;
|
||||
|
||||
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
origin = ostree_sysroot_upgrader_dup_origin (upgrader);
|
||||
merge_deployment = ostree_sysroot_get_merge_deployment (sysroot, self->osname);
|
||||
|
||||
self->refspec = g_strdup (rpmostree_sysroot_upgrader_get_refspec (upgrader));
|
||||
|
||||
/* Determine if we're upgrading before we set the refspec. */
|
||||
upgrading = (self->refspec == NULL && self->revision == NULL);
|
||||
@ -152,15 +150,6 @@ package_diff_transaction_execute (RpmostreedTransaction *transaction,
|
||||
NULL, NULL, error))
|
||||
goto out;
|
||||
}
|
||||
else if (origin != NULL)
|
||||
{
|
||||
self->refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
|
||||
if (self->refspec == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Could not find refspec for booted deployment");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
@ -177,8 +166,6 @@ package_diff_transaction_execute (RpmostreedTransaction *transaction,
|
||||
g_autofree char *checksum = NULL;
|
||||
g_autofree char *version = NULL;
|
||||
|
||||
upgrader_flags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;
|
||||
|
||||
if (!rpmostreed_parse_revision (self->revision,
|
||||
&checksum,
|
||||
&version,
|
||||
@ -201,35 +188,26 @@ package_diff_transaction_execute (RpmostreedTransaction *transaction,
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_key_file_set_string (origin, "origin", "override-commit", checksum);
|
||||
|
||||
if (!ostree_sysroot_upgrader_set_origin (upgrader, origin,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
rpmostree_sysroot_upgrader_set_origin_override (upgrader, checksum);
|
||||
}
|
||||
else if (upgrading)
|
||||
{
|
||||
if (g_key_file_remove_key (origin, "origin", "override-commit", NULL))
|
||||
{
|
||||
if (!ostree_sysroot_upgrader_set_origin (upgrader, origin,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
rpmostree_sysroot_upgrader_set_origin_override (upgrader, NULL);
|
||||
}
|
||||
|
||||
origin_description = ostree_sysroot_upgrader_get_origin_description (upgrader);
|
||||
origin_description = rpmostree_sysroot_upgrader_get_origin_description (upgrader);
|
||||
if (origin_description != NULL)
|
||||
rpmostreed_transaction_emit_message_printf (transaction,
|
||||
"Updating from: %s",
|
||||
origin_description);
|
||||
|
||||
if (!ostree_sysroot_upgrader_pull_one_dir (upgrader,
|
||||
"/usr/share/rpm",
|
||||
0, upgrader_flags,
|
||||
progress,
|
||||
&changed,
|
||||
cancellable,
|
||||
error))
|
||||
if (!rpmostree_sysroot_upgrader_pull (upgrader,
|
||||
"/usr/share/rpm",
|
||||
0,
|
||||
progress,
|
||||
&changed,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));
|
||||
@ -584,50 +562,36 @@ upgrade_transaction_execute (RpmostreedTransaction *transaction,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
UpgradeTransaction *self;
|
||||
OstreeSysroot *sysroot;
|
||||
|
||||
glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object RpmOstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
g_autoptr(GKeyFile) origin = NULL;
|
||||
|
||||
g_autofree gchar *origin_description = NULL;
|
||||
|
||||
OstreeSysrootUpgraderPullFlags upgrader_pull_flags = 0;
|
||||
|
||||
RpmOstreeSysrootUpgraderFlags upgrader_flags = 0;
|
||||
gboolean changed = FALSE;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
self = (UpgradeTransaction *) transaction;
|
||||
|
||||
sysroot = rpmostreed_transaction_get_sysroot (transaction);
|
||||
|
||||
upgrader = ostree_sysroot_upgrader_new_for_os (sysroot, self->osname,
|
||||
cancellable, error);
|
||||
if (self->allow_downgrade)
|
||||
upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER;
|
||||
|
||||
upgrader = rpmostree_sysroot_upgrader_new (sysroot, self->osname, upgrader_flags,
|
||||
cancellable, error);
|
||||
if (upgrader == NULL)
|
||||
goto out;
|
||||
|
||||
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
origin = ostree_sysroot_upgrader_dup_origin (upgrader);
|
||||
if (origin != NULL)
|
||||
{
|
||||
/* Strip any override-commit from the origin file so
|
||||
* we always upgrade to the latest available commit. */
|
||||
if (g_key_file_remove_key (origin, "origin", "override-commit", NULL))
|
||||
{
|
||||
/* XXX GCancellable parameter is not used. */
|
||||
if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, NULL, error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
rpmostree_sysroot_upgrader_set_origin_override (upgrader, NULL);
|
||||
|
||||
if (self->allow_downgrade)
|
||||
upgrader_pull_flags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;
|
||||
|
||||
origin_description = ostree_sysroot_upgrader_get_origin_description (upgrader);
|
||||
origin_description = rpmostree_sysroot_upgrader_get_origin_description (upgrader);
|
||||
if (origin_description != NULL)
|
||||
rpmostreed_transaction_emit_message_printf (transaction,
|
||||
"Updating from: %s",
|
||||
@ -637,16 +601,16 @@ upgrade_transaction_execute (RpmostreedTransaction *transaction,
|
||||
rpmostreed_transaction_connect_download_progress (transaction, progress);
|
||||
rpmostreed_transaction_connect_signature_progress (transaction, repo);
|
||||
|
||||
if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgrader_pull_flags,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
if (!rpmostree_sysroot_upgrader_pull (upgrader, NULL, 0,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
if (!rpmostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (self->reboot)
|
||||
@ -747,7 +711,7 @@ rebase_transaction_execute (RpmostreedTransaction *transaction,
|
||||
RebaseTransaction *self;
|
||||
OstreeSysroot *sysroot;
|
||||
|
||||
glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object RpmOstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
|
||||
@ -758,13 +722,22 @@ rebase_transaction_execute (RpmostreedTransaction *transaction,
|
||||
gboolean changed = FALSE;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
RpmOstreeSysrootUpgraderFlags flags = 0;
|
||||
|
||||
self = (RebaseTransaction *) transaction;
|
||||
|
||||
sysroot = rpmostreed_transaction_get_sysroot (transaction);
|
||||
|
||||
upgrader = ostree_sysroot_upgrader_new_for_os_with_flags (sysroot, self->osname,
|
||||
OSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED,
|
||||
cancellable, error);
|
||||
/* Always allow older; there's not going to be a chronological
|
||||
* relationship necessarily. */
|
||||
flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER;
|
||||
|
||||
/* We should be able to switch to a different tree even if the current origin
|
||||
* is unconfigured */
|
||||
flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED;
|
||||
|
||||
upgrader = rpmostree_sysroot_upgrader_new (sysroot, self->osname, flags,
|
||||
cancellable, error);
|
||||
if (upgrader == NULL)
|
||||
goto out;
|
||||
|
||||
@ -780,17 +753,14 @@ rebase_transaction_execute (RpmostreedTransaction *transaction,
|
||||
rpmostreed_transaction_connect_download_progress (transaction, progress);
|
||||
rpmostreed_transaction_connect_signature_progress (transaction, repo);
|
||||
|
||||
/* Always allow older; there's not going to be a chronological
|
||||
* relationship necessarily. */
|
||||
if (!ostree_sysroot_upgrader_pull (upgrader, 0,
|
||||
OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
if (!rpmostree_sysroot_upgrader_pull (upgrader, NULL, 0,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));
|
||||
|
||||
if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
if (!rpmostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!self->skip_purge)
|
||||
@ -904,7 +874,7 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
|
||||
DeployTransaction *self;
|
||||
OstreeSysroot *sysroot;
|
||||
|
||||
glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object RpmOstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
|
||||
@ -919,15 +889,16 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
|
||||
|
||||
sysroot = rpmostreed_transaction_get_sysroot (transaction);
|
||||
|
||||
upgrader = ostree_sysroot_upgrader_new_for_os (sysroot, self->osname,
|
||||
cancellable, error);
|
||||
upgrader = rpmostree_sysroot_upgrader_new (sysroot, self->osname,
|
||||
RPMOSTREE_SYSROOT_UPGRADER_FLAGS_ALLOW_OLDER,
|
||||
cancellable, error);
|
||||
if (upgrader == NULL)
|
||||
goto out;
|
||||
|
||||
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
origin = ostree_sysroot_upgrader_dup_origin (upgrader);
|
||||
origin = rpmostree_sysroot_upgrader_dup_origin (upgrader);
|
||||
if (origin == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
@ -947,13 +918,13 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
|
||||
|
||||
if (version != NULL)
|
||||
{
|
||||
g_autofree char *refspec = NULL;
|
||||
const char *refspec = NULL;
|
||||
|
||||
rpmostreed_transaction_emit_message_printf (transaction,
|
||||
"Resolving version '%s'",
|
||||
version);
|
||||
|
||||
refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
|
||||
refspec = rpmostree_sysroot_upgrader_get_refspec (upgrader);
|
||||
if (refspec == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
@ -982,19 +953,18 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
|
||||
g_key_file_set_comment (origin, "origin", "override-commit", comment, NULL);
|
||||
}
|
||||
|
||||
if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, cancellable, error))
|
||||
if (!rpmostree_sysroot_upgrader_set_origin (upgrader, origin, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!ostree_sysroot_upgrader_pull (upgrader, 0,
|
||||
OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER,
|
||||
progress, &changed, cancellable, error))
|
||||
if (!rpmostree_sysroot_upgrader_pull (upgrader, NULL, 0,
|
||||
progress, &changed, cancellable, error))
|
||||
goto out;
|
||||
|
||||
rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
if (!rpmostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (self->reboot)
|
||||
|
@ -72,3 +72,12 @@ RpmostreedTransaction *
|
||||
gboolean reboot,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
RpmostreedTransaction *
|
||||
rpmostreed_transaction_new_pkg_add (GDBusMethodInvocation *invocation,
|
||||
OstreeSysroot *sysroot,
|
||||
const char *osname,
|
||||
const char *const *packages,
|
||||
gboolean reboot,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
@ -130,7 +130,7 @@ rpmostreed_generate_object_path_from_va (const gchar *base,
|
||||
*/
|
||||
gboolean
|
||||
rpmostreed_refspec_parse_partial (const gchar *new_provided_refspec,
|
||||
gchar *base_refspec,
|
||||
const gchar *base_refspec,
|
||||
gchar **out_refspec,
|
||||
GError **error)
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ gchar * rpmostreed_generate_object_path_from_va (const gchar *base,
|
||||
va_list va);
|
||||
|
||||
gboolean rpmostreed_refspec_parse_partial (const gchar *new_provided_refspec,
|
||||
gchar *base_refspec,
|
||||
const gchar *base_refspec,
|
||||
gchar **out_refspec,
|
||||
GError **error);
|
||||
void
|
||||
|
@ -695,7 +695,6 @@ workaround_selinux_cross_labeling_recurse (int dfd,
|
||||
|
||||
nonbin_name = g_strndup (name, lastdot - name);
|
||||
|
||||
g_print ("Setting mtime of '%s' to newer than '%s'\n", nonbin_name, name);
|
||||
if (TEMP_FAILURE_RETRY (utimensat (dfd_iter.fd, nonbin_name, NULL, 0)) == -1)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
@ -1570,12 +1569,14 @@ read_xattrs_cb (OstreeRepo *repo,
|
||||
}
|
||||
|
||||
gboolean
|
||||
rpmostree_commit (GFile *rootfs,
|
||||
rpmostree_commit (int rootfs_fd,
|
||||
OstreeRepo *repo,
|
||||
const char *refname,
|
||||
GVariant *metadata,
|
||||
const char *gpg_keyid,
|
||||
gboolean enable_selinux,
|
||||
OstreeRepoDevInoCache *devino_cache,
|
||||
char **out_new_revision,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
@ -1586,10 +1587,6 @@ rpmostree_commit (GFile *rootfs,
|
||||
gs_free char *new_revision = NULL;
|
||||
gs_unref_object GFile *root_tree = NULL;
|
||||
gs_unref_object OstreeSePolicy *sepolicy = NULL;
|
||||
gs_fd_close int rootfs_fd = -1;
|
||||
|
||||
if (!gs_file_open_dir_fd (rootfs, &rootfs_fd, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* hardcode targeted policy for now */
|
||||
if (enable_selinux)
|
||||
@ -1598,7 +1595,6 @@ rpmostree_commit (GFile *rootfs,
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_print ("Committing '%s' ...\n", gs_file_get_path_cached (rootfs));
|
||||
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
|
||||
goto out;
|
||||
|
||||
@ -1607,12 +1603,9 @@ rpmostree_commit (GFile *rootfs,
|
||||
ostree_repo_commit_modifier_set_xattr_callback (commit_modifier,
|
||||
read_xattrs_cb, NULL,
|
||||
GINT_TO_POINTER (rootfs_fd));
|
||||
|
||||
if (sepolicy && ostree_sepolicy_get_name (sepolicy) != NULL)
|
||||
{
|
||||
const char *policy_name = ostree_sepolicy_get_name (sepolicy);
|
||||
g_print ("Labeling with SELinux policy '%s'\n", policy_name);
|
||||
ostree_repo_commit_modifier_set_sepolicy (commit_modifier, sepolicy);
|
||||
}
|
||||
ostree_repo_commit_modifier_set_sepolicy (commit_modifier, sepolicy);
|
||||
else if (enable_selinux)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
@ -1620,13 +1613,19 @@ rpmostree_commit (GFile *rootfs,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_repo_write_directory_to_mtree (repo, rootfs, mtree, commit_modifier, cancellable, error))
|
||||
if (devino_cache)
|
||||
ostree_repo_commit_modifier_set_devino_cache (commit_modifier, devino_cache);
|
||||
|
||||
if (!ostree_repo_write_dfd_to_mtree (repo, rootfs_fd, ".", mtree, commit_modifier, cancellable, error))
|
||||
goto out;
|
||||
if (!ostree_repo_write_mtree (repo, mtree, &root_tree, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!ostree_repo_resolve_rev (repo, refname, TRUE, &parent_revision, error))
|
||||
goto out;
|
||||
if (refname)
|
||||
{
|
||||
if (!ostree_repo_resolve_rev (repo, refname, TRUE, &parent_revision, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_repo_write_commit (repo, parent_revision, "", "", metadata,
|
||||
(OstreeRepoFile*)root_tree, &new_revision,
|
||||
@ -1635,25 +1634,20 @@ rpmostree_commit (GFile *rootfs,
|
||||
|
||||
if (gpg_keyid)
|
||||
{
|
||||
g_print ("Signing commit %s with key %s\n", new_revision, gpg_keyid);
|
||||
if (!ostree_repo_sign_commit (repo, new_revision, gpg_keyid, NULL,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
ostree_repo_transaction_set_ref (repo, NULL, refname, new_revision);
|
||||
if (refname)
|
||||
ostree_repo_transaction_set_ref (repo, NULL, refname, new_revision);
|
||||
|
||||
if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
|
||||
goto out;
|
||||
|
||||
g_print ("%s => %s\n", refname, new_revision);
|
||||
|
||||
if (!g_getenv ("RPM_OSTREE_PRESERVE_ROOTFS"))
|
||||
(void) gs_shutil_rm_rf (rootfs, NULL, NULL);
|
||||
else
|
||||
g_print ("Preserved %s\n", gs_file_get_path_cached (rootfs));
|
||||
|
||||
ret = TRUE;
|
||||
if (out_new_revision)
|
||||
*out_new_revision = g_steal_pointer (&new_revision);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <ostree.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
#include "rpmostree-json-parsing.h"
|
||||
|
||||
gboolean
|
||||
rpmostree_treefile_postprocessing (GFile *rootfs,
|
||||
@ -43,12 +43,14 @@ rpmostree_prepare_rootfs_for_commit (GFile *rootfs,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
rpmostree_commit (GFile *rootfs,
|
||||
rpmostree_commit (int rootfs_dfd,
|
||||
OstreeRepo *repo,
|
||||
const char *refname,
|
||||
GVariant *metadata,
|
||||
const char *gpg_keyid,
|
||||
gboolean enable_selinux,
|
||||
OstreeRepoDevInoCache *devino_cache,
|
||||
char **out_new_revision,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean
|
||||
|
@ -405,3 +405,51 @@ _rpmostree_util_next_version (const char *auto_version_prefix,
|
||||
num = g_ascii_strtoull (end, NULL, 10);
|
||||
return g_strdup_printf ("%s.%llu", auto_version_prefix, num + 1);
|
||||
}
|
||||
|
||||
GKeyFile *
|
||||
_rpmostree_util_keyfile_clone (GKeyFile *keyfile)
|
||||
{
|
||||
GKeyFile *ret = g_key_file_new ();
|
||||
gsize len;
|
||||
gs_free char *data = g_key_file_to_data (keyfile, &len, NULL);
|
||||
gboolean loaded;
|
||||
|
||||
loaded = g_key_file_load_from_data (ret, data, len, 0, NULL);
|
||||
g_assert (loaded);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_rpmostree_util_parse_origin (GKeyFile *origin,
|
||||
char **out_refspec,
|
||||
char ***out_packages,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autofree char *origin_refspec = NULL;
|
||||
g_auto(GStrv) origin_packages = NULL;
|
||||
gboolean origin_is_bare_refspec = TRUE;
|
||||
|
||||
origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
|
||||
if (!origin_refspec)
|
||||
{
|
||||
origin_refspec = g_key_file_get_string (origin, "origin", "baserefspec", NULL);
|
||||
origin_is_bare_refspec = FALSE;
|
||||
}
|
||||
if (!origin_refspec)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No origin/refspec or origin/baserefspec in current deployment origin; cannot upgrade via rpm-ostree");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*out_refspec = g_steal_pointer (&origin_refspec);
|
||||
if (origin_is_bare_refspec)
|
||||
*out_packages = NULL;
|
||||
else
|
||||
*out_packages = g_key_file_get_string_list (origin, "packages", "requested", NULL, NULL);
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -86,3 +86,12 @@ _rpmostree_sync_wait_on_pid (pid_t pid,
|
||||
char *
|
||||
_rpmostree_util_next_version (const char *auto_version_prefix,
|
||||
const char *last_version);
|
||||
|
||||
GKeyFile *
|
||||
_rpmostree_util_keyfile_clone (GKeyFile *keyfile);
|
||||
|
||||
gboolean
|
||||
_rpmostree_util_parse_origin (GKeyFile *origin,
|
||||
char **out_refspec,
|
||||
char ***out_packages,
|
||||
GError **error);
|
||||
|
Loading…
Reference in New Issue
Block a user