int
rpmostree_builtin_deploy (int            argc,
                          char         **argv,
                          GCancellable  *cancellable,
                          GError       **error)
{
  int exit_status = EXIT_FAILURE;
  g_autoptr(GOptionContext) context = NULL;
  glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
  glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL;
  g_autoptr(GVariant) default_deployment = NULL;
  g_autofree char *transaction_address = NULL;
  const char * const packages[] = { NULL };
  const char *revision;

  context = g_option_context_new ("REVISION - Deploy a specific commit");

  if (!rpmostree_option_context_parse (context,
                                       option_entries,
                                       &argc, &argv,
                                       RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT,
                                       cancellable,
                                       &sysroot_proxy,
                                       error))
    goto out;

  if (argc < 2)
    {
      rpmostree_usage_error (context, "REVISION must be specified", error);
      goto out;
    }

  revision = argv[1];

  if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname,
                                cancellable, &os_proxy, error))
    goto out;

  if (opt_preview)
    {
      if (!rpmostree_os_call_download_deploy_rpm_diff_sync (os_proxy,
                                                            revision,
                                                            packages,
                                                            &transaction_address,
                                                            cancellable,
                                                            error))
        goto out;
    }
  else
    {
      /* This will set the GVariant if the default deployment changes. */
      g_signal_connect (os_proxy, "notify::default-deployment",
                        G_CALLBACK (default_deployment_changed_cb),
                        &default_deployment);

      if (!rpmostree_os_call_deploy_sync (os_proxy,
                                          revision,
                                          get_args_variant (),
                                          &transaction_address,
                                          cancellable,
                                          error))
        goto out;
    }

  if (!rpmostree_transaction_get_response_sync (sysroot_proxy,
                                                transaction_address,
                                                cancellable,
                                                error))
    goto out;

  if (opt_preview)
    {
      g_autoptr(GVariant) result = NULL;
      g_autoptr(GVariant) details = NULL;

      if (!rpmostree_os_call_get_cached_deploy_rpm_diff_sync (os_proxy,
                                                              revision,
                                                              packages,
                                                              &result,
                                                              &details,
                                                              cancellable,
                                                              error))
        goto out;

      if (g_variant_n_children (result) == 0)
        {
          exit_status = RPM_OSTREE_EXIT_UNCHANGED;
          goto out;
        }

      rpmostree_print_package_diffs (result);
    }
  else if (!opt_reboot)
    {
      const char *sysroot_path;

      if (default_deployment == NULL)
        {
          exit_status = RPM_OSTREE_EXIT_UNCHANGED;
          goto out;
        }

      sysroot_path = rpmostree_sysroot_get_path (sysroot_proxy);

      if (!rpmostree_print_treepkg_diff_from_sysroot_path (sysroot_path,
                                                           cancellable,
                                                           error))
        goto out;

      g_print ("Run \"systemctl reboot\" to start a reboot\n");
    }

  exit_status = EXIT_SUCCESS;

out:
  /* Does nothing if using the message bus. */
  rpmostree_cleanup_peer ();

  return exit_status;
}
int
rpmostree_builtin_upgrade (int             argc,
                           char          **argv,
                           GCancellable   *cancellable,
                           GError        **error)
{
  int exit_status = EXIT_FAILURE;

  GOptionContext *context = g_option_context_new ("- Perform a system upgrade");
  glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
  glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL;
  g_autoptr(GVariant) default_deployment = NULL;
  g_autofree char *transaction_address = NULL;

  if (!rpmostree_option_context_parse (context,
                                       option_entries,
                                       &argc, &argv,
                                       RPM_OSTREE_BUILTIN_FLAG_NONE,
                                       cancellable,
                                       &sysroot_proxy,
                                       error))
    goto out;

  if (opt_reboot && opt_preview)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
                   "Cannot specify both --reboot and --preview");
      goto out;
    }

  if (opt_reboot && opt_check)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
                   "Cannot specify both --reboot and --check");
      goto out;
    }

  /* If both --check and --preview were passed, --preview overrides. */
  if (opt_preview)
    opt_check = FALSE;

  if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname,
                                cancellable, &os_proxy, error))
    goto out;

  if (opt_preview || opt_check)
    {
      if (!rpmostree_os_call_download_update_rpm_diff_sync (os_proxy,
                                                            &transaction_address,
                                                            cancellable,
                                                            error))
        goto out;
    }
  else
    {
      g_signal_connect (os_proxy, "notify::default-deployment",
                        G_CALLBACK (default_changed_callback),
                        &default_deployment);

      if (!rpmostree_os_call_upgrade_sync (os_proxy,
                                           get_args_variant (),
                                           &transaction_address,
                                           cancellable,
                                           error))
        goto out;
    }

  if (!rpmostree_transaction_get_response_sync (sysroot_proxy,
                                                transaction_address,
                                                cancellable,
                                                error))
    goto out;

  if (opt_preview || opt_check)
    {
      g_autoptr(GVariant) result = NULL;
      g_autoptr(GVariant) details = NULL;

      if (!rpmostree_os_call_get_cached_update_rpm_diff_sync (os_proxy,
                                                              "",
                                                              &result,
                                                              &details,
                                                              cancellable,
                                                              error))
        goto out;

      if (g_variant_n_children (result) == 0)
        {
          exit_status = RPM_OSTREE_EXIT_UNCHANGED;
          goto out;
        }

      if (!opt_check)
        rpmostree_print_package_diffs (result);
    }
  else if (!opt_reboot)
    {
      const char *sysroot_path;

      if (default_deployment == NULL)
        {
          exit_status = RPM_OSTREE_EXIT_UNCHANGED;
          goto out;
        }

      sysroot_path = rpmostree_sysroot_get_path (sysroot_proxy);

      if (!rpmostree_print_treepkg_diff_from_sysroot_path (sysroot_path,
                                                           cancellable,
                                                           error))
        goto out;

      g_print ("Run \"systemctl reboot\" to start a reboot\n");
    }

  exit_status = EXIT_SUCCESS;

out:
  /* Does nothing if using the message bus. */
  rpmostree_cleanup_peer ();

  return exit_status;
}