Beispiel #1
0
static gboolean status_callback(mega_status_data* data, gpointer userdata)
{
  if (opt_stream && data->type == MEGA_STATUS_DATA)
  {
    fwrite(data->data.buf, data->data.size, 1, stdout);
    fflush(stdout);
  }

  if (data->type == MEGA_STATUS_FILEINFO)
  {
    cur_file = g_strdup(data->fileinfo.name);
  }

  if (!opt_noprogress && data->type == MEGA_STATUS_PROGRESS)
  {
    gchar* done_str = g_format_size_full(data->progress.done, G_FORMAT_SIZE_IEC_UNITS);
    gchar* total_str = g_format_size_full(data->progress.total, G_FORMAT_SIZE_IEC_UNITS);

    if (data->progress.total > 0)
      g_print(ESC_WHITE "%s" ESC_NORMAL ": " ESC_GREEN "%" G_GUINT64_FORMAT "%%" ESC_NORMAL " - " ESC_GREEN "%s" ESC_NORMAL " of %s" ESC_CLREOL "\r", cur_file, 100 * data->progress.done / data->progress.total, done_str, total_str);

    g_free(done_str);
    g_free(total_str);
  }

  return FALSE;
}
Beispiel #2
0
char *
sysinfo_format_memory (guint64 totalmem, guint64 freemem)
{
    char *total_fmt, *free_fmt, *ret;

    total_fmt = g_format_size_full (totalmem, G_FORMAT_SIZE_IEC_UNITS);
    free_fmt = g_format_size_full (freemem, G_FORMAT_SIZE_IEC_UNITS);
    ret = g_strdup_printf ("%s Total (%s Free)", total_fmt, free_fmt);

    g_free (total_fmt);
    g_free (free_fmt);
    return ret;
}
Beispiel #3
0
static void
print_result (const gchar *filename,
              guint64      disk_usage,
              guint64      num_dirs,
              guint64      num_files,
              GError      *error,
              gchar        nl)
{
  if (!error)
    {
      if (option_format_size)
        {
          GFormatSizeFlags format_flags;
          gchar *str;

          format_flags = (option_format_size > 1) ? G_FORMAT_SIZE_LONG_FORMAT : G_FORMAT_SIZE_DEFAULT;
          str = g_format_size_full (disk_usage, format_flags);
          g_print ("%s: %s (%"G_GUINT64_FORMAT" dirs, %"G_GUINT64_FORMAT" files)%c",
                   filename, str, num_dirs, num_files, nl);
          g_free (str);
        }
      else
        g_print ("%s: %"G_GUINT64_FORMAT" (%"G_GUINT64_FORMAT" dirs, %"G_GUINT64_FORMAT" files)%c",
                 filename, disk_usage, num_dirs, num_files, nl);
    }
  else
    {
      g_printerr ("%s: %s\n", filename, error->message);
      g_error_free (error);
    }
}
Beispiel #4
0
static gboolean status_callback(mega_status_data* data, gpointer userdata)
{
  if (!opt_noprogress && data->type == MEGA_STATUS_PROGRESS)
  {
    gchar* done_str = g_format_size_full(data->progress.done, G_FORMAT_SIZE_IEC_UNITS);
    gchar* total_str = g_format_size_full(data->progress.total, G_FORMAT_SIZE_IEC_UNITS);

    if (data->progress.total > 0)
      g_print("  " ESC_GREEN "%" G_GUINT64_FORMAT "%%" ESC_NORMAL " - " ESC_GREEN "%s" ESC_NORMAL " of %s" ESC_CLREOL "\r", 100 * data->progress.done / data->progress.total, done_str, total_str);

    g_free(done_str);
    g_free(total_str);
  }

  return FALSE;
}
Beispiel #5
0
char *
sysinfo_format_disk (guint64 total, guint64 free)
{
    char *total_fmt, *free_fmt, *used_fmt, *ret;
    GFormatSizeFlags format_flags = G_FORMAT_SIZE_DEFAULT;

#ifdef WIN32 /* Windows uses IEC size (with SI format) */
    format_flags = G_FORMAT_SIZE_IEC_UNITS;
#endif

    total_fmt = g_format_size_full (total, format_flags);
    free_fmt = g_format_size_full (free, format_flags);
    used_fmt = g_format_size_full (total - free, format_flags);
    ret = g_strdup_printf ("%s / %s (%s Free)", used_fmt, total_fmt, free_fmt);

    g_free (total_fmt);
    g_free (free_fmt);
    g_free (used_fmt);
    return ret;
}
Beispiel #6
0
static void
pragha_database_print_stats (PraghaDatabase *database)
{
	PraghaDatabasePrivate *priv = database->priv;
	int current = 0, high = 0;

	sqlite3_db_status (priv->sqlitedb, SQLITE_DBSTATUS_STMT_USED, &current, &high, 0);
	gchar *formatted = g_format_size_full (current, G_FORMAT_SIZE_IEC_UNITS);
	CDEBUG (DBG_DB, "statements in cache: %i, mem used: %s",
			g_hash_table_size (priv->statements_cache),
			formatted);
	g_free (formatted);
}
Beispiel #7
0
void tool_show_progress(const gchar* file, const mega_status_data *data)
{
  if (data->progress.total <= 0)
    return;

  gc_free gchar* done_str = g_format_size_full(data->progress.done, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_LONG_FORMAT);
  gc_free gchar* total_str = g_format_size_full(data->progress.total, G_FORMAT_SIZE_IEC_UNITS);
  const guint64 rate = (data->progress.done - data->progress.last) * 1e6 / data->progress.span;
  gc_free gchar* rate_str = g_format_size_full(rate, G_FORMAT_SIZE_IEC_UNITS);
  const double percentage = (double)(data->progress.done * 100 * 1000 / data->progress.total) / 1000.0;

  g_print(
    ESC_WHITE "%s"
    ESC_NORMAL ": " ESC_YELLOW "%.2f%%"
    ESC_NORMAL " - " ESC_GREEN "%s"
    ESC_BLUE " of %s"
    ESC_NORMAL " (%s/s)" ESC_CLREOL "\r",
    file,
    percentage,
    done_str,
    total_str,
    rate_str
  );
}
Beispiel #8
0
static void
proper_unit (guint64 size, char *buf, size_t buf_len)
{
	gchar *formatted_str;
	GFormatSizeFlags format_flags = G_FORMAT_SIZE_DEFAULT;

#ifndef __APPLE__ /* OS X uses SI */
#ifndef WIN32 /* Windows uses IEC size (with SI format) */
	if (prefs.hex_gui_filesize_iec) /* Linux can't decide... */
#endif
		format_flags = G_FORMAT_SIZE_IEC_UNITS;
#endif

	formatted_str = g_format_size_full (size, format_flags);
	g_strlcpy (buf, formatted_str, buf_len);

	g_free (formatted_str);
}
static VALUE
rbglib_m_format_size(int argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
    VALUE rb_size, rb_options;

    rb_scan_args(argc, argv, "11", &rb_size, &rb_options);
    if (NIL_P(rb_options)) {
      return CSTR2RVAL_FREE(g_format_size(NUM2ULONG(rb_size)));
    } else {
      VALUE rb_flags;
      rbg_scan_options(rb_options,
                       "flags", &rb_flags,
                       NULL);

      return CSTR2RVAL_FREE(g_format_size_full(NUM2ULONG(rb_size),
                                               RVAL2GFORMATSIZEFLAGS(rb_flags)));
    }
}
Beispiel #10
0
gboolean
ostree_builtin_diff (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  g_autoptr(GOptionContext) context = NULL;
  g_autoptr(OstreeRepo) repo = NULL;
  const char *src;
  const char *target;
  g_autofree char *src_prev = NULL;
  g_autoptr(GFile) srcf = NULL;
  g_autoptr(GFile) targetf = NULL;
  g_autoptr(GPtrArray) modified = NULL;
  g_autoptr(GPtrArray) removed = NULL;
  g_autoptr(GPtrArray) added = NULL;

  context = g_option_context_new ("REV TARGETDIR");

  if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
    goto out;

  if (argc < 2)
    {
      gchar *help = g_option_context_get_help (context, TRUE, NULL);
      g_printerr ("%s\n", help);
      g_free (help);
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                               "REV must be specified");
      goto out;
    }

  if (argc == 2)
    {
      src_prev = g_strconcat (argv[1], "^", NULL);
      src = src_prev;
      target = argv[1];
    }
  else
    {
      src = argv[1];
      target = argv[2];
    }

  if (!opt_stats && !opt_fs_diff)
    opt_fs_diff = TRUE;

  if (opt_fs_diff)
    {
      OstreeDiffFlags diff_flags = OSTREE_DIFF_FLAGS_NONE; 

      if (opt_no_xattrs)
        diff_flags |= OSTREE_DIFF_FLAGS_IGNORE_XATTRS;
      
      if (!parse_file_or_commit (repo, src, &srcf, cancellable, error))
        goto out;
      if (!parse_file_or_commit (repo, target, &targetf, cancellable, error))
        goto out;

      modified = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_diff_item_unref);
      removed = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
      added = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);

      OstreeDiffDirsOptions diff_opts = { opt_owner_uid, opt_owner_gid };
      if (!ostree_diff_dirs_with_options (diff_flags, srcf, targetf, modified, removed,
                                          added, &diff_opts, cancellable, error))
        goto out;

      ostree_diff_print (srcf, targetf, modified, removed, added);
    }

  if (opt_stats)
    {
      g_autoptr(GHashTable) reachable_a = NULL;
      g_autoptr(GHashTable) reachable_b = NULL;
      g_autoptr(GHashTable) reachable_intersection = NULL;
      g_autofree char *rev_a = NULL;
      g_autofree char *rev_b = NULL;
      g_autofree char *size = NULL;
      guint a_size;
      guint b_size;
      guint64 total_common;

      if (!ostree_repo_resolve_rev (repo, src, FALSE, &rev_a, error))
        goto out;
      if (!ostree_repo_resolve_rev (repo, target, FALSE, &rev_b, error))
        goto out;

      if (!ostree_repo_traverse_commit (repo, rev_a, 0, &reachable_a, cancellable, error))
        goto out;
      if (!ostree_repo_traverse_commit (repo, rev_b, 0, &reachable_b, cancellable, error))
        goto out;

      a_size = g_hash_table_size (reachable_a);
      b_size = g_hash_table_size (reachable_b);
      g_print ("[A] Object Count: %u\n", a_size);
      g_print ("[B] Object Count: %u\n", b_size);

      reachable_intersection = reachable_set_intersect (reachable_a, reachable_b);

      g_print ("Common Object Count: %u\n", g_hash_table_size (reachable_intersection));

      if (!object_set_total_size (repo, reachable_intersection, &total_common,
                                  cancellable, error))
        goto out;
      size = g_format_size_full (total_common, 0);
      g_print ("Common Object Size: %s\n", size);
    }

  ret = TRUE;
 out:
  return ret;
}
Beispiel #11
0
gboolean
ostree_builtin_prune (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  GOptionContext *context;
  glnx_unref_object OstreeRepo *repo = NULL;
  g_autofree char *formatted_freed_size = NULL;
  OstreeRepoPruneFlags pruneflags = 0;
  gint n_objects_total;
  gint n_objects_pruned;
  guint64 objsize_total;

  context = g_option_context_new ("- Search for unreachable objects");

  if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error))
    goto out;

  if (!opt_no_prune && !ostree_ensure_repo_writable (repo, error))
    goto out;

  if (opt_delete_commit)
    {
      if (opt_no_prune)
        {
          ot_util_usage_error (context, "Cannot specify both --delete-commit and --no-prune", error);
          goto out;
        }
        if (opt_static_deltas_only)
          {
            if(!ostree_repo_prune_static_deltas (repo, opt_delete_commit, cancellable, error))
              goto out;
          }
        else if (!delete_commit (repo, opt_delete_commit, cancellable, error))
          goto out;
    }
  if (opt_keep_younger_than)
    {
      if (opt_no_prune)
        {
          ot_util_usage_error (context, "Cannot specify both --keep-younger-than and --no-prune", error);
          goto out;
        }
      if (!prune_commits_keep_younger_than_date (repo, opt_keep_younger_than, cancellable, error))
        goto out;
    }

  if (opt_refs_only)
    pruneflags |= OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY;
  if (opt_no_prune)
    pruneflags |= OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE;

  if (!ostree_repo_prune (repo, pruneflags, opt_depth,
                          &n_objects_total, &n_objects_pruned, &objsize_total,
                          cancellable, error))
    goto out;

  formatted_freed_size = g_format_size_full (objsize_total, 0);

  g_print ("Total objects: %u\n", n_objects_total);
  if (n_objects_pruned == 0)
    g_print ("No unreachable objects\n");
  else if (pruneflags & OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE)
    g_print ("Would delete: %u objects, freeing %s\n",
             n_objects_pruned, formatted_freed_size);
  else
    g_print ("Deleted %u objects, %s freed\n",
             n_objects_pruned, formatted_freed_size);

  ret = TRUE;
 out:
  if (context)
    g_option_context_free (context);
  return ret;
}
static gboolean
generate_deployment_refs_and_prune (OstreeSysroot       *self,
                                    OstreeRepo          *repo,
                                    int                  bootversion,
                                    int                  subbootversion,
                                    GPtrArray           *deployments,
                                    GCancellable        *cancellable,
                                    GError             **error)
{
    gboolean ret = FALSE;
    int cleanup_bootversion;
    int cleanup_subbootversion;
    guint i;
    gint n_objects_total, n_objects_pruned;
    guint64 freed_space;

    cleanup_bootversion = (bootversion == 0) ? 1 : 0;
    cleanup_subbootversion = (subbootversion == 0) ? 1 : 0;

    if (!cleanup_ref_prefix (repo, cleanup_bootversion, 0,
                             cancellable, error))
        goto out;

    if (!cleanup_ref_prefix (repo, cleanup_bootversion, 1,
                             cancellable, error))
        goto out;

    if (!cleanup_ref_prefix (repo, bootversion, cleanup_subbootversion,
                             cancellable, error))
        goto out;

    for (i = 0; i < deployments->len; i++)
    {
        OstreeDeployment *deployment = deployments->pdata[i];
        gs_free char *refname = g_strdup_printf ("ostree/%d/%d/%u",
                                bootversion, subbootversion,
                                i);

        if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
            goto out;

        ostree_repo_transaction_set_refspec (repo, refname, ostree_deployment_get_csum (deployment));

        if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
            goto out;
    }

    if (!ostree_repo_prune (repo, OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY, 0,
                            &n_objects_total, &n_objects_pruned, &freed_space,
                            cancellable, error))
        goto out;
    if (freed_space > 0)
    {
        char *freed_space_str = g_format_size_full (freed_space, 0);
        g_print ("Freed objects: %s\n", freed_space_str);
    }

    ret = TRUE;
out:
    ostree_repo_abort_transaction (repo, cancellable, NULL);
    return ret;
}
Beispiel #13
0
gboolean
ostree_builtin_diff (int argc, char **argv, OstreeRepo *repo, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  GOptionContext *context;
  const char *src;
  const char *target;
  gs_free char *src_prev = NULL;
  gs_unref_object GFile *srcf = NULL;
  gs_unref_object GFile *targetf = NULL;
  gs_unref_ptrarray GPtrArray *modified = NULL;
  gs_unref_ptrarray GPtrArray *removed = NULL;
  gs_unref_ptrarray GPtrArray *added = NULL;

  context = g_option_context_new ("REV TARGETDIR - Compare directory TARGETDIR against revision REV");
  g_option_context_add_main_entries (context, options, NULL);

  if (!g_option_context_parse (context, &argc, &argv, error))
    goto out;

  if (argc < 2)
    {
      gchar *help = g_option_context_get_help (context, TRUE, NULL);
      g_printerr ("%s\n", help);
      g_free (help);
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                               "REV must be specified");
      goto out;
    }

  if (argc == 2)
    {
      src_prev = g_strconcat (argv[1], "^", NULL);
      src = src_prev;
      target = argv[1];
    }
  else
    {
      src = argv[1];
      target = argv[2];
    }

  if (!opt_stats && !opt_fs_diff)
    opt_fs_diff = TRUE;

  if (opt_fs_diff)
    {
      if (!parse_file_or_commit (repo, src, &srcf, cancellable, error))
        goto out;
      if (!parse_file_or_commit (repo, target, &targetf, cancellable, error))
        goto out;

      modified = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_diff_item_unref);
      removed = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
      added = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
      
      if (!ostree_diff_dirs (OSTREE_DIFF_FLAGS_NONE, srcf, targetf, modified, removed, added, cancellable, error))
        goto out;

      ostree_diff_print (srcf, targetf, modified, removed, added);
    }

  if (opt_stats)
    {
      gs_unref_hashtable GHashTable *reachable_a = NULL;
      gs_unref_hashtable GHashTable *reachable_b = NULL;
      gs_unref_hashtable GHashTable *reachable_intersection = NULL;
      gs_free char *rev_a = NULL;
      gs_free char *rev_b = NULL;
      gs_free char *size = NULL;
      guint a_size;
      guint b_size;
      guint64 total_common;

      if (!ostree_repo_resolve_rev (repo, src, FALSE, &rev_a, error))
        goto out;
      if (!ostree_repo_resolve_rev (repo, target, FALSE, &rev_b, error))
        goto out;

      if (!ostree_repo_traverse_commit (repo, rev_a, -1, &reachable_a, cancellable, error))
        goto out;
      if (!ostree_repo_traverse_commit (repo, rev_b, -1, &reachable_b, cancellable, error))
        goto out;

      a_size = g_hash_table_size (reachable_a);
      b_size = g_hash_table_size (reachable_b);
      g_print ("[A] Object Count: %u\n", a_size);
      g_print ("[B] Object Count: %u\n", b_size);

      reachable_intersection = reachable_set_intersect (reachable_a, reachable_b);

      g_print ("Common Object Count: %u\n", g_hash_table_size (reachable_intersection));

      if (!object_set_total_size (repo, reachable_intersection, &total_common,
                                  cancellable, error))
        goto out;
      size = g_format_size_full (total_common, 0);
      g_print ("Common Object Size: %s\n", size);
    }

  ret = TRUE;
 out:
  if (context)
    g_option_context_free (context);
  return ret;
}
/**
* transaction_console_get_progress_line
*
* Similar to ostree_repo_pull_default_console_progress_changed
*
* Displays outstanding fetch progress in bytes/sec,
* or else outstanding content or metadata writes to the repository in
* number of objects.
**/
static gchar *
transaction_get_progress_line (guint64 start_time,
                               guint64 elapsed_secs,
                               guint outstanding_fetches,
                               guint outstanding_writes,
                               guint n_scanned_metadata,
                               guint metadata_fetched,
                               guint outstanding_metadata_fetches,
                               guint total_delta_parts,
                               guint fetched_delta_parts,
                               guint total_delta_superblocks,
                               guint64 total_delta_part_size,
                               guint fetched,
                               guint requested,
                               guint64 bytes_transferred,
                               guint64 bytes_sec)
{
  GString *buf;

  buf = g_string_new ("");

  if (outstanding_fetches)
    {
      g_autofree gchar *formatted_bytes_transferred = g_format_size_full (bytes_transferred, 0);
      g_autofree gchar *formatted_bytes_sec = NULL;

      if (!bytes_sec)
        formatted_bytes_sec = g_strdup ("-");
      else
        formatted_bytes_sec = g_format_size (bytes_sec);

      if (total_delta_parts > 0)
        {
          g_autofree gchar *formatted_total = g_format_size (total_delta_part_size);
          g_string_append_printf (buf, "Receiving delta parts: %u/%u %s/s %s/%s",
                                  fetched_delta_parts, total_delta_parts,
                                  formatted_bytes_sec, formatted_bytes_transferred,
                                  formatted_total);
        }
      else if (outstanding_metadata_fetches)
        {
          g_string_append_printf (buf, "Receiving metadata objects: %u/(estimating) %s/s %s",
                                  metadata_fetched, formatted_bytes_sec, formatted_bytes_transferred);
        }
      else
        {
          g_string_append_printf (buf, "Receiving objects: %u%% (%u/%u) %s/s %s",
                                  (guint)((((double)fetched) / requested) * 100),
                                  fetched, requested, formatted_bytes_sec, formatted_bytes_transferred);
        }
    }
  else if (outstanding_writes)
    {
      g_string_append_printf (buf, "Writing objects: %u", outstanding_writes);
    }
  else
    {
      g_string_append_printf (buf, "Scanning metadata: %u", n_scanned_metadata);
    }

  return g_string_free (buf, FALSE);
}
Beispiel #15
0
int main(int ac, char* av[])
{
  mega_session* s;
  gc_error_free GError *local_err = NULL;
  GSList *l = NULL, *i;
  gint j;

  tool_init(&ac, &av, "- list files stored at mega.nz", entries);

  s = tool_start_session();
  if (!s)
    return 1;

  // gather nodes
  if (ac == 1)
  {
    l = mega_session_ls_all(s);
    opt_names = FALSE;
  }
  else
  {
    if (ac > 2 || opt_recursive)
      opt_names = FALSE;

    for (j = 1; j < ac; j++)
    {
      gc_free gchar* path = tool_convert_filename(av[j], FALSE);

      mega_node* n = mega_session_stat(s, path);
      if (n && (n->type == MEGA_NODE_FILE || !opt_names))
        l = g_slist_append(l, n);

      l = g_slist_concat(l, mega_session_ls(s, path, opt_recursive));
    }
  }

  l = g_slist_sort(l, (GCompareFunc)compare_node);

  // export if requested
  if (opt_export && !mega_session_addlinks(s, l, &local_err))
  {
    g_printerr("ERROR: Can't read links info from mega.nz: %s\n", local_err->message);
    g_slist_free(l);
    tool_fini(s);
    return 1;
  }

  if (l && opt_long && opt_header && !opt_export)
  {
    g_print("===================================================================================\n");
    g_print("%-11s %-11s %-1s %13s %-19s %s\n", "Handle", "Owner", "T", "Size", "Mod. Date", opt_names ? "Filename" : "Path");
    g_print("===================================================================================\n");
  }

  for (i = l; i; i = i->next)
  {
    mega_node* n = i->data;
    gc_free gchar* node_path = mega_node_get_path_dup(n);

    if (opt_export)
      g_print("%73s ", n->link ? mega_node_get_link(n, TRUE) : "");

    if (opt_long)
    {
      GDateTime* dt = g_date_time_new_from_unix_local(n->timestamp);
      gc_free gchar* time_str = g_date_time_format(dt, "%Y-%m-%d %H:%M:%S");
      g_date_time_unref(dt);

      gc_free gchar* size_str = NULL;
      if (opt_human)
        size_str = n->size > 0 ? g_format_size_full(n->size, G_FORMAT_SIZE_IEC_UNITS) : g_strdup("-");
      else
        size_str = n->size > 0 ? g_strdup_printf("%" G_GUINT64_FORMAT, n->size) : g_strdup("-");

      g_print("%-11s %-11s %d %13s %19s %s\n",
        n->handle, 
        n->user_handle ? n->user_handle : "",
        n->type,
        size_str,
        n->timestamp > 0 ? time_str : "", 
        opt_names ? n->name : node_path
      );
    }
    else
      g_print("%s\n", opt_names ? n->name : node_path);
  }

  g_slist_free(l);
  tool_fini(s);
  return 0;
}
gboolean
flatpak_builtin_build_update_repo (int argc, char **argv,
                                   GCancellable *cancellable, GError **error)
{
  g_autoptr(GOptionContext) context = NULL;
  g_autoptr(GFile) repofile = NULL;
  g_autoptr(OstreeRepo) repo = NULL;
  const char *location;
  g_autoptr(GPtrArray) unwanted_deltas = NULL;

  context = g_option_context_new (_("LOCATION - Update repository metadata"));
  g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);

  if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
    return FALSE;

  if (argc < 2)
    return usage_error (context, _("LOCATION must be specified"), error);

  if (opt_static_delta_jobs <= 0)
    opt_static_delta_jobs = g_get_num_processors ();

  location = argv[1];

  repofile = g_file_new_for_commandline_arg (location);
  repo = ostree_repo_new (repofile);

  if (!ostree_repo_open (repo, cancellable, error))
    return FALSE;

  if (opt_generate_delta_to)
    {
      if (!generate_one_delta (repo, opt_generate_delta_from, opt_generate_delta_to, opt_generate_delta_ref, cancellable, error))
        return FALSE;
      return TRUE;
    }

  if (opt_title &&
      !flatpak_repo_set_title (repo, opt_title[0] ? opt_title : NULL, error))
    return FALSE;

  if (opt_comment &&
      !flatpak_repo_set_comment (repo, opt_comment[0] ? opt_comment : NULL, error))
    return FALSE;

  if (opt_description &&
      !flatpak_repo_set_description (repo, opt_description[0] ? opt_description : NULL, error))
    return FALSE;

  if (opt_homepage &&
      !flatpak_repo_set_homepage (repo, opt_homepage[0] ? opt_homepage : NULL, error))
    return FALSE;

  if (opt_icon &&
      !flatpak_repo_set_icon (repo, opt_icon[0] ? opt_icon : NULL, error))
    return FALSE;

  if (opt_redirect_url &&
      !flatpak_repo_set_redirect_url (repo, opt_redirect_url[0] ? opt_redirect_url : NULL, error))
    return FALSE;

  if (opt_default_branch &&
      !flatpak_repo_set_default_branch (repo, opt_default_branch[0] ? opt_default_branch : NULL, error))
    return FALSE;

  if (opt_collection_id != NULL)
    {
      /* Only allow a transition from no collection ID to a non-empty collection ID.
       * Changing the collection ID between two different non-empty values is too
       * dangerous: it will break all clients who have previously pulled from the repository.
       * Require the user to recreate the repository from scratch in that case. */
      const char *old_collection_id = ostree_repo_get_collection_id (repo);
      const char *new_collection_id = opt_collection_id[0] ? opt_collection_id : NULL;

      if (old_collection_id != NULL &&
          g_strcmp0 (old_collection_id, new_collection_id) != 0)
        return flatpak_fail (error, "The collection ID of an existing repository cannot be changed. "
                                    "Recreate the repository to change or clear its collection ID.");

      if (!flatpak_repo_set_collection_id (repo, new_collection_id, error))
        return FALSE;
    }

  if (opt_deploy_collection_id &&
      !flatpak_repo_set_deploy_collection_id (repo, TRUE, error))
    return FALSE;

  if (opt_gpg_import)
    {
      g_autoptr(GBytes) gpg_data = flatpak_load_gpg_keys (opt_gpg_import, cancellable, error);
      if (gpg_data == NULL)
        return FALSE;

      if (!flatpak_repo_set_gpg_keys (repo, gpg_data, error))
        return FALSE;
    }

  if (!opt_no_update_appstream)
    {
      g_print (_("Updating appstream branch\n"));
      if (!flatpak_repo_generate_appstream (repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, 0, cancellable, error))
        return FALSE;
    }

  if (opt_generate_deltas &&
      !generate_all_deltas (repo, &unwanted_deltas, cancellable, error))
    return FALSE;

  if (unwanted_deltas != NULL)
    {
      int i;
      for (i = 0; i < unwanted_deltas->len; i++)
        {
          const char *delta = g_ptr_array_index (unwanted_deltas, i);
          g_print ("Deleting unwanted delta: %s\n", delta);
          g_autoptr(GError) my_error = NULL;
          if (!_ostree_repo_static_delta_delete (repo, delta, cancellable, &my_error))
            g_printerr ("Unable to delete delta %s: %s\n", delta, my_error->message);
        }
    }

  if (!opt_no_update_summary)
    {
      g_print (_("Updating summary\n"));
      if (!flatpak_repo_update (repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, cancellable, error))
        return FALSE;
    }

  if (opt_prune)
    {
      gint n_objects_total;
      gint n_objects_pruned;
      guint64 objsize_total;
      g_autofree char *formatted_freed_size = NULL;

      g_print ("Pruning old commits\n");
      if (!ostree_repo_prune (repo, OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY, opt_prune_depth,
                              &n_objects_total, &n_objects_pruned, &objsize_total,
                              cancellable, error))
        return FALSE;

      formatted_freed_size = g_format_size_full (objsize_total, 0);

      g_print (_("Total objects: %u\n"), n_objects_total);
      if (n_objects_pruned == 0)
        g_print (_("No unreachable objects\n"));
      else
        g_print (_("Deleted %u objects, %s freed\n"),
                 n_objects_pruned, formatted_freed_size);
    }

  return TRUE;
}