diff --git a/Makefile-libpriv.am b/Makefile-libpriv.am index d19f5e05..1fbe45f0 100644 --- a/Makefile-libpriv.am +++ b/Makefile-libpriv.am @@ -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 \ diff --git a/src/daemon/rpmostree-sysroot-upgrader.c b/src/daemon/rpmostree-sysroot-upgrader.c index 70aeab93..cefe66f6 100644 --- a/src/daemon/rpmostree-sysroot-upgrader.c +++ b/src/daemon/rpmostree-sysroot-upgrader.c @@ -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, diff --git a/src/daemon/rpmostree-sysroot-upgrader.h b/src/daemon/rpmostree-sysroot-upgrader.h index 5cfd6941..99a8fa0f 100644 --- a/src/daemon/rpmostree-sysroot-upgrader.h +++ b/src/daemon/rpmostree-sysroot-upgrader.h @@ -21,6 +21,7 @@ #pragma once #include +#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); diff --git a/src/daemon/rpmostreed-deployment-utils.c b/src/daemon/rpmostreed-deployment-utils.c index 8e6e8d7a..8123cbc5 100644 --- a/src/daemon/rpmostreed-deployment-utils.c +++ b/src/daemon/rpmostreed-deployment-utils.c @@ -19,6 +19,8 @@ #include "config.h" #include "rpmostreed-deployment-utils.h" +#include "rpmostree-origin.h" +#include "rpmostree-util.h" #include @@ -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); diff --git a/src/daemon/rpmostreed-deployment-utils.h b/src/daemon/rpmostreed-deployment-utils.h index 8dbc273c..da004650 100644 --- a/src/daemon/rpmostreed-deployment-utils.h +++ b/src/daemon/rpmostreed-deployment-utils.h @@ -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, diff --git a/src/daemon/rpmostreed-os.c b/src/daemon/rpmostreed-os.c index 9d0a2ee0..bb6c2f09 100644 --- a/src/daemon/rpmostreed-os.c +++ b/src/daemon/rpmostreed-os.c @@ -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 (); diff --git a/src/daemon/rpmostreed-transaction-types.c b/src/daemon/rpmostreed-transaction-types.c index 966d56b4..ff3318d8 100644 --- a/src/daemon/rpmostreed-transaction-types.c +++ b/src/daemon/rpmostreed-transaction-types.c @@ -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; diff --git a/src/libpriv/rpmostree-origin.c b/src/libpriv/rpmostree-origin.c new file mode 100644 index 00000000..40b2a8e8 --- /dev/null +++ b/src/libpriv/rpmostree-origin.c @@ -0,0 +1,146 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2017 Colin Walters + * + * 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); +} diff --git a/src/libpriv/rpmostree-origin.h b/src/libpriv/rpmostree-origin.h new file mode 100644 index 00000000..b8c79c5d --- /dev/null +++ b/src/libpriv/rpmostree-origin.h @@ -0,0 +1,85 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2017 Colin Walters + * + * 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 + +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); + diff --git a/src/libpriv/rpmostree-util.c b/src/libpriv/rpmostree-util.c index 34289cec..ab381b6f 100644 --- a/src/libpriv/rpmostree-util.c +++ b/src/libpriv/rpmostree-util.c @@ -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, diff --git a/src/libpriv/rpmostree-util.h b/src/libpriv/rpmostree-util.h index 24fb44bc..937653b7 100644 --- a/src/libpriv/rpmostree-util.h +++ b/src/libpriv/rpmostree-util.h @@ -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,