diff --git a/src/daemon/rpmostree-sysroot-core.c b/src/daemon/rpmostree-sysroot-core.c index 73507237..52678696 100644 --- a/src/daemon/rpmostree-sysroot-core.c +++ b/src/daemon/rpmostree-sysroot-core.c @@ -384,6 +384,48 @@ rpmostree_syscore_add_deployment (OstreeSysroot *sysroot, return g_steal_pointer (&new_deployments); } +/* Find the pending and rollback deployments (if any) for @osname. */ +void +rpmostree_syscore_query_deployments (OstreeSysroot *sysroot, + const char *osname, + OstreeDeployment **out_pending, + OstreeDeployment **out_rollback) +{ + g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot); + OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); + g_autoptr(OstreeDeployment) ret_pending = NULL; + g_autoptr(OstreeDeployment) ret_rollback = NULL; + + gboolean found_booted = FALSE; + for (guint i = 0; i < deployments->len; i++) + { + OstreeDeployment *deployment = deployments->pdata[i]; + + /* Is this deployment booted? If so, note we're past the booted */ + if (booted_deployment != NULL && + ostree_deployment_equal (deployment, booted_deployment)) + { + found_booted = TRUE; + continue; + } + + /* Ignore deployments not for this osname */ + if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0) + continue; + + if (!found_booted && !ret_pending) + ret_pending = g_object_ref (deployment); + + if (found_booted && !ret_rollback) + ret_rollback = g_object_ref (deployment); + } + if (out_pending) + *out_pending = g_steal_pointer (&ret_pending); + if (out_rollback) + *out_rollback = g_steal_pointer (&ret_rollback); +} + + /* Also a variant of ostree_sysroot_simple_write_deployment(), but here we are * just trying to remove a pending and/or rollback. */ diff --git a/src/daemon/rpmostree-sysroot-core.h b/src/daemon/rpmostree-sysroot-core.h index 407c9c31..afdb9fa4 100644 --- a/src/daemon/rpmostree-sysroot-core.h +++ b/src/daemon/rpmostree-sysroot-core.h @@ -42,6 +42,11 @@ GPtrArray *rpmostree_syscore_add_deployment (OstreeSysroot *sysroot, OstreeDeployment *merge_deployment, gboolean pushing_rollback); +void rpmostree_syscore_query_deployments (OstreeSysroot *sysroot, + const char *osname, + OstreeDeployment **out_pending, + OstreeDeployment **out_rollback); + GPtrArray *rpmostree_syscore_filter_deployments (OstreeSysroot *sysroot, const char *osname, gboolean remove_pending, diff --git a/src/daemon/rpmostreed-deployment-utils.c b/src/daemon/rpmostreed-deployment-utils.c index f05ea3d4..6cc2f0f8 100644 --- a/src/daemon/rpmostreed-deployment-utils.c +++ b/src/daemon/rpmostreed-deployment-utils.c @@ -346,60 +346,3 @@ rpmostreed_commit_generate_cached_details_variant (OstreeDeployment *deployment, g_variant_dict_insert (&dict, "gpg-enabled", "b", gpg_enabled); return g_variant_dict_end (&dict); } - -gint -rpmostreed_rollback_deployment_index (const gchar *name, - OstreeSysroot *ot_sysroot, - GError **error) -{ - g_autoptr(GPtrArray) deployments = NULL; - glnx_unref_object OstreeDeployment *merge_deployment = NULL; - - gint index_to_prepend = -1; - gint merge_index = -1; - gint previous_index = -1; - guint i; - - merge_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name); - if (merge_deployment == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No deployments found for os %s", name); - goto out; - } - - deployments = ostree_sysroot_get_deployments (ot_sysroot); - if (deployments->len < 2) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Found %u deployments, at least 2 required for rollback", - deployments->len); - goto out; - } - - g_assert (merge_deployment != NULL); - for (i = 0; i < deployments->len; i++) - { - if (deployments->pdata[i] == merge_deployment) - merge_index = i; - - if (g_strcmp0 (ostree_deployment_get_osname (deployments->pdata[i]), name) == 0 && - deployments->pdata[i] != merge_deployment && - previous_index < 0) - { - previous_index = i; - } - } - - g_assert (merge_index < deployments->len); - g_assert (deployments->pdata[merge_index] == merge_deployment); - - /* If merge deployment is not booted assume we are using it. */ - if (merge_index == 0 && previous_index > 0) - index_to_prepend = previous_index; - else - index_to_prepend = merge_index; - -out: - return index_to_prepend; -} diff --git a/src/daemon/rpmostreed-deployment-utils.h b/src/daemon/rpmostreed-deployment-utils.h index 68f31238..f47adf15 100644 --- a/src/daemon/rpmostreed-deployment-utils.h +++ b/src/daemon/rpmostreed-deployment-utils.h @@ -40,7 +40,3 @@ GVariant * rpmostreed_commit_generate_cached_details_variant (OstreeDeploym OstreeRepo *repo, const gchar *refspec, GError **error); - -gint rpmostreed_rollback_deployment_index (const gchar *name, - OstreeSysroot *ot_sysroot, - GError **error); diff --git a/src/daemon/rpmostreed-os.c b/src/daemon/rpmostreed-os.c index a62abb98..b4cdc315 100644 --- a/src/daemon/rpmostreed-os.c +++ b/src/daemon/rpmostreed-os.c @@ -27,6 +27,7 @@ #include "rpmostree-package-variants.h" #include "rpmostreed-errors.h" #include "rpmostree-origin.h" +#include "rpmostree-sysroot-core.h" #include "rpmostreed-os.h" #include "rpmostreed-utils.h" #include "rpmostree-util.h" @@ -1172,9 +1173,6 @@ rpmostreed_os_load_internals (RpmostreedOS *self, GError **error) GVariant *cached_update = NULL; gboolean has_cached_updates = FALSE; - gint rollback_index; - guint i; - name = rpmostree_os_get_name (RPMOSTREE_OS (self)); g_debug ("loading %s", name); @@ -1192,7 +1190,7 @@ rpmostreed_os_load_internals (RpmostreedOS *self, GError **error) } deployments = ostree_sysroot_get_deployments (ot_sysroot); - for (i=0; ilen; i++) + for (guint i=0; ilen; i++) { if (g_strcmp0 (ostree_deployment_get_osname (deployments->pdata[i]), name) == 0) { @@ -1206,17 +1204,21 @@ rpmostreed_os_load_internals (RpmostreedOS *self, GError **error) } } - if (deployments->len >= 2) + if (booted) { - rollback_index = rpmostreed_rollback_deployment_index (name, ot_sysroot, NULL); - if (rollback_index >= 0) - { - rollback_variant = rpmostreed_deployment_generate_variant (ot_sysroot, - deployments->pdata[rollback_index], booted_id, - ot_repo, error); - if (!rollback_variant) - return FALSE; - } + g_autoptr(OstreeDeployment) pending = NULL; + g_autoptr(OstreeDeployment) rollback = NULL; + + rpmostree_syscore_query_deployments (ot_sysroot, ostree_deployment_get_osname (booted), + NULL, &rollback); + + if (rollback) + { + rollback_variant = rpmostreed_deployment_generate_variant (ot_sysroot, rollback, booted_id, + ot_repo, error); + if (!rollback_variant) + return FALSE; + } } merge_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name); diff --git a/src/daemon/rpmostreed-transaction-types.c b/src/daemon/rpmostreed-transaction-types.c index 9980da34..fbbe904c 100644 --- a/src/daemon/rpmostreed-transaction-types.c +++ b/src/daemon/rpmostreed-transaction-types.c @@ -344,42 +344,38 @@ rollback_transaction_execute (RpmostreedTransaction *transaction, { RollbackTransaction *self; OstreeSysroot *sysroot; - OstreeDeployment *deployment; g_autoptr(GPtrArray) old_deployments = NULL; g_autoptr(GPtrArray) new_deployments = NULL; - - gint rollback_index; - guint i; + g_autoptr(OstreeDeployment) rollback_deployment = NULL; gboolean ret = FALSE; self = (RollbackTransaction *) transaction; sysroot = rpmostreed_transaction_get_sysroot (transaction); - rollback_index = rpmostreed_rollback_deployment_index (self->osname, sysroot, error); - if (rollback_index < 0) - goto out; + rpmostree_syscore_query_deployments (sysroot, self->osname, NULL, &rollback_deployment); + if (!rollback_deployment) + { + (void) glnx_throw (error, "No rollback deployment found"); + goto out; + } old_deployments = ostree_sysroot_get_deployments (sysroot); new_deployments = g_ptr_array_new_with_free_func (g_object_unref); - /* build out the reordered array */ - - deployment = old_deployments->pdata[rollback_index]; - g_ptr_array_add (new_deployments, g_object_ref (deployment)); + /* build out the reordered array; rollback is first now */ + g_ptr_array_add (new_deployments, g_object_ref (rollback_deployment)); rpmostreed_transaction_emit_message_printf (transaction, "Moving '%s.%d' to be first deployment", - ostree_deployment_get_csum (deployment), - ostree_deployment_get_deployserial (deployment)); + ostree_deployment_get_csum (rollback_deployment), + ostree_deployment_get_deployserial (rollback_deployment)); - for (i = 0; i < old_deployments->len; i++) + for (guint i = 0; i < old_deployments->len; i++) { - if (i == rollback_index) - continue; - - deployment = old_deployments->pdata[i]; - g_ptr_array_add (new_deployments, g_object_ref (deployment)); + OstreeDeployment *deployment = old_deployments->pdata[i]; + if (deployment != rollback_deployment) + g_ptr_array_add (new_deployments, g_object_ref (deployment)); } /* if default changed write it */ @@ -396,7 +392,6 @@ rollback_transaction_execute (RpmostreedTransaction *transaction, rpmostreed_reboot (cancellable, error); ret = TRUE; - out: return ret; }