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 int batch_one_object(const char *obj_name
, int print_contents
)
122 unsigned char sha1
[20];
123 enum object_type type
= 0;
125 void *contents
= NULL
;
130 if (get_sha1(obj_name
, sha1
)) {
131 printf("%s missing\n", obj_name
);
136 if (print_contents
== BATCH
)
137 contents
= read_sha1_file(sha1
, &type
, &size
);
139 type
= sha1_object_info(sha1
, &size
);
142 printf("%s missing\n", obj_name
);
144 if (print_contents
== BATCH
)
149 printf("%s %s %lu\n", sha1_to_hex(sha1
), typename(type
), size
);
152 if (print_contents
== BATCH
) {
153 write_or_die(1, contents
, size
);
162 static int batch_objects(int print_contents
)
164 struct strbuf buf
= STRBUF_INIT
;
166 while (strbuf_getline(&buf
, stdin
, '\n') != EOF
) {
167 int error
= batch_one_object(buf
.buf
, print_contents
);
175 static const char * const cat_file_usage
[] = {
176 N_("git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"),
177 N_("git cat-file (--batch|--batch-check) < <list_of_objects>"),
181 static int git_cat_file_config(const char *var
, const char *value
, void *cb
)
183 if (userdiff_config(var
, value
) < 0)
186 return git_default_config(var
, value
, cb
);
189 int cmd_cat_file(int argc
, const char **argv
, const char *prefix
)
191 int opt
= 0, batch
= 0;
192 const char *exp_type
= NULL
, *obj_name
= NULL
;
194 const struct option options
[] = {
195 OPT_GROUP(N_("<type> can be one of: blob, tree, commit, tag")),
196 OPT_SET_INT('t', NULL
, &opt
, N_("show object type"), 't'),
197 OPT_SET_INT('s', NULL
, &opt
, N_("show object size"), 's'),
198 OPT_SET_INT('e', NULL
, &opt
,
199 N_("exit with zero when there's no error"), 'e'),
200 OPT_SET_INT('p', NULL
, &opt
, N_("pretty-print object's content"), 'p'),
201 OPT_SET_INT(0, "textconv", &opt
,
202 N_("for blob objects, run textconv on object's content"), 'c'),
203 OPT_SET_INT(0, "batch", &batch
,
204 N_("show info and content of objects fed from the standard input"),
206 OPT_SET_INT(0, "batch-check", &batch
,
207 N_("show info about objects fed from the standard input"),
212 git_config(git_cat_file_config
, NULL
);
214 if (argc
!= 3 && argc
!= 2)
215 usage_with_options(cat_file_usage
, options
);
217 argc
= parse_options(argc
, argv
, prefix
, options
, cat_file_usage
, 0);
223 usage_with_options(cat_file_usage
, options
);
225 if (!opt
&& !batch
) {
230 usage_with_options(cat_file_usage
, options
);
232 if (batch
&& (opt
|| argc
)) {
233 usage_with_options(cat_file_usage
, options
);
237 return batch_objects(batch
);
239 return cat_one_file(opt
, exp_type
, obj_name
);