_flatpak_dir_ensure_repo (FlatpakDir   *self,
                          gboolean      allow_empty,
                          GCancellable *cancellable,
                          GError      **error)
{
  g_autoptr(GFile) repodir = NULL;
  g_autoptr(OstreeRepo) repo = NULL;
  g_autoptr(GError) my_error = NULL;
  g_autoptr(GFile) cache_dir = NULL;
  g_autoptr(GHashTable) flatpakrepos = NULL;

  if (self->repo != NULL)
    return TRUE;

  if (!g_file_query_exists (self->basedir, cancellable))
    {
      if (flatpak_dir_use_system_helper (self, NULL))
        {
          g_autoptr(GError) local_error = NULL;
          const char *installation = flatpak_dir_get_id (self);

          if (!flatpak_dir_system_helper_call_ensure_repo (self,
                                                           FLATPAK_HELPER_ENSURE_REPO_FLAGS_NONE,
                                                           installation ? installation : "",
                                                           NULL, &local_error))
            {
              if (allow_empty)
                return TRUE;

              g_propagate_error (error, g_steal_pointer (&local_error));
              return FALSE;
            }
        }
      else
        {
          g_autoptr(GError) local_error = NULL;
          if (!flatpak_dir_ensure_path (self, cancellable, &local_error))
            {
              if (allow_empty)
                return TRUE;

              g_propagate_error (error, g_steal_pointer (&local_error));
              return FALSE;
            }
        }
    }

  repodir = g_file_get_child (self->basedir, "repo");

  repo = ostree_repo_new (repodir);

  if (!g_file_query_exists (repodir, cancellable))
    {
      /* We always use bare-user-only these days, except old installations
         that still user bare-user */
      OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER_ONLY;

      if (!ostree_repo_create (repo, mode, cancellable, &my_error))
        {
          flatpak_rm_rf (repodir, cancellable, NULL);

          if (allow_empty)
            return TRUE;

          g_propagate_error (error, g_steal_pointer (&my_error));
          return FALSE;
        }

      /* Create .changed file early to avoid polling non-existing file in monitor */
      if (!flatpak_dir_mark_changed (self, &my_error))
        {
          g_warning ("Error marking directory as changed: %s", my_error->message);
          g_clear_error (&my_error);
        }
    }
  else
    {
      if (!ostree_repo_open (repo, cancellable, error))
        {
          g_autofree char *repopath = NULL;

          repopath = g_file_get_path (repodir);
          g_prefix_error (error, _("While opening repository %s: "), repopath);
          return FALSE;
        }
    }

  /* In the system-helper case we're directly using the global repo, and we can't write any
   * caches for summaries there, so we need to set a custom dir for this. Note, as per #3303
   * this has to be called after ostree_repo_open() in order to the custom cachedir being
   * overridden if the system dir is writable (like in the testsuite).
   */
  if (flatpak_dir_use_system_helper (self, NULL))
    {
      g_autofree char *cache_path = NULL;

      cache_dir = flatpak_ensure_user_cache_dir_location (error);
      if (cache_dir == NULL)
        return FALSE;

      cache_path = g_file_get_path (cache_dir);
      if (!ostree_repo_set_cache_dir (repo,
                                      AT_FDCWD, cache_path,
                                      cancellable, error))
        return FALSE;
    }

  /* Earlier flatpak used to reset min-free-space-percent to 0 every time, but now we
   * favor min-free-space-size instead of it (See below).
   */
  if (!flatpak_dir_use_system_helper (self, NULL))
    {
      GKeyFile *orig_config = NULL;
      g_autoptr(GKeyFile) new_config = NULL;
      g_autofree char *orig_min_free_space_percent = NULL;
      g_autofree char *orig_min_free_space_size = NULL;
      const char *min_free_space_size = "500MB";
      guint64 min_free_space_percent_int;

      orig_config = ostree_repo_get_config (repo);
      orig_min_free_space_percent = g_key_file_get_value (orig_config, "core", "min-free-space-percent", NULL);
      orig_min_free_space_size = g_key_file_get_value (orig_config, "core", "min-free-space-size", NULL);

      if (orig_min_free_space_size == NULL)
        new_config = ostree_repo_copy_config (repo);

      /* Scrap previously written min-free-space-percent=0 and replace it with min-free-space-size */
      if (orig_min_free_space_size == NULL &&
          orig_min_free_space_percent != NULL &&
          flatpak_utils_ascii_string_to_unsigned (orig_min_free_space_percent, 10,
                                                  0, G_MAXUINT64,
                                                  &min_free_space_percent_int, &my_error))
        {
          if (min_free_space_percent_int == 0)
            {
              g_key_file_remove_key (new_config, "core", "min-free-space-percent", NULL);
              g_key_file_set_string (new_config, "core", "min-free-space-size", min_free_space_size);
            }
        }
      else if (my_error != NULL)
        {
          g_propagate_error (error, g_steal_pointer (&my_error));
          return FALSE;
        }

      if (orig_min_free_space_size == NULL &&
          orig_min_free_space_percent == NULL)
        g_key_file_set_string (new_config, "core", "min-free-space-size", min_free_space_size);

      if (new_config != NULL)
        {
          if (!ostree_repo_write_config (repo, new_config, error))
            return FALSE;

          if (!ostree_repo_reload_config (repo, cancellable, error))
            return FALSE;
        }
    }

  flatpakrepos = _flatpak_dir_find_new_flatpakrepos (self, repo);
  if (flatpakrepos)
    {
      if (flatpak_dir_use_system_helper (self, NULL))
        {
          const char *installation = flatpak_dir_get_id (self);
          if (!flatpak_dir_system_helper_call_ensure_repo (self,
                                                           FLATPAK_HELPER_ENSURE_REPO_FLAGS_NONE,
                                                           installation ? installation : "",
                                                           NULL, &my_error))
            {
              if (allow_empty)
                return TRUE;

              g_propagate_error (error, g_steal_pointer (&my_error));
              return FALSE;
            }

          if (!ostree_repo_reload_config (repo, cancellable, error))
            return FALSE;
        }
      else
        {
          GLNX_HASH_TABLE_FOREACH_KV (flatpakrepos, const char *, remote_name, GFile *, file)
            {
              if (!apply_new_flatpakrepo (remote_name, file, repo, error))
                return FALSE;
            }
        }
    }


  if (cache_dir == NULL)
    cache_dir = g_file_get_child (repodir, "tmp/cache");

  /* Make sure we didn't reenter weirdly */
  g_assert (self->repo == NULL);
  self->repo = g_object_ref (repo);
  self->cache_dir = g_object_ref (cache_dir);

  return TRUE;
}