static gboolean
_builtin_db_version (OstreeRepo *repo, GPtrArray *revs,
                     GCancellable   *cancellable,
                     GError        **error)
{
  for (guint num = 0; num < revs->len; num++)
    {
      char *rev = revs->pdata[num];
      g_autoptr(RpmRevisionData) rpmrev = NULL;
      g_autofree char *rpmdbv = NULL;
      char *mrev = strstr (rev, "..");

      if (mrev)
        {
          g_autoptr(GPtrArray) range_revs = NULL;
          g_autofree char *revdup = g_strdup (rev);

          mrev = revdup + (mrev - rev);
          *mrev = 0;
          mrev += 2;

          if (!*mrev)
            mrev = NULL;

          range_revs = _rpmostree_util_get_commit_hashes (repo, revdup, mrev, cancellable, error);
          if (!range_revs)
            return FALSE;

          if (!_builtin_db_version (repo, range_revs,
                                    cancellable, error))
            return FALSE;

          continue;
        }

        rpmrev = rpmrev_new (repo, rev, NULL, cancellable, error);
        if (!rpmrev)
          return FALSE;

        rpmdbv = rpmhdrs_rpmdbv (rpmrev_get_headers (rpmrev),
                                 cancellable, error);
        if (rpmdbv == NULL)
          return FALSE;

        /* FIXME: g_console? */
        if (!g_str_equal (rev, rpmrev_get_commit (rpmrev)))
          printf ("ostree commit: %s (%s)\n", rev, rpmrev_get_commit (rpmrev));
        else
          printf ("ostree commit: %s\n", rev);

        printf ("  rpmdbv is: %66s\n", rpmdbv);
      }

  return TRUE;
}
static gboolean
_builtin_db_version (OstreeRepo *repo, GPtrArray *revs,
                     GCancellable   *cancellable,
                     GError        **error)
{
  int num = 0;
  gboolean ret = FALSE;

  for (num = 0; num < revs->len; num++)
    {
      char *rev = revs->pdata[num];
      _cleanup_rpmrev_ struct RpmRevisionData *rpmrev = NULL;
      gs_free char *rpmdbv = NULL;
      char *mrev = strstr (rev, "..");

      if (mrev)
        {
          gs_unref_ptrarray GPtrArray *range_revs = NULL;
          gs_free char *revdup = g_strdup (rev);

          mrev = revdup + (mrev - rev);
          *mrev = 0;
          mrev += 2;

          if (!*mrev)
            mrev = NULL;

          range_revs = _rpmostree_util_get_commit_hashes (repo, revdup, mrev, cancellable, error);
          if (!range_revs)
            goto out;

          if (!_builtin_db_version (repo, range_revs,
                                    cancellable, error))
            goto out;

          continue;
        }

        rpmrev = rpmrev_new (repo, rev, NULL, cancellable, error);
        if (!rpmrev)
          goto out;

        rpmdbv = rpmhdrs_rpmdbv (rpmrev_get_headers (rpmrev),
                                 cancellable, error);
        if (rpmdbv == NULL)
          goto out;

        /* FIXME: g_console? */
        if (!g_str_equal (rev, rpmrev_get_commit (rpmrev)))
          printf ("ostree commit: %s (%s)\n", rev, rpmrev_get_commit (rpmrev));
        else
          printf ("ostree commit: %s\n", rev);

        printf ("  rpmdbv is: %66s\n", rpmdbv);
      }

  ret = TRUE;

 out:
  return ret;
}
int
rpmostree_db_builtin_diff (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  int exit_status = EXIT_FAILURE;
  GOptionContext *context;
  glnx_unref_object OstreeRepo *repo = NULL;
  struct RpmRevisionData *rpmrev1 = NULL;
  struct RpmRevisionData *rpmrev2 = NULL;

  context = g_option_context_new ("COMMIT COMMIT - Show package changes between two commits");

  if (!rpmostree_db_option_context_parse (context, option_entries, &argc, &argv, &repo,
                                          cancellable, error))
    goto out;

  if (argc != 3)
    {
      g_autofree char *message = NULL;

      message = g_strdup_printf ("\"%s\" takes exactly 2 arguments",
                                 g_get_prgname ());
      rpmostree_usage_error (context, message, error);
      goto out;
    }

  if (!(rpmrev1 = rpmrev_new (repo, argv[1], NULL, cancellable, error)))
    goto out;

  if (!(rpmrev2 = rpmrev_new (repo, argv[2], NULL, cancellable, error)))
    goto out;

  if (!g_str_equal (argv[1], rpmrev_get_commit (rpmrev1)))
    printf ("ostree diff commit old: %s (%s)\n", argv[1], rpmrev_get_commit (rpmrev1));
  else
    printf ("ostree diff commit old: %s\n", argv[1]);

  if (!g_str_equal (argv[2], rpmrev_get_commit (rpmrev2)))
    printf ("ostree diff commit new: %s (%s)\n", argv[2], rpmrev_get_commit (rpmrev2));
  else
    printf ("ostree diff commit new: %s\n", argv[2]);

  if (opt_format == NULL)
    opt_format = "block";

  if (g_str_equal (opt_format, "diff"))
    {
      rpmhdrs_diff_prnt_diff (rpmhdrs_diff (rpmrev_get_headers (rpmrev1),
                                            rpmrev_get_headers (rpmrev2)));
    }
  else if (g_str_equal (opt_format, "block"))
    {
      rpmhdrs_diff_prnt_block (rpmhdrs_diff (rpmrev_get_headers (rpmrev1),
                                             rpmrev_get_headers (rpmrev2)));
    }
  else
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Format argument is invalid, pick one of: diff, block");
      goto out;
    }

  exit_status = EXIT_SUCCESS;

out:
  /* Free the RpmRevisionData structs explicitly *before* possibly removing
   * the database directory, since rpmhdrs_free() depends on that directory
   * being there. */
  rpmrev_free (rpmrev1);
  rpmrev_free (rpmrev2);

  g_option_context_free (context);

  return exit_status;
}