summaryrefslogtreecommitdiff
path: root/src/ostree/ot-builtin-diff.c
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2013-07-17 19:20:22 -0400
committerColin Walters <walters@verbum.org>2013-07-17 19:20:53 -0400
commit1b3ef57cf43997dbb71dac0d28e97b93a451c6a5 (patch)
treed120c2dba73e99c0889da40f3cf5603015342c0c /src/ostree/ot-builtin-diff.c
parenta3b6401788f8c353343deb68debb5444038c1ab6 (diff)
downloadostree-1b3ef57cf43997dbb71dac0d28e97b93a451c6a5.tar.gz
diff: Add --stats option
This a neat way to see how many objects are shared between two commits.
Diffstat (limited to 'src/ostree/ot-builtin-diff.c')
-rw-r--r--src/ostree/ot-builtin-diff.c127
1 files changed, 114 insertions, 13 deletions
diff --git a/src/ostree/ot-builtin-diff.c b/src/ostree/ot-builtin-diff.c
index 143fe26a..0668609e 100644
--- a/src/ostree/ot-builtin-diff.c
+++ b/src/ostree/ot-builtin-diff.c
@@ -25,7 +25,12 @@
#include "ot-builtins.h"
#include "ostree.h"
+static gboolean opt_stats;
+static gboolean opt_fs_diff;
+
static GOptionEntry options[] = {
+ { "stats", 0, 0, G_OPTION_ARG_NONE, &opt_stats, "Print various statistics", NULL },
+ { "fs-diff", 0, 0, G_OPTION_ARG_NONE, &opt_fs_diff, "Print filesystem diff", NULL },
{ NULL }
};
@@ -57,6 +62,61 @@ parse_file_or_commit (OstreeRepo *repo,
return ret;
}
+static GHashTable *
+reachable_set_intersect (GHashTable *a, GHashTable *b)
+{
+ GHashTable *ret = ostree_repo_traverse_new_reachable ();
+ GHashTableIter hashiter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&hashiter, a);
+ while (g_hash_table_iter_next (&hashiter, &key, &value))
+ {
+ GVariant *v = key;
+ if (g_hash_table_contains (b, v))
+ g_hash_table_insert (ret, g_variant_ref (v), v);
+ }
+
+ return ret;
+}
+
+static gboolean
+object_set_total_size (OstreeRepo *repo,
+ GHashTable *reachable,
+ guint64 *out_total,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GHashTableIter hashiter;
+ gpointer key, value;
+
+ *out_total = 0;
+
+ g_hash_table_iter_init (&hashiter, reachable);
+ while (g_hash_table_iter_next (&hashiter, &key, &value))
+ {
+ GVariant *v = key;
+ const char *csum;
+ OstreeObjectType objtype;
+ gs_unref_object GFile *objpath = NULL;
+ gs_unref_object GFileInfo *finfo = NULL;
+
+ ostree_object_name_deserialize (v, &csum, &objtype);
+ objpath = ostree_repo_get_object_path (repo, csum, objtype);
+ finfo = g_file_query_info (objpath, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!finfo)
+ goto out;
+
+ *out_total += g_file_info_get_size (finfo);
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
gboolean
ostree_builtin_diff (int argc, char **argv, GFile *repo_path, GCancellable *cancellable, GError **error)
{
@@ -68,7 +128,6 @@ ostree_builtin_diff (int argc, char **argv, GFile *repo_path, GCancellable *canc
gs_free char *src_prev = NULL;
gs_unref_object GFile *srcf = NULL;
gs_unref_object GFile *targetf = NULL;
- gs_unref_object GFile *cwd = NULL;
gs_unref_ptrarray GPtrArray *modified = NULL;
gs_unref_ptrarray GPtrArray *removed = NULL;
gs_unref_ptrarray GPtrArray *added = NULL;
@@ -105,21 +164,63 @@ ostree_builtin_diff (int argc, char **argv, GFile *repo_path, GCancellable *canc
target = argv[2];
}
- cwd = g_file_new_for_path (".");
+ if (!opt_stats && !opt_fs_diff)
+ opt_fs_diff = TRUE;
- if (!parse_file_or_commit (repo, src, &srcf, cancellable, error))
- goto out;
- if (!parse_file_or_commit (repo, target, &targetf, cancellable, error))
- goto out;
+ 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 (srcf, targetf, modified, removed, added, 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 (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 = ostree_repo_traverse_new_reachable ();
+ gs_unref_hashtable GHashTable *reachable_b = ostree_repo_traverse_new_reachable ();
+ 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;
- ostree_diff_print (srcf, targetf, modified, removed, added);
+ 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: