git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH 3/6] receive-pack: receive.denyDeleteCurrent
Date: Mon,  9 Feb 2009 01:09:22 -0800	[thread overview]
Message-ID: <1234170565-6740-4-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1234170565-6740-3-git-send-email-gitster@pobox.com>

This is a companion patch to the recent 3d95d92 (receive-pack: explain
what to do when push updates the current branch, 2009-01-31).

Deleting the current branch from a remote will result in the next clone
from it not check out anything, among other things.  It also is one of the
cause that makes remotes/origin/HEAD a dangling symbolic ref.  This patch
still allows the traditional behaviour but with a big warning, and promises
that the default will change to 'refuse' in a future release.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-receive-pack.c |   72 ++++++++++++++++++++++++++++++++++++++++-------
 t/t5400-send-pack.sh   |    7 ++++
 2 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index b2cb4ba..f7e04c4 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -21,11 +21,13 @@ enum deny_action {
 static int deny_deletes;
 static int deny_non_fast_forwards;
 static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
+static enum deny_action deny_delete_current = DENY_UNCONFIGURED;
 static int receive_fsck_objects;
 static int receive_unpack_limit = -1;
 static int transfer_unpack_limit = -1;
 static int unpack_limit = 100;
 static int report_status;
+static const char *head_name;
 
 static char capabilities[] = " report-status delete-refs ";
 static int capabilities_sent;
@@ -77,6 +79,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
+	if (strcmp(var, "receive.denydeletecurrent") == 0) {
+		deny_delete_current = parse_deny_action(var, value);
+		return 0;
+	}
+
 	return git_default_config(var, value, cb);
 }
 
@@ -203,16 +210,12 @@ static int run_update_hook(struct command *cmd)
 
 static int is_ref_checked_out(const char *ref)
 {
-	unsigned char sha1[20];
-	const char *head;
-
 	if (is_bare_repository())
 		return 0;
 
-	head = resolve_ref("HEAD", sha1, 0, NULL);
-	if (!head)
+	if (!head_name)
 		return 0;
-	return !strcmp(head, ref);
+	return !strcmp(head_name, ref);
 }
 
 static char *warn_unconfigured_deny_msg[] = {
@@ -244,6 +247,32 @@ static void warn_unconfigured_deny(void)
 		warning(warn_unconfigured_deny_msg[i]);
 }
 
+static char *warn_unconfigured_deny_delete_current_msg[] = {
+	"Deleting the current branch can cause confusion by making the next",
+	"'git clone' not check out any file.",
+	"",
+	"You can set 'receive.denyDeleteCurrent' configuration variable to",
+	"'refuse' in the remote repository to disallow deleting the current",
+	"branch.",
+	"",
+	"You can set it to 'ignore' to allow such a delete without a warning.",
+	"",
+	"To make this warning message less loud, you can set it to 'warn'.",
+	"",
+	"Note that the default will change in a future version of git",
+	"to refuse deleting the current branch unless you have the",
+	"configuration variable set to either 'ignore' or 'warn'."
+};
+
+static void warn_unconfigured_deny_delete_current(void)
+{
+	int i;
+	for (i = 0;
+	     i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
+	     i++)
+		warning(warn_unconfigured_deny_delete_current_msg[i]);
+}
+
 static const char *update(struct command *cmd)
 {
 	const char *name = cmd->ref_name;
@@ -278,12 +307,30 @@ static const char *update(struct command *cmd)
 		      "but I can't find it!", sha1_to_hex(new_sha1));
 		return "bad pack";
 	}
