static-delta: Add `show` subcommand
authorColin Walters <walters@verbum.org>
Thu, 28 Jan 2016 03:02:36 +0000 (22:02 -0500)
committerColin Walters <walters@verbum.org>
Thu, 28 Jan 2016 20:38:09 +0000 (15:38 -0500)
Right now though, almost all of the details of deltas are private, so
we can't do the "honest thing" and have the command line just use the
shared library.

Eventually some of this should appear in the API, but for now add
command line which is useful for debugging.

src/libostree/ostree-cmdprivate.c
src/libostree/ostree-cmdprivate.h
src/libostree/ostree-repo-static-delta-core.c
src/libostree/ostree-repo-static-delta-private.h
src/libotutil/ot-variant-utils.c
src/libotutil/ot-variant-utils.h
src/ostree/ot-builtin-static-delta.c

index 998349375a0ce3eaa9616cc097b8dd4245572c5d..74c32a3c32bed0ac9c6678c6bf105e42eb0321fa 100644 (file)
@@ -23,6 +23,7 @@
 #include "ostree-cmdprivate.h"
 #include "ostree-repo-private.h"
 #include "ostree-core-private.h"
+#include "ostree-repo-static-delta-private.h"
 #include "ostree-sysroot.h"
 #include "ostree-bootloader-grub2.h"
 
@@ -44,7 +45,8 @@ const OstreeCmdPrivateVTable *
 ostree_cmd__private__ (void)
 {
   static OstreeCmdPrivateVTable table = {
-    impl_ostree_generate_grub2_config
+    impl_ostree_generate_grub2_config,
+    _ostree_repo_static_delta_dump
   };
 
   return &table;
index 317a7592b044efc2e9c81420cdd49965d8b34f0a..7746406b770417bc138a0b2d1074854819455fb0 100644 (file)
@@ -26,6 +26,7 @@ G_BEGIN_DECLS
 
 typedef struct {
   gboolean (* ostree_generate_grub2_config) (OstreeSysroot *sysroot, int bootversion, int target_fd, GCancellable *cancellable, GError **error);
+  gboolean (* ostree_static_delta_dump) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error);
 } OstreeCmdPrivateVTable;
 
 const OstreeCmdPrivateVTable *
index b2ffddc553f0432324f0fa6ef44d26b4537143bb..bc1b460c753a4213c79ebbc534b641add5d84781 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "ostree-core-private.h"
 #include "ostree-repo-private.h"
+#include "ostree-cmdprivate.h"
 #include "ostree-repo-static-delta-private.h"
 #include "otutil.h"
 
@@ -404,3 +405,95 @@ ostree_repo_static_delta_execute_offline (OstreeRepo                    *self,
  out:
   return ret;
 }
