diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index cba6ec46..027f25c5 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -172,6 +172,7 @@ OstreeDiffItem ostree_diff_item_ref ostree_diff_item_unref ostree_diff_dirs +ostree_diff_dirs_with_options ostree_diff_print ostree_diff_item_get_type diff --git a/man/ostree-diff.xml b/man/ostree-diff.xml index aaa76b13..906374b4 100644 --- a/man/ostree-diff.xml +++ b/man/ostree-diff.xml @@ -78,6 +78,20 @@ Boston, MA 02111-1307, USA. Print filesystem diff. + + + + + Use file ownership user id for local files. + + + + + + + Use file ownership group id for local files. + + diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index 9067a26c..649c6f1f 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -389,6 +389,7 @@ global: LIBOSTREE_2017.4 { global: ostree_check_version; + ostree_diff_dirs_with_options; } LIBOSTREE_2017.3; /* Stub section for the stable release *after* this development one; don't diff --git a/src/libostree/ostree-diff.c b/src/libostree/ostree-diff.c index 69a67b76..5537ee87 100644 --- a/src/libostree/ostree-diff.c +++ b/src/libostree/ostree-diff.c @@ -225,6 +225,37 @@ ostree_diff_dirs (OstreeDiffFlags flags, GPtrArray *added, GCancellable *cancellable, GError **error) +{ + return ostree_diff_dirs_with_options (flags, a, b, modified, + removed, added, NULL, + cancellable, error); +} + +/** + * ostree_diff_dirs_with_options: + * @flags: Flags + * @a: First directory path, or %NULL + * @b: First directory path + * @modified: (element-type OstreeDiffItem): Modified files + * @removed: (element-type Gio.File): Removed files + * @added: (element-type Gio.File): Added files + * @cancellable: Cancellable + * @options: (allow-none): Options + * @error: Error + * + * Compute the difference between directory @a and @b as 3 separate + * sets of #OstreeDiffItem in @modified, @removed, and @added. + */ +gboolean +ostree_diff_dirs_with_options (OstreeDiffFlags flags, + GFile *a, + GFile *b, + GPtrArray *modified, + GPtrArray *removed, + GPtrArray *added, + OstreeDiffDirsOptions *options, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; GError *temp_error = NULL; @@ -233,6 +264,10 @@ ostree_diff_dirs (OstreeDiffFlags flags, g_autoptr(GFile) child_b = NULL; g_autoptr(GFileInfo) child_a_info = NULL; g_autoptr(GFileInfo) child_b_info = NULL; + OstreeDiffDirsOptions default_opts = OSTREE_DIFF_DIRS_OPTIONS_INIT; + + if (!options) + options = &default_opts; if (a == NULL) { @@ -316,6 +351,11 @@ ostree_diff_dirs (OstreeDiffFlags flags, } else { + if (options->owner_uid >= 0) + g_file_info_set_attribute_uint32 (child_b_info, "unix::uid", options->owner_uid); + if (options->owner_gid >= 0) + g_file_info_set_attribute_uint32 (child_b_info, "unix::gid", options->owner_gid); + child_b_type = g_file_info_get_file_type (child_b_info); if (child_a_type != child_b_type) { @@ -337,8 +377,9 @@ ostree_diff_dirs (OstreeDiffFlags flags, if (child_a_type == G_FILE_TYPE_DIRECTORY) { - if (!ostree_diff_dirs (flags, child_a, child_b, modified, - removed, added, cancellable, error)) + if (!ostree_diff_dirs_with_options (flags, child_a, child_b, modified, + removed, added, options, + cancellable, error)) goto out; } } diff --git a/src/libostree/ostree-diff.h b/src/libostree/ostree-diff.h index 781bf768..b33bd63a 100644 --- a/src/libostree/ostree-diff.h +++ b/src/libostree/ostree-diff.h @@ -71,6 +71,42 @@ gboolean ostree_diff_dirs (OstreeDiffFlags flags, GCancellable *cancellable, GError **error); +/** + * OstreeDiffDirsOptions: + * + * An extensible options structure controlling diff dirs. Make sure + * that owner_uid/gid is set to -1 when not used. This is used by + * ostree_diff_dirs_with_options(). + */ +typedef struct { + gint owner_uid; + gint owner_gid; + + OstreeRepoDevInoCache *devino_to_csum_cache; + + gboolean unused_bools[7]; + int unused_ints[6]; + gpointer unused_ptrs[7]; +} OstreeDiffDirsOptions; + +/** + * OSTREE_DIFF_DIRS_OPTIONS_INIT: + * + * Use this to initialize an `OstreeDiffDirsOptions` structure. + */ +#define OSTREE_DIFF_DIRS_OPTIONS_INIT { .owner_uid = -1, .owner_gid = -1, } + +_OSTREE_PUBLIC +gboolean ostree_diff_dirs_with_options (OstreeDiffFlags flags, + GFile *a, + GFile *b, + GPtrArray *modified, + GPtrArray *removed, + GPtrArray *added, + OstreeDiffDirsOptions *options, + GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC void ostree_diff_print (GFile *a, GFile *b, diff --git a/src/ostree/ot-builtin-diff.c b/src/ostree/ot-builtin-diff.c index 963a8b7c..a7e2aad2 100644 --- a/src/ostree/ot-builtin-diff.c +++ b/src/ostree/ot-builtin-diff.c @@ -30,11 +30,15 @@ static gboolean opt_stats; static gboolean opt_fs_diff; static gboolean opt_no_xattrs; +static gint opt_owner_uid = -1; +static gint opt_owner_gid = -1; 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 }, { "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Skip output of extended attributes", NULL }, + { "owner-uid", 0, 0, G_OPTION_ARG_INT, &opt_owner_uid, "Use file ownership user id for local files", "UID" }, + { "owner-gid", 0, 0, G_OPTION_ARG_INT, &opt_owner_gid, "Use file ownership group id for local files", "GID" }, { NULL } }; @@ -177,8 +181,10 @@ ostree_builtin_diff (int argc, char **argv, GCancellable *cancellable, GError ** 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 (diff_flags, srcf, targetf, modified, removed, added, cancellable, error)) + + 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); diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 045e4217..68c7b0a6 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -19,7 +19,7 @@ set -euo pipefail -echo "1..63" +echo "1..65" $CMD_PREFIX ostree --version > version.yaml python -c 'import yaml; yaml.safe_load(open("version.yaml"))' @@ -171,6 +171,21 @@ cd ${test_tmpdir} assert_file_has_content diff-test2-2 'A *oh-look-a-file$' echo "ok diff cwd" +cd ${test_tmpdir}/checkout-test2-4 +$OSTREE diff test2 ./ > ${test_tmpdir}/diff-test2 +assert_file_empty ${test_tmpdir}/diff-test2 +$OSTREE diff test2 --owner-uid=$((`id -u`+1)) ./ > ${test_tmpdir}/diff-test2 +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet$' +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/message$' +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/another/tree/green$' +echo "ok diff file with different uid" + +$OSTREE diff test2 --owner-gid=$((`id -g`+1)) ./ > ${test_tmpdir}/diff-test2 +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet$' +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/message$' +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/another/tree/green$' +echo "ok diff file with different gid" + cd ${test_tmpdir}/checkout-test2-4 rm four mkdir four