All of lore.kernel.org
 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 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.