Pretty-print tagger dates.
We can show commit objects with human readable dates using various --pretty options, but there was no way to do so with tags. This introduces two such ways: $ git-cat-file -p v1.2.3 shows the tag object with tagger dates in human readable format. $ git-verify-tag --verbose v1.2.3 uses it to show the contents of the tag object as well as doing GPG verification. Signed-off-by: Junio C Hamano <junkio@cox.net>maint
							parent
							
								
									e1a0c8b148
								
							
						
					
					
						commit
						a0f15fa502
					
				
							
								
								
									
										119
									
								
								cat-file.c
								
								
								
								
							
							
						
						
									
										119
									
								
								cat-file.c
								
								
								
								
							|  | @ -4,6 +4,92 @@ | ||||||
|  * Copyright (C) Linus Torvalds, 2005 |  * Copyright (C) Linus Torvalds, 2005 | ||||||
|  */ |  */ | ||||||
| #include "cache.h" | #include "cache.h" | ||||||
|  | #include "exec_cmd.h" | ||||||
|  |  | ||||||
|  | static void flush_buffer(const char *buf, unsigned long size) | ||||||
|  | { | ||||||
|  | 	while (size > 0) { | ||||||
|  | 		long ret = xwrite(1, buf, size); | ||||||
|  | 		if (ret < 0) { | ||||||
|  | 			/* Ignore epipe */ | ||||||
|  | 			if (errno == EPIPE) | ||||||
|  | 				break; | ||||||
|  | 			die("git-cat-file: %s", strerror(errno)); | ||||||
|  | 		} else if (!ret) { | ||||||
|  | 			die("git-cat-file: disk full?"); | ||||||
|  | 		} | ||||||
|  | 		size -= ret; | ||||||
|  | 		buf += ret; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pprint_tag(const unsigned char *sha1, const char *buf, unsigned long size) | ||||||
|  | { | ||||||
|  | 	/* the parser in tag.c is useless here. */ | ||||||
|  | 	const char *endp = buf + size; | ||||||
|  | 	const char *cp = buf; | ||||||
|  |  | ||||||
|  | 	while (cp < endp) { | ||||||
|  | 		char c = *cp++; | ||||||
|  | 		if (c != '\n') | ||||||
|  | 			continue; | ||||||
|  | 		if (7 <= endp - cp && !memcmp("tagger ", cp, 7)) { | ||||||
|  | 			const char *tagger = cp; | ||||||
|  |  | ||||||
|  | 			/* Found the tagger line.  Copy out the contents | ||||||
|  | 			 * of the buffer so far. | ||||||
|  | 			 */ | ||||||
|  | 			flush_buffer(buf, cp - buf); | ||||||
|  |  | ||||||
|  | 			/* | ||||||
|  | 			 * Do something intelligent, like pretty-printing | ||||||
|  | 			 * the date. | ||||||
|  | 			 */ | ||||||
|  | 			while (cp < endp) { | ||||||
|  | 				if (*cp++ == '\n') { | ||||||
|  | 					/* tagger to cp is a line | ||||||
|  | 					 * that has ident and time. | ||||||
|  | 					 */ | ||||||
|  | 					const char *sp = tagger; | ||||||
|  | 					char *ep; | ||||||
|  | 					unsigned long date; | ||||||
|  | 					long tz; | ||||||
|  | 					while (sp < cp && *sp != '>') | ||||||
|  | 						sp++; | ||||||
|  | 					if (sp == cp) { | ||||||
|  | 						/* give up */ | ||||||
|  | 						flush_buffer(tagger, | ||||||
|  | 							     cp - tagger); | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 					while (sp < cp && | ||||||
|  | 					       !('0' <= *sp && *sp <= '9')) | ||||||
|  | 						sp++; | ||||||
|  | 					flush_buffer(tagger, sp - tagger); | ||||||
|  | 					date = strtoul(sp, &ep, 10); | ||||||
|  | 					tz = strtol(ep, NULL, 10); | ||||||
|  | 					sp = show_date(date, tz); | ||||||
|  | 					flush_buffer(sp, strlen(sp)); | ||||||
|  | 					xwrite(1, "\n", 1); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (cp < endp && *cp == '\n') | ||||||
|  | 			/* end of header */ | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 	/* At this point, we have copied out the header up to the end of | ||||||
|  | 	 * the tagger line and cp points at one past \n.  It could be the | ||||||
|  | 	 * next header line after the tagger line, or it could be another | ||||||
|  | 	 * \n that marks the end of the headers.  We need to copy out the | ||||||
|  | 	 * remainder as is. | ||||||
|  | 	 */ | ||||||
|  | 	if (cp < endp) | ||||||
|  | 		flush_buffer(cp, endp - cp); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| int main(int argc, char **argv) | int main(int argc, char **argv) | ||||||
| { | { | ||||||
|  | @ -15,7 +101,7 @@ int main(int argc, char **argv) | ||||||
|  |  | ||||||
| 	setup_git_directory(); | 	setup_git_directory(); | ||||||
| 	if (argc != 3 || get_sha1(argv[2], sha1)) | 	if (argc != 3 || get_sha1(argv[2], sha1)) | ||||||
| 		usage("git-cat-file [-t|-s|-e|<type>] <sha1>"); | 		usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>"); | ||||||
|  |  | ||||||
| 	opt = 0; | 	opt = 0; | ||||||
| 	if ( argv[1][0] == '-' ) { | 	if ( argv[1][0] == '-' ) { | ||||||
|  | @ -43,6 +129,23 @@ int main(int argc, char **argv) | ||||||
| 	case 'e': | 	case 'e': | ||||||
| 		return !has_sha1_file(sha1); | 		return !has_sha1_file(sha1); | ||||||
|  |  | ||||||
|  | 	case 'p': | ||||||
|  | 		if (get_sha1(argv[2], sha1) || | ||||||
|  | 		    sha1_object_info(sha1, type, NULL)) | ||||||
|  | 			die("Not a valid object name %s", argv[2]); | ||||||
|  |  | ||||||
|  | 		/* custom pretty-print here */ | ||||||
|  | 		if (!strcmp(type, "tree")) | ||||||
|  | 			return execl_git_cmd("ls-tree", argv[2], NULL); | ||||||
|  |  | ||||||
|  | 		buf = read_sha1_file(sha1, type, &size); | ||||||
|  | 		if (!buf) | ||||||
|  | 			die("Cannot read object %s", argv[2]); | ||||||
|  | 		if (!strcmp(type, "tag")) | ||||||
|  | 			return pprint_tag(sha1, buf, size); | ||||||
|  |  | ||||||
|  | 		/* otherwise just spit out the data */ | ||||||
|  | 		break; | ||||||
| 	case 0: | 	case 0: | ||||||
| 		buf = read_object_with_reference(sha1, argv[1], &size, NULL); | 		buf = read_object_with_reference(sha1, argv[1], &size, NULL); | ||||||
| 		break; | 		break; | ||||||
|  | @ -54,18 +157,6 @@ int main(int argc, char **argv) | ||||||
| 	if (!buf) | 	if (!buf) | ||||||
| 		die("git-cat-file %s: bad file", argv[2]); | 		die("git-cat-file %s: bad file", argv[2]); | ||||||
|  |  | ||||||
| 	while (size > 0) { | 	flush_buffer(buf, size); | ||||||
| 		long ret = xwrite(1, buf, size); |  | ||||||
| 		if (ret < 0) { |  | ||||||
| 			/* Ignore epipe */ |  | ||||||
| 			if (errno == EPIPE) |  | ||||||
| 				break; |  | ||||||
| 			die("git-cat-file: %s", strerror(errno)); |  | ||||||
| 		} else if (!ret) { |  | ||||||
| 			die("git-cat-file: disk full?"); |  | ||||||
| 		} |  | ||||||
| 		size -= ret; |  | ||||||
| 		buf += ret; |  | ||||||
| 	} |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,9 +4,21 @@ USAGE='<tag>' | ||||||
| SUBDIRECTORY_OK='Yes' | SUBDIRECTORY_OK='Yes' | ||||||
| . git-sh-setup | . git-sh-setup | ||||||
|  |  | ||||||
|  | verbose= | ||||||
|  | while case $# in 0) break;; esac | ||||||
|  | do | ||||||
|  | 	case "$1" in | ||||||
|  | 	-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) | ||||||
|  | 		verbose=t ;; | ||||||
|  | 	*) | ||||||
|  | 		break ;; | ||||||
|  | 	esac | ||||||
|  | 	shift | ||||||
|  | done | ||||||
|  |  | ||||||
| if [ "$#" != "1" ] | if [ "$#" != "1" ] | ||||||
| then | then | ||||||
|   usage | 	usage | ||||||
| fi | fi | ||||||
|  |  | ||||||
| type="$(git-cat-file -t "$1" 2>/dev/null)" || | type="$(git-cat-file -t "$1" 2>/dev/null)" || | ||||||
|  | @ -15,6 +27,13 @@ type="$(git-cat-file -t "$1" 2>/dev/null)" || | ||||||
| test "$type" = tag || | test "$type" = tag || | ||||||
| 	die "$1: cannot verify a non-tag object of type $type." | 	die "$1: cannot verify a non-tag object of type $type." | ||||||
|  |  | ||||||
|  | case "$verbose" in | ||||||
|  | t) | ||||||
|  | 	git-cat-file -p "$1" | | ||||||
|  | 	sed -n -e '/^-----BEGIN PGP SIGNATURE-----/q' -e p | ||||||
|  | 	;; | ||||||
|  | esac | ||||||
|  |  | ||||||
| git-cat-file tag "$1" >"$GIT_DIR/.tmp-vtag" || exit 1 | git-cat-file tag "$1" >"$GIT_DIR/.tmp-vtag" || exit 1 | ||||||
| cat "$GIT_DIR/.tmp-vtag" | | cat "$GIT_DIR/.tmp-vtag" | | ||||||
| sed '/-----BEGIN PGP/Q' | | sed '/-----BEGIN PGP/Q' | | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano