diff --git a/Makefile-tests.am b/Makefile-tests.am
index 4986b427..bb1cee41 100644
--- a/Makefile-tests.am
+++ b/Makefile-tests.am
@@ -72,7 +72,6 @@ test_scripts = \
tests/test-repo-checkout-subpath.sh \
tests/test-reset-nonlinear.sh \
tests/test-oldstyle-partial.sh \
- tests/test-setuid.sh \
tests/test-delta.sh \
tests/test-xattrs.sh \
tests/test-auto-summary.sh \
diff --git a/man/ostree-commit.xml b/man/ostree-commit.xml
index 4a86c1d2..c4842584 100644
--- a/man/ostree-commit.xml
+++ b/man/ostree-commit.xml
@@ -163,7 +163,15 @@ Boston, MA 02111-1307, USA.
="PATH"
- File containing list of modifications to make permissions.
+ File containing list of modifications to make permissions (file mode, followed by space, followed by file path).
+
+
+
+
+ ="PATH"
+
+
+ File containing list of file paths to skip (one path per line).
diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c
index 1d96855d..a021fbfa 100644
--- a/src/ostree/ot-builtin-commit.c
+++ b/src/ostree/ot-builtin-commit.c
@@ -36,6 +36,7 @@ static char *opt_parent;
static gboolean opt_orphan;
static char *opt_branch;
static char *opt_statoverride_file;
+static char *opt_skiplist_file;
static char **opt_metadata_strings;
static char **opt_detached_metadata_strings;
static gboolean opt_link_checkout_speedup;
@@ -84,6 +85,7 @@ static GOptionEntry options[] = {
{ "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &opt_tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL },
{ "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &opt_skip_if_unchanged, "If the contents are unchanged from previous commit, do nothing", NULL },
{ "statoverride", 0, 0, G_OPTION_ARG_FILENAME, &opt_statoverride_file, "File containing list of modifications to make to permissions", "PATH" },
+ { "skip-list", 0, 0, G_OPTION_ARG_FILENAME, &opt_skiplist_file, "File containing list of files to skip", "PATH" },
{ "table-output", 0, 0, G_OPTION_ARG_NONE, &opt_table_output, "Output more information in a KEY: VALUE format", NULL },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"},
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"},
@@ -95,65 +97,85 @@ static GOptionEntry options[] = {
};
static gboolean
-parse_statoverride_file (GHashTable **out_mode_add,
- GCancellable *cancellable,
- GError **error)
+parse_file_by_line (const char *path,
+ gboolean (*cb)(const char*, void*, GError**),
+ void *cbdata,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
- gsize len;
- char **iter = NULL; /* nofree */
- g_autoptr(GHashTable) ret_hash = NULL;
- g_autoptr(GFile) path = NULL;
g_autofree char *contents = NULL;
+ g_autoptr(GFile) file = NULL;
char **lines = NULL;
- path = g_file_new_for_path (opt_statoverride_file);
-
- if (!g_file_load_contents (path, cancellable, &contents, &len, NULL,
- error))
+ file = g_file_new_for_path (path);
+ if (!g_file_load_contents (file, cancellable, &contents, NULL, NULL, error))
goto out;
-
- ret_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
lines = g_strsplit (contents, "\n", -1);
-
- for (iter = lines; iter && *iter; iter++)
+ for (char **iter = lines; iter && *iter; iter++)
{
- const char *line = *iter;
+ /* skip empty lines at least */
+ if (**iter == '\0')
+ continue;
- if (*line == '+')
- {
- const char *spc;
- guint mode_add;
-
- spc = strchr (line + 1, ' ');
- if (!spc)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Malformed statoverride file");
- goto out;
- }
-
- mode_add = (guint32)(gint32)g_ascii_strtod (line + 1, NULL);
- g_hash_table_insert (ret_hash,
- g_strdup (spc + 1),
- GUINT_TO_POINTER((gint32)mode_add));
- }
+ if (!cb (*iter, cbdata, error))
+ goto out;
}
ret = TRUE;
- ot_transfer_out_value (out_mode_add, &ret_hash);
- out:
+out:
g_strfreev (lines);
return ret;
}
+static gboolean
+handle_statoverride_line (const char *line,
+ void *data,
+ GError **error)
+{
+ GHashTable *files = data;
+ const char *spc;
+ guint mode_add;
+
+ spc = strchr (line, ' ');
+ if (spc == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Malformed statoverride file (no space found)");
+ return FALSE;
+ }
+
+ mode_add = (guint32)(gint32)g_ascii_strtod (line, NULL);
+ g_hash_table_insert (files, g_strdup (spc + 1),
+ GUINT_TO_POINTER((gint32)mode_add));
+ return TRUE;
+}
+
+static gboolean
+handle_skiplist_line (const char *line,
+ void *data,
+ GError **error)
+{
+ GHashTable *files = data;
+ g_hash_table_add (files, g_strdup (line));
+ return TRUE;
+}
+
+struct CommitFilterData {
+ GHashTable *mode_adds;
+ GHashTable *skip_list;
+};
+
static OstreeRepoCommitFilterResult
commit_filter (OstreeRepo *self,
const char *path,
GFileInfo *file_info,
gpointer user_data)
{
- GHashTable *mode_adds = user_data;
+ struct CommitFilterData *data = user_data;
+ GHashTable *mode_adds = data->mode_adds;
+ GHashTable *skip_list = data->skip_list;
gpointer value;
if (opt_owner_uid >= 0)
@@ -169,7 +191,13 @@ commit_filter (OstreeRepo *self,
current_mode | mode_add);
g_hash_table_remove (mode_adds, path);
}
-
+
+ if (skip_list && g_hash_table_contains (skip_list, path))
+ {
+ g_hash_table_remove (skip_list, path);
+ return OSTREE_REPO_COMMIT_FILTER_SKIP;
+ }
+
return OSTREE_REPO_COMMIT_FILTER_ALLOW;
}
@@ -310,9 +338,11 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
glnx_unref_object OstreeMutableTree *mtree = NULL;
g_autofree char *tree_type = NULL;
g_autoptr(GHashTable) mode_adds = NULL;
+ g_autoptr(GHashTable) skip_list = NULL;
OstreeRepoCommitModifierFlags flags = 0;
OstreeRepoCommitModifier *modifier = NULL;
OstreeRepoTransactionStats stats;
+ struct CommitFilterData filter_data = { 0, };
context = g_option_context_new ("[PATH] - Commit a new revision");
@@ -324,7 +354,17 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
if (opt_statoverride_file)
{
- if (!parse_statoverride_file (&mode_adds, cancellable, error))
+ mode_adds = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ if (!parse_file_by_line (opt_statoverride_file, handle_statoverride_line,
+ mode_adds, cancellable, error))
+ goto out;
+ }
+
+ if (opt_skiplist_file)
+ {
+ skip_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ if (!parse_file_by_line (opt_skiplist_file, handle_skiplist_line,
+ skip_list, cancellable, error))
goto out;
}
@@ -359,9 +399,13 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
|| opt_owner_uid >= 0
|| opt_owner_gid >= 0
|| opt_statoverride_file != NULL
+ || opt_skiplist_file != NULL
|| opt_no_xattrs)
{
- modifier = ostree_repo_commit_modifier_new (flags, commit_filter, mode_adds, NULL);
+ filter_data.mode_adds = mode_adds;
+ filter_data.skip_list = skip_list;
+ modifier = ostree_repo_commit_modifier_new (flags, commit_filter,
+ &filter_data, NULL);
}
if (opt_parent)
@@ -491,6 +535,22 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
goto out;
}
+ if (skip_list && g_hash_table_size (skip_list) > 0)
+ {
+ GHashTableIter hash_iter;
+ gpointer key;
+
+ g_hash_table_iter_init (&hash_iter, skip_list);
+
+ while (g_hash_table_iter_next (&hash_iter, &key, NULL))
+ {
+ g_printerr ("Unmatched skip-list path: %s\n", (char*)key);
+ }
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Unmatched skip-list paths");
+ goto out;
+ }
+
if (!ostree_repo_write_mtree (repo, mtree, &root, cancellable, error))
goto out;
diff --git a/tests/basic-test.sh b/tests/basic-test.sh
index b2477955..a44ee630 100755
--- a/tests/basic-test.sh
+++ b/tests/basic-test.sh
@@ -19,7 +19,7 @@
set -euo pipefail
-echo "1..54"
+echo "1..55"
$OSTREE checkout test2 checkout-test2
echo "ok checkout"
@@ -179,13 +179,31 @@ cd ${test_tmpdir}/checkout-test2-4
$OSTREE commit -b test2 -s "no xattrs" --no-xattrs
echo "ok commit with no xattrs"
+# NB: The + is optional, but we need to make sure we support it
cd ${test_tmpdir}
cat > test-statoverride.txt < test-skiplist.txt <
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-set -euo pipefail
-
-echo "1..1"
-
-. $(dirname $0)/libtest.sh
-
-setup_test_repository "bare"
-
-cd ${test_tmpdir}
-cat > test-statoverride.txt <