/**
 * ostree_repo_resolve_rev:
 * @self: Repo
 * @refspec: A refspec
 * @allow_noent: Do not throw an error if refspec does not exist
 * @out_rev: (out) (transfer full): A checksum,or %NULL if @allow_noent is true and it does not exist
 * @error: Error
 *
 * Look up the given refspec, returning the checksum it references in
 * the parameter @out_rev.
 */
gboolean
ostree_repo_resolve_rev (OstreeRepo     *self,
                         const char     *refspec,
                         gboolean        allow_noent,
                         char          **out_rev,
                         GError        **error)
{
    gboolean ret = FALSE;
    g_autofree char *ret_rev = NULL;

    g_return_val_if_fail (refspec != NULL, FALSE);

    if (ostree_validate_checksum_string (refspec, NULL))
    {
        ret_rev = g_strdup (refspec);
    }

    else if (!ostree_repo_resolve_partial_checksum (self, refspec, &ret_rev, error))
        goto out;

    if (!ret_rev)
    {
        if (error != NULL && *error != NULL)
            goto out;

        if (g_str_has_suffix (refspec, "^"))
        {
            g_autofree char *parent_refspec = NULL;
            g_autofree char *parent_rev = NULL;
            g_autoptr(GVariant) commit = NULL;

            parent_refspec = g_strdup (refspec);
            parent_refspec[strlen(parent_refspec) - 1] = '\0';

            if (!ostree_repo_resolve_rev (self, parent_refspec, allow_noent, &parent_rev, error))
                goto out;

            if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, parent_rev,
                                           &commit, error))
                goto out;

            if (!(ret_rev = ostree_commit_get_parent (commit)))
            {
                g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                             "Commit %s has no parent", parent_rev);
                goto out;
            }
        }
        else
        {
            g_autofree char *remote = NULL;
            g_autofree char *ref = NULL;

            if (!ostree_parse_refspec (refspec, &remote, &ref, error))
                goto out;

            if (!resolve_refspec (self, remote, ref, allow_noent,
                                  &ret_rev, error))
                goto out;
        }
    }

    ret = TRUE;
    ot_transfer_out_value (out_rev, &ret_rev);
out:
    return ret;
}
static gboolean
_ostree_repo_resolve_rev_internal (OstreeRepo     *self,
                                   const char     *refspec,
                                   gboolean        allow_noent,
                                   gboolean        fallback_remote,
                                   char          **out_rev,
                                   GError        **error)
{
  g_autofree char *ret_rev = NULL;

  g_return_val_if_fail (refspec != NULL, FALSE);

  if (ostree_validate_checksum_string (refspec, NULL))
    {
      ret_rev = g_strdup (refspec);
    }

  else if (!ostree_repo_resolve_partial_checksum (self, refspec, &ret_rev, error))
    return FALSE;

  if (!ret_rev)
    {
      if (error != NULL && *error != NULL)
        return FALSE;

      if (g_str_has_suffix (refspec, "^"))
        {
          g_autofree char *parent_refspec = NULL;
          g_autofree char *parent_rev = NULL;
          g_autoptr(GVariant) commit = NULL;

          parent_refspec = g_strdup (refspec);
          parent_refspec[strlen(parent_refspec) - 1] = '\0';

          if (!ostree_repo_resolve_rev (self, parent_refspec, allow_noent, &parent_rev, error))
            return FALSE;

          if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, parent_rev,
                                         &commit, error))
            return FALSE;

          if (!(ret_rev = ostree_commit_get_parent (commit)))
            return glnx_throw (error, "Commit %s has no parent", parent_rev);
        }
      else
        {
          g_autofree char *remote = NULL;
          g_autofree char *ref = NULL;

          if (!ostree_parse_refspec (refspec, &remote, &ref, error))
            return FALSE;

          if (!resolve_refspec (self, remote, ref, allow_noent,
                                fallback_remote, &ret_rev, error))
            return FALSE;
        }
    }

  ot_transfer_out_value (out_rev, &ret_rev);
  return TRUE;
}