git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* git remote rm considered harmful?
@ 2009-02-01 14:52 Jay Soffian
  2009-02-01 15:48 ` [PATCH] builtin-remote: make rm operation safer in mirrored repository Jay Soffian
  0 siblings, 1 reply; 17+ messages in thread
From: Jay Soffian @ 2009-02-01 14:52 UTC (permalink / raw)
  To: Git Mailing List

Yesterday I was not paying attention to a repository I was in when I
used git remote to make a mirror:

$ git remote add --mirror bar git://foo/bar

I realized my mistake and removed the mirror:

$ git remote rm bar

Poof. All of my local branches and their reflogs were gone. Reproduce with:

# Setup a repository
mkdir foo && cd foo && git init
echo foo > foo && git add foo && git commit -m foo

# Make some branches for demonstration purposes
git co -b branch1
git co -b branch2
git co -b branch3
git co master
find .git/refs .git/logs
.git/refs
.git/refs/heads
.git/refs/heads/branch1
.git/refs/heads/branch2
.git/refs/heads/branch3
.git/refs/heads/master
.git/refs/tags
.git/logs
.git/logs/HEAD
.git/logs/refs
.git/logs/refs/heads
.git/logs/refs/heads/branch1
.git/logs/refs/heads/branch2
.git/logs/refs/heads/branch3
.git/logs/refs/heads/master

# Setup a remote
git remote add --mirror bar git://foo/bar

# Oops, didn't mean to do that, remove the repo
git remote rm bar # poof!
find .git/refs .git/logs
.git/refs
.git/refs/heads
.git/refs/tags
.git/logs
.git/logs/HEAD
.git/logs/refs
.git/logs/refs/heads

I just realized that at least the HEAD log is still there. I missed
that originally since:

git reflog
fatal: bad default revision 'HEAD'

(Separate issue, but shouldn't "git reflog" work even if .git/HEAD is invalid?)

Anyway, it would seem to me it should be harder to remove local refs.
This one was somewhat painful to recover from. Not sure what better
behavior would be: should it be harder to do "remote add --mirror" on
a repository with content, should "remote rm" on mirrored repository
require a --force switch with a stern warning first, or...?

Thoughts?

j.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] builtin-remote: make rm operation safer in mirrored repository
  2009-02-01 14:52 git remote rm considered harmful? Jay Soffian
@ 2009-02-01 15:48 ` Jay Soffian
  2009-02-02 13:29   ` Jeff King
  0 siblings, 1 reply; 17+ messages in thread
From: Jay Soffian @ 2009-02-01 15:48 UTC (permalink / raw)
  To: git; +Cc: Jay Soffian

"git remote rm <repo>" is happy to remove non-remote branches (and their
reflogs). 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 branches and instead
advises the user on how to remove such branches using "git branch -d", which
itself has nice safety checks wrt to branch removal lacking from "git remote
rm".

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
On Sun, Feb 1, 2009 at 9:52 AM, Jay Soffian <jaysoffian@gmail.com> wrote:
> Anyway, it would seem to me it should be harder to remove local refs.
> This one was somewhat painful to recover from. Not sure what better
> behavior would be: should it be harder to do "remote add --mirror" on
> a repository with content, should "remote rm" on mirrored repository
> require a --force switch with a stern warning first, or...?

Perhaps something like this?

 builtin-remote.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/builtin-remote.c b/builtin-remote.c
index abc8dd8..2629bc5 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -310,6 +310,13 @@ static int add_branch_for_removal(const char *refname,
 	struct string_list_item *item;
 	struct known_remote *kr;
 
+	/* don't delete non-remote branches */
+	if (prefixcmp(refname, "refs/remotes")) {
+		warning("not removing non-remote branch; use git branch -d %s to remove",
+			abbrev_branch(refname));
+		return 0;
+	}
+
 	memset(&refspec, 0, sizeof(refspec));
 	refspec.dst = (char *)refname;
 	if (remote_find_tracking(branches->remote, &refspec))
-- 
1.6.1.224.gb56c

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] builtin-remote: make rm operation safer in mirrored repository
  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
  0 siblings, 1 reply; 17+ messages in thread
From: Jeff King @ 2009-02-02 13:29 UTC (permalink / raw)
  To: Jay Soffian; +Cc: git

On Sun, Feb 01, 2009 at 10:48:29AM -0500, Jay Soffian wrote:

> "git remote rm <repo>" is happy to remove non-remote branches (and their
> reflogs). 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 branches and instead
> advises the user on how to remove such branches using "git branch -d", which
> itself has nice safety checks wrt to branch removal lacking from "git remote
> rm".

I think this is sensible. The point of "git remote rm" removing tracking
branches is just to clean up cruft in a repository that has otherwise
interesting stuff. Blowing away a mirror implies getting rid of all
refs. At which point I have to wonder why you would want to do that
versus just removing the repo entirely. I.e., the common use case for
"git remote rm" on a mirror would seem to be "oops, I did this wrong"
and not "I really want to get rid of all my refs".

So I think a safety valve is reasonable.  I wonder if would be simpler
still to just not delete _any_ refs for a mirrored remote. On the other
hand, your safety valve also protects against unusual refspecs that
might touch refs not in refs/remotes (e.g., if I didn't use
remote.foo.mirror, but I had a manually-written refspec that touched
some subset of refs/heads/). In that case, your safety valve makes more
sense.

>  builtin-remote.c |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)

Tests?

-Peff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] builtin-remote: make rm operation safer in mirrored  repository
  2009-02-02 13:29   ` Jeff King
@ 2009-02-02 13:36     ` Jay Soffian
  2009-02-02 18:40       ` Jay Soffian
  0 siblings, 1 reply; 17+ messages in thread
From: Jay Soffian @ 2009-02-02 13:36 UTC (permalink / raw)
  To: Jeff King; +Cc: git

On Mon, Feb 2, 2009 at 8:29 AM, Jeff King <peff@peff.net> wrote:
> In that case, your safety valve makes more
> sense.

Thank you for the review.

>>  builtin-remote.c |    7 +++++++
>>  1 files changed, 7 insertions(+), 0 deletions(-)
>
> Tests?

Yep, will resend w/tests.

j.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] builtin-remote: make rm operation safer in mirrored repository
  2009-02-02 13:36     ` Jay Soffian
@ 2009-02-02 18:40       ` Jay Soffian
  2009-02-03  7:24         ` Jeff King
  0 siblings, 1 reply; 17+ messages in thread
From: Jay Soffian @ 2009-02-02 18:40 UTC (permalink / raw)
  To: git; +Cc: Jay Soffian, Jeff King, Junio C Hamano

"git remote rm <repo>" is happy to remove non-remote branches (and their
reflogs). 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 branches and instead
advises the user on how to remove such branches using "git branch -d", which
itself has nice safety checks wrt to branch removal lacking from "git remote
rm".

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
This version adds a test case. I also noticed that the check I'd added to
add_branch_for_removal() was generating spurious warnings because I'd added it
in the wrong place; this version moves the check below the
remote_find_tracking() checks.

 builtin-remote.c  |    7 +++++++
 t/t5505-remote.sh |    9 +++++++++
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/builtin-remote.c b/builtin-remote.c
index abc8dd8..571caff 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -323,6 +323,13 @@ static int add_branch_for_removal(const char *refname,
 			return 0;
 	}
 
+	/* don't delete non-remote branches */
+	if (prefixcmp(refname, "refs/remotes")) {
+		warning("not removing non-remote branch; use git branch -d %s to remove",
+			abbrev_branch(refname));
+		return 0;
+	}
+
 	/* make sure that symrefs are deleted */
 	if (flags & REF_ISSYMREF)
 		return unlink(git_path("%s", refname));
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 1f59960..80d40ea 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -107,6 +107,15 @@ test_expect_success 'remove remote' '
 )
 '
 
+test_expect_success 'remove remote protects non-remote branches' '
+(
+	cd test &&
+	git config --add remote.oops.fetch "+refs/*:refs/*" &&
+	git remote rm oops 2>stderr &&
+	grep "not removing non-remote branch.* master " stderr
+)
+'
+
 cat > test/expect << EOF
 * remote origin
   URL: $(pwd)/one
-- 
1.6.1.2.308.gd57ba

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] builtin-remote: make rm operation safer in mirrored repository
  2009-02-02 18:40       ` Jay Soffian
@ 2009-02-03  7:24         ` Jeff King
  2009-02-03  7:54           ` Junio C Hamano
  0 siblings, 1 reply; 17+ messages in thread
From: Jeff King @ 2009-02-03  7:24 UTC (permalink / raw)
  To: Jay Soffian; +Cc: git, Junio C Hamano

On Mon, Feb 02, 2009 at 01:40:14PM -0500, Jay Soffian wrote:

> This version adds a test case. I also noticed that the check I'd added to
> add_branch_for_removal() was generating spurious warnings because I'd added it
> in the wrong place; this version moves the check below the
> remote_find_tracking() checks.

This version looks fine to me, and I would be OK with it being applied.

However, I have one small nit. The output produces long lines with a lot
of repeated text (assuming you have multiple matched branches, which is
likely if you have a mirrored setup). So maybe it would be nicer to have
something like:

  warning: non-remote branches were not removed; you can delete them with:
          git branch -d master
          git branch -d next
          git branch -d topic

which is a little more obvious (to me, anyway), and allows you to cut
and paste if you really did want to delete them.

But this should be a pretty seldom seen message, so it might not matter
much.  I just thought I would throw it out there.

-Peff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] builtin-remote: make rm operation safer in mirrored repository
  2009-02-03  7:24         ` Jeff King
@ 2009-02-03  7:54           ` Junio C Hamano
  2009-02-03 14:38             ` Jay Soffian
  0 siblings, 1 reply; 17+ messages in thread
From: Junio C Hamano @ 2009-02-03  7:54 UTC (permalink / raw)
  To: Jeff King; +Cc: Jay Soffian, git

Jeff King <peff@peff.net> writes:

> On Mon, Feb 02, 2009 at 01:40:14PM -0500, Jay Soffian wrote:
>
>> This version adds a test case. I also noticed that the check I'd added to
>> add_branch_for_removal() was generating spurious warnings because I'd added it
>> in the wrong place; this version moves the check below the
>> remote_find_tracking() checks.
>
> This version looks fine to me, and I would be OK with it being applied.
>
> However, I have one small nit. The output produces long lines with a lot
> of repeated text (assuming you have multiple matched branches, which is
> likely if you have a mirrored setup). So maybe it would be nicer to have
> something like:
>
>   warning: non-remote branches were not removed; you can delete them with:
>           git branch -d master
>           git branch -d next
>           git branch -d topic
>
> which is a little more obvious (to me, anyway), and allows you to cut
> and paste if you really did want to delete them.

Thanks for a review, and I actually shared that exact nit when I first
read the patch.  It would be a very good change to collect them in a list
and show a single warning at the end (I do not have particular preference
about the cut & paste-ability either way myself).
 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] builtin-remote: make rm operation safer in mirrored  repository
  2009-02-03  7:54           ` Junio C Hamano
@ 2009-02-03 14:38             ` Jay Soffian
  2009-02-03 14:53               ` Johannes Schindelin
                                 ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Jay Soffian @ 2009-02-03 14:38 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, git

On Tue, Feb 3, 2009 at 2:54 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>> However, I have one small nit. The output produces long lines with a lot
>> of repeated text (assuming you have multiple matched branches, which is
>> likely if you have a mirrored setup). So maybe it would be nicer to have
>> something like:
>>
>>   warning: non-remote branches were not removed; you can delete them with:
>>           git branch -d master
>>           git branch -d next
>>           git branch -d topic
>>
>> which is a little more obvious (to me, anyway), and allows you to cut
>> and paste if you really did want to delete them.
>
> Thanks for a review, and I actually shared that exact nit when I first
> read the patch.  It would be a very good change to collect them in a list
> and show a single warning at the end (I do not have particular preference
> about the cut & paste-ability either way myself).

