1 /*
2  * GIT - The information manager from hell
3  *
4  * Copyright (C) Linus Torvalds, 2005
5  */
6 #define USE_THE_INDEX_COMPATIBILITY_MACROS
7 #include "cache.h"
8 #include "config.h"
9 #include "builtin.h"
10 #include "diff.h"
11 #include "parse-options.h"
12 #include "userdiff.h"
13 #include "streaming.h"
14 #include "tree-walk.h"
15 #include "oid-array.h"
16 #include "packfile.h"
17 #include "object-store.h"
18 #include "promisor-remote.h"
19 
20 struct batch_options {
21 	int enabled;
22 	int follow_symlinks;
23 	int print_contents;
24 	int buffer_output;
25 	int all_objects;
26 	int unordered;
27 	int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
28 	const char *format;
29 };
30 
31 static const char *force_path;
32 
filter_object(const char * path,unsigned mode,const struct object_id * oid,char ** buf,unsigned long * size)33 static int filter_object(const char *path, unsigned mode,
34 			 const struct object_id *oid,
35 			 char **buf, unsigned long *size)
36 {
37 	enum object_type type;
38 
39 	*buf = read_object_file(oid, &type, size);
40 	if (!*buf)
41 		return error(_("cannot read object %s '%s'"),
42 			     oid_to_hex(oid), path);
43 	if ((type == OBJ_BLOB) && S_ISREG(mode)) {
44 		struct strbuf strbuf = STRBUF_INIT;
45 		struct checkout_metadata meta;
46 
47 		init_checkout_metadata(&meta, NULL, NULL, oid);
48 		if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf, &meta)) {
49 			free(*buf);
50 			*size = strbuf.len;
51 			*buf = strbuf_detach(&strbuf, NULL);
52 		}
53 	}
54 
55 	return 0;
56 }
57 
stream_blob(const struct object_id * oid)58 static int stream_blob(const struct object_id *oid)
59 {
60 	if (stream_blob_to_fd(1, oid, NULL, 0))
61 		die("unable to stream %s to stdout", oid_to_hex(oid));
62 	return 0;
63 }
64 
cat_one_file(int opt,const char * exp_type,const char * obj_name,int unknown_type)65 static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
66 			int unknown_type)
67 {
68 	struct object_id oid;
69 	enum object_type type;
70 	char *buf;
71 	unsigned long size;
72 	struct object_context obj_context;
73 	struct object_info oi = OBJECT_INFO_INIT;
74 	struct strbuf sb = STRBUF_INIT;
75 	unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
76 	const char *path = force_path;
77 
78 	if (unknown_type)
79 		flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
80 
81 	if (get_oid_with_context(the_repository, obj_name,
82 				 GET_OID_RECORD_PATH,
83 				 &oid, &obj_context))
84 		die("Not a valid object name %s", obj_name);
85 
86 	if (!path)
87 		path = obj_context.path;
88 	if (obj_context.mode == S_IFINVALID)
89 		obj_context.mode = 0100644;
90 
91 	buf = NULL;
92 	switch (opt) {
93 	case 't':
94 		oi.type_name = &sb;
95 		if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
96 			die("git cat-file: could not get object info");
97 		if (sb.len) {
98 			printf("%s\n", sb.buf);
99 			strbuf_release(&sb);
100 			return 0;
101 		}
102 		break;
103 
104 	case 's':
105 		oi.sizep = &size;
106 		if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
107 			die("git cat-file: could not get object info");
108 		printf("%"PRIuMAX"\n", (uintmax_t)size);
109 		return 0;
110 
111 	case 'e':
112 		return !has_object_file(&oid);
113 
114 	case 'w':
115 		if (!path)
116 			die("git cat-file --filters %s: <object> must be "
117 			    "<sha1:path>", obj_name);
118 
119 		if (filter_object(path, obj_context.mode,
120 				  &oid, &buf, &size))
121 			return -1;
122 		break;
123 
124 	case 'c':
125 		if (!path)
126 			die("git cat-file --textconv %s: <object> must be <sha1:path>",
127 			    obj_name);
128 
129 		if (textconv_object(the_repository, path, obj_context.mode,
130 				    &oid, 1, &buf, &size))
131 			break;
132 		/* else fallthrough */
133 
134 	case 'p':
135 		type = oid_object_info(the_repository, &oid, NULL);
136 		if (type < 0)
137 			die("Not a valid object name %s", obj_name);
138 
139 		/* custom pretty-print here */
140 		if (type == OBJ_TREE) {
141 			const char *ls_args[3] = { NULL };
142 			ls_args[0] =  "ls-tree";
143 			ls_args[1] =  obj_name;
144 			return cmd_ls_tree(2, ls_args, NULL);
145 		}
146 
147 		if (type == OBJ_BLOB)
148 			return stream_blob(&oid);
149 		buf = read_object_file(&oid, &type, &size);
150 		if (!buf)
151 			die("Cannot read object %s", obj_name);
152 
153 		/* otherwise just spit out the data */
154 		break;
155 
156 	case 0:
157 		if (type_from_string(exp_type) == OBJ_BLOB) {
158 			struct object_id blob_oid;
159 			if (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) {
160 				char *buffer = read_object_file(&oid, &type,
161 								&size);
162 				const char *target;
163 				if (!skip_prefix(buffer, "object ", &target) ||
164 				    get_oid_hex(target, &blob_oid))
165 					die("%s not a valid tag", oid_to_hex(&oid));
166 				free(buffer);
167 			} else
168 				oidcpy(&blob_oid, &oid);
169 
170 			if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB)
171 				return stream_blob(&blob_oid);
172 			/*
173 			 * we attempted to dereference a tag to a blob
174 			 * and failed; there may be new dereference
175 			 * mechanisms this code is not aware of.
176 			 * fall-back to the usual case.
177 			 */
178 		}
179 		buf = read_object_with_reference(the_repository,
180 						 &oid, exp_type, &size, NULL);
181 		break;
182 
183 	default:
184 		die("git cat-file: unknown option: %s", exp_type);
185 	}
186 
187 	if (!buf)
188 		die("git cat-file %s: bad file", obj_name);
189 
190 	write_or_die(1, buf, size);
191 	free(buf);
192 	free(obj_context.path);
193 	return 0;
194 }
195 
196 struct expand_data {
197 	struct object_id oid;
198 	enum object_type type;
199 	unsigned long size;
200 	off_t disk_size;
201 	const char *rest;
202 	struct object_id delta_base_oid;
203 
204 	/*
205 	 * If mark_query is true, we do not expand anything, but rather
206 	 * just mark the object_info with items we wish to query.
207 	 */
208 	int mark_query;
209 
210 	/*
211 	 * Whether to split the input on whitespace before feeding it to
212 	 * get_sha1; this is decided during the mark_query phase based on
213 	 * whether we have a %(rest) token in our format.
214 	 */
215 	int split_on_whitespace;
216 
217 	/*
218 	 * After a mark_query run, this object_info is set up to be
219 	 * passed to oid_object_info_extended. It will point to the data
220 	 * elements above, so you can retrieve the response from there.
221 	 */
222 	struct object_info info;
223 
224 	/*
225 	 * This flag will be true if the requested batch format and options
226 	 * don't require us to call oid_object_info, which can then be
227 	 * optimized out.
228 	 */
229 	unsigned skip_object_info : 1;
230 };
231 
is_atom(const char * atom,const char * s,int slen)232 static int is_atom(const char *atom, const char *s, int slen)
233 {
234 	int alen = strlen(atom);
235 	return alen == slen && !memcmp(atom, s, alen);
236 }
237 
expand_atom(struct strbuf * sb,const char * atom,int len,void * vdata)238 static void expand_atom(struct strbuf *sb, const char *atom, int len,
239 			void *vdata)
240 {
241 	struct expand_data *data = vdata;
242 
243 	if (is_atom("objectname", atom, len)) {
244 		if (!data->mark_query)
245 			strbuf_addstr(sb, oid_to_hex(&data->oid));
246 	} else if (is_atom("objecttype", atom, len)) {
247 		if (data->mark_query)
248 			data->info.typep = &data->type;
249 		else
250 			strbuf_addstr(sb, type_name(data->type));
251 	} else if (is_atom("objectsize", atom, len)) {
252 		if (data->mark_query)
253 			data->info.sizep = &data->size;
254 		else
255 			strbuf_addf(sb, "%"PRIuMAX , (uintmax_t)data->size);
256 	} else if (is_atom("objectsize:disk", atom, len)) {
257 		if (data->mark_query)
258 			data->info.disk_sizep = &data->disk_size;
259 		else
260 			strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
261 	} else if (is_atom("rest", atom, len)) {
262 		if (data->mark_query)
263 			data->split_on_whitespace = 1;
264 		else if (data->rest)
265 			strbuf_addstr(sb, data->rest);
266 	} else if (is_atom("deltabase", atom, len)) {
267 		if (data->mark_query)
268 			data->info.delta_base_oid = &data->delta_base_oid;
269 		else
270 			strbuf_addstr(sb,
271 				      oid_to_hex(&data->delta_base_oid));
272 	} else
273 		die("unknown format element: %.*s", len, atom);
274 }
275 
expand_format(struct strbuf * sb,const char * start,void * data)276 static size_t expand_format(struct strbuf *sb, const char *start, void *data)
277 {
278 	const char *end;
279 
280 	if (*start != '(')
281 		return 0;
282 	end = strchr(start + 1, ')');
283 	if (!end)
284 		die("format element '%s' does not end in ')'", start);
285 
286 	expand_atom(sb, start + 1, end - start - 1, data);
287 
288 	return end - start + 1;
289 }
290 
batch_write(struct batch_options * opt,const void * data,int len)291 static void batch_write(struct batch_options *opt, const void *data, int len)
292 {
293 	if (opt->buffer_output) {
294 		if (fwrite(data, 1, len, stdout) != len)
295 			die_errno("unable to write to stdout");
296 	} else
297 		write_or_die(1, data, len);
298 }
299 
print_object_or_die(struct batch_options * opt,struct expand_data * data)300 static void print_object_or_die(struct batch_options *opt, struct expand_data *data)
301 {
302 	const struct object_id *oid = &data->oid;
303 
304 	assert(data->info.typep);
305 
306 	if (data->type == OBJ_BLOB) {
307 		if (opt->buffer_output)
308 			fflush(stdout);
309 		if (opt->cmdmode) {
310 			char *contents;
311 			unsigned long size;
312 
313 			if (!data->rest)
314 				die("missing path for '%s'", oid_to_hex(oid));
315 
316 			if (opt->cmdmode == 'w') {
317 				if (filter_object(data->rest, 0100644, oid,
318 						  &contents, &size))
319 					die("could not convert '%s' %s",
320 					    oid_to_hex(oid), data->rest);
321 			} else if (opt->cmdmode == 'c') {
322 				enum object_type type;
323 				if (!textconv_object(the_repository,
324 						     data->rest, 0100644, oid,
325 						     1, &contents, &size))
326 					contents = read_object_file(oid,
327 								    &type,
328 								    &size);
329 				if (!contents)
330 					die("could not convert '%s' %s",
331 					    oid_to_hex(oid), data->rest);
332 			} else
333 				BUG("invalid cmdmode: %c", opt->cmdmode);
334 			batch_write(opt, contents, size);
335 			free(contents);
336 		} else {
337 			stream_blob(oid);
338 		}
339 	}
340 	else {
341 		enum object_type type;
342 		unsigned long size;
343 		void *contents;
344 
345 		contents = read_object_file(oid, &type, &size);
346 		if (!contents)
347 			die("object %s disappeared", oid_to_hex(oid));
348 		if (type != data->type)
349 			die("object %s changed type!?", oid_to_hex(oid));
350 		if (data->info.sizep && size != data->size)
351 			die("object %s changed size!?", oid_to_hex(oid));
352 
353 		batch_write(opt, contents, size);
354 		free(contents);
355 	}
356 }
357 
358 /*
359  * If "pack" is non-NULL, then "offset" is the byte offset within the pack from
360  * which the object may be accessed (though note that we may also rely on
361  * data->oid, too). If "pack" is NULL, then offset is ignored.
362  */
batch_object_write(const char * obj_name,struct strbuf * scratch,struct batch_options * opt,struct expand_data * data,struct packed_git * pack,off_t offset)363 static void batch_object_write(const char *obj_name,
364 			       struct strbuf *scratch,
365 			       struct batch_options *opt,
366 			       struct expand_data *data,
367 			       struct packed_git *pack,
368 			       off_t offset)
369 {
370 	if (!data->skip_object_info) {
371 		int ret;
372 
373 		if (pack)
374 			ret = packed_object_info(the_repository, pack, offset,
375 						 &data->info);
376 		else
377 			ret = oid_object_info_extended(the_repository,
378 						       &data->oid, &data->info,
379 						       OBJECT_INFO_LOOKUP_REPLACE);
380 		if (ret < 0) {
381 			printf("%s missing\n",
382 			       obj_name ? obj_name : oid_to_hex(&data->oid));
383 			fflush(stdout);
384 			return;
385 		}
386 	}
387 
388 	strbuf_reset(scratch);
389 	strbuf_expand(scratch, opt->format, expand_format, data);
390 	strbuf_addch(scratch, '\n');
391 	batch_write(opt, scratch->buf, scratch->len);
392 
393 	if (opt->print_contents) {
394 		print_object_or_die(opt, data);
395 		batch_write(opt, "\n", 1);
396 	}
397 }
398 
batch_one_object(const char * obj_name,struct strbuf * scratch,struct batch_options * opt,struct expand_data * data)399 static void batch_one_object(const char *obj_name,
400 			     struct strbuf *scratch,
401 			     struct batch_options *opt,
402 			     struct expand_data *data)
403 {
404 	struct object_context ctx;
405 	int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
406 	enum get_oid_result result;
407 
408 	result = get_oid_with_context(the_repository, obj_name,
409 				      flags, &data->oid, &ctx);
410 	if (result != FOUND) {
411 		switch (result) {
412 		case MISSING_OBJECT:
413 			printf("%s missing\n", obj_name);
414 			break;
415 		case SHORT_NAME_AMBIGUOUS:
416 			printf("%s ambiguous\n", obj_name);
417 			break;
418 		case DANGLING_SYMLINK:
419 			printf("dangling %"PRIuMAX"\n%s\n",
420 			       (uintmax_t)strlen(obj_name), obj_name);
421 			break;
422 		case SYMLINK_LOOP:
423 			printf("loop %"PRIuMAX"\n%s\n",
424 			       (uintmax_t)strlen(obj_name), obj_name);
425 			break;
426 		case NOT_DIR:
427 			printf("notdir %"PRIuMAX"\n%s\n",
428 			       (uintmax_t)strlen(obj_name), obj_name);
429 			break;
430 		default:
431 			BUG("unknown get_sha1_with_context result %d\n",
432 			       result);
433 			break;
434 		}
435 		fflush(stdout);
436 		return;
437 	}
438 
439 	if (ctx.mode == 0) {
440 		printf("symlink %"PRIuMAX"\n%s\n",
441 		       (uintmax_t)ctx.symlink_path.len,
442 		       ctx.symlink_path.buf);
443 		fflush(stdout);
444 		return;
445 	}
446 
447 	batch_object_write(obj_name, scratch, opt, data, NULL, 0);
448 }
449 
450 struct object_cb_data {
451 	struct batch_options *opt;
452 	struct expand_data *expand;
453 	struct oidset *seen;
454 	struct strbuf *scratch;
455 };
456 
batch_object_cb(const struct object_id * oid,void * vdata)457 static int batch_object_cb(const struct object_id *oid, void *vdata)
458 {
459 	struct object_cb_data *data = vdata;
460 	oidcpy(&data->expand->oid, oid);
461 	batch_object_write(NULL, data->scratch, data->opt, data->expand,
462 			   NULL, 0);
463 	return 0;
464 }
465 
collect_loose_object(const struct object_id * oid,const char * path,void * data)466 static int collect_loose_object(const struct object_id *oid,
467 				const char *path,
468 				void *data)
469 {
470 	oid_array_append(data, oid);
471 	return 0;
472 }
473 
collect_packed_object(const struct object_id * oid,struct packed_git * pack,uint32_t pos,void * data)474 static int collect_packed_object(const struct object_id *oid,
475 				 struct packed_git *pack,
476 				 uint32_t pos,
477 				 void *data)
478 {
479 	oid_array_append(data, oid);
480 	return 0;
481 }
482 
batch_unordered_object(const struct object_id * oid,struct packed_git * pack,off_t offset,void * vdata)483 static int batch_unordered_object(const struct object_id *oid,
484 				  struct packed_git *pack, off_t offset,
485 				  void *vdata)
486 {
487 	struct object_cb_data *data = vdata;
488 
489 	if (oidset_insert(data->seen, oid))
490 		return 0;
491 
492 	oidcpy(&data->expand->oid, oid);
493 	batch_object_write(NULL, data->scratch, data->opt, data->expand,
494 			   pack, offset);
495 	return 0;
496 }
497 
batch_unordered_loose(const struct object_id * oid,const char * path,void * data)498 static int batch_unordered_loose(const struct object_id *oid,
499 				 const char *path,
500 				 void *data)
501 {
502 	return batch_unordered_object(oid, NULL, 0, data);
503 }
504 
batch_unordered_packed(const struct object_id * oid,struct packed_git * pack,uint32_t pos,void * data)505 static int batch_unordered_packed(const struct object_id *oid,
506 				  struct packed_git *pack,
507 				  uint32_t pos,
508 				  void *data)
509 {
510 	return batch_unordered_object(oid, pack,
511 				      nth_packed_object_offset(pack, pos),
512 				      data);
513 }
514 
batch_objects(struct batch_options * opt)515 static int batch_objects(struct batch_options *opt)
516 {
517 	struct strbuf input = STRBUF_INIT;
518 	struct strbuf output = STRBUF_INIT;
519 	struct expand_data data;
520 	int save_warning;
521 	int retval = 0;
522 
523 	if (!opt->format)
524 		opt->format = "%(objectname) %(objecttype) %(objectsize)";
525 
526 	/*
527 	 * Expand once with our special mark_query flag, which will prime the
528 	 * object_info to be handed to oid_object_info_extended for each
529 	 * object.
530 	 */
531 	memset(&data, 0, sizeof(data));
532 	data.mark_query = 1;
533 	strbuf_expand(&output, opt->format, expand_format, &data);
534 	data.mark_query = 0;
535 	strbuf_release(&output);
536 	if (opt->cmdmode)
537 		data.split_on_whitespace = 1;
538 
539 	/*
540 	 * If we are printing out the object, then always fill in the type,
541 	 * since we will want to decide whether or not to stream.
542 	 */
543 	if (opt->print_contents)
544 		data.info.typep = &data.type;
545 
546 	if (opt->all_objects) {
547 		struct object_cb_data cb;
548 		struct object_info empty = OBJECT_INFO_INIT;
549 
550 		if (!memcmp(&data.info, &empty, sizeof(empty)))
551 			data.skip_object_info = 1;
552 
553 		if (has_promisor_remote())
554 			warning("This repository uses promisor remotes. Some objects may not be loaded.");
555 
556 		read_replace_refs = 0;
557 
558 		cb.opt = opt;
559 		cb.expand = &data;
560 		cb.scratch = &output;
561 
562 		if (opt->unordered) {
563 			struct oidset seen = OIDSET_INIT;
564 
565 			cb.seen = &seen;
566 
567 			for_each_loose_object(batch_unordered_loose, &cb, 0);
568 			for_each_packed_object(batch_unordered_packed, &cb,
569 					       FOR_EACH_OBJECT_PACK_ORDER);
570 
571 			oidset_clear(&seen);
572 		} else {
573 			struct oid_array sa = OID_ARRAY_INIT;
574 
575 			for_each_loose_object(collect_loose_object, &sa, 0);
576 			for_each_packed_object(collect_packed_object, &sa, 0);
577 
578 			oid_array_for_each_unique(&sa, batch_object_cb, &cb);
579 
580 			oid_array_clear(&sa);
581 		}
582 
583 		strbuf_release(&output);
584 		return 0;
585 	}
586 
587 	/*
588 	 * We are going to call get_sha1 on a potentially very large number of
589 	 * objects. In most large cases, these will be actual object sha1s. The
590 	 * cost to double-check that each one is not also a ref (just so we can
591 	 * warn) ends up dwarfing the actual cost of the object lookups
592 	 * themselves. We can work around it by just turning off the warning.
593 	 */
594 	save_warning = warn_on_object_refname_ambiguity;
595 	warn_on_object_refname_ambiguity = 0;
596 
597 	while (strbuf_getline(&input, stdin) != EOF) {
598 		if (data.split_on_whitespace) {
599 			/*
600 			 * Split at first whitespace, tying off the beginning
601 			 * of the string and saving the remainder (or NULL) in
602 			 * data.rest.
603 			 */
604 			char *p = strpbrk(input.buf, " \t");
605 			if (p) {
606 				while (*p && strchr(" \t", *p))
607 					*p++ = '\0';
608 			}
609 			data.rest = p;
610 		}
611 
612 		batch_one_object(input.buf, &output, opt, &data);
613 	}
614 
615 	strbuf_release(&input);
616 	strbuf_release(&output);
617 	warn_on_object_refname_ambiguity = save_warning;
618 	return retval;
619 }
620 
621 static const char * const cat_file_usage[] = {
622 	N_("git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | <type> | --textconv | --filters) [--path=<path>] <object>"),
623 	N_("git cat-file (--batch[=<format>] | --batch-check[=<format>]) [--follow-symlinks] [--textconv | --filters]"),
624 	NULL
625 };
626 
git_cat_file_config(const char * var,const char * value,void * cb)627 static int git_cat_file_config(const char *var, const char *value, void *cb)
628 {
629 	if (userdiff_config(var, value) < 0)
630 		return -1;
631 
632 	return git_default_config(var, value, cb);
633 }
634 
batch_option_callback(const struct option * opt,const char * arg,int unset)635 static int batch_option_callback(const struct option *opt,
636 				 const char *arg,
637 				 int unset)
638 {
639 	struct batch_options *bo = opt->value;
640 
641 	BUG_ON_OPT_NEG(unset);
642 
643 	if (bo->enabled) {
644 		return error(_("only one batch option may be specified"));
645 	}
646 
647 	bo->enabled = 1;
648 	bo->print_contents = !strcmp(opt->long_name, "batch");
649 	bo->format = arg;
650 
651 	return 0;
652 }
653 
cmd_cat_file(int argc,const char ** argv,const char * prefix)654 int cmd_cat_file(int argc, const char **argv, const char *prefix)
655 {
656 	int opt = 0;
657 	const char *exp_type = NULL, *obj_name = NULL;
658 	struct batch_options batch = {0};
659 	int unknown_type = 0;
660 
661 	const struct option options[] = {
662 		OPT_GROUP(N_("<type> can be one of: blob, tree, commit, tag")),
663 		OPT_CMDMODE('t', NULL, &opt, N_("show object type"), 't'),
664 		OPT_CMDMODE('s', NULL, &opt, N_("show object size"), 's'),
665 		OPT_CMDMODE('e', NULL, &opt,
666 			    N_("exit with zero when there's no error"), 'e'),
667 		OPT_CMDMODE('p', NULL, &opt, N_("pretty-print object's content"), 'p'),
668 		OPT_CMDMODE(0, "textconv", &opt,
669 			    N_("for blob objects, run textconv on object's content"), 'c'),
670 		OPT_CMDMODE(0, "filters", &opt,
671 			    N_("for blob objects, run filters on object's content"), 'w'),
672 		OPT_STRING(0, "path", &force_path, N_("blob"),
673 			   N_("use a specific path for --textconv/--filters")),
674 		OPT_BOOL(0, "allow-unknown-type", &unknown_type,
675 			  N_("allow -s and -t to work with broken/corrupt objects")),
676 		OPT_BOOL(0, "buffer", &batch.buffer_output, N_("buffer --batch output")),
677 		OPT_CALLBACK_F(0, "batch", &batch, "format",
678 			N_("show info and content of objects fed from the standard input"),
679 			PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
680 			batch_option_callback),
681 		OPT_CALLBACK_F(0, "batch-check", &batch, "format",
682 			N_("show info about objects fed from the standard input"),
683 			PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
684 			batch_option_callback),
685 		OPT_BOOL(0, "follow-symlinks", &batch.follow_symlinks,
686 			 N_("follow in-tree symlinks (used with --batch or --batch-check)")),
687 		OPT_BOOL(0, "batch-all-objects", &batch.all_objects,
688 			 N_("show all objects with --batch or --batch-check")),
689 		OPT_BOOL(0, "unordered", &batch.unordered,
690 			 N_("do not order --batch-all-objects output")),
691 		OPT_END()
692 	};
693 
694 	git_config(git_cat_file_config, NULL);
695 
696 	batch.buffer_output = -1;
697 	argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
698 
699 	if (opt) {
700 		if (batch.enabled && (opt == 'c' || opt == 'w'))
701 			batch.cmdmode = opt;
702 		else if (argc == 1)
703 			obj_name = argv[0];
704 		else
705 			usage_with_options(cat_file_usage, options);
706 	}
707 	if (!opt && !batch.enabled) {
708 		if (argc == 2) {
709 			exp_type = argv[0];
710 			obj_name = argv[1];
711 		} else
712 			usage_with_options(cat_file_usage, options);
713 	}
714 	if (batch.enabled) {
715 		if (batch.cmdmode != opt || argc)
716 			usage_with_options(cat_file_usage, options);
717 		if (batch.cmdmode && batch.all_objects)
718 			die("--batch-all-objects cannot be combined with "
719 			    "--textconv nor with --filters");
720 	}
721 
722 	if ((batch.follow_symlinks || batch.all_objects) && !batch.enabled) {
723 		usage_with_options(cat_file_usage, options);
724 	}
725 
726 	if (force_path && opt != 'c' && opt != 'w') {
727 		error("--path=<path> needs --textconv or --filters");
728 		usage_with_options(cat_file_usage, options);
729 	}
730 
731 	if (force_path && batch.enabled) {
732 		error("--path=<path> incompatible with --batch");
733 		usage_with_options(cat_file_usage, options);
734 	}
735 
736 	if (batch.buffer_output < 0)
737 		batch.buffer_output = batch.all_objects;
738 
739 	if (batch.enabled)
740 		return batch_objects(&batch);
741 
742 	if (unknown_type && opt != 't' && opt != 's')
743 		die("git cat-file --allow-unknown-type: use with -s or -t");
744 	return cat_one_file(opt, exp_type, obj_name, unknown_type);
745 }
746