gboolean ot_admin_builtin_diff (int argc, char **argv, OstreeSysroot *sysroot, GCancellable *cancellable, GError **error) { GOptionContext *context; gboolean ret = FALSE; gs_unref_object OstreeDeployment *deployment = NULL; gs_unref_object GFile *deployment_dir = NULL; gs_unref_ptrarray GPtrArray *modified = NULL; gs_unref_ptrarray GPtrArray *removed = NULL; gs_unref_ptrarray GPtrArray *added = NULL; gs_unref_object GFile *orig_etc_path = NULL; gs_unref_object GFile *new_etc_path = NULL; context = g_option_context_new ("Diff current /etc configuration versus default"); g_option_context_add_main_entries (context, options, NULL); if (!g_option_context_parse (context, &argc, &argv, error)) goto out; if (!ostree_sysroot_load (sysroot, cancellable, error)) goto out; if (!ot_admin_require_booted_deployment_or_osname (sysroot, opt_osname, cancellable, error)) goto out; if (opt_osname != NULL) { deployment = ostree_sysroot_get_merge_deployment (sysroot, opt_osname); if (deployment == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No deployment for OS '%s'", opt_osname); goto out; } } else deployment = g_object_ref (ostree_sysroot_get_booted_deployment (sysroot)); deployment_dir = ostree_sysroot_get_deployment_directory (sysroot, deployment); orig_etc_path = g_file_resolve_relative_path (deployment_dir, "usr/etc"); new_etc_path = g_file_resolve_relative_path (deployment_dir, "etc"); 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_IGNORE_XATTRS, orig_etc_path, new_etc_path, modified, removed, added, cancellable, error)) goto out; ostree_diff_print (orig_etc_path, new_etc_path, modified, removed, added); ret = TRUE; out: if (context) g_option_context_free (context); return ret; }
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; }
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; }