diff options
Diffstat (limited to 'builtin-cat-file.c')
| -rw-r--r-- | builtin-cat-file.c | 131 | 
1 files changed, 115 insertions, 16 deletions
| diff --git a/builtin-cat-file.c b/builtin-cat-file.c index f132d583d3..880e75af5e 100644 --- a/builtin-cat-file.c +++ b/builtin-cat-file.c @@ -8,6 +8,10 @@  #include "tag.h"  #include "tree.h"  #include "builtin.h" +#include "parse-options.h" + +#define BATCH 1 +#define BATCH_CHECK 2  static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long size)  { @@ -76,31 +80,16 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long  		write_or_die(1, cp, endp - cp);  } -int cmd_cat_file(int argc, const char **argv, const char *prefix) +static int cat_one_file(int opt, const char *exp_type, const char *obj_name)  {  	unsigned char sha1[20];  	enum object_type type;  	void *buf;  	unsigned long size; -	int opt; -	const char *exp_type, *obj_name; - -	git_config(git_default_config); -	if (argc != 3) -		usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>"); -	exp_type = argv[1]; -	obj_name = argv[2];  	if (get_sha1(obj_name, sha1))  		die("Not a valid object name %s", obj_name); -	opt = 0; -	if ( exp_type[0] == '-' ) { -		opt = exp_type[1]; -		if ( !opt || exp_type[2] ) -			opt = -1; /* Not a single character option */ -	} -  	buf = NULL;  	switch (opt) {  	case 't': @@ -157,3 +146,113 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)  	write_or_die(1, buf, size);  	return 0;  } + +static int batch_one_object(const char *obj_name, int print_contents) +{ +	unsigned char sha1[20]; +	enum object_type type = 0; +	unsigned long size; +	void *contents = contents; + +	if (!obj_name) +	   return 1; + +	if (get_sha1(obj_name, sha1)) { +		printf("%s missing\n", obj_name); +		fflush(stdout); +		return 0; +	} + +	if (print_contents == BATCH) +		contents = read_sha1_file(sha1, &type, &size); +	else +		type = sha1_object_info(sha1, &size); + +	if (type <= 0) { +		printf("%s missing\n", obj_name); +		fflush(stdout); +		return 0; +	} + +	printf("%s %s %lu\n", sha1_to_hex(sha1), typename(type), size); +	fflush(stdout); + +	if (print_contents == BATCH) { +		write_or_die(1, contents, size); +		printf("\n"); +		fflush(stdout); +		free(contents); +	} + +	return 0; +} + +static int batch_objects(int print_contents) +{ +	struct strbuf buf; + +	strbuf_init(&buf, 0); +	while (strbuf_getline(&buf, stdin, '\n') != EOF) { +		int error = batch_one_object(buf.buf, print_contents); +		if (error) +			return error; +	} + +	return 0; +} + +static const char * const cat_file_usage[] = { +	"git-cat-file [-t|-s|-e|-p|<type>] <sha1>", +	"git-cat-file [--batch|--batch-check] < <list_of_sha1s>", +	NULL +}; + +int cmd_cat_file(int argc, const char **argv, const char *prefix) +{ +	int opt = 0, batch = 0; +	const char *exp_type = NULL, *obj_name = NULL; + +	const struct option options[] = { +		OPT_GROUP("<type> can be one of: blob, tree, commit, tag"), +		OPT_SET_INT('t', NULL, &opt, "show object type", 't'), +		OPT_SET_INT('s', NULL, &opt, "show object size", 's'), +		OPT_SET_INT('e', NULL, &opt, +			    "exit with zero when there's no error", 'e'), +		OPT_SET_INT('p', NULL, &opt, "pretty-print object's content", 'p'), +		OPT_SET_INT(0, "batch", &batch, +			    "show info and content of objects feeded on stdin", BATCH), +		OPT_SET_INT(0, "batch-check", &batch, +			    "show info about objects feeded on stdin", +			    BATCH_CHECK), +		OPT_END() +	}; + +	git_config(git_default_config, NULL); + +	if (argc != 3 && argc != 2) +		usage_with_options(cat_file_usage, options); + +	argc = parse_options(argc, argv, options, cat_file_usage, 0); + +	if (opt) { +		if (argc == 1) +			obj_name = argv[0]; +		else +			usage_with_options(cat_file_usage, options); +	} +	if (!opt && !batch) { +		if (argc == 2) { +			exp_type = argv[0]; +			obj_name = argv[1]; +		} else +			usage_with_options(cat_file_usage, options); +	} +	if (batch && (opt || argc)) { +		usage_with_options(cat_file_usage, options); +	} + +	if (batch) +		return batch_objects(batch); + +	return cat_one_file(opt, exp_type, obj_name); +} | 
