flatpak_remote_state_fetch_commit_object (FlatpakRemoteState *self,
                                          FlatpakDir   *dir,
                                          const char   *ref,
                                          const char   *checksum,
                                          const char   *token,
                                          GCancellable *cancellable,
                                          GError      **error)
{
  g_autofree char *base_url = NULL;
  g_autofree char *object_url = NULL;
  g_autofree char *part1 = NULL;
  g_autofree char *part2 = NULL;
  g_autoptr(GBytes) bytes = NULL;
  g_autoptr(GVariant) commit_data = NULL;
  g_autoptr(GVariant) commit_metadata = NULL;

  if (!ostree_repo_remote_get_url (dir->repo, self->remote_name, &base_url, error))
    return NULL;

  ensure_soup_session (dir);

  part1 = g_strndup (checksum, 2);
  part2 = g_strdup_printf ("%s.commit", checksum + 2);

  object_url = g_build_filename (base_url, "objects", part1, part2, NULL);

  bytes = flatpak_load_uri (dir->soup_session, object_url, 0, token,
                            NULL, NULL, NULL,
                            cancellable, error);
  if (bytes == NULL)
    return NULL;

  commit_data = g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_COMMIT_GVARIANT_FORMAT,
                                                              bytes, FALSE));

  /* We downloaded this without validating the signature, so we do some basic verification
     of it. However, the signature will be checked when the download is done, and the final
     metadata is compared to what we got here, so its pretty ok to use it for resolving
     the transaction op. However, we do some basic checks. */
  if (!ostree_validate_structureof_commit (commit_data, error))
    return NULL;

  commit_metadata = g_variant_get_child_value (commit_data, 0);
  if (ref != NULL)
    {
      const char *xa_ref = NULL;
      const char *collection_binding = NULL;
      g_autofree const char **commit_refs = NULL;

      if ((g_variant_lookup (commit_metadata, "xa.ref", "&s", &xa_ref) &&
           g_strcmp0 (xa_ref, ref) != 0) ||
          (g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_REF_BINDING, "^a&s", &commit_refs) &&
           !g_strv_contains ((const char * const *) commit_refs, ref)))
        {
          flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Commit has no requested ref ‘%s’ in ref binding metadata"),  ref);
          return NULL;
        }

      /* Check that the locally configured collection ID is correct by looking
       * for it in the commit metadata */
      if (self->collection_id != NULL &&
          (!g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_COLLECTION_BINDING, "&s", &collection_binding) ||
           g_strcmp0 (self->collection_id, collection_binding) != 0))
        {
          g_autoptr(GVariantIter) collection_refs_iter = NULL;
          gboolean found_in_collection_refs_binding = FALSE;
          /* Note: the OSTREE_COMMIT_META_... define for this is not yet merged
           * in https://github.com/ostreedev/ostree/pull/1805 */
          if (g_variant_lookup (commit_metadata, "ostree.collection-refs-binding", "a(ss)", &collection_refs_iter))
            {
              const gchar *crb_collection_id, *crb_ref_name;
              while (g_variant_iter_loop (collection_refs_iter, "(&s&s)", &crb_collection_id, &crb_ref_name))
                {
                  if (g_strcmp0 (self->collection_id, crb_collection_id) == 0 &&
                      g_strcmp0 (ref, crb_ref_name) == 0)
                    {
                      found_in_collection_refs_binding = TRUE;
                      break;
                    }
                }
            }

          if (!found_in_collection_refs_binding)
            {
              flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA,
                                  _("Configured collection ID ‘%s’ not in binding metadata"),
                                  self->collection_id);
              return NULL;
            }
        }
    }

  return g_steal_pointer (&commit_data);
}
flatpak_remote_state_fetch_commit_object (FlatpakRemoteState *self,
                                          FlatpakDir   *dir,
                                          const char   *ref,
                                          const char   *checksum,
                                          const char   *token,
                                          GCancellable *cancellable,
                                          GError      **error)
{
  g_autofree char *base_url = NULL;
  g_autofree char *object_url = NULL;
  g_autofree char *part1 = NULL;
  g_autofree char *part2 = NULL;
  g_autoptr(GBytes) bytes = NULL;
  g_autoptr(GVariant) commit_data = NULL;
  g_autoptr(GVariant) commit_metadata = NULL;

  if (!ostree_repo_remote_get_url (dir->repo, self->remote_name, &base_url, error))
    return NULL;

  ensure_soup_session (dir);

  part1 = g_strndup (checksum, 2);
  part2 = g_strdup_printf ("%s.commit", checksum + 2);

  object_url = g_build_filename (base_url, "objects", part1, part2, NULL);

  bytes = flatpak_load_uri (dir->soup_session, object_url, 0, token,
                            NULL, NULL, NULL,
                            cancellable, error);
  if (bytes == NULL)
    return NULL;

  commit_data = g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_COMMIT_GVARIANT_FORMAT,
                                                              bytes, FALSE));

   
  if (!ostree_validate_structureof_commit (commit_data, error))
    return NULL;

  commit_metadata = g_variant_get_child_value (commit_data, 0);
  if (ref != NULL)
    {
      const char *xa_ref = NULL;
      const char *collection_binding = NULL;
      g_autofree const char **commit_refs = NULL;

      if ((g_variant_lookup (commit_metadata, "xa.ref", "&s", &xa_ref) &&
           g_strcmp0 (xa_ref, ref) != 0) ||
          (g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_REF_BINDING, "^a&s", &commit_refs) &&
           !g_strv_contains ((const char * const *) commit_refs, ref)))
        {
          flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Commit has no requested ref ‘%s’ in ref binding metadata"),  ref);
          return NULL;
        }

       
      if (self->collection_id != NULL &&
          (!g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_COLLECTION_BINDING, "&s", &collection_binding) ||
           g_strcmp0 (self->collection_id, collection_binding) != 0))
        {
          g_autoptr(GVariantIter) collection_refs_iter = NULL;
          gboolean found_in_collection_refs_binding = FALSE;
           
          if (g_variant_lookup (commit_metadata, "ostree.collection-refs-binding", "a(ss)", &collection_refs_iter))
            {
              const gchar *crb_collection_id, *crb_ref_name;
              while (g_variant_iter_loop (collection_refs_iter, "(&s&s)", &crb_collection_id, &crb_ref_name))
                {
                  if (g_strcmp0 (self->collection_id, crb_collection_id) == 0 &&
                      g_strcmp0 (ref, crb_ref_name) == 0)
                    {
                      found_in_collection_refs_binding = TRUE;
                      break;
                    }
                }
            }

          if (!found_in_collection_refs_binding)
            {
              flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA,
                                  _("Configured collection ID ‘%s’ not in binding metadata"),
                                  self->collection_id);
              return NULL;
            }
        }
    }

  return g_steal_pointer (&commit_data);
}