diff mbox series

[v2,6/6] sparse-checkout: reject arguments in cone-mode that look like patterns

Message ID 286c22e5ecdd1e19cc4ca53126b2616085de6133.1644913943.git.gitgitgadget@gmail.com (mailing list archive)
State Superseded
Headers show
Series [v2,1/6] sparse-checkout: correct reapply's handling of options | expand

Commit Message

Elijah Newren Feb. 15, 2022, 8:32 a.m. UTC
From: Elijah Newren <newren@gmail.com>

In sparse-checkout add/set under cone mode, the arguments passed are
supposed to be directories rather than gitignore-style patterns.
However, given the amount of effort spent in the manual discussing
patterns, it is easy for users to assume they need to pass patterns such
as
   /foo/*
or
   !/bar/*/
or perhaps they really do ignore the directory rule and specify a
random gitignore-style pattern like
   *.c

To help catch such mistakes, throw an error if any of the positional
arguments:
  * starts with any of '/!'
  * contains any of '*\?[]'

Inform users they can pass --skip-checks if they have a directory that
really does have such special characters in its name.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 builtin/sparse-checkout.c          | 16 ++++++++++++++--
 t/t1091-sparse-checkout-builtin.sh |  2 +-
 2 files changed, 15 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 74d64ada9f9..a30c77e7a1a 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -710,10 +710,22 @@  static void sanitize_paths(int argc, const char **argv,
 	if (skip_checks)
 		return;
 
-	if (!core_sparse_checkout_cone)
-		for (i = 0; i < argc; i++)
+	for (i = 0; i < argc; i++) {
+		if (core_sparse_checkout_cone) {
+			if (argv[i][0] == '/')
+				die(_("specify directories rather than patterns (no leading slash)"));
+			if (argv[i][0] == '!')
+				die(_("specify directories rather than patterns.  If your directory starts with a '!', pass --skip-checks"));
+			if (strchr(argv[i], '*') ||
+			    strchr(argv[i], '?') ||
+			    strchr(argv[i], '[') ||
+			    strchr(argv[i], ']'))
+				die(_("specify directories rather than patterns.  If your directory really has any of '*?[]' in it, pass --skip-checks"));
+		} else {
 			if (argv[i][0] == '#')
 				die(_("paths beginning with a '#' must be preceeded by a backslash"));
+		}
+	}
 
 	for (i = 0; i < argc; i++) {
 		struct cache_entry *ce;
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index 3c811724d5d..72157fc6f1f 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -673,7 +673,7 @@  test_expect_success BSLASHPSPEC 'pattern-checks: escaped characters' '
 	git -C escaped reset --hard $COMMIT &&
 	check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? &&
 	git -C escaped sparse-checkout init --cone &&
-	git -C escaped sparse-checkout set zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" &&
+	git -C escaped sparse-checkout set --skip-checks zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" &&
 	cat >expect <<-\EOF &&
 	/*
 	!/*/