# [PATCH v2 2/2] Make old sha1 optional with git update-ref -d

6 messages from 2008-06-02 to 2008-06-03. Participants: Karl Hasselström, Junio C Hamano.
Thread: https://gitlist.dev/t/13769

## Karl Hasselström, 2008-06-02 23:34

Subject: [PATCH v2 0/2] Make old sha1 optional with git update-ref -d
Message-ID: <20080602233244.26087.51827.stgit@yoghurt>
URL: https://gitlist.dev/e/20080602233244.26087.51827.stgit%40yoghurt
In-Reply-To: <20080525193213.GB5674@diana.vm.bytemark.co.uk>

```
This series makes the old ref value optional for update-ref -d (it's
already optional for update-ref without -d).

---

Patch 1/2 updated after comments from Junio.

Karl Hasselström (2):
      Make old sha1 optional with git update-ref -d
      Clean up builtin-update-ref's option parsing


 Documentation/git-update-ref.txt |    2 +-
 builtin-update-ref.c             |   36 ++++++++++++++++++++----------------
 t/t1400-update-ref.sh            |    8 ++++++++
 3 files changed, 29 insertions(+), 17 deletions(-)

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

```

## Karl Hasselström, 2008-06-02 23:34

Subject: [PATCH v2 1/2] Clean up builtin-update-ref's option parsing
Message-ID: <20080602233447.26087.14533.stgit@yoghurt>
URL: https://gitlist.dev/e/20080602233447.26087.14533.stgit%40yoghurt
In-Reply-To: <20080602233244.26087.51827.stgit@yoghurt>

```
builtin-update-ref's option parsing was somewhat tricky to follow,
especially if the -d option was given. This patch cleans it upp a bit,
at the expense of making it a bit longer.

Signed-off-by: Karl Hasselström <kha@treskal.com>

---

 builtin-update-ref.c |   34 +++++++++++++++++++---------------
 1 files changed, 19 insertions(+), 15 deletions(-)


diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index 93c1271..cc8bc5c 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -11,7 +11,7 @@ static const char * const git_update_ref_usage[] = {
 
 int cmd_update_ref(int argc, const char **argv, const char *prefix)
 {
-	const char *refname, *value, *oldval, *msg=NULL;
+	const char *refname, *oldval, *msg=NULL;
 	unsigned char sha1[20], oldsha1[20];
 	int delete = 0, no_deref = 0;
 	struct option options[] = {
@@ -27,25 +27,29 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 	if (msg && !*msg)
 		die("Refusing to perform update with empty message.");
 
-	if (argc < 2 || argc > 3)
-		usage_with_options(git_update_ref_usage, options);
-	refname = argv[0];
-	value   = argv[1];
-	oldval  = argv[2];
-
-	if (get_sha1(value, sha1))
-		die("%s: not a valid SHA1", value);
-
 	if (delete) {
-		if (oldval)
+		if (argc != 2)
+			usage_with_options(git_update_ref_usage, options);
+		refname = argv[0];
+		oldval = argv[1];
+	} else {
+                const char *value;
+		if (argc < 2 || argc > 3)
 			usage_with_options(git_update_ref_usage, options);
-		return delete_ref(refname, sha1);
+		refname = argv[0];
+		value = argv[1];
+		oldval = argv[2];
+		if (get_sha1(value, sha1))
+			die("%s: not a valid SHA1", value);
 	}
 
-	hashclr(oldsha1);
+	hashclr(oldsha1); /* all-zero hash in case oldval is the empty string */
 	if (oldval && *oldval && get_sha1(oldval, oldsha1))
 		die("%s: not a valid old SHA1", oldval);
 
-	return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
-			  no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
+	if (delete)
+		return delete_ref(refname, oldsha1);
+	else
+		return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
+				  no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
 }

```

## Karl Hasselström, 2008-06-02 23:34

Subject: [PATCH v2 2/2] Make old sha1 optional with git update-ref -d
Message-ID: <20080602233453.26087.52259.stgit@yoghurt>
URL: https://gitlist.dev/e/20080602233453.26087.52259.stgit%40yoghurt
In-Reply-To: <20080602233244.26087.51827.stgit@yoghurt>