This is a tough crowd. I'll see what I can do.

j.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] builtin-remote: make rm operation safer in mirrored  repository
  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-03 17:51               ` [PATCH 2/2] builtin-remote: make rm operation safer in mirrored repository Jay Soffian
  2 siblings, 0 replies; 17+ messages in thread
From: Johannes Schindelin @ 2009-02-03 14:53 UTC (permalink / raw)
  To: Jay Soffian; +Cc: Junio C Hamano, Jeff King, git

Hi,

On Tue, 3 Feb 2009, Jay Soffian wrote:

> On Tue, Feb 3, 2009 at 2:54 AM, Junio C Hamano <gitster@pobox.com> wrote:
> > Jeff King <peff@peff.net> writes:
> >> However, I have one small nit. The output produces long lines with a lot
> >> of repeated text (assuming you have multiple matched branches, which is
> >> likely if you have a mirrored setup). So maybe it would be nicer to have
> >> something like:
> >>
> >>   warning: non-remote branches were not removed; you can delete them with:
> >>           git branch -d master
> >>           git branch -d next
> >>           git branch -d topic
> >>
> >> which is a little more obvious (to me, anyway), and allows you to cut
> >> and paste if you really did want to delete them.
> >
> > Thanks for a review, and I actually shared that exact nit when I first
> > read the patch.  It would be a very good change to collect them in a list
> > and show a single warning at the end (I do not have particular preference
> > about the cut & paste-ability either way myself).
> 
> This is a tough crowd. I'll see what I can do.

We polish it until it shines! :-)

Thank you for you efforts,
Dscho

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 1/2] builtin-remote: make rm() use properly named variable to hold return value
  2009-02-03 14:38             ` Jay Soffian
  2009-02-03 14:53               ` Johannes Schindelin
@ 2009-02-03 17:51               ` 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
  2 siblings, 1 reply; 17+ messages in thread
From: Jay Soffian @ 2009-02-03 17:51 UTC (permalink / raw)
  To: git; +Cc: Jay Soffian, Jeff King, Junio C Hamano

"i" is a loop counter and should not be used to hold a return value; use
"result" instead which is consistent with the rest of builtin-remote.c.

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
I'm not sure this minor change needed to be broken out into its own commit,
so squash with 2/2 if that's appropriate.

 builtin-remote.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/builtin-remote.c b/builtin-remote.c
index abc8dd8..21885fb 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -543,7 +543,7 @@ static int rm(int argc, const char **argv)
 	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 };
-	int i;
+	int i, result;
 
 	if (argc != 2)
 		usage_with_options(builtin_remote_usage, options);
@@ -583,14 +583,14 @@ static int rm(int argc, const char **argv)
 	 * refs, which are invalidated when deleting a branch.
 	 */
 	cb_data.remote = remote;
-	i = for_each_ref(add_branch_for_removal, &cb_data);
+	result = for_each_ref(add_branch_for_removal, &cb_data);
 	strbuf_release(&buf);
 
-	if (!i)
-		i = remove_branches(&branches);
+	if (!result)
+		result = remove_branches(&branches);
 	string_list_clear(&branches, 1);
 
-	return i;
+	return result;
 }
 
 static void show_list(const char *title, struct string_list *list,
-- 
1.6.1.2.311.g2d7f3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/2] builtin-remote: make rm operation safer in mirrored repository
  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-03 17:51               ` Jay Soffian
  2009-02-04 15:42                 ` Jeff King
  2 siblings, 1 reply; 17+ messages in thread
From: Jay Soffian @ 2009-02-03 17:51 UTC (permalink / raw)
  To: git; +Cc: Jay Soffian, Jeff King, Junio C Hamano

"git remote rm <repo>" is happy to remove non-remote branches (and their
reflogs). 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 branches and instead
advises the user on how to remove such branches using "git branch -d", which
itself has nice safety checks wrt to branch removal lacking from "git remote
rm".

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---

