daemon: Introduce an origin structure

In prep for adding "regenerates initramfs" to "is locally assembled",
we need more abstraction.  I previously introduced a helper function, but
I'd still need to touch every call site when changing that.

Rather than having each caller re-parse the origin, let's parse it once into a
structure, and then have error-free accessors for it (that also don't malloc).
This way when adding a new flag, I don't need to touch every call site.

Notes:

 - Some places in the code (like the deployments -> variant bits) tried to
   handle deployments without an origin gracefully.  That's no
   longer true.  I'm not sure how much we care - do we?
 - There are a few places where I changed `packagelist.len() > 0` to
   `is_locally_assembled()`.  I think this is right, but we'll need
   to be sure the "no packages to overlay, just initramfs" case
   works when that lands.

Closes: #566
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-01-11 14:05:18 -05:00 committed by Atomic Bot
parent f215acb64f
commit f8edd59d5f
11 changed files with 388 additions and 317 deletions

View File

@ -34,6 +34,8 @@ librpmostreepriv_la_SOURCES = \
src/libpriv/rpmostree-bwrap.h \
src/libpriv/rpmostree-kernel.c \
src/libpriv/rpmostree-kernel.h \
src/libpriv/rpmostree-origin.c \
src/libpriv/rpmostree-origin.h \
src/libpriv/rpmostree-scripts.c \
src/libpriv/rpmostree-scripts.h \
src/libpriv/rpmostree-refsack.h \

View File

@ -27,6 +27,7 @@
#include "rpmostree-sysroot-upgrader.h"
#include "rpmostree-core.h"
#include "rpmostree-origin.h"
#include "rpmostree-rpm-util.h"
#include "rpmostree-postprocess.h"
#include "rpmostree-output.h"
@ -57,13 +58,10 @@ struct RpmOstreeSysrootUpgrader {
RpmOstreeSysrootUpgraderFlags flags;
OstreeDeployment *merge_deployment;
GKeyFile *origin;
char *origin_refspec;
char **requested_packages;
RpmOstreeOrigin *origin;
GHashTable *ignore_scripts;
GHashTable *packages_to_add;
GHashTable *packages_to_delete;
char *override_csum;
char *new_revision;
};
@ -82,46 +80,40 @@ G_DEFINE_TYPE_WITH_CODE (RpmOstreeSysrootUpgrader, rpmostree_sysroot_upgrader, G
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, rpmostree_sysroot_upgrader_initable_iface_init))
static gboolean
parse_refspec (RpmOstreeSysrootUpgrader *self,
GCancellable *cancellable,
GError **error)
parse_origin_keyfile (RpmOstreeSysrootUpgrader *self,
GKeyFile *origin,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autofree char *unconfigured_state = NULL;
g_autofree char *csum = NULL;
RpmOstreeOriginFlags origin_flags = 0;
if ((self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED) == 0)
g_clear_pointer (&self->origin, (GDestroyNotify)rpmostree_origin_unref);
if (self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED)
origin_flags |= RPMOSTREE_ORIGIN_FLAGS_IGNORE_UNCONFIGURED;
self->origin = rpmostree_origin_parse_keyfile (origin, origin_flags, error);
if (!self->origin)
return FALSE;
return TRUE;
}
static gboolean
parse_origin_deployment (RpmOstreeSysrootUpgrader *self,
OstreeDeployment *deployment,
GCancellable *cancellable,
GError **error)
{
GKeyFile *origin = ostree_deployment_get_origin (deployment);
if (!origin)
{
/* 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;
}
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No origin known for deployment %s.%d",
ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment));
return FALSE;
}
g_clear_pointer (&self->requested_packages, g_strfreev);
g_clear_pointer (&self->origin_refspec, g_free);
if (!_rpmostree_util_parse_origin (self->origin, &self->origin_refspec,
&self->requested_packages, error))
goto out;
/* it's just easier to make it a proper empty list than to check for NULL
* everytime */
if (self->requested_packages == NULL)
self->requested_packages = g_new0 (gchar *, 1);
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;
return parse_origin_keyfile (self, origin, cancellable, error);
}
static gboolean
@ -165,37 +157,17 @@ rpmostree_sysroot_upgrader_initable_init (GInitable *initable,
self->new_revision =
g_strdup (ostree_deployment_get_csum (self->merge_deployment));
self->origin = NULL;
{
GKeyFile *original_origin = /* I just had to use that name */
ostree_deployment_get_origin (self->merge_deployment);
if (original_origin)
self->origin = _rpmostree_util_keyfile_clone (original_origin);
}
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);
/* Should we consider requiring --discard-hotfix here?
* See also `ostree admin upgrade` bits.
*/
g_key_file_remove_key (self->origin, "origin", "unlocked", NULL);
if (!parse_origin_deployment (self, self->merge_deployment, cancellable, error))
goto out;
self->packages_to_add = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
self->packages_to_delete = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
if (!parse_refspec (self, cancellable, error))
goto out;
ret = TRUE;
out:
return ret;
@ -216,13 +188,9 @@ rpmostree_sysroot_upgrader_finalize (GObject *object)
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_clear_pointer (&self->origin, (GDestroyNotify)rpmostree_origin_unref);
g_hash_table_unref (self->packages_to_add);
g_hash_table_unref (self->packages_to_delete);
g_free (self->override_csum);
g_free (self->new_revision);
G_OBJECT_CLASS (rpmostree_sysroot_upgrader_parent_class)->finalize (object);
@ -348,39 +316,12 @@ rpmostree_sysroot_upgrader_new (OstreeSysroot *sysroot,
*
* Returns: (transfer none): The origin file, or %NULL if unknown
*/
GKeyFile *
RpmOstreeOrigin *
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 (RPMOSTREE_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
@ -398,11 +339,10 @@ rpmostree_sysroot_upgrader_set_origin (RpmOstreeSysrootUpgrader *self,
{
gboolean ret = FALSE;
g_clear_pointer (&self->origin, g_key_file_unref);
g_clear_pointer (&self->origin, (GDestroyNotify)rpmostree_origin_unref);
if (origin)
{
self->origin = g_key_file_ref (origin);
if (!parse_refspec (self, cancellable, error))
if (!parse_origin_keyfile (self, origin, cancellable, error))
goto out;
}
@ -435,7 +375,7 @@ rpmostree_sysroot_upgrader_set_origin_rebase (RpmOstreeSysrootUpgrader *self,
const char *new_refspec,
GError **error)
{
g_autoptr(GKeyFile) new_origin = rpmostree_sysroot_upgrader_dup_origin (self);
g_autoptr(GKeyFile) new_origin = rpmostree_origin_dup_keyfile (self->origin);
if (!origin_set_refspec (new_origin, new_refspec, error))
return FALSE;
@ -443,11 +383,7 @@ rpmostree_sysroot_upgrader_set_origin_rebase (RpmOstreeSysrootUpgrader *self,
/* we don't want to carry any commit overrides during a rebase */
g_key_file_remove_key (new_origin, "origin", "override-commit", NULL);
g_clear_pointer (&self->origin, g_key_file_unref);
self->origin = g_key_file_ref (new_origin);
/* this will update self->origin_refspec */
if (!parse_refspec (self, NULL, error))
if (!parse_origin_keyfile (self, new_origin, NULL, error))
return FALSE;
return TRUE;
@ -457,14 +393,15 @@ 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);
g_autoptr(GKeyFile) new_origin = rpmostree_origin_dup_keyfile (self->origin);
/* just update self manually rather than re-parsing the whole thing */
g_free (self->override_csum);
self->override_csum = g_strdup (override_commit);
if (override_commit != NULL)
g_key_file_set_string (new_origin, "origin", "override-commit", override_commit);
else
g_key_file_remove_key (new_origin, "origin", "override-commit", NULL);
if (!parse_origin_keyfile (self, new_origin, NULL, NULL))
g_assert_not_reached ();
}
void
@ -478,13 +415,13 @@ rpmostree_sysroot_upgrader_set_ignore_scripts (RpmOstreeSysrootUpgrader *self,
const char *
rpmostree_sysroot_upgrader_get_refspec (RpmOstreeSysrootUpgrader *self)
{
return self->origin_refspec;
return rpmostree_origin_get_refspec (self->origin);
}
const char *const*
rpmostree_sysroot_upgrader_get_packages (RpmOstreeSysrootUpgrader *self)
{
return (const char * const *)self->requested_packages;
return rpmostree_origin_get_packages (self->origin);
}
OstreeDeployment*
@ -506,11 +443,11 @@ rpmostree_sysroot_upgrader_get_origin_description (RpmOstreeSysrootUpgrader *sel
}
static GHashTable*
hashset_from_strv (char **strv)
hashset_from_strv (const char *const*strv)
{
GHashTable *ht = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
for (char **it = strv; it && *it; it++)
for (char **it = (char**)strv; it && *it; it++)
g_hash_table_add (ht, g_strdup (*it));
return ht;
}
@ -532,7 +469,7 @@ rpmostree_sysroot_upgrader_add_packages (RpmOstreeSysrootUpgrader *self,
{
gboolean ret = FALSE;
g_autoptr(GHashTable) requested_packages =
hashset_from_strv (self->requested_packages);
hashset_from_strv (rpmostree_origin_get_packages (self->origin));
for (char **it = packages; it && *it; it++)
{
@ -567,7 +504,7 @@ rpmostree_sysroot_upgrader_delete_packages (RpmOstreeSysrootUpgrader *self,
{
gboolean ret = FALSE;
g_autoptr(GHashTable) requested_packages =
hashset_from_strv (self->requested_packages);
hashset_from_strv (rpmostree_origin_get_packages (self->origin));
for (char **it = packages; it && *it; it++)
{
@ -617,14 +554,14 @@ rpmostree_sysroot_upgrader_pull (RpmOstreeSysrootUpgrader *self,
g_autofree char *origin_remote = NULL;
g_autofree char *origin_ref = NULL;
if (!ostree_parse_refspec (self->origin_refspec,
if (!ostree_parse_refspec (rpmostree_origin_get_refspec (self->origin),
&origin_remote,
&origin_ref,
error))
goto out;
if (self->override_csum != NULL)
refs_to_fetch[0] = self->override_csum;
if (rpmostree_origin_get_override_commit (self->origin) != NULL)
refs_to_fetch[0] = (char*)rpmostree_origin_get_override_commit (self->origin);
else
refs_to_fetch[0] = origin_ref;
@ -645,24 +582,23 @@ rpmostree_sysroot_upgrader_pull (RpmOstreeSysrootUpgrader *self,
ostree_async_progress_finish (progress);
}
if (self->override_csum != NULL)
if (rpmostree_origin_get_override_commit (self->origin) != NULL)
{
if (!ostree_repo_set_ref_immediate (repo,
origin_remote,
origin_ref,
self->override_csum,
rpmostree_origin_get_override_commit (self->origin),
cancellable,
error))
goto out;
self->new_revision = g_strdup (self->override_csum);
self->new_revision = g_strdup (rpmostree_origin_get_override_commit (self->origin));
}
else
{
if (!ostree_repo_resolve_rev (repo, self->origin_refspec, FALSE,
if (!ostree_repo_resolve_rev (repo, rpmostree_origin_get_refspec (self->origin), FALSE,
&self->new_revision, error))
goto out;
}
{
@ -676,7 +612,7 @@ rpmostree_sysroot_upgrader_pull (RpmOstreeSysrootUpgrader *self,
{
/* if there are pkgs layered on the from rev, then we should compare
* the parent instead, which is the 'base' layer */
if (g_strv_length (self->requested_packages) > 0)
if (rpmostree_origin_is_locally_assembled (self->origin))
{
if (!commit_get_parent_csum (repo, from_revision, &base_rev, error))
goto out;
@ -710,16 +646,17 @@ update_requested_packages (RpmOstreeSysrootUpgrader *self,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GKeyFile) new_origin = rpmostree_origin_dup_keyfile (self->origin);
glnx_free char **pkgv =
(char**) g_hash_table_get_keys_as_array (pkgset, NULL);
g_key_file_set_string_list (self->origin, "packages", "requested",
g_key_file_set_string_list (new_origin, "packages", "requested",
(const char* const*) pkgv, g_strv_length(pkgv));
/* migrate to baserefspec model if necessary */
g_key_file_set_value (self->origin, "origin", "baserefspec",
self->origin_refspec);
if (!g_key_file_remove_key (self->origin, "origin", "refspec", error))
g_key_file_set_value (new_origin, "origin", "baserefspec",
rpmostree_origin_get_refspec (self->origin));
if (!g_key_file_remove_key (new_origin, "origin", "refspec", error))
{
if (g_error_matches (*error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_KEY_NOT_FOUND))
@ -727,9 +664,8 @@ update_requested_packages (RpmOstreeSysrootUpgrader *self,
else
goto out;
}
/* reread spec file --> this will update the current requested_packages */
if (!parse_refspec (self, cancellable, error))
g_clear_pointer (&self->origin, (GDestroyNotify)rpmostree_origin_unref);
if (!parse_origin_keyfile (self, new_origin, cancellable, error))
goto out;
ret = TRUE;
@ -886,7 +822,8 @@ finalize_requested_packages (RpmOstreeSysrootUpgrader *self,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GHashTable) pkgset = hashset_from_strv (self->requested_packages);
g_autoptr(GHashTable) pkgset =
hashset_from_strv (rpmostree_origin_get_packages (self->origin));
/* remove packages_to_delete from the set */
{ GHashTableIter it;
@ -985,7 +922,7 @@ overlay_final_pkgset (RpmOstreeSysrootUpgrader *self,
g_autoptr(RpmOstreeContext) ctx = NULL;
g_autoptr(RpmOstreeTreespec) treespec = NULL;
g_autoptr(RpmOstreeInstall) install = {0,};
g_autoptr(GHashTable) pkgset = hashset_from_strv (self->requested_packages);
g_autoptr(GHashTable) pkgset = hashset_from_strv (rpmostree_origin_get_packages (self->origin));
glnx_unref_object OstreeRepo *pkgcache_repo = NULL;
ctx = rpmostree_context_new_system (cancellable, error);
@ -1104,7 +1041,7 @@ overlay_packages (RpmOstreeSysrootUpgrader *self,
* redeploying and there's already stuff layered down, in which case, it's the
* parent commit */
if ((self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_REDEPLOY) &&
(g_strv_length (self->requested_packages) > 0))
rpmostree_origin_is_locally_assembled (self->origin))
{
if (!commit_get_parent_csum (repo, self->new_revision, &base_rev, error))
goto out;
@ -1127,7 +1064,7 @@ overlay_packages (RpmOstreeSysrootUpgrader *self,
* that the user wants to stop overlaying them), so we have another
* optimization here for that case.
*/
if (g_strv_length (self->requested_packages) == 0)
if (!rpmostree_origin_is_locally_assembled (self->origin))
{
g_free (self->new_revision);
self->new_revision = g_steal_pointer (&base_rev);
@ -1160,13 +1097,13 @@ get_base_commit_for_deployment (RpmOstreeSysrootUpgrader *self,
char **out_base,
GError **error)
{
GKeyFile *origin = ostree_deployment_get_origin (deployment);
gboolean is_local;
g_autoptr(RpmOstreeOrigin) origin = NULL;
if (!_rpmostree_origin_is_locally_assembled (origin, &is_local, error))
origin = rpmostree_origin_parse_deployment (deployment, error);
if (!origin)
return FALSE;
if (is_local)
if (rpmostree_origin_is_locally_assembled (origin))
{
const char *csum = ostree_deployment_get_csum (deployment);
g_autofree char *base_rev = NULL;
@ -1326,13 +1263,13 @@ clean_pkgcache_orphans (RpmOstreeSysrootUpgrader *self,
for (guint i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
GKeyFile *origin = ostree_deployment_get_origin (deployment);
gboolean is_local;
g_autoptr(RpmOstreeOrigin) origin = NULL;
if (!_rpmostree_origin_is_locally_assembled (origin, &is_local, error))
origin = rpmostree_origin_parse_deployment (deployment, error);
if (!origin)
return FALSE;
if (is_local)
if (rpmostree_origin_is_locally_assembled (origin))
{
g_autoptr(RpmOstreeRefSack) rsack = NULL;
g_autofree char *deployment_dirpath = NULL;
@ -1438,7 +1375,7 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
g_assert (self->new_revision);
/* any packages requested for overlay? */
if ((g_strv_length (self->requested_packages) > 0) ||
if (rpmostree_origin_is_locally_assembled (self->origin) ||
(g_hash_table_size (self->packages_to_add) > 0) ||
(g_hash_table_size (self->packages_to_delete) > 0))
if (!overlay_packages (self, cancellable, error))
@ -1452,7 +1389,7 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
if (!ostree_sysroot_deploy_tree (self->sysroot, self->osname,
self->new_revision,
self->origin,
rpmostree_origin_get_keyfile (self->origin),
self->merge_deployment,
NULL,
&new_deployment,

View File

@ -21,6 +21,7 @@
#pragma once
#include <ostree.h>
#include "rpmostree-origin.h"
G_BEGIN_DECLS
@ -68,8 +69,7 @@ const char *const*rpmostree_sysroot_upgrader_get_packages (RpmOstreeSysrootUpgra
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);
RpmOstreeOrigin *rpmostree_sysroot_upgrader_get_origin (RpmOstreeSysrootUpgrader *self);
gboolean rpmostree_sysroot_upgrader_set_origin (RpmOstreeSysrootUpgrader *self, GKeyFile *origin,
GCancellable *cancellable, GError **error);

View File

@ -19,6 +19,8 @@
#include "config.h"
#include "rpmostreed-deployment-utils.h"
#include "rpmostree-origin.h"
#include "rpmostree-util.h"
#include <libglnx.h>
@ -126,41 +128,6 @@ out:
return ret;
}
char *
rpmostreed_deployment_get_refspec (OstreeDeployment *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)
{
*out_refspec = NULL;
*out_packages = NULL;
return;
}
*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);
if (out_packages)
*out_packages = g_key_file_get_string_list (origin, "packages", "requested", &len, NULL);
}
GVariant *
rpmostreed_deployment_generate_blank_variant (void)
{
@ -197,8 +164,7 @@ rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
GError **error)
{
g_autoptr(GVariant) commit = NULL;
g_autofree gchar *origin_refspec = NULL;
g_auto(GStrv) origin_packages = NULL;
g_autoptr(RpmOstreeOrigin) origin = NULL;
g_autofree gchar *id = NULL;
GVariant *sigs = NULL; /* floating variant */
@ -219,7 +185,9 @@ rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
id = rpmostreed_deployment_generate_id (deployment);
rpmostreed_deployment_get_refspec_packages (deployment, &origin_refspec, &origin_packages);
origin = rpmostree_origin_parse_deployment (deployment, error);
if (!origin)
return NULL;
g_variant_dict_init (&dict, NULL);
@ -228,22 +196,22 @@ rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
g_variant_dict_insert (&dict, "osname", "s", osname);
g_variant_dict_insert (&dict, "serial", "i", serial);
g_variant_dict_insert (&dict, "checksum", "s", csum);
if (origin_packages != NULL && g_strv_length (origin_packages) > 0)
if (rpmostree_origin_is_locally_assembled (origin))
{
const char *parent = ostree_commit_get_parent (commit);
g_assert (parent);
g_variant_dict_insert (&dict, "base-checksum", "s", parent);
if (origin_refspec)
sigs = rpmostreed_deployment_gpg_results (repo, origin_refspec, parent, &gpg_enabled);
sigs = rpmostreed_deployment_gpg_results (repo, rpmostree_origin_get_refspec (origin),
parent, &gpg_enabled);
}
else if (origin_refspec)
sigs = rpmostreed_deployment_gpg_results (repo, origin_refspec, csum, &gpg_enabled);
else
sigs = rpmostreed_deployment_gpg_results (repo, rpmostree_origin_get_refspec (origin),
csum, &gpg_enabled);
variant_add_commit_details (&dict, commit);
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);
g_variant_dict_insert (&dict, "origin", "s", rpmostree_origin_get_refspec (origin));
if (rpmostree_origin_get_packages (origin) != NULL)
g_variant_dict_insert (&dict, "packages", "^as", rpmostree_origin_get_packages (origin));
if (sigs != NULL)
g_variant_dict_insert_value (&dict, "signatures", sigs);
g_variant_dict_insert (&dict, "gpg-enabled", "b", gpg_enabled);
@ -276,7 +244,14 @@ rpmostreed_commit_generate_cached_details_variant (OstreeDeployment *deployment,
if (refspec)
origin_refspec = g_strdup (refspec);
else
origin_refspec = rpmostreed_deployment_get_refspec (deployment);
{
g_autoptr(RpmOstreeOrigin) origin = NULL;
origin = rpmostree_origin_parse_deployment (deployment, error);
if (!origin)
return NULL;
origin_refspec = g_strdup (rpmostree_origin_get_refspec (origin));
}
g_assert (origin_refspec);

View File

@ -28,12 +28,6 @@ OstreeDeployment *
rpmostreed_deployment_get_for_id (OstreeSysroot *sysroot,
const gchar *deploy_id);
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,

View File

@ -26,8 +26,10 @@
#include "rpmostreed-deployment-utils.h"
#include "rpmostree-package-variants.h"
#include "rpmostreed-errors.h"
#include "rpmostree-origin.h"
#include "rpmostreed-os.h"
#include "rpmostreed-utils.h"
#include "rpmostree-util.h"
#include "rpmostreed-transaction.h"
#include "rpmostreed-transaction-monitor.h"
#include "rpmostreed-transaction-types.h"
@ -208,7 +210,7 @@ os_handle_get_cached_update_rpm_diff (RPMOSTreeOS *interface,
{
RpmostreedSysroot *global_sysroot;
const gchar *name;
g_autofree gchar *comp_ref = NULL;
g_autoptr(RpmOstreeOrigin) origin = NULL;
OstreeSysroot *ot_sysroot = NULL;
OstreeRepo *ot_repo = NULL;
glnx_unref_object OstreeDeployment *base_deployment = NULL;
@ -246,17 +248,13 @@ os_handle_get_cached_update_rpm_diff (RPMOSTreeOS *interface,
}
}
comp_ref = rpmostreed_deployment_get_refspec (base_deployment);
if (!comp_ref)
{
local_error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED,
"No upgrade remote found for os %s", name);
goto out;
}
origin = rpmostree_origin_parse_deployment (base_deployment, &local_error);
if (!origin)
goto out;
value = rpm_ostree_db_diff_variant (ot_repo,
ostree_deployment_get_csum (base_deployment),
comp_ref,
rpmostree_origin_get_refspec (origin),
cancellable,
&local_error);
if (value == NULL)
@ -264,7 +262,7 @@ os_handle_get_cached_update_rpm_diff (RPMOSTreeOS *interface,
details = rpmostreed_commit_generate_cached_details_variant (base_deployment,
ot_repo,
comp_ref,
rpmostree_origin_get_refspec (origin),
&local_error);
if (!details)
goto out;
@ -784,8 +782,8 @@ os_handle_get_cached_rebase_rpm_diff (RPMOSTreeOS *interface,
OstreeRepo *ot_repo = NULL;
const gchar *name;
glnx_unref_object OstreeDeployment *base_deployment = NULL;
g_autoptr(RpmOstreeOrigin) origin = NULL;
g_autofree gchar *comp_ref = NULL;
g_autofree gchar *base_refspec = NULL;
GError *local_error = NULL;
GVariant *value = NULL; /* freed when invoked */
GVariant *details = NULL; /* freed when invoked */
@ -806,9 +804,12 @@ os_handle_get_cached_rebase_rpm_diff (RPMOSTreeOS *interface,
goto out;
}
base_refspec = rpmostreed_deployment_get_refspec (base_deployment);
origin = rpmostree_origin_parse_deployment (base_deployment, &local_error);
if (!origin)
goto out;
if (!rpmostreed_refspec_parse_partial (arg_refspec,
base_refspec,
rpmostree_origin_get_refspec (origin),
&comp_ref,
&local_error))
goto out;
@ -907,13 +908,14 @@ os_handle_get_cached_deploy_rpm_diff (RPMOSTreeOS *interface,
OstreeSysroot *ot_sysroot = NULL;
OstreeRepo *ot_repo = NULL;
glnx_unref_object OstreeDeployment *base_deployment = NULL;
g_autofree char *base_refspec = NULL;
g_autoptr(RpmOstreeOrigin) origin = NULL;
g_autofree char *checksum = NULL;
g_autofree char *version = NULL;
g_autoptr(GCancellable) cancellable = NULL;
GVariant *value = NULL;
GVariant *details = NULL;
GError *local_error = NULL;
GError **error = &local_error;
/* XXX Ignoring arg_packages for now. */
@ -929,8 +931,11 @@ os_handle_get_cached_deploy_rpm_diff (RPMOSTreeOS *interface,
goto out;
}
origin = rpmostree_origin_parse_deployment (base_deployment, error);
if (!origin)
goto out;
base_checksum = ostree_deployment_get_csum (base_deployment);
base_refspec = rpmostreed_deployment_get_refspec (base_deployment);
if (!rpmostreed_parse_revision (arg_revision,
&checksum,
@ -941,7 +946,7 @@ os_handle_get_cached_deploy_rpm_diff (RPMOSTreeOS *interface,
if (version != NULL)
{
if (!rpmostreed_repo_lookup_cached_version (ot_repo,
base_refspec,
rpmostree_origin_get_refspec (origin),
version,
cancellable,
&checksum,
@ -1098,17 +1103,21 @@ rpmostreed_os_load_internals (RpmostreedOS *self, GError **error)
merge_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name);
if (merge_deployment)
{
/* Determine whether we have a refspec to use for updates */
g_autofree char *refspec = rpmostreed_deployment_get_refspec (merge_deployment);
if (refspec != NULL)
cached_update = rpmostreed_commit_generate_cached_details_variant (merge_deployment,
ot_repo,
refspec,
error);
if (!cached_update)
return FALSE;
has_cached_updates = cached_update != NULL;
}
g_autoptr(RpmOstreeOrigin) origin = NULL;
/* Don't fail here for unknown origin types */
origin = rpmostree_origin_parse_deployment (merge_deployment, NULL);
if (origin)
{
cached_update = rpmostreed_commit_generate_cached_details_variant (merge_deployment,
ot_repo,
rpmostree_origin_get_refspec (origin),
error);
if (!cached_update)
return FALSE;
has_cached_updates = cached_update != NULL;
}
}
if (!booted_variant)
booted_variant = rpmostreed_deployment_generate_blank_variant ();

View File

@ -80,18 +80,12 @@ apply_revision_override (RpmostreedTransaction *transaction,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GKeyFile) origin = NULL;
RpmOstreeOrigin *origin = rpmostree_sysroot_upgrader_get_origin (upgrader);
g_autoptr(GKeyFile) new_origin = NULL;
g_autofree char *checksum = NULL;
g_autofree char *version = NULL;
const char *refspec;
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");
return FALSE;
}
new_origin = rpmostree_origin_dup_keyfile (origin);
if (!rpmostreed_parse_revision (revision,
&checksum,
@ -99,21 +93,14 @@ apply_revision_override (RpmostreedTransaction *transaction,
error))
return FALSE;
refspec = rpmostree_sysroot_upgrader_get_refspec (upgrader);
if (refspec == NULL)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Could not find refspec for booted deployment");
return FALSE;
}
if (version != NULL)
{
rpmostreed_transaction_emit_message_printf (transaction,
"Resolving version '%s'",
version);
if (!rpmostreed_repo_lookup_version (repo, refspec, version, progress,
if (!rpmostreed_repo_lookup_version (repo, rpmostree_origin_get_refspec (origin),
version, progress,
cancellable, &checksum, error))
return FALSE;
}
@ -125,12 +112,12 @@ apply_revision_override (RpmostreedTransaction *transaction,
"Validating checksum '%s'",
checksum);
if (!rpmostreed_repo_lookup_checksum (repo, refspec, checksum,
progress, cancellable, error))
if (!rpmostreed_repo_lookup_checksum (repo, rpmostree_origin_get_refspec (origin),
checksum, progress, cancellable, error))
return FALSE;
}
g_key_file_set_string (origin, "origin", "override-commit", checksum);
g_key_file_set_string (new_origin, "origin", "override-commit", checksum);
if (version != NULL)
{
@ -138,10 +125,10 @@ apply_revision_override (RpmostreedTransaction *transaction,
/* Add a comment with the version, to be nice. */
comment = g_strdup_printf ("Version %s [%.10s]", version, checksum);
g_key_file_set_comment (origin, "origin", "override-commit", comment, NULL);
g_key_file_set_comment (new_origin, "origin", "override-commit", comment, NULL);
}
if (!rpmostree_sysroot_upgrader_set_origin (upgrader, origin, cancellable, error))
if (!rpmostree_sysroot_upgrader_set_origin (upgrader, new_origin, cancellable, error))
return FALSE;
return TRUE;

View File

@ -0,0 +1,146 @@
/* -*- 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 "rpmostree-origin.h"
struct RpmOstreeOrigin {
GKeyFile *kf;
char *refspec;
char **packages;
char *override_commit;
};
static GKeyFile *
keyfile_dup (GKeyFile *kf)
{
GKeyFile *ret = g_key_file_new ();
gsize length = 0;
g_autofree char *data = g_key_file_to_data (kf, &length, NULL);
g_key_file_load_from_data (ret, data, length, G_KEY_FILE_KEEP_COMMENTS, NULL);
return ret;
}
RpmOstreeOrigin *
rpmostree_origin_parse_keyfile (GKeyFile *origin,
RpmOstreeOriginFlags flags,
GError **error)
{
g_autoptr(RpmOstreeOrigin) ret = NULL;
ret = g_new0 (RpmOstreeOrigin, 1);
ret->kf = keyfile_dup (origin);
/* NOTE hack here - see https://github.com/ostreedev/ostree/pull/343 */
g_key_file_remove_key (ret->kf, "origin", "unlocked", NULL);
if ((flags & RPMOSTREE_ORIGIN_FLAGS_IGNORE_UNCONFIGURED) == 0)
{
g_autofree char *unconfigured_state = NULL;
/* If explicit action by the OS creator is requried to upgrade, print their text as an error */
unconfigured_state = g_key_file_get_string (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);
return NULL;
}
}
ret->refspec = g_key_file_get_string (ret->kf, "origin", "refspec", NULL);
if (!ret->refspec)
{
ret->refspec = g_key_file_get_string (ret->kf, "origin", "baserefspec", NULL);
if (!ret->refspec)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No origin/refspec or origin/baserefspec in current deployment origin; cannot handle via rpm-ostree");
return NULL;
}
ret->packages = g_key_file_get_string_list (ret->kf, "packages", "requested", NULL, NULL);
}
/* Canonicalize NULL to an empty list for sanity */
if (!ret->packages)
ret->packages = g_new0 (char*, 1);
ret->override_commit = g_key_file_get_string (ret->kf, "origin", "override-commit", NULL);
return g_steal_pointer (&ret);
}
const char *
rpmostree_origin_get_refspec (RpmOstreeOrigin *origin)
{
return origin->refspec;
}
const char *const*
rpmostree_origin_get_packages (RpmOstreeOrigin *origin)
{
return (const char * const*)origin->packages;
}
const char *
rpmostree_origin_get_override_commit (RpmOstreeOrigin *origin)
{
return origin->override_commit;
}
gboolean
rpmostree_origin_is_locally_assembled (RpmOstreeOrigin *origin)
{
return g_strv_length (origin->packages) > 0;
}
GKeyFile *
rpmostree_origin_get_keyfile (RpmOstreeOrigin *origin)
{
return origin->kf;
}
GKeyFile *
rpmostree_origin_dup_keyfile (RpmOstreeOrigin *origin)
{
return keyfile_dup (origin->kf);
}
char *
rpmostree_origin_get_string (RpmOstreeOrigin *origin,
const char *section,
const char *value)
{
return g_key_file_get_string (origin->kf, section, value, NULL);
}
void
rpmostree_origin_unref (RpmOstreeOrigin *origin)
{
g_key_file_unref (origin->kf);
g_free (origin->refspec);
g_strfreev (origin->packages);
g_free (origin);
}

View File

@ -0,0 +1,85 @@
/* -*- 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.
*/
#pragma once
#include <ostree.h>
typedef struct RpmOstreeOrigin RpmOstreeOrigin;
void rpmostree_origin_unref (RpmOstreeOrigin *origin);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(RpmOstreeOrigin, rpmostree_origin_unref)
typedef enum {
RPMOSTREE_ORIGIN_FLAGS_IGNORE_UNCONFIGURED = (1 << 0)
} RpmOstreeOriginFlags;
RpmOstreeOrigin *
rpmostree_origin_parse_keyfile (GKeyFile *keyfile,
RpmOstreeOriginFlags flags,
GError **error);
static inline
RpmOstreeOrigin *
rpmostree_origin_parse_deployment_ex (OstreeDeployment *deployment,
RpmOstreeOriginFlags flags,
GError **error)
{
GKeyFile *origin = ostree_deployment_get_origin (deployment);
if (!origin)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No origin known for deployment %s.%d",
ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment));
return NULL;
}
return rpmostree_origin_parse_keyfile (origin, flags, error);
}
static inline
RpmOstreeOrigin *
rpmostree_origin_parse_deployment (OstreeDeployment *deployment,
GError **error)
{
return rpmostree_origin_parse_deployment_ex (deployment, 0, error);
}
gboolean
rpmostree_origin_is_locally_assembled (RpmOstreeOrigin *origin);
const char *
rpmostree_origin_get_refspec (RpmOstreeOrigin *origin);
const char *const*
rpmostree_origin_get_packages (RpmOstreeOrigin *origin);
const char *
rpmostree_origin_get_override_commit (RpmOstreeOrigin *origin);
char *
rpmostree_origin_get_string (RpmOstreeOrigin *origin,
const char *section,
const char *value);
GKeyFile *
rpmostree_origin_get_keyfile (RpmOstreeOrigin *origin);
GKeyFile *
rpmostree_origin_dup_keyfile (RpmOstreeOrigin *origin);

View File

@ -424,59 +424,6 @@ _rpmostree_util_keyfile_clone (GKeyFile *keyfile)
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;
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;
}
if (out_refspec)
*out_refspec = g_steal_pointer (&origin_refspec);
if (out_packages)
{
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;
}
gboolean
_rpmostree_origin_is_locally_assembled (GKeyFile *origin,
gboolean *out_is_local,
GError **error)
{
g_auto(GStrv) pkgs = NULL;
if (!_rpmostree_util_parse_origin (origin, NULL, &pkgs, error))
return FALSE;
*out_is_local = (pkgs != NULL && g_strv_length (pkgs) > 0);
return TRUE;
}
gboolean
rpmostree_split_path_ptrarray_validate (const char *path,
GPtrArray **out_components,

View File

@ -95,17 +95,6 @@ _rpmostree_util_next_version (const char *auto_version_prefix,
GKeyFile *
_rpmostree_util_keyfile_clone (GKeyFile *keyfile);
gboolean
_rpmostree_util_parse_origin (GKeyFile *origin,
char **out_refspec,
char ***out_packages,
GError **error);
gboolean
_rpmostree_origin_is_locally_assembled (GKeyFile *origin,
gboolean *out_is_local,
GError **error);
gboolean
rpmostree_split_path_ptrarray_validate (const char *path,
GPtrArray **out_components,