```
Giving the old sha1 is already optional when changing a ref, and it's
quite handy when running update-ref manually. So make it optional for
deleting a ref too.

Signed-off-by: Karl Hasselström <kha@treskal.com>

---

 Documentation/git-update-ref.txt |    2 +-
 builtin-update-ref.c             |    6 +++---
 t/t1400-update-ref.sh            |    8 ++++++++
 3 files changed, 12 insertions(+), 4 deletions(-)


diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 4dc4759..80b94c3 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -7,7 +7,7 @@ git-update-ref - Update the object name stored in a ref safely
 
 SYNOPSIS
 --------
-'git-update-ref' [-m <reason>] (-d <ref> <oldvalue> | [--no-deref] <ref> <newvalue> [<oldvalue>])
+'git-update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>])
 
 DESCRIPTION
 -----------
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index cc8bc5c..9546488 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char * const git_update_ref_usage[] = {
-	"git-update-ref [options] -d <refname> <oldval>",
+	"git-update-ref [options] -d <refname> [<oldval>]",
 	"git-update-ref [options]    <refname> <newval> [<oldval>]",
 	NULL
 };
@@ -28,7 +28,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 		die("Refusing to perform update with empty message.");
 
 	if (delete) {
-		if (argc != 2)
+		if (argc < 1 || argc > 2)
 			usage_with_options(git_update_ref_usage, options);
 		refname = argv[0];
 		oldval = argv[1];
@@ -48,7 +48,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 		die("%s: not a valid old SHA1", oldval);
 
 	if (delete)
-		return delete_ref(refname, oldsha1);
+		return delete_ref(refname, oldval ? oldsha1 : NULL);
 	else
 		return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
 				  no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index b8b7ab4..f387d46 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -42,6 +42,14 @@ test_expect_success "delete $m" '
 '
 rm -f .git/$m
 
+test_expect_success "delete $m without oldvalue verification" "
+	git update-ref $m $A &&
+	test $A = \$(cat .git/$m) &&
+	git update-ref -d $m &&
+	! test -f .git/$m
+"
+rm -f .git/$m
+
 test_expect_success \
 	"fail to create $n" \
 	"touch .git/$n_dir

```

## Junio C Hamano, 2008-06-03 05:51

Subject: Re: [PATCH v2 2/2] Make old sha1 optional with git update-ref -d
Message-ID: <7vk5h73w2i.fsf@gitster.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vk5h73w2i.fsf%40gitster.siamese.dyndns.org
In-Reply-To: <20080602233453.26087.52259.stgit@yoghurt>

```
Karl Hasselström <kha@treskal.com> writes:

> Giving the old sha1 is already optional when changing a ref, and it's
> quite handy when running update-ref manually. So make it optional for
> deleting a ref too.
>
> Signed-off-by: Karl Hasselström <kha@treskal.com>

"Handy" is not a very good reason when talking about plumbing command like
update-ref that takes an extra parameter for safety of the last step in
read, operate, verify-and-update sequence.

Although it is not a reason _bad enough_ to make your patch a bad idea,
perhaps you should rethink the problem at the same time?  Whatever you are
trying to do cannot be done without manually invoking update-ref directly
by the end user, perhaps that needs to be addressed?

```

## Karl Hasselström, 2008-06-03 06:49

Subject: Re: [PATCH v2 2/2] Make old sha1 optional with git update-ref -d
Message-ID: <20080603064957.GA6701@diana.vm.bytemark.co.uk>
URL: https://gitlist.dev/e/20080603064957.GA6701%40diana.vm.bytemark.co.uk
In-Reply-To: <7vk5h73w2i.fsf@gitster.siamese.dyndns.org>

```
On 2008-06-02 22:51:33 -0700, Junio C Hamano wrote:

> Karl Hasselström <kha@treskal.com> writes:
>
> > Giving the old sha1 is already optional when changing a ref, and
> > it's quite handy when running update-ref manually. So make it
> > optional for deleting a ref too.
>
> "Handy" is not a very good reason when talking about plumbing
> command like update-ref that takes an extra parameter for safety of
> the last step in read, operate, verify-and-update sequence.
>
> Although it is not a reason _bad enough_ to make your patch a bad
> idea, perhaps you should rethink the problem at the same time?
> Whatever you are trying to do cannot be done without manually
> invoking update-ref directly by the end user, perhaps that needs to
> be addressed?

I need this from time to time when experimenting with StGit -- or,
more precisely, when cleaning up afterwards in case it didn't go so
well. Packed refs means I can't safely just edit/delete files under
.git/refs anymore, so I use update-ref instead. And having to use the
safety belt every time is just plain tedious. I'd say this is a
perfect example of when using the plumbing by hand is really what you
want.

(In this kind of situation, branch -D often doesn't work since my ref
isn't under refs/heads, and besides I really don't want any of it's
smarts right then -- I want to delete a ref, nothing more.)

Better suggestions welcome, of course.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

```

## Junio C Hamano, 2008-06-03 19:39

Subject: Re: [PATCH v2 2/2] Make old sha1 optional with git update-ref -d
Message-ID: <7v3anu2tqs.fsf@gitster.siamese.dyndns.org>
URL: https://gitlist.dev/e/7v3anu2tqs.fsf%40gitster.siamese.dyndns.org
In-Reply-To: <20080603064957.GA6701@diana.vm.bytemark.co.uk>

```
Karl Hasselström <kha@treskal.com> writes:

> I need this from time to time when experimenting with StGit -- or,
> more precisely, when cleaning up afterwards in case it didn't go so
> well. Packed refs means I can't safely just edit/delete files under
> .git/refs anymore, so I use update-ref instead. And having to use the
> safety belt every time is just plain tedious. I'd say this is a
> perfect example of when using the plumbing by hand is really what you
> want.

Oh, I should have guessed, and I am relieved by your answer.

I was worried that in some workflow people may have to use "update-ref -d"
all the time because our Porcelain allows them to create some ref without
giving a clean way to remove it (e.g. "branch" and "tag" allow creation
and deletion with -d/-D, so they are Ok, but I was worried there might be
something else I overlooked).

Manually cleaning up what an experimental version of Porcelain left behind
does not fall into category of "normal user has to do this all the time",
so I do not have to worry.

Thanks.

```
