<commit_before>/*
 * Copyright © 2018 <NAME>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       <NAME> <<EMAIL>>
 */

#include "config.h"

#include <locale.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <glib/gi18n.h>

#include "libglnx/libglnx.h"

#include "flatpak-builtins.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-utils-private.h"
#include "flatpak-error.h"

static char *opt_arch;
static char *opt_destination_repo;
static gboolean opt_runtime;
static gboolean opt_app;

static GOptionEntry options[] = {
  { "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("Look for app with the specified name"), NULL },
  { "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to copy"), N_("ARCH") },
  { "destination-repo", 0, 0, G_OPTION_ARG_FILENAME, &opt_destination_repo, "Use custom repository directory within the mount", N_("DEST") },
  { "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Look for runtime with the specified name"), NULL },
  { NULL }
};

typedef struct CommitAndSubpaths
{
  gchar  *commit;
  gchar **subpaths;
} CommitAndSubpaths;

static void
commit_and_subpaths_free (CommitAndSubpaths *c_s)
{
  g_free (c_s->commit);
  g_strfreev (c_s->subpaths);
  g_free (c_s);
}

static CommitAndSubpaths *
commit_and_subpaths_new (const char *commit, const char * const *subpaths)
{
  CommitAndSubpaths *c_s = g_new (CommitAndSubpaths, 1);

  c_s->commit = g_strdup (commit);
  c_s->subpaths = g_strdupv ((char **) subpaths);
  return c_s;
}

/* Add related refs specified in the metadata of @ref to @all_refs, also
 * updating @all_collection_ids with any new collection IDs. A warning will be
 * printed for related refs that are not installed, and they won't be added to
 * the list. */
static gboolean
add_related (GHashTable   *all_refs,
             GHashTable   *all_collection_ids,
             const char   *ref,
             FlatpakDir   *dir,
             GCancellable *cancellable,
             GError      **error)
{
  g_autoptr(GVariant) deploy_data = NULL;
  g_autoptr(FlatpakDeploy) deploy = NULL;
  g_autoptr(GKeyFile) metakey = NULL;
  g_auto(GStrv) parts = NULL;
  const char *commit = NULL;
  const char *arch = NULL;
  const char *branch = NULL;
  GList *extensions, *l;

  g_debug ("Finding related refs for ‘%s’", ref);

  parts = g_strsplit (ref, "/", 0);
  arch = parts[2];
  branch = parts[3];

  deploy_data = flatpak_dir_get_deploy_data (dir, ref, cancellable, error);
  if (deploy_data == NULL)
    return FALSE;

  commit = flatpak_deploy_data_get_commit (deploy_data);

  deploy = flatpak_dir_load_deployed (dir, ref, commit, cancellable, error);
  if (deploy == NULL)
    return FALSE;

  metakey = flatpak_deploy_get_metadata (deploy);

  extensions = flatpak_list_extensions (metakey, arch, branch);
  for (l = extensions; l; l = l->next)
    {
      FlatpakExtension *ext = l->data;
      g_autoptr(GVariant) ext_deploy_data = NULL;
      g_autoptr(OstreeCollectionRef) ext_collection_ref = NULL;
      g_autofree char *ext_collection_id = NULL;
      g_autofree const char **ext_subpaths = NULL;
      const char *ext_remote;
      const char *ext_commit = NULL;
      CommitAndSubpaths *c_s;

      if (ext->is_unmaintained)
        continue;

      g_assert (ext->ref);

      ext_deploy_data = flatpak_dir_get_deploy_data (dir, ext->ref, cancellable, error);
      if (ext_deploy_data == NULL)
        {
          g_printerr (_("Warning: Omitting related ref ‘%s’ because it is not installed.\n"),
                      ext->ref);
          continue;
        }

      ext_remote = flatpak_deploy_data_get_origin (ext_deploy_data);
      if (ext_remote == NULL)
        return FALSE;
      ext_collection_id = flatpak_dir_get_remote_collection_id (dir, ext_remote);
      if (ext_collection_id == NULL)
        {
          g_printerr (_("Warning: Omitting related ref ‘%s’ because its remote ‘%s’ does not have a collection ID set.\n"),
                      ext->ref, ext_remote);
          continue;
        }

      ext_commit = flatpak_deploy_data_get_commit (ext_deploy_data);
      ext_subpaths = flatpak_deploy_data_get_subpaths (ext_deploy_data);
      c_s = commit_and_subpaths_new (ext_commit, ext_subpaths[0] == NULL ? NULL : ext_subpaths);

      g_hash_table_insert (all_collection_ids, g_strdup (ext_collection_id), g_strdup (ext_remote));
      ext_collection_ref = ostree_collection_ref_new (ext_collection_id, ext->ref);
      g_hash_table_insert (all_refs, g_steal_pointer (&ext_collection_ref), c_s);
    }

  return TRUE;
}

/* Add the runtime and its related refs to @all_refs, also updating
 * @all_collection_ids with any new collection IDs */
static gboolean
add_runtime (GHashTable   *all_refs,
             GHashTable   *all_collection_ids,
             const char   *ref,
             FlatpakDir   *dir,
             GCancellable *cancellable,
             GError      **error)<commit_msg>create-usb: Fix a leak of the list of extensions<commit_after>/*
 * Copyright © 2018 <NAME>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       <NAME> <<EMAIL>>
 */

#include "config.h"

#include <locale.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <glib/gi18n.h>

#include "libglnx/libglnx.h"

#include "flatpak-builtins.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-utils-private.h"
#include "flatpak-error.h"

static char *opt_arch;
static char *opt_destination_repo;
static gboolean opt_runtime;
static gboolean opt_app;

static GOptionEntry options[] = {
  { "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("Look for app with the specified name"), NULL },
  { "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to copy"), N_("ARCH") },
  { "destination-repo", 0, 0, G_OPTION_ARG_FILENAME, &opt_destination_repo, "Use custom repository directory within the mount", N_("DEST") },
  { "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Look for runtime with the specified name"), NULL },
  { NULL }
};

typedef struct CommitAndSubpaths
{
  gchar  *commit;
  gchar **subpaths;
} CommitAndSubpaths;

static void
commit_and_subpaths_free (CommitAndSubpaths *c_s)
{
  g_free (c_s->commit);
  g_strfreev (c_s->subpaths);
  g_free (c_s);
}

static CommitAndSubpaths *
commit_and_subpaths_new (const char *commit, const char * const *subpaths)
{
  CommitAndSubpaths *c_s = g_new (CommitAndSubpaths, 1);

  c_s->commit = g_strdup (commit);
  c_s->subpaths = g_strdupv ((char **) subpaths);
  return c_s;
}

/* Add related refs specified in the metadata of @ref to @all_refs, also
 * updating @all_collection_ids with any new collection IDs. A warning will be
 * printed for related refs that are not installed, and they won't be added to
 * the list. */
static gboolean
add_related (GHashTable   *all_refs,
             GHashTable   *all_collection_ids,
             const char   *ref,
             FlatpakDir   *dir,
             GCancellable *cancellable,
             GError      **error)
{
  g_autoptr(GVariant) deploy_data = NULL;
  g_autoptr(FlatpakDeploy) deploy = NULL;
  g_autoptr(GKeyFile) metakey = NULL;
  g_auto(GStrv) parts = NULL;
  const char *commit = NULL;
  const char *arch = NULL;
  const char *branch = NULL;
  GList *extensions, *l;

  g_debug ("Finding related refs for ‘%s’", ref);

  parts = g_strsplit (ref, "/", 0);
  arch = parts[2];
  branch = parts[3];

  deploy_data = flatpak_dir_get_deploy_data (dir, ref, cancellable, error);
  if (deploy_data == NULL)
    return FALSE;

  commit = flatpak_deploy_data_get_commit (deploy_data);

  deploy = flatpak_dir_load_deployed (dir, ref, commit, cancellable, error);
  if (deploy == NULL)
    return FALSE;

  metakey = flatpak_deploy_get_metadata (deploy);

  extensions = flatpak_list_extensions (metakey, arch, branch);
  for (l = extensions; l; l = l->next)
    {
      FlatpakExtension *ext = l->data;
      g_autoptr(GVariant) ext_deploy_data = NULL;
      g_autoptr(OstreeCollectionRef) ext_collection_ref = NULL;
      g_autofree char *ext_collection_id = NULL;
      g_autofree const char **ext_subpaths = NULL;
      const char *ext_remote;
      const char *ext_commit = NULL;
      CommitAndSubpaths *c_s;

      if (ext->is_unmaintained)
        continue;

      g_assert (ext->ref);

      ext_deploy_data = flatpak_dir_get_deploy_data (dir, ext->ref, cancellable, error);
      if (ext_deploy_data == NULL)
        {
          g_printerr (_("Warning: Omitting related ref ‘%s’ because it is not installed.\n"),
                      ext->ref);
          continue;
        }

      ext_remote = flatpak_deploy_data_get_origin (ext_deploy_data);
      if (ext_remote == NULL)
        return FALSE;
      ext_collection_id = flatpak_dir_get_remote_collection_id (dir, ext_remote);
      if (ext_collection_id == NULL)
        {
          g_printerr (_("Warning: Omitting related ref ‘%s’ because its remote ‘%s’ does not have a collection ID set.\n"),
                      ext->ref, ext_remote);
          continue;
        }

      ext_commit = flatpak_deploy_data_get_commit (ext_deploy_data);
      ext_subpaths = flatpak_deploy_data_get_subpaths (ext_deploy_data);
      c_s = commit_and_subpaths_new (ext_commit, ext_subpaths[0] == NULL ? NULL : ext_subpaths);

      g_hash_table_insert (all_collection_ids, g_strdup (ext_collection_id), g_strdup (ext_remote));
      ext_collection_ref = ostree_collection_ref_new (ext_collection_id, ext->ref);
      g_hash_table_insert (all_refs, g_steal_pointer (&ext_collection_ref), c_s);
    }

  g_list_free_full (extensions, (GDestroyNotify) flatpak_extension_free);

  return TRUE;
}

/* Add the runtime and its related refs to @all_refs, also updating
 * @all_collection_ids with any new collection IDs */
static gboolean
add_runtime (GHashTable   *all_refs,
             GHashTable   *all_collection_ids,
             const char   *ref,
             FlatpakDir   *dir,
             GCancellable *cancellable,
             GError      **error)
{'fraction_non_alphanumeric': 0.10132001427042454, 'fraction_numerical': 0.003745986443096682, 'mean_word_length': 3.469111199681148, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4506470', 'n_tokens_mistral': 3816, 'n_tokens_neox': 3700, 'n_words': 1067}