Skip to content

Commit f406140

Browse files
committed
Merge branch 'fc/at-head'
Instead of typing four capital letters "HEAD", you can say "@" now, e.g. "git log @". * fc/at-head: Add new @ shortcut for HEAD sha1-name: pass len argument to interpret_branch_name()
2 parents 005a1de + 9ba89f4 commit f406140

File tree

7 files changed

+54
-7
lines changed

7 files changed

+54
-7
lines changed

Documentation/git-check-ref-format.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ Git imposes the following rules on how references are named:
5454

5555
. They cannot contain a sequence `@{`.
5656

57+
. They cannot be the single character `@`.
58+
5759
. They cannot contain a `\`.
5860

5961
These rules make it easy for shell script based tools to parse

Documentation/revisions.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ the '$GIT_DIR/refs' directory or from the '$GIT_DIR/packed-refs' file.
5858
While the ref name encoding is unspecified, UTF-8 is preferred as
5959
some output processing may assume ref names in UTF-8.
6060

61+
'@'::
62+
'@' alone is a shortcut for 'HEAD'.
63+
6164
'<refname>@\{<date>\}', e.g. 'master@\{yesterday\}', 'HEAD@\{5 minutes ago\}'::
6265
A ref followed by the suffix '@' with a date specification
6366
enclosed in a brace

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, i
880880

881881
extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
882882
extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
883-
extern int interpret_branch_name(const char *str, struct strbuf *);
883+
extern int interpret_branch_name(const char *str, int len, struct strbuf *);
884884
extern int get_sha1_mb(const char *str, unsigned char *sha1);
885885

886886
extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);

refs.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ int check_refname_format(const char *refname, int flags)
7272
{
7373
int component_len, component_count = 0;
7474

75+
if (!strcmp(refname, "@"))
76+
/* Refname is a single character '@'. */
77+
return -1;
78+
7579
while (1) {
7680
/* We are at the start of a path component. */
7781
component_len = check_refname_component(refname, flags);
@@ -1951,7 +1955,7 @@ static int remove_empty_directories(const char *file)
19511955
static char *substitute_branch_name(const char **string, int *len)
19521956
{
19531957
struct strbuf buf = STRBUF_INIT;
1954-
int ret = interpret_branch_name(*string, &buf);
1958+
int ret = interpret_branch_name(*string, *len, &buf);
19551959

19561960
if (ret == *len) {
19571961
size_t size;

revision.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static void add_pending_object_with_mode(struct rev_info *revs,
200200
revs->no_walk = 0;
201201
if (revs->reflog_info && obj->type == OBJ_COMMIT) {
202202
struct strbuf buf = STRBUF_INIT;
203-
int len = interpret_branch_name(name, &buf);
203+
int len = interpret_branch_name(name, 0, &buf);
204204
int st;
205205

206206
if (0 < len && name[len] && buf.len)

sha1_name.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,28 @@ int get_sha1_mb(const char *name, unsigned char *sha1)
10061006
return st;
10071007
}
10081008

1009+
/* parse @something syntax, when 'something' is not {.*} */
1010+
static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf)
1011+
{
1012+
const char *next;
1013+
1014+
if (len || name[1] == '{')
1015+
return -1;
1016+
1017+
/* make sure it's a single @, or @@{.*}, not @foo */
1018+
next = strchr(name + len + 1, '@');
1019+
if (next && next[1] != '{')
1020+
return -1;
1021+
if (!next)
1022+
next = name + namelen;
1023+
if (next != name + 1)
1024+
return -1;
1025+
1026+
strbuf_reset(buf);
1027+
strbuf_add(buf, "HEAD", 4);
1028+
return 1;
1029+
}
1030+
10091031
static int reinterpret(const char *name, int namelen, int len, struct strbuf *buf)
10101032
{
10111033
/* we have extra data, which might need further processing */
@@ -1014,7 +1036,7 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
10141036
int ret;
10151037

10161038
strbuf_add(buf, name + len, namelen - len);
1017-
ret = interpret_branch_name(buf->buf, &tmp);
1039+
ret = interpret_branch_name(buf->buf, buf->len, &tmp);
10181040
/* that data was not interpreted, remove our cruft */
10191041
if (ret < 0) {
10201042
strbuf_setlen(buf, used);
@@ -1048,14 +1070,16 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
10481070
* If the input was ok but there are not N branch switches in the
10491071
* reflog, it returns 0.
10501072
*/
1051-
int interpret_branch_name(const char *name, struct strbuf *buf)
1073+
int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
10521074
{
10531075
char *cp;
10541076
struct branch *upstream;
1055-
int namelen = strlen(name);
10561077
int len = interpret_nth_prior_checkout(name, buf);
10571078
int tmp_len;
10581079

1080+
if (!namelen)
1081+
namelen = strlen(name);
1082+
10591083
if (!len) {
10601084
return len; /* syntax Ok, not enough switches */
10611085
} else if (len > 0) {
@@ -1068,9 +1092,15 @@ int interpret_branch_name(const char *name, struct strbuf *buf)
10681092
cp = strchr(name, '@');
10691093
if (!cp)
10701094
return -1;
1095+
1096+
len = interpret_empty_at(name, namelen, cp - name, buf);
1097+
if (len > 0)
1098+
return reinterpret(name, namelen, len, buf);
1099+
10711100
tmp_len = upstream_mark(cp, namelen - (cp - name));
10721101
if (!tmp_len)
10731102
return -1;
1103+
10741104
len = cp + tmp_len - name;
10751105
cp = xstrndup(name, cp - name);
10761106
upstream = branch_get(*cp ? cp : NULL);
@@ -1102,7 +1132,7 @@ int interpret_branch_name(const char *name, struct strbuf *buf)
11021132
int strbuf_branchname(struct strbuf *sb, const char *name)
11031133
{
11041134
int len = strlen(name);
1105-
int used = interpret_branch_name(name, sb);
1135+
int used = interpret_branch_name(name, len, sb);
11061136

11071137
if (used == len)
11081138
return 0;

t/t1508-at-combinations.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ test_expect_success 'setup' '
3232
git checkout -b upstream-branch &&
3333
test_commit upstream-one &&
3434
test_commit upstream-two &&
35+
git checkout -b @/at-test &&
36+
git checkout -b @@/at-test &&
37+
git checkout -b @at-test &&
3538
git checkout -b old-branch &&
3639
test_commit old-one &&
3740
test_commit old-two &&
@@ -55,6 +58,11 @@ check "HEAD@{u}" ref refs/heads/upstream-branch
5558
check "@{u}@{1}" commit upstream-one
5659
check "@{-1}@{u}" ref refs/heads/master
5760
check "@{-1}@{u}@{1}" commit master-one
61+
check "@" commit new-two
62+
check "@@{u}" ref refs/heads/upstream-branch
63+
check "@@/at-test" ref refs/heads/@@/at-test
64+
check "@/at-test" ref refs/heads/@/at-test
65+
check "@at-test" ref refs/heads/@at-test
5866
nonsense "@{u}@{-1}"
5967
nonsense "@{0}@{0}"
6068
nonsense "@{1}@{u}"

0 commit comments

Comments
 (0)