Add new @ shortcut for HEAD
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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
			
			
				maint
			
			
		
							parent
							
								
									cf99a761d3
								
							
						
					
					
						commit
						9ba89f484e
					
				|  | @ -54,6 +54,8 @@ Git imposes the following rules on how references are named: | ||||||
|  |  | ||||||
| . They cannot contain a sequence `@{`. | . They cannot contain a sequence `@{`. | ||||||
|  |  | ||||||
|  | . They cannot be the single character `@`. | ||||||
|  |  | ||||||
| . They cannot contain a `\`. | . They cannot contain a `\`. | ||||||
|  |  | ||||||
| These rules make it easy for shell script based tools to parse | These rules make it easy for shell script based tools to parse | ||||||
|  |  | ||||||
|  | @ -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 | While the ref name encoding is unspecified, UTF-8 is preferred as | ||||||
| some output processing may assume ref names in UTF-8. | 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\}':: | '<refname>@\{<date>\}', e.g. 'master@\{yesterday\}', 'HEAD@\{5 minutes ago\}':: | ||||||
|   A ref followed by the suffix '@' with a date specification |   A ref followed by the suffix '@' with a date specification | ||||||
|   enclosed in a brace |   enclosed in a brace | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								refs.c
								
								
								
								
							
							
						
						
									
										4
									
								
								refs.c
								
								
								
								
							|  | @ -72,6 +72,10 @@ int check_refname_format(const char *refname, int flags) | ||||||
| { | { | ||||||
| 	int component_len, component_count = 0; | 	int component_len, component_count = 0; | ||||||
|  |  | ||||||
|  | 	if (!strcmp(refname, "@")) | ||||||
|  | 		/* Refname is a single character '@'. */ | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
| 	while (1) { | 	while (1) { | ||||||
| 		/* We are at the start of a path component. */ | 		/* We are at the start of a path component. */ | ||||||
| 		component_len = check_refname_component(refname, flags); | 		component_len = check_refname_component(refname, flags); | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								sha1_name.c
								
								
								
								
							
							
						
						
									
										28
									
								
								sha1_name.c
								
								
								
								
							|  | @ -1004,6 +1004,28 @@ int get_sha1_mb(const char *name, unsigned char *sha1) | ||||||
| 	return st; | 	return st; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* parse @something syntax, when 'something' is not {.*} */ | ||||||
|  | static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf) | ||||||
|  | { | ||||||
|  | 	const char *next; | ||||||
|  |  | ||||||
|  | 	if (len || name[1] == '{') | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	/* make sure it's a single @, or @@{.*}, not @foo */ | ||||||
|  | 	next = strchr(name + len + 1, '@'); | ||||||
|  | 	if (next && next[1] != '{') | ||||||
|  | 		return -1; | ||||||
|  | 	if (!next) | ||||||
|  | 		next = name + namelen; | ||||||
|  | 	if (next != 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) | static int reinterpret(const char *name, int namelen, int len, struct strbuf *buf) | ||||||
| { | { | ||||||
| 	/* we have extra data, which might need further processing */ | 	/* we have extra data, which might need further processing */ | ||||||
|  | @ -1068,9 +1090,15 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf) | ||||||
| 	cp = strchr(name, '@'); | 	cp = strchr(name, '@'); | ||||||
| 	if (!cp) | 	if (!cp) | ||||||
| 		return -1; | 		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)); | 	tmp_len = upstream_mark(cp, namelen - (cp - name)); | ||||||
| 	if (!tmp_len) | 	if (!tmp_len) | ||||||
| 		return -1; | 		return -1; | ||||||
|  |  | ||||||
| 	len = cp + tmp_len - name; | 	len = cp + tmp_len - name; | ||||||
| 	cp = xstrndup(name, cp - name); | 	cp = xstrndup(name, cp - name); | ||||||
| 	upstream = branch_get(*cp ? cp : NULL); | 	upstream = branch_get(*cp ? cp : NULL); | ||||||
|  |  | ||||||
|  | @ -32,6 +32,9 @@ test_expect_success 'setup' ' | ||||||
| 	git checkout -b upstream-branch && | 	git checkout -b upstream-branch && | ||||||
| 	test_commit upstream-one && | 	test_commit upstream-one && | ||||||
| 	test_commit upstream-two && | 	test_commit upstream-two && | ||||||
|  | 	git checkout -b @/at-test && | ||||||
|  | 	git checkout -b @@/at-test && | ||||||
|  | 	git checkout -b @at-test && | ||||||
| 	git checkout -b old-branch && | 	git checkout -b old-branch && | ||||||
| 	test_commit old-one && | 	test_commit old-one && | ||||||
| 	test_commit old-two && | 	test_commit old-two && | ||||||
|  | @ -55,6 +58,11 @@ check "HEAD@{u}" ref refs/heads/upstream-branch | ||||||
| check "@{u}@{1}" commit upstream-one | check "@{u}@{1}" commit upstream-one | ||||||
| check "@{-1}@{u}" ref refs/heads/master | check "@{-1}@{u}" ref refs/heads/master | ||||||
| check "@{-1}@{u}@{1}" commit master-one | check "@{-1}@{u}@{1}" commit master-one | ||||||
|  | check "@" commit new-two | ||||||
|  | check "@@{u}" ref refs/heads/upstream-branch | ||||||
|  | check "@@/at-test" ref refs/heads/@@/at-test | ||||||
|  | check "@/at-test" ref refs/heads/@/at-test | ||||||
|  | check "@at-test" ref refs/heads/@at-test | ||||||
| nonsense "@{u}@{-1}" | nonsense "@{u}@{-1}" | ||||||
| nonsense "@{0}@{0}" | nonsense "@{0}@{0}" | ||||||
| nonsense "@{1}@{u}" | nonsense "@{1}@{u}" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Felipe Contreras
						Felipe Contreras