-	if (deny_deletes && is_null_sha1(new_sha1) &&
-	    !is_null_sha1(old_sha1) &&
-	    !prefixcmp(name, "refs/heads/")) {
-		error("denying ref deletion for %s", name);
-		return "deletion prohibited";
+
+	if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
+		if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
+			error("denying ref deletion for %s", name);
+			return "deletion prohibited";
+		}
+
+		if (!strcmp(name, head_name)) {
+			switch (deny_delete_current) {
+			case DENY_IGNORE:
+				break;
+			case DENY_WARN:
+			case DENY_UNCONFIGURED:
+				if (deny_delete_current == DENY_UNCONFIGURED)
+					warn_unconfigured_deny_delete_current();
+				warning("deleting the current branch");
+				break;
+			case DENY_REFUSE:
+				error("refusing to delete the current branch: %s", name);
+				return "deletion of the current branch prohibited";
+			}
+		}
 	}
+
 	if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
 	    !is_null_sha1(old_sha1) &&
 	    !prefixcmp(name, "refs/heads/")) {
@@ -377,6 +424,7 @@ static void run_update_post_hook(struct command *cmd)
 static void execute_commands(const char *unpacker_error)
 {
 	struct command *cmd = commands;
+	unsigned char sha1[20];
 
 	if (unpacker_error) {
 		while (cmd) {
@@ -394,6 +442,8 @@ static void execute_commands(const char *unpacker_error)
 		return;
 	}
 
+	head_name = resolve_ref("HEAD", sha1, 0, NULL);
+
 	while (cmd) {
 		cmd->error_string = update(cmd);
 		cmd = cmd->next;
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index 013aced..7b21f5f 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -193,4 +193,11 @@ test_expect_success 'pushing wildcard refspecs respects forcing' '
     )
 '
 
+test_expect_success 'deny pushing to delete current branch' '
+    (
+	rewound_push_setup &&
+	git send-pack ../parent/.git :refs/heads/master 2>errs
+    )
+'
+
 test_done
-- 
1.6.2.rc0.28.g2593d

  reply	other threads:[~2009-02-09  9:11 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-07 15:27 Deleting the "current" branch in remote bare repositories Jan Krüger
2009-02-07 22:05 ` Felipe Contreras
2009-02-08  0:18   ` Jan Krüger
2009-02-08  8:44     ` Jeff King
2009-02-08  9:42     ` Junio C Hamano
2009-02-08 11:18       ` Jeff King
2009-02-08 19:05         ` Junio C Hamano
2009-02-09  9:09           ` [PATCH 0/6] Deleting the "current" branch in a remote repository Junio C Hamano
2009-02-09  9:09             ` [PATCH 1/6] builtin-receive-pack.c: do not initialize statics to 0 Junio C Hamano
2009-02-09  9:09               ` [PATCH 2/6] t5400: allow individual tests to fail Junio C Hamano
2009-02-09  9:09                 ` Junio C Hamano [this message]
2009-02-09  9:09                   ` [PATCH 4/6] remote prune: warn dangling symrefs Junio C Hamano
2009-02-09  9:09                     ` [PATCH 5/6] Warn use of "origin" when remotes/origin/HEAD is dangling Junio C Hamano
2009-02-09  9:09                       ` [PATCH 6/6] receive-pack: default receive.denyDeleteCurrent to refuse Junio C Hamano
2009-02-09 19:15                     ` [PATCH 4/6] remote prune: warn dangling symrefs Jeff King
2009-02-11 17:30                       ` Junio C Hamano
2009-02-11 18:35                         ` Jeff King
2009-02-11 18:42                           ` Jeff King
2009-02-09 18:53                   ` [PATCH 3/6] receive-pack: receive.denyDeleteCurrent Jeff King
2009-02-09 19:22                     ` Jeff King
2009-02-09 21:38                       ` Junio C Hamano
2009-02-10 12:07                         ` Jeff King
2009-02-10 15:15                           ` Junio C Hamano
2009-02-09 18:46                 ` [PATCH 2/6] t5400: allow individual tests to fail Jeff King
2009-02-09 19:08                   ` Junio C Hamano
2009-02-09 21:39                     ` Junio C Hamano
2009-02-10 12:01                       ` Jeff King
2009-02-09 18:28           ` Deleting the "current" branch in remote bare repositories Jeff King
2009-02-09 18:36             ` Jeff King

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=1234170565-6740-4-git-send-email-gitster@pobox.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).