gboolean ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GOptionContext) context = NULL; glnx_unref_object OstreeSysroot *sysroot = NULL; glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL; g_autoptr(GKeyFile) origin = NULL; glnx_unref_object OstreeAsyncProgress *progress = NULL; gboolean changed; OstreeSysrootUpgraderPullFlags upgraderpullflags = 0; context = g_option_context_new ("Construct new tree from current origin and deploy it, if it changed"); if (!ostree_admin_option_context_parse (context, options, &argc, &argv, OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER, &sysroot, cancellable, error)) goto out; if (!ostree_sysroot_load (sysroot, cancellable, error)) goto out; upgrader = ostree_sysroot_upgrader_new_for_os (sysroot, opt_osname, cancellable, error); if (!upgrader) goto out; origin = ostree_sysroot_upgrader_dup_origin (upgrader); if (origin != NULL) { gboolean origin_changed = FALSE; if (opt_override_commit != NULL) { /* Override the commit to pull and deploy. */ g_key_file_set_string (origin, "origin", "override-commit", opt_override_commit); origin_changed = TRUE; } else { /* Strip any override-commit from the origin file so * we always upgrade to the latest available commit. */ origin_changed = g_key_file_remove_key (origin, "origin", "override-commit", NULL); } /* Should we consider requiring --discard-hotfix here? */ origin_changed |= g_key_file_remove_key (origin, "origin", "unlocked", NULL); if (origin_changed) { /* XXX GCancellable parameter is not used. */ if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, NULL, error)) goto out; } } { g_auto(GLnxConsoleRef) console = { 0, }; glnx_console_lock (&console); if (console.is_tty) progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console); if (opt_allow_downgrade) upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER; if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags, progress, &changed, cancellable, error)) goto out; if (progress) ostree_async_progress_finish (progress); } if (!changed) { g_print ("No update available.\n"); } else { if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error)) goto out; if (opt_reboot) { if (!ot_admin_execve_reboot (sysroot, error)) goto out; } } ret = TRUE; out: return ret; }
gboolean ot_admin_builtin_upgrade (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = g_option_context_new (""); g_autoptr(OstreeSysroot) sysroot = NULL; if (!ostree_admin_option_context_parse (context, options, &argc, &argv, OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER, invocation, &sysroot, cancellable, error)) return FALSE; if (opt_pull_only && opt_deploy_only) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Cannot simultaneously specify --pull-only and --deploy-only"); return FALSE; } else if (opt_pull_only && opt_reboot) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Cannot simultaneously specify --pull-only and --reboot"); return FALSE; } g_autoptr(OstreeSysrootUpgrader) upgrader = ostree_sysroot_upgrader_new_for_os (sysroot, opt_osname, cancellable, error); if (!upgrader) return FALSE; g_autoptr(GKeyFile) origin = ostree_sysroot_upgrader_dup_origin (upgrader); if (origin != NULL) { gboolean origin_changed = FALSE; if (opt_override_commit != NULL) { /* Override the commit to pull and deploy. */ g_key_file_set_string (origin, "origin", "override-commit", opt_override_commit); origin_changed = TRUE; } else { /* Strip any override-commit from the origin file so * we always upgrade to the latest available commit. */ origin_changed = g_key_file_remove_key (origin, "origin", "override-commit", NULL); } /* Should we consider requiring --discard-hotfix here? */ origin_changed |= g_key_file_remove_key (origin, "origin", "unlocked", NULL); if (origin_changed) { /* XXX GCancellable parameter is not used. */ if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, NULL, error)) return FALSE; } } gboolean changed; OstreeSysrootUpgraderPullFlags upgraderpullflags = 0; if (opt_deploy_only) upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_SYNTHETIC; { g_auto(GLnxConsoleRef) console = { 0, }; glnx_console_lock (&console); g_autoptr(OstreeAsyncProgress) progress = NULL; if (console.is_tty) progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console); if (opt_allow_downgrade) upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER; if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags, progress, &changed, cancellable, error)) { /* In the pull-only case, we do a cleanup here to ensure that if * multiple commits were pulled, we garbage collect any old * partially-pulled intermediate commits before pulling more. This is * really a best practice in general, but for maximum compatiblity, we * only do cleanup if a user specifies the new --pull-only option. * Otherwise, we would break the case of trying to deploy a commit that * isn't directly referenced. */ if (opt_pull_only) (void) ostree_sysroot_cleanup (sysroot, NULL, NULL); return FALSE; } if (progress) ostree_async_progress_finish (progress); } if (!changed) { g_print ("No update available.\n"); } else { if (!opt_pull_only) { if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error)) return FALSE; } if (opt_reboot) { if (!ot_admin_execve_reboot (sysroot, error)) return FALSE; } } return TRUE; }
static gboolean package_diff_transaction_execute (RpmostreedTransaction *transaction, GCancellable *cancellable, GError **error) { PackageDiffTransaction *self; OstreeSysroot *sysroot; glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL; glnx_unref_object OstreeAsyncProgress *progress = NULL; glnx_unref_object OstreeRepo *repo = NULL; g_autoptr(GKeyFile) origin = NULL; g_autofree gchar *origin_description = NULL; OstreeSysrootUpgraderPullFlags upgrader_flags = 0; gboolean upgrading = FALSE; gboolean changed = FALSE; gboolean ret = FALSE; self = (PackageDiffTransaction *) transaction; sysroot = rpmostreed_transaction_get_sysroot (transaction); upgrader = ostree_sysroot_upgrader_new_for_os (sysroot, self->osname, 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); /* Determine if we're upgrading before we set the refspec. */ upgrading = (self->refspec == NULL && self->revision == NULL); if (self->refspec != NULL) { if (!change_upgrader_refspec (sysroot, upgrader, self->refspec, cancellable, 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, "Booted deployment has no origin"); goto out; } progress = ostree_async_progress_new (); rpmostreed_transaction_connect_download_progress (transaction, progress); rpmostreed_transaction_connect_signature_progress (transaction, repo); if (self->revision != NULL) { 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, error)) goto out; if (version != NULL) { rpmostreed_transaction_emit_message_printf (transaction, "Resolving version '%s'", version); if (!rpmostreed_repo_lookup_version (repo, self->refspec, version, progress, cancellable, &checksum, error)) goto out; } g_key_file_set_string (origin, "origin", "override-commit", checksum); if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, cancellable, error)) goto out; } 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; } } origin_description = ostree_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)) goto out; rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction)); if (!changed) { if (upgrading) rpmostreed_transaction_emit_message_printf (transaction, "No upgrade available."); else rpmostreed_transaction_emit_message_printf (transaction, "No change."); } ret = TRUE; out: return ret; }