+
+gboolean
+_ostree_repo_static_delta_dump (OstreeRepo                    *self,
+                                const char                    *delta_id,
+                                GCancellable                  *cancellable,
+                                GError                      **error)
+{
+  gboolean ret = FALSE;
+  g_autofree char *from = NULL; 
+  g_autofree char *to = NULL;
+  g_autofree char *superblock_path = NULL;
+  glnx_fd_close int superblock_fd = -1;
+  g_autoptr(GVariant) delta_superblock = NULL;
+  guint64 total_size = 0, total_usize = 0;
+  guint64 total_fallback_size = 0, total_fallback_usize = 0;
+  guint i;
+
+  _ostree_parse_delta_name (delta_id, &from, &to);
+  superblock_path = _ostree_get_relative_static_delta_superblock_path (from, to);
+
+  if (!ot_util_variant_map_at (self->repo_dir_fd, superblock_path,
+                               (GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT,
+                               TRUE, &delta_superblock, error))
+    goto out;
+
+  g_print ("Delta: %s\n", delta_id);
+  { guint64 ts;
+    g_variant_get_child (delta_superblock, 1, "t", &ts);
+    g_print ("Timestamp: %" G_GUINT64_FORMAT "\n", GUINT64_FROM_BE (ts));
+  }
+  { g_autoptr(GVariant) recurse = NULL;
+    g_variant_get_child (delta_superblock, 5, "@ay", &recurse);
+    g_print ("Number of parents: %u\n", (guint)(g_variant_get_size (recurse) / (OSTREE_SHA256_DIGEST_LEN * 2)));
+  }
+  { g_autoptr(GVariant) fallback = NULL;
+    guint n_fallback;
+
+    g_variant_get_child (delta_superblock, 7, "@a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT, &fallback);
+    n_fallback = g_variant_n_children (fallback);
+
+    g_print ("Number of fallback entries: %u\n", n_fallback);
+
+    for (i = 0; i < n_fallback; i++)
+      {
+        guint64 size, usize;
+        g_variant_get_child (fallback, i, "(y@aytt)", NULL, NULL, &size, &usize);
+        total_fallback_size += size;
+        total_fallback_usize += usize;
+      }
+    { g_autofree char *sizestr = g_format_size (total_fallback_size);
+      g_autofree char *usizestr = g_format_size (total_fallback_usize);
+      g_print ("Total Fallback Size: %" G_GUINT64_FORMAT " (%s)\n", total_fallback_size, sizestr);
+      g_print ("Total Fallback Uncompressed Size: %" G_GUINT64_FORMAT " (%s)\n", total_fallback_usize, usizestr);
+    }
+  }
+  { g_autoptr(GVariant) meta_entries = NULL;
+    guint n_parts;
+
+    g_variant_get_child (delta_superblock, 6, "@a" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT, &meta_entries);
+    n_parts = g_variant_n_children (meta_entries);
+    g_print ("Number of parts: %u\n", n_parts);
+
+    for (i = 0; i < n_parts; i++)
+      {
+        guint32 version;
+        guint64 size, usize;
+        g_autoptr(GVariant) objects = NULL;
+        g_variant_get_child (meta_entries, i, "(u@aytt@ay)", &version, NULL, &size, &usize, &objects);
+        total_size += size;
+        total_usize += usize;
+        g_print ("Part%u: nobjects=%u size=%" G_GUINT64_FORMAT " usize=%" G_GUINT64_FORMAT "\n",
+                 i, (guint)(g_variant_get_size (objects) / OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN), size, usize);
+      }
+  }
+
+  { g_autofree char *sizestr = g_format_size (total_size);
+    g_autofree char *usizestr = g_format_size (total_usize);
+    g_print ("Total Part Size: %" G_GUINT64_FORMAT " (%s)\n", total_size, sizestr);
+    g_print ("Total Part Uncompressed Size: %" G_GUINT64_FORMAT " (%s)\n", total_usize, usizestr);
+  }
+  { guint64 overall_size = total_size + total_fallback_size;
+    guint64 overall_usize = total_usize + total_fallback_usize;
+    g_autofree char *sizestr = g_format_size (overall_size);
+    g_autofree char *usizestr = g_format_size (overall_usize);
+    g_print ("Total Size: %" G_GUINT64_FORMAT " (%s)\n", overall_size, sizestr);
+    g_print ("Total Uncompressed Size: %" G_GUINT64_FORMAT " (%s)\n", overall_usize, usizestr);
+  }
+
+  ret = TRUE;
+ out:
+  return ret;
+}
index de32ec65f29a698578b17001a5d7c3f59d99eb2e..b0e82ade69938dcd9c94b195e7b300ec430fb36a 100644 (file)
@@ -103,6 +103,11 @@ G_BEGIN_DECLS
  */ 
 #define OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT "(a{sv}tayay" OSTREE_COMMIT_GVARIANT_STRING "aya" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT ")"
 
+gboolean _ostree_static_delta_dump (OstreeRepo     *repo,
+                                    const char *delta_id,
+                                    GCancellable   *cancellable,
+                                    GError        **error);
+
 gboolean _ostree_static_delta_part_validate (OstreeRepo     *repo,
                                              GInputStream   *in,
                                              guint           part_offset,
@@ -177,4 +182,10 @@ _ostree_delta_compute_similar_objects (OstreeRepo                 *repo,
                                        GCancellable               *cancellable,
                                        GError                    **error);
 
+gboolean
+_ostree_repo_static_delta_dump (OstreeRepo                 *repo,
+                                const char                 *delta_id,
+                                GCancellable               *cancellable,
+                                GError                    **error);
+
 G_END_DECLS
index 1210a785223499de7734f617fd414bfcc777ac4e..ed650268f0a6e7942c46b6eb9a11c8588025a178 100644 (file)
@@ -154,6 +154,28 @@ ot_util_variant_map (GFile              *src,
   return ret;
 }
 
+gboolean
+ot_util_variant_map_at (int dfd,
+                        const char *path,
+                        const GVariantType *type,
+                        gboolean trusted,
+                        GVariant **out_variant,
+                        GError  **error)
+{
+  glnx_fd_close int fd = -1;
+  g_autoptr(GVariant) ret_variant = NULL;
+
+  fd = openat (dfd, path, O_RDONLY | O_CLOEXEC);
+  if (fd < 0)
+    {
+      glnx_set_error_from_errno (error);
+      g_prefix_error (error, "Opening %s: ", path);
+      return FALSE;
+    }
+
+  return ot_util_variant_map_fd (fd, 0, type, trusted, out_variant, error);
+}
+
 typedef struct {
   gpointer addr;
   gsize len;
index 34b6eb5d5d2d92538882b4ec521cf24eb60d1b55..1a7abe0e3a40c3b66b013a0d224fb15db60c039e 100644 (file)
@@ -48,6 +48,13 @@ gboolean ot_util_variant_map (GFile *src,
                               GVariant **out_variant,
                               GError  **error);
 
+gboolean ot_util_variant_map_at (int dfd,
+                                 const char *path,
+                                 const GVariantType *type,
+                                 gboolean trusted,
+                                 GVariant **out_variant,
+                                 GError  **error);
+
 gboolean ot_util_variant_map_fd (int                  fd,
                                  goffset              offset,
                                  const GVariantType  *type,
index 903e5fd678cc10139121b13a58ae3d93861334a4..c3c99ba01d2b2b82c6abba7912c223a01ad61a9e 100644 (file)
@@ -23,6 +23,7 @@
 #include "ot-main.h"
 #include "ot-builtins.h"
 #include "ostree.h"
+#include "ostree-cmdprivate.h"
 #include "ot-main.h"
 #include "otutil.h"
 
@@ -38,6 +39,7 @@ static gboolean opt_disable_bsdiff;
 #define BUILTINPROTO(name) static gboolean ot_static_delta_builtin_ ## name (int argc, char **argv, GCancellable *cancellable, GError **error)
 
 BUILTINPROTO(list);
+BUILTINPROTO(show);
 BUILTINPROTO(generate);
 BUILTINPROTO(apply_offline);
 
@@ -45,6 +47,7 @@ BUILTINPROTO(apply_offline);
 
 static OstreeCommand static_delta_subcommands[] = {
   { "list", ot_static_delta_builtin_list },
+  { "show", ot_static_delta_builtin_show },
   { "generate", ot_static_delta_builtin_generate },
   { "apply-offline", ot_static_delta_builtin_apply_offline },
   { NULL, NULL }
@@ -129,6 +132,38 @@ ot_static_delta_builtin_list (int argc, char **argv, GCancellable *cancellable,
   return ret;
 }
 
+static gboolean
+ot_static_delta_builtin_show (int argc, char **argv, GCancellable *cancellable, GError **error)
+{
+  gboolean ret = FALSE;
+  GOptionContext *context;
+  glnx_unref_object OstreeRepo *repo = NULL;
+  const char *delta_id = NULL;
+
+  context = g_option_context_new ("SHOW - Dump information on a delta");
+
+  if (!ostree_option_context_parse (context, list_options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error))
+    goto out;
+
+  if (argc < 3)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                           "DELTA must be specified");
+      goto out;
+    }
+
+  delta_id = argv[2];
+
+  if (!ostree_cmd__private__ ()->ostree_static_delta_dump (repo, delta_id, cancellable, error))
+    goto out;
+      
+  ret = TRUE;
+ out:
+  if (context)
+    g_option_context_free (context);
+  return ret;
+}
+
 static gboolean
 ot_static_delta_builtin_generate (int argc, char **argv, GCancellable *cancellable, GError **error)
 {