On Tue, Feb 3, 2009 at 2:54 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>> However, I have one small nit. The output produces long lines with a lot
>> of repeated text (assuming you have multiple matched branches, which is
>> likely if you have a mirrored setup). So maybe it would be nicer to have
>> something like:
>>
>>   warning: non-remote branches were not removed; you can delete them with:
>>           git branch -d master
>>           git branch -d next
>>           git branch -d topic
>>
>> which is a little more obvious (to me, anyway), and allows you to cut
>> and paste if you really did want to delete them.
>
> Thanks for a review, and I actually shared that exact nit when I first
> read the patch.  It would be a very good change to collect them in a list
> and show a single warning at the end (I do not have particular preference
> about the cut & paste-ability either way myself).

So much work for what seemed such a minor change. :) I hope this version is
well-polished enough.

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

diff --git a/builtin-remote.c b/builtin-remote.c
index 21885fb..ae1eed4 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,14 @@ static int add_branch_for_removal(const char *refname,
 			return 0;
 	}
 
+	/* don't delete non-remote branches */
+	if (prefixcmp(refname, "refs/remotes")) {
+		if (!prefixcmp(refname, "refs/heads/"))
+			string_list_append(abbrev_branch(refname),
+					   branches->skipped);
+		return 0;
+	}
+
 	/* make sure that symrefs are deleted */
 	if (flags & REF_ISSYMREF)
 		return unlink(git_path("%s", refname));
@@ -542,7 +550,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 +601,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.311.g2d7f3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 1/2] builtin-remote: make rm() use properly named variable to hold return value
  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
  0 siblings, 0 replies; 17+ messages in thread
From: Jeff King @ 2009-02-04 15:34 UTC (permalink / raw)
  To: Jay Soffian; +Cc: git, Junio C Hamano

On Tue, Feb 03, 2009 at 12:51:12PM -0500, Jay Soffian wrote:

> "i" is a loop counter and should not be used to hold a return value; use
> "result" instead which is consistent with the rest of builtin-remote.c.
> 
> Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
> ---
> I'm not sure this minor change needed to be broken out into its own commit,
> so squash with 2/2 if that's appropriate.

Looks obviously correct to me...

-Peff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/2] builtin-remote: make rm operation safer in mirrored repository
  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
  0 siblings, 1 reply; 17+ messages in thread
From: Jeff King @ 2009-02-04 15:42 UTC (permalink / raw)
  To: Jay Soffian; +Cc: git, Junio C Hamano

On Tue, Feb 03, 2009 at 12:51:13PM -0500, Jay Soffian wrote:

> So much work for what seemed such a minor change. :) I hope this version is
> well-polished enough.

The more minor the change, the more major the comments. :) Thanks for
sticking with it. This version looks good to me except for one thing:

> +	/* don't delete non-remote branches */
> +	if (prefixcmp(refname, "refs/remotes")) {
> +		if (!prefixcmp(refname, "refs/heads/"))
> +			string_list_append(abbrev_branch(refname),
> +					   branches->skipped);
> +		return 0;
> +	}

Why does this version introduce the "only skip refs/heads/" check?
Shouldn't we also protect other random refs (or if not, shouldn't the
commit message explain why not)?

> +	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");

Ooh, proper pluralization. Classy.

-Peff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/2] builtin-remote: make rm operation safer in mirrored  repository
  2009-02-04 15:42                 ` Jeff King
@ 2009-02-04 15:56                   ` Jay Soffian
  2009-02-04 16:06                     ` [PATCH] " Jay Soffian
  2009-02-04 16:16                     ` [PATCH 2/2] " Jeff King
  0 siblings, 2 replies; 17+ messages in thread
From: Jay Soffian @ 2009-02-04 15:56 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Junio C Hamano

On Wed, Feb 4, 2009 at 10:42 AM, Jeff King <peff@peff.net> wrote:
>> +     /* don't delete non-remote branches */
>> +     if (prefixcmp(refname, "refs/remotes")) {
>> +             if (!prefixcmp(refname, "refs/heads/"))
>> +                     string_list_append(abbrev_branch(refname),
>> +                                        branches->skipped);
>> +             return 0;
>> +     }
>
> Why does this version introduce the "only skip refs/heads/" check?
> Shouldn't we also protect other random refs (or if not, shouldn't the
> commit message explain why not)?

Note that we do protect refs, but we only emit messages about those
refs which are obviously branches. Frankly, I wasn't sure what other
kinds of refs there might be, so wasn't sure what an appropriate
message is for anything other than those under refs/heads.

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.

Alternately, it could do something like:

Note: A non-remote branch was not removed; to delete it use:
   git branch -d ...

Note: Tags were not removed, to delete them use:
   git tag -d ...

Note: Some refs were ignored:
   refs/whoknows/whatthisis
   refs/whoknows/whatthiscouldbe

But that's getting a little insane me thinks.

j.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] builtin-remote: make rm operation safer in mirrored repository
  2009-02-04 15:56                   ` Jay Soffian
@ 2009-02-04 16:06                     ` Jay Soffian
  2009-02-04 16:18                       ` Jeff King
  2009-02-04 16:16                     ` [PATCH 2/2] " Jeff King
  1 sibling, 1 reply; 17+ messages in thread
From: Jay Soffian @ 2009-02-04 16:06 UTC (permalink / raw)
  To: git; +Cc: Jay Soffian, Jeff King, Junio C Hamano

"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

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/2] builtin-remote: make rm operation safer in mirrored repository
  2009-02-04 15:56                   ` Jay Soffian
  2009-02-04 16:06                     ` [PATCH] " Jay Soffian
@ 2009-02-04 16:16                     ` Jeff King
  1 sibling, 0 replies; 17+ messages in thread
From: Jeff King @ 2009-02-04 16:16 UTC (permalink / raw)
  To: Jay Soffian; +Cc: git, Junio C Hamano

On Wed, Feb 04, 2009 at 10:56:06AM -0500, Jay Soffian wrote:

> On Wed, Feb 4, 2009 at 10:42 AM, Jeff King <peff@peff.net> wrote:
> >> +     /* don't delete non-remote branches */
> >> +     if (prefixcmp(refname, "refs/remotes")) {
> >> +             if (!prefixcmp(refname, "refs/heads/"))
> >> +                     string_list_append(abbrev_branch(refname),
> >> +                                        branches->skipped);
> >> +             return 0;
> >> +     }
> >
> > Why does this version introduce the "only skip refs/heads/" check?
> > Shouldn't we also protect other random refs (or if not, shouldn't the
> > commit message explain why not)?
> 
> Note that we do protect refs, but we only emit messages about those
> refs which are obviously branches. Frankly, I wasn't sure what other
> kinds of refs there might be, so wasn't sure what an appropriate
> message is for anything other than those under refs/heads.

Oh, right. I was just reading it wrong. Your new version with the two
comments makes it even more clear.

> Note: A non-remote branch was not removed; to delete it use:
>    git branch -d ...
> 
> Note: Tags were not removed, to delete them use:
>    git tag -d ...
>
> Note: Some refs were ignored:
>    refs/whoknows/whatthisis
>    refs/whoknows/whatthiscouldbe

Nah, I think deleting branches was the main intention. So we are
properly protecting everything now, but only warning about what you
_might_ have meant.

> But that's getting a little insane me thinks.

Agreed.

-Peff

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] builtin-remote: make rm operation safer in mirrored repository
  2009-02-04 16:06                     ` [PATCH] " Jay Soffian
@ 2009-02-04 16:18                       ` Jeff King
  0 siblings, 0 replies; 17+ messages in thread
From: Jeff King @ 2009-02-04 16:18 UTC (permalink / raw)
  To: Jay Soffian; +Cc: git, Junio C Hamano

On Wed, Feb 04, 2009 at 11:06:07AM -0500, Jay Soffian wrote:

> "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>

I like it.

Acked-by: Jeff King <peff@peff.net>

-Peff

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2009-02-04 16:19 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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                     ` [PATCH] " Jay Soffian
2009-02-04 16:18                       ` Jeff King
2009-02-04 16:16                     ` [PATCH 2/2] " Jeff King

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).