flatpak_dir_find_local_related_for_metadata (FlatpakDir   *self,
                                             const char   *ref,
                                             const char   *remote_name,
                                             GKeyFile     *metakey,
                                             GCancellable *cancellable,
                                             GError      **error)
{
  int i;

  g_auto(GStrv) parts = NULL;
  g_autoptr(GPtrArray) related = g_ptr_array_new_with_free_func ((GDestroyNotify) flatpak_related_free);
  g_autofree char *collection_id = NULL;
  g_auto(GStrv) groups = NULL;

  /* Derive the collection ID from the remote we are querying. This will act as
   * a sanity check on the summary ref lookup. */
  if (!repo_get_remote_collection_id (self->repo, remote_name, &collection_id, error))
    return NULL;

  parts = flatpak_decompose_ref (ref, error);
  if (parts == NULL)
    return NULL;

  if (!flatpak_dir_ensure_repo (self, cancellable, error))
    return NULL;

  groups = g_key_file_get_groups (metakey, NULL);
  for (i = 0; groups[i] != NULL; i++)
    {
      char *tagged_extension;

      if (g_str_has_prefix (groups[i], FLATPAK_METADATA_GROUP_PREFIX_EXTENSION) &&
          *(tagged_extension = (groups[i] + strlen (FLATPAK_METADATA_GROUP_PREFIX_EXTENSION))) != 0)
        {
          g_autofree char *extension = NULL;
          g_autofree char *version = g_key_file_get_string (metakey, groups[i],
                                                            FLATPAK_METADATA_KEY_VERSION, NULL);
          gboolean subdirectories = g_key_file_get_boolean (metakey, groups[i],
                                                            FLATPAK_METADATA_KEY_SUBDIRECTORIES, NULL);
          gboolean no_autodownload = g_key_file_get_boolean (metakey, groups[i],
                                                             FLATPAK_METADATA_KEY_NO_AUTODOWNLOAD, NULL);
          g_autofree char *download_if = g_key_file_get_string (metakey, groups[i],
                                                                FLATPAK_METADATA_KEY_DOWNLOAD_IF, NULL);
          g_autofree char *autoprune_unless = g_key_file_get_string (metakey, groups[i],
                                                                     FLATPAK_METADATA_KEY_AUTOPRUNE_UNLESS, NULL);
          gboolean autodelete = g_key_file_get_boolean (metakey, groups[i],
                                                        FLATPAK_METADATA_KEY_AUTODELETE, NULL);
          gboolean locale_subset = g_key_file_get_boolean (metakey, groups[i],
                                                           FLATPAK_METADATA_KEY_LOCALE_SUBSET, NULL);
          const char *branch;
          g_autofree char *extension_ref = NULL;
          g_autofree char *prefixed_extension_ref = NULL;
          g_autofree char *checksum = NULL;
          g_autofree char *extension_collection_id = NULL;

          /* Parse actual extension name */
          flatpak_parse_extension_with_tag (tagged_extension, &extension, NULL);

          if (version)
            branch = version;
          else
            branch = parts[3];

          extension_collection_id = g_key_file_get_string (metakey, groups[i],
                                                           FLATPAK_METADATA_KEY_COLLECTION_ID, NULL);

          /* As we’re looking locally, we can’t support extension
           * collection IDs which don’t match the current remote (since the
           * associated refs could be anywhere). */
          if (extension_collection_id != NULL && *extension_collection_id != '\0' &&
              g_strcmp0 (extension_collection_id, collection_id) != 0)
            {
              g_debug ("Skipping related extension ‘%s’ because it’s in collection "
                       "‘%s’ which does not match the current remote ‘%s’.",
                       extension, extension_collection_id, collection_id);
              continue;
            }

          g_clear_pointer (&extension_collection_id, g_free);
          extension_collection_id = g_strdup (collection_id);

          extension_ref = g_build_filename ("runtime", extension, parts[2], branch, NULL);
          prefixed_extension_ref = g_strdup_printf ("%s:%s", remote_name, extension_ref);
          if (ostree_repo_resolve_rev (self->repo,
                                       prefixed_extension_ref,
                                       FALSE,
                                       &checksum,
                                       NULL))
            {
              add_related (self, related, extension, extension_collection_id, extension_ref,
                           checksum, no_autodownload, download_if, autoprune_unless, autodelete, locale_subset);
            }
          else if (subdirectories)
            {
              g_autoptr(GPtrArray) matches = local_match_prefix (self, extension_ref, remote_name);
              int j;
              for (j = 0; j < matches->len; j++)
                {
                  const char *match = g_ptr_array_index (matches, j);
                  g_autofree char *prefixed_match = NULL;
                  g_autofree char *match_checksum = NULL;

                  prefixed_match = g_strdup_printf ("%s:%s", remote_name, match);

                  if (ostree_repo_resolve_rev (self->repo,
                                               prefixed_match,
                                               FALSE,
                                               &match_checksum,
                                               NULL))
                    {
                      add_related (self, related, extension,
                                   extension_collection_id, match, match_checksum,
                                   no_autodownload, download_if, autoprune_unless, autodelete, locale_subset);
                    }
                }
            }
        }
    }

  return g_steal_pointer (&related);
}