static int
pkg_change (RPMOSTreeSysroot *sysroot_proxy,
            const char *const* packages_to_add,
            const char *const* packages_to_remove,
            GCancellable  *cancellable,
            GError       **error)
{
  int exit_status = EXIT_FAILURE;
  glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
  g_autoptr(GVariant) default_deployment = NULL;
  g_autofree char *transaction_address = NULL;
  const char *const strv_empty[] = { NULL };

  if (!packages_to_add)
    packages_to_add = strv_empty;
  if (!packages_to_remove)
    packages_to_remove = strv_empty;

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

  if (!rpmostree_os_call_pkg_change_sync (os_proxy,
                                          get_args_variant (),
                                          packages_to_add,
                                          packages_to_remove,
                                          &transaction_address,
                                          cancellable,
                                          error))
    goto out;

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

  if (opt_dry_run)
    {
      g_print ("Exiting because of '--dry-run' option\n");
    }
  else if (!opt_reboot)
    {
      const char *sysroot_path;


      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;
}
static gboolean
pkg_change (RpmOstreeCommandInvocation *invocation,
            RPMOSTreeSysroot *sysroot_proxy,
            const char *const* packages_to_add,
            const char *const* packages_to_remove,
            GCancellable  *cancellable,
            GError       **error)
{
  const char *const strv_empty[] = { NULL };

  if (!packages_to_add)
    packages_to_add = strv_empty;
  if (!packages_to_remove)
    packages_to_remove = strv_empty;

  glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
  if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname,
                                cancellable, &os_proxy, error))
    return FALSE;

  g_autoptr(GVariant) previous_deployment = rpmostree_os_dup_default_deployment (os_proxy);

  GVariantDict dict;
  g_variant_dict_init (&dict, NULL);
  g_variant_dict_insert (&dict, "reboot", "b", opt_reboot);
  g_variant_dict_insert (&dict, "cache-only", "b", opt_cache_only);
  g_variant_dict_insert (&dict, "download-only", "b", opt_download_only);
  g_variant_dict_insert (&dict, "no-pull-base", "b", TRUE);
  g_variant_dict_insert (&dict, "dry-run", "b", opt_dry_run);
  g_variant_dict_insert (&dict, "allow-inactive", "b", opt_allow_inactive);
  g_variant_dict_insert (&dict, "no-layering", "b", opt_uninstall_all);
  g_autoptr(GVariant) options = g_variant_ref_sink (g_variant_dict_end (&dict));

  gboolean met_local_pkg = FALSE;
  for (const char *const* it = packages_to_add; it && *it; it++)
    met_local_pkg = met_local_pkg || g_str_has_suffix (*it, ".rpm");

  /* Use newer D-Bus API only if we have to. */
  g_autofree char *transaction_address = NULL;
  if (met_local_pkg)
    {
      if (!rpmostree_update_deployment (os_proxy,
                                        NULL, /* refspec */
                                        NULL, /* revision */
                                        packages_to_add,
                                        packages_to_remove,
                                        NULL, /* override replace */
                                        NULL, /* override remove */
                                        NULL, /* override reset */
                                        options,
                                        &transaction_address,
                                        cancellable,
                                        error))
        return FALSE;
    }
  else
    {
      if (!rpmostree_os_call_pkg_change_sync (os_proxy,
                                              options,
                                              packages_to_add,
                                              packages_to_remove,
                                              NULL,
                                              &transaction_address,
                                              NULL,
                                              cancellable,
                                              error))
        return FALSE;
    }

  return rpmostree_transaction_client_run (invocation, sysroot_proxy, os_proxy,
                                           options, FALSE,
                                           transaction_address,
                                           previous_deployment,
                                           cancellable, error);
}