2 * GIT - The information manager from hell
4 * Copyright (C) Linus Torvalds, 2005
11 #include "parse-options.h"
14 #include "streaming.h"
19 static int cat_one_file(int opt
, const char *exp_type
, const char *obj_name
)
21 unsigned char sha1
[20];
22 enum object_type type
;
25 struct object_context obj_context
;
27 if (get_sha1_with_context(obj_name
, 0, sha1
, &obj_context
))
28 die("Not a valid object name %s", obj_name
);
33 type
= sha1_object_info(sha1
, NULL
);
35 printf("%s\n", typename(type
));
41 type
= sha1_object_info(sha1
, &size
);
43 printf("%lu\n", size
);
49 return !has_sha1_file(sha1
);
52 type
= sha1_object_info(sha1
, NULL
);
54 die("Not a valid object name %s", obj_name
);
56 /* custom pretty-print here */
57 if (type
== OBJ_TREE
) {
58 const char *ls_args
[3] = { NULL
};
59 ls_args
[0] = "ls-tree";
60 ls_args
[1] = obj_name
;
61 return cmd_ls_tree(2, ls_args
, NULL
);
65 return stream_blob_to_fd(1, sha1
, NULL
, 0);
66 buf
= read_sha1_file(sha1
, &type
, &size
);
68 die("Cannot read object %s", obj_name
);
70 /* otherwise just spit out the data */
74 if (!obj_context
.path
[0])
75 die("git cat-file --textconv %s: <object> must be <sha1:path>",
78 if (!textconv_object(obj_context
.path
, obj_context
.mode
, sha1
, 1, &buf
, &size
))
79 die("git cat-file --textconv: unable to run textconv on %s",
84 if (type_from_string(exp_type
) == OBJ_BLOB
) {
85 unsigned char blob_sha1
[20];
86 if (sha1_object_info(sha1
, NULL
) == OBJ_TAG
) {
87 enum object_type type
;
89 char *buffer
= read_sha1_file(sha1
, &type
, &size
);
90 if (memcmp(buffer
, "object ", 7) ||
91 get_sha1_hex(buffer
+ 7, blob_sha1
))
92 die("%s not a valid tag", sha1_to_hex(sha1
));
95 hashcpy(blob_sha1
, sha1
);
97 if (sha1_object_info(blob_sha1
, NULL
) == OBJ_BLOB
)
98 return stream_blob_to_fd(1, blob_sha1
, NULL
, 0);
100 * we attempted to dereference a tag to a blob
101 * and failed; there may be new dereference
102 * mechanisms this code is not aware of.
103 * fall-back to the usual case.
106 buf
= read_object_with_reference(sha1
, exp_type
, &size
, NULL
);
110 die("git cat-file: unknown option: %s", exp_type
);
114 die("git cat-file %s: bad file", obj_name
);
116 write_or_die(1, buf
, size
);
120 static void print_object_or_die(int fd
, const unsigned char *sha1
,
121 enum object_type type
, unsigned long size
)
123 if (type
== OBJ_BLOB
) {
124 if (stream_blob_to_fd(fd
, sha1
, NULL
, 0) < 0)
125 die("unable to stream %s to stdout", sha1_to_hex(sha1
));
128 enum object_type rtype
;
132 contents
= read_sha1_file(sha1
, &rtype
, &rsize
);
134 die("object %s disappeared", sha1_to_hex(sha1
));
136 die("object %s changed type!?", sha1_to_hex(sha1
));
138 die("object %s change size!?", sha1_to_hex(sha1
));
140 write_or_die(fd
, contents
, size
);
145 static int batch_one_object(const char *obj_name
, int print_contents
)
147 unsigned char sha1
[20];
148 enum object_type type
= 0;
154 if (get_sha1(obj_name
, sha1
)) {
155 printf("%s missing\n", obj_name
);
160 type
= sha1_object_info(sha1
, &size
);
162 printf("%s missing\n", obj_name
);
167 printf("%s %s %lu\n", sha1_to_hex(sha1
), typename(type
), size
);
170 if (print_contents
== BATCH
) {
171 print_object_or_die(1, sha1
, type
, size
);
172 write_or_die(1, "\n", 1);
177 static int batch_objects(int print_contents
)
179 struct strbuf buf
= STRBUF_INIT
;
181 while (strbuf_getline(&buf
, stdin
, '\n') != EOF
) {
182 int error
= batch_one_object(buf
.buf
, print_contents
);
190 static const char * const cat_file_usage
[] = {
191 N_("git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"),
192 N_("git cat-file (--batch|--batch-check) < <list_of_objects>"),
196 static int git_cat_file_config(const char *var
, const char *value
, void *cb
)
198 if (userdiff_config(var
, value
) < 0)
201 return git_default_config(var
, value
, cb
);
204 int cmd_cat_file(int argc
, const char **argv
, const char *prefix
)
206 int opt
= 0, batch
= 0;
207 const char *exp_type
= NULL
, *obj_name
= NULL
;
209 const struct option options
[] = {
210 OPT_GROUP(N_("<type> can be one of: blob, tree, commit, tag")),
211 OPT_SET_INT('t', NULL
, &opt
, N_("show object type"), 't'),
212 OPT_SET_INT('s', NULL
, &opt
, N_("show object size"), 's'),
213 OPT_SET_INT('e', NULL
, &opt
,
214 N_("exit with zero when there's no error"), 'e'),
215 OPT_SET_INT('p', NULL
, &opt
, N_("pretty-print object's content"), 'p'),
216 OPT_SET_INT(0, "textconv", &opt
,
217 N_("for blob objects, run textconv on object's content"), 'c'),
218 OPT_SET_INT(0, "batch", &batch
,
219 N_("show info and content of objects fed from the standard input"),
221 OPT_SET_INT(0, "batch-check", &batch
,
222 N_("show info about objects fed from the standard input"),
227 git_config(git_cat_file_config
, NULL
);
229 if (argc
!= 3 && argc
!= 2)
230 usage_with_options(cat_file_usage
, options
);
232 argc
= parse_options(argc
, argv
, prefix
, options
, cat_file_usage
, 0);
238 usage_with_options(cat_file_usage
, options
);
240 if (!opt
&& !batch
) {
245 usage_with_options(cat_file_usage
, options
);
247 if (batch
&& (opt
|| argc
)) {
248 usage_with_options(cat_file_usage
, options
);
252 return batch_objects(batch
);
254 return cat_one_file(opt
, exp_type
, obj_name
);