git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jay Soffian <jaysoffian@gmail.com>
To: git@vger.kernel.org
Cc: Jay Soffian <jaysoffian@gmail.com>, Jeff King <peff@peff.net>,
	Junio C Hamano <gitster@pobox.com>
Subject: [PATCH] builtin-remote: make rm operation safer in mirrored repository
Date: Wed,  4 Feb 2009 11:06:07 -0500	[thread overview]
Message-ID: <1233763567-6155-1-git-send-email-jaysoffian@gmail.com> (raw)
In-Reply-To: <76718490902040756m1f5c6f37o45865c51ad1a2e6d@mail.gmail.com>

"git remote rm <repo>" is happy to remove non-remote refs (and their
reflogs in the case of branches). This may be okay if the repository truely is a mirror, but if the
user had done "git remote add --mirror <repo>" by accident and was just
undoing their mistake, then they are left in a situation that is difficult to
recover from.

After this commit, "git remote rm" skips over non-remote refs. The user is
advised on how remove branches using "git branch -d", which itself has nice
safety checks wrt to branch removal lacking from "git remote rm". Non-remote
non-branch refs are skipped silently.

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
On Wed, Feb 4, 2009 at 10:56 AM, Jay Soffian <jaysoffian@gmail.com> wrote:
> In particular though, I noticed that w/o this check, I was emitting an
> incorrect message about anything under refs/tags. I thought about
> saying "and you can clean up these ignored tags like so", but that is
> likely to emit a huge number of messages, so I thought it best just to
> silently ignore non-remote non-branch refs. Perhaps I should better
> explain that in a code comment.

I think I made what's going on clearer, assuming this is what we want to do.
Slightly revised the commit message.

This thread is getting sotra long, so here's the gmane threaded view for
easier following:

http://thread.gmane.org/gmane.comp.version-control.git/107982/

 builtin-remote.c  |   29 +++++++++++++++++++++++++++--
 t/t5505-remote.sh |   26 ++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/builtin-remote.c b/builtin-remote.c
index 21885fb..db18bcf 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -298,7 +298,7 @@ static int add_known_remote(struct remote *remote, void *cb_data)
 
 struct branches_for_remote {
 	struct remote *remote;
-	struct string_list *branches;
+	struct string_list *branches, *skipped;
 	struct known_remotes *keep;
 };
 
@@ -323,6 +323,16 @@ static int add_branch_for_removal(const char *refname,
 			return 0;
 	}
 
+	/* don't delete non-remote refs */
+	if (prefixcmp(refname, "refs/remotes")) {
+		/* advise user how to delete local branches */
+		if (!prefixcmp(refname, "refs/heads/"))
+			string_list_append(abbrev_branch(refname),
+					   branches->skipped);
+		/* silently skip over other non-remote refs */
+		return 0;
+	}
+
 	/* make sure that symrefs are deleted */
 	if (flags & REF_ISSYMREF)
 		return unlink(git_path("%s", refname));
@@ -542,7 +552,10 @@ static int rm(int argc, const char **argv)
 	struct strbuf buf = STRBUF_INIT;
 	struct known_remotes known_remotes = { NULL, NULL };
 	struct string_list branches = { NULL, 0, 0, 1 };
-	struct branches_for_remote cb_data = { NULL, &branches, &known_remotes };
+	struct string_list skipped = { NULL, 0, 0, 1 };
+	struct branches_for_remote cb_data = {
+		NULL, &branches, &skipped, &known_remotes
+	};
 	int i, result;
 
 	if (argc != 2)
@@ -590,6 +603,18 @@ static int rm(int argc, const char **argv)
 		result = remove_branches(&branches);
 	string_list_clear(&branches, 1);
 
+	if (skipped.nr) {
+		fprintf(stderr, skipped.nr == 1 ?
+			"Note: A non-remote branch was not removed; "
+			"to delete it, use:\n" :
+			"Note: Non-remote branches were not removed; "
+			"to delete them, use:\n");
+		for (i = 0; i < skipped.nr; i++)
+			fprintf(stderr, "  git branch -d %s\n",
+				skipped.items[i].string);
+	}
+	string_list_clear(&skipped, 0);
+
 	return result;
 }
 
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 1f59960..bc5b7ce 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -107,6 +107,32 @@ test_expect_success 'remove remote' '
 )
 '
 
+test_expect_success 'remove remote protects non-remote branches' '
+(
+	cd test &&
+	(cat >expect1 <<EOF
+Note: A non-remote branch was not removed; to delete it, use:
+  git branch -d master
+EOF
+    cat >expect2 <<EOF
+Note: Non-remote branches were not removed; to delete them, use:
+  git branch -d foobranch
+  git branch -d master
+EOF
+) &&
+	git tag footag
+	git config --add remote.oops.fetch "+refs/*:refs/*" &&
+	git remote rm oops 2>actual1 &&
+	git branch foobranch &&
+	git config --add remote.oops.fetch "+refs/*:refs/*" &&
+	git remote rm oops 2>actual2 &&
+	git branch -d foobranch &&
+	git tag -d footag &&
+	test_cmp expect1 actual1 &&
+	test_cmp expect2 actual2
+)
+'
+
 cat > test/expect << EOF
 * remote origin
   URL: $(pwd)/one
-- 
1.6.1.2.322.g9a647

  reply	other threads:[~2009-02-04 16:07 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-01 14:52 git remote rm considered harmful? Jay Soffian
2009-02-01 15:48 ` [PATCH] builtin-remote: make rm operation safer in mirrored repository Jay Soffian
2009-02-02 13:29   ` Jeff King
2009-02-02 13:36     ` Jay Soffian
2009-02-02 18:40       ` Jay Soffian
2009-02-03  7:24         ` Jeff King
2009-02-03  7:54           ` Junio C Hamano
2009-02-03 14:38             ` Jay Soffian
2009-02-03 14:53               ` Johannes Schindelin
2009-02-03 17:51               ` [PATCH 1/2] builtin-remote: make rm() use properly named variable to hold return value Jay Soffian
2009-02-04 15:34                 ` Jeff King
2009-02-03 17:51               ` [PATCH 2/2] builtin-remote: make rm operation safer in mirrored repository Jay Soffian
2009-02-04 15:42                 ` Jeff King
2009-02-04 15:56                   ` Jay Soffian
2009-02-04 16:06                     ` Jay Soffian [this message]
2009-02-04 16:18                       ` [PATCH] " Jeff King
2009-02-04 16:16                     ` [PATCH 2/2] " 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=1233763567-6155-1-git-send-email-jaysoffian@gmail.com \
    --to=jaysoffian@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    /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).