All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiang Xin <worldhello.net@gmail.com>
To: Git List <git@vger.kernel.org>
Cc: Junio C Hamano <gitster@pobox.com>
Subject: [PATCH] Use clean.requireforce to protect untracked files.
Date: Fri, 03 Jun 2011 19:12:46 +0800	[thread overview]
Message-ID: <4DE8C1AE.4000007@gmail.com> (raw)

Untracked files may be significant for certain repositories, but if run the
command "git clean -fdx" by accident, all untracked files will be lost.

This hack adds three values in addtion to true/false to "clean.requireforce",
which can protect untracked files from cleaning:

* true or unset : can not clean without -f/--force option provided.
* false         : clean untracked files just as -f/--force option provided.
* lockignored   : can not clean untracked ignored files.
* lockunignored : can not clean untracked unignored files.
* lockall       : can not clean anything.

Signed-off-by: Jiang Xin <jiangxin@ossxp.com>
---
 Documentation/config.txt |    7 +++-
 builtin/clean.c          |   29 ++++++++++++++++++-
 t/t7300-clean.sh         |   69 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+), 4 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 6b93777..b930f42 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -684,8 +684,11 @@ browser.<tool>.path::
 	working repository in gitweb (see linkgit:git-instaweb[1]).
 
 clean.requireForce::
-	A boolean to make git-clean do nothing unless given -f
-	or -n.   Defaults to true.
+	When set to `LockIgnored`, cleaning untracked ignored files is
+	denied. When set to `LockUnIgnored`, only allow cleaning untracked
+	ignored files using -X option. When set to `LockAll`, no files
+	can be cleaned until unset this variable. A boolean to make
+	git-clean do nothing unless given -f or -n. Defaults to true.
 
 color.branch::
 	A boolean to enable/disable color in the output of
diff --git a/builtin/clean.c b/builtin/clean.c
index 75697f7..441f35a 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -13,7 +13,11 @@
 #include "string-list.h"
 #include "quote.h"
 
+#define LOCK_IGNORED	01
+#define LOCK_UNIGNORED	02
+
 static int force = -1; /* unset */
+static int lock_flag = 0;
 
 static const char *const builtin_clean_usage[] = {
 	"git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>...",
@@ -22,8 +26,17 @@ static const char *const builtin_clean_usage[] = {
 
 static int git_clean_config(const char *var, const char *value, void *cb)
 {
-	if (!strcmp(var, "clean.requireforce"))
-		force = !git_config_bool(var, value);
+	if (!strcmp(var, "clean.requireforce")) {
+		if (value && !strcasecmp(value, "LockIgnored"))
+			lock_flag = LOCK_IGNORED;
+		else if (value && !strcasecmp(value, "LockUnIgnored"))
+			lock_flag = LOCK_UNIGNORED;
+		else if (value && !strcasecmp(value, "LockAll"))
+			lock_flag = LOCK_IGNORED | LOCK_UNIGNORED;
+		else
+			force = !git_config_bool(var, value);
+		return 0;
+	}
 	return git_default_config(var, value, cb);
 }
 
@@ -77,6 +90,18 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (ignored && ignored_only)
 		die(_("-x and -X cannot be used together"));
 
+	if (!show_only && lock_flag) {
+		if (lock_flag & LOCK_IGNORED && lock_flag & LOCK_UNIGNORED)
+			die(_("clean.requireForce set to LockAll; "
+				  "refusing to clean until reset clean.requireForce"));
+		else if (lock_flag & LOCK_IGNORED && (ignored_only || ignored))
+			die(_("clean.requireForce set to LockIgnored and conflict with -x or -X; "
+				  "refusing to clean"));
+		else if (lock_flag & LOCK_UNIGNORED && !ignored_only)
+			die(_("clean.requireForce set to LockUnIgnored and can only work with -X; "
+				  "refusing to clean"));
+	}
+
 	if (!show_only && !force) {
 		if (config_set)
 			die(_("clean.requireForce set to true and neither -n nor -f given; "
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 800b536..b4f38dd 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -460,4 +460,73 @@ test_expect_success SANITY 'git clean -d with an unreadable empty directory' '
 	! test -d foo
 '
 
+test_expect_success 'clean.requireForce LockIgnored' '
+
+	git config clean.requireForce LockIgnored &&
+	mkdir -p build docs &&
+	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
+	test_must_fail git clean &&
+	test_must_fail git clean -f -x &&
+	test_must_fail git clean -f -X &&
+	git clean -f &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test ! -f src/part3.c &&
+	test -f docs/manual.txt &&
+	test -f obj.o &&
+	test -f build/lib.so &&
+	git clean -f -d &&
+	test ! -f docs/manual.txt &&
+	test -f build/lib.so &&
+	git config clean.requireForce true
+'
+
+test_expect_success 'clean.requireForce LockUnIgnored' '
+
+	git config clean.requireForce LockUnIgnored &&
+	mkdir -p build docs &&
+	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
+	test_must_fail git clean &&
+	test_must_fail git clean -f &&
+	test_must_fail git clean -f -x &&
+	git clean -f -X &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test -f src/part3.c &&
+	test -f docs/manual.txt &&
+	test ! -f obj.o &&
+	test -f build/lib.so &&
+	git clean -f -d -X &&
+	test ! -f build/lib.so &&
+	test -f src/part3.c &&
+	git config clean.requireForce true
+'
+
+test_expect_success 'clean.requireForce LockAll' '
+
+	git config clean.requireForce lockall &&
+	mkdir -p build docs &&
+	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
+	test_must_fail git clean -f &&
+	test_must_fail git clean -f -x &&
+	test_must_fail git clean -f -X &&
+	git clean -ndx &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test -f src/part3.c &&
+	test -f docs/manual.txt &&
+	test -f obj.o &&
+	test -f build/lib.so &&
+	git config clean.requireForce true
+'
+
 test_done
-- 
1.7.5.4.1.g6c49.dirty

             reply	other threads:[~2011-06-03 11:13 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-03 11:12 Jiang Xin [this message]
2011-06-03 15:11 ` [PATCH] Use clean.requireforce to protect untracked files Junio C Hamano
2011-06-03 16:20   ` Jiang Xin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DE8C1AE.4000007@gmail.com \
    --to=worldhello.net@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.