# [PATCH v4 0/2] New @ shortcut for HEAD

3 messages from 2013-05-07 to 2013-05-07. Participants: Felipe Contreras.
Thread: https://gitlist.dev/t/33743

## Felipe Contreras, 2013-05-07 22:04

Subject: [PATCH v4 0/2] New @ shortcut for HEAD
Message-ID: <1367964271-11422-1-git-send-email-felipe.contreras@gmail.com>
URL: https://gitlist.dev/e/1367964271-11422-1-git-send-email-felipe.contreras%40gmail.com

```
Hi,

Same patches as before, except that the cleanup ones are in a different series,
and this one doesn't depend on the other one.

Felipe Contreras (2):
  sha1_name: refactor reinterpret()
  Add new @ shortcut for HEAD

 Documentation/git-check-ref-format.txt |  2 ++
 Documentation/revisions.txt            |  3 ++
 refs.c                                 |  4 +++
 sha1_name.c                            | 59 +++++++++++++++++++++++-----------
 t/t1508-at-combinations.sh             |  2 ++
 5 files changed, 51 insertions(+), 19 deletions(-)

-- 
1.8.3.rc0.401.g45bba44

```

## Felipe Contreras, 2013-05-07 22:04

Subject: [PATCH v4 1/2] sha1_name: refactor reinterpret()
Message-ID: <1367964271-11422-2-git-send-email-felipe.contreras@gmail.com>
URL: https://gitlist.dev/e/1367964271-11422-2-git-send-email-felipe.contreras%40gmail.com
In-Reply-To: <1367964271-11422-1-git-send-email-felipe.contreras@gmail.com>

```
This code essentially replaces part of ref with another ref, for example
'@{-1}@{u}' is replaced with 'master@{u}', but this can be reused for
other purposes other than nth prior checkouts.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 sha1_name.c | 42 +++++++++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 19 deletions(-)

diff --git a/sha1_name.c b/sha1_name.c
index 3820f28..fd2a95a 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -966,6 +966,27 @@ int get_sha1_mb(const char *name, unsigned char *sha1)
 	return st;
 }
 
+static int reinterpret(const char *name, int namelen, int len, struct strbuf *buf)
+{
+	/* we have extra data, which might need further processing */
+	struct strbuf tmp = STRBUF_INIT;
+	int used = buf->len;
+	int ret;
+
+	strbuf_add(buf, name + len, namelen - len);
+	ret = interpret_branch_name(buf->buf, &tmp);
+	/* that data was not interpreted, remove our cruft */
+	if (ret < 0) {
+		strbuf_setlen(buf, used);
+		return len;
+	}
+	strbuf_reset(buf);
+	strbuf_addbuf(buf, &tmp);
+	strbuf_release(&tmp);
+	/* tweak for size of {-N} versus expanded ref name */
+	return ret - used + len;
+}
+
 /*
  * This reads short-hand syntax that not only evaluates to a commit
  * object name, but also can act as if the end user spelled the name
@@ -999,25 +1020,8 @@ int interpret_branch_name(const char *name, struct strbuf *buf)
 		return len; /* syntax Ok, not enough switches */
 	if (0 < len && len == namelen)
 		return len; /* consumed all */
-	else if (0 < len) {
-		/* we have extra data, which might need further processing */
-		struct strbuf tmp = STRBUF_INIT;
-		int used = buf->len;
-		int ret;
-
-		strbuf_add(buf, name + len, namelen - len);
-		ret = interpret_branch_name(buf->buf, &tmp);
-		/* that data was not interpreted, remove our cruft */
-		if (ret < 0) {
-			strbuf_setlen(buf, used);
-			return len;
-		}
-		strbuf_reset(buf);
-		strbuf_addbuf(buf, &tmp);
-		strbuf_release(&tmp);
-		/* tweak for size of {-N} versus expanded ref name */
-		return ret - used + len;
-	}
+	else if (0 < len)
+		return reinterpret(name, namelen, len, buf);
 
 	cp = strchr(name, '@');
 	if (!cp)
-- 
1.8.3.rc0.401.g45bba44

```

## Felipe Contreras, 2013-05-07 22:04

Subject: [PATCH v4 2/2] Add new @ shortcut for HEAD
Message-ID: <1367964271-11422-3-git-send-email-felipe.contreras@gmail.com>
URL: https://gitlist.dev/e/1367964271-11422-3-git-send-email-felipe.contreras%40gmail.com
In-Reply-To: <1367964271-11422-1-git-send-email-felipe.contreras@gmail.com>

```
Typing 'HEAD' is tedious, especially when we can use '@' instead.

The reason for choosing '@' is that it follows naturally from the
ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no
operation, and when we don't have those, it makes sens to assume
'HEAD'.

So now we can use 'git show @~1', and all that goody goodness.

Until now '@' was a valid name, but it conflicts with this idea, so
let's make it invalid. Probably very few people, if any, used this name.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Documentation/git-check-ref-format.txt |  2 ++
 Documentation/revisions.txt            |  3 +++
 refs.c                                 |  4 ++++
 sha1_name.c                            | 17 +++++++++++++++++
 t/t1508-at-combinations.sh             |  2 ++
 5 files changed, 28 insertions(+)

diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt
index ec1739a..e8035ec 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -54,6 +54,8 @@ Git imposes the following rules on how references are named:
 
 . They cannot contain a sequence `@{`.
 
+. They cannot be the single character `@`.
+
 . They cannot contain a `\`.
 
 These rules make it easy for shell script based tools to parse
diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
index d477b3f..09896a3 100644
--- a/Documentation/revisions.txt
+++ b/Documentation/revisions.txt
@@ -58,6 +58,9 @@ the '$GIT_DIR/refs' directory or from the '$GIT_DIR/packed-refs' file.
 While the ref name encoding is unspecified, UTF-8 is preferred as
 some output processing may assume ref names in UTF-8.
 
+'@'::
+  '@' alone is a shortcut for 'HEAD'.
+
 '<refname>@\{<date>\}', e.g. 'master@\{yesterday\}', 'HEAD@\{5 minutes ago\}'::
   A ref followed by the suffix '@' with a date specification
   enclosed in a brace
diff --git a/refs.c b/refs.c
index de2d8eb..4e70b3e 100644
--- a/refs.c
+++ b/refs.c
@@ -72,6 +72,10 @@ int check_refname_format(const char *refname, int flags)
 {
 	int component_len, component_count = 0;
 
+	if (!strcmp(refname, "@"))
+		/* Refname is a single character '@'. */
+		return -1;
+
 	while (1) {
 		/* We are at the start of a path component. */
 		component_len = check_refname_component(refname, flags);
diff --git a/sha1_name.c b/sha1_name.c
index fd2a95a..dd30c7c 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -966,6 +966,17 @@ int get_sha1_mb(const char *name, unsigned char *sha1)
 	return st;
 }
 
+/* parse @something syntax, when 'something' is not {.*} */
+static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf)
+{
+	if (len || name[1] == '{')
+		return -1;
+
+	strbuf_reset(buf);
+	strbuf_add(buf, "HEAD", 4);
+	return 1;
+}
+
 static int reinterpret(const char *name, int namelen, int len, struct strbuf *buf)
 {
 	/* we have extra data, which might need further processing */
@@ -1026,9 +1037,15 @@ int interpret_branch_name(const char *name, struct strbuf *buf)
 	cp = strchr(name, '@');
 	if (!cp)
 		return -1;
+
+	len = interpret_empty_at(name, namelen, cp - name, buf);
+	if (len > 0)
+		return reinterpret(name, namelen, len, buf);
+
 	tmp_len = upstream_mark(cp, namelen - (cp - name));
 	if (!tmp_len)
 		return -1;
+
 	len = cp + tmp_len - name;
 	cp = xstrndup(name, cp - name);
 	upstream = branch_get(*cp ? cp : NULL);
diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh
index d5d6244..277a1a2 100755
--- a/t/t1508-at-combinations.sh
+++ b/t/t1508-at-combinations.sh
@@ -45,6 +45,8 @@ check "@{u}" upstream-two
 check "@{u}@{1}" upstream-one
 check "@{-1}@{u}" master-two
 check "@{-1}@{u}@{1}" master-one
+check "@" new-two
+check "@@{u}" upstream-two
 nonsense "@{u}@{-1}"
 nonsense "@{1}@{u}"
 
-- 
1.8.3.rc0.401.g45bba44

```
