Subject: [PATCH] git submodule add: Require the new --force option to add ignored paths

From: Jens Lehmann <[email-masked]>
Date: Sat, 17 Jul 2010 17:11:43 +0200

To make the behavior of "git submodule add" more consistent with "git add"
ignored submodule paths should not be silently added when they match an
entry in a .gitignore file. To be able to override that default behavior
in the same way as we can do that for "git add", the new option "--force"
is introduced.

Signed-off-by: Jens Lehmann <[email-masked]>
---

Am 13.07.2010 00:14, schrieb Junio C Hamano:
> Jens Lehmann <[email-masked]> writes:
> 
>> With this patch it should be easy to have "git submodule add" return
>> an error /before/ adding a submodule path and its contents when it
>> is found in .gitignore.
>>
>> Opinions?
> 
> Sounds like a right thing to do.

So here we go. This patch applies to pu as it needs the
'git add: Add the "--ignore-missing" option for the dry run'
patch to work.

 Documentation/git-submodule.txt |    7 ++++++-
 git-submodule.sh                |   16 ++++++++++++++--
 t/t7400-submodule-basic.sh      |   27 +++++++++++++++------------
 3 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 76a832a..617069f 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -9,7 +9,7 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
-'git submodule' [--quiet] add [-b branch]
+'git submodule' [--quiet] add [-b branch] [-f|--force]
 	      [--reference <repository>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
@@ -187,6 +187,11 @@ OPTIONS
 --branch::
 	Branch of repository to add as submodule.

+-f::
+--force::
+	This option is only valid for the add command.
+	Allow adding an otherwise ignored submodule path.
+
 --cached::
 	This option is only valid for status and summary commands.  These
 	commands typically use the commit found in the submodule HEAD, but
diff --git a/git-submodule.sh b/git-submodule.sh
index ad2417d..170186f 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -5,7 +5,7 @@
 # Copyright (c) 2007 Lars Hjemli

 dashless=$(basename "$0" | sed -e 's/-/ /')
-USAGE="[--quiet] add [-b branch] [--reference <repository>] [--] <repository> [<path>]
+USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
@@ -19,6 +19,7 @@ require_work_tree

 command=
 branch=
+force=
 reference=
 cached=
 recursive=
@@ -133,6 +134,9 @@ cmd_add()
 			branch=$2
 			shift
 			;;
+		-f | --force)
+			force=$1
+			;;
 		-q|--quiet)
 			GIT_QUIET=1
 			;;
@@ -201,6 +205,14 @@ cmd_add()
 	git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
 	die "'$path' already exists in the index"

+	if test -z "$force" && ! git add --dry-run --ignore-missing "$path" > /dev/null 2>&1
+	then
+		echo >&2 "The following path is ignored by one of your .gitignore files:" &&
+		echo >&2 $path &&
+		echo >&2 "Use -f if you really want to add it."
+		exit 1
+	fi
+
 	# perhaps the path exists and is already a git repo, else clone it
 	if test -e "$path"
 	then
@@ -234,7 +246,7 @@ cmd_add()
 		) || die "Unable to checkout submodule '$path'"
 	fi

-	git add --force "$path" ||
+	git add $force "$path" ||
 	die "Failed to add submodule '$path'"

 	git config -f .gitmodules submodule."$path".path "$path" &&
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index d9f2785..9bda970 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -86,25 +86,28 @@ test_expect_success 'submodule add' '
 	test_cmp empty untracked
 '

-test_expect_success 'submodule add to .gitignored path' '
-	echo "refs/heads/master" >expect &&
-	>empty &&
-
+test_expect_success 'submodule add to .gitignored path fails' '
 	(
 		cd addtest-ignore &&
+		cat <<-\EOF >expect &&
+		The following path is ignored by one of your .gitignore files:
+		submod
+		Use -f if you really want to add it.
+		EOF
 		# Does not use test_commit due to the ignore
 		echo "*" > .gitignore &&
 		git add --force .gitignore &&
 		git commit -m"Ignore everything" &&
-		git submodule add "$submodurl" submod &&
-		git submodule init
-	) &&
+		! git submodule add "$submodurl" submod >actual 2>&1 &&
+		test_cmp expect actual
+	)
+'

-	rm -f heads head untracked &&
-	inspect addtest/submod ../.. &&
-	test_cmp expect heads &&
-	test_cmp expect head &&
-	test_cmp empty untracked
+test_expect_success 'submodule add to .gitignored path with --force' '
+	(
+		cd addtest-ignore &&
+		git submodule add --force "$submodurl" submod
+	)
 '

 test_expect_success 'submodule add --branch' '
-- 
1.7.2.rc3.262.gcf61