diff options
Diffstat (limited to 'builtin/cat-file.c')
-rw-r--r-- | builtin/cat-file.c | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 41afaa534b..f8d81291b9 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -45,6 +45,14 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) case 'e': return !has_sha1_file(sha1); + case 'c': + if (!obj_context.path[0]) + die("git cat-file --textconv %s: <object> must be <sha1:path>", + obj_name); + + if (textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size)) + break; + case 'p': type = sha1_object_info(sha1, NULL); if (type < 0) @@ -67,16 +75,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) /* otherwise just spit out the data */ break; - case 'c': - if (!obj_context.path[0]) - die("git cat-file --textconv %s: <object> must be <sha1:path>", - obj_name); - - if (!textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size)) - die("git cat-file --textconv: unable to run textconv on %s", - obj_name); - break; - case 0: if (type_from_string(exp_type) == OBJ_BLOB) { unsigned char blob_sha1[20]; @@ -84,8 +82,9 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) enum object_type type; unsigned long size; char *buffer = read_sha1_file(sha1, &type, &size); - if (memcmp(buffer, "object ", 7) || - get_sha1_hex(buffer + 7, blob_sha1)) + const char *target; + if (!skip_prefix(buffer, "object ", &target) || + get_sha1_hex(target, blob_sha1)) die("%s not a valid tag", sha1_to_hex(sha1)); free(buffer); } else @@ -120,6 +119,7 @@ struct expand_data { unsigned long size; unsigned long disk_size; const char *rest; + unsigned char delta_base_sha1[20]; /* * If mark_query is true, we do not expand anything, but rather @@ -176,6 +176,11 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len, data->split_on_whitespace = 1; else if (data->rest) strbuf_addstr(sb, data->rest); + } else if (is_atom("deltabase", atom, len)) { + if (data->mark_query) + data->info.delta_base_sha1 = data->delta_base_sha1; + else + strbuf_addstr(sb, sha1_to_hex(data->delta_base_sha1)); } else die("unknown format element: %.*s", len, atom); } @@ -195,25 +200,28 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *data) return end - start + 1; } -static void print_object_or_die(int fd, const unsigned char *sha1, - enum object_type type, unsigned long size) +static void print_object_or_die(int fd, struct expand_data *data) { - if (type == OBJ_BLOB) { + const unsigned char *sha1 = data->sha1; + + assert(data->info.typep); + + if (data->type == OBJ_BLOB) { if (stream_blob_to_fd(fd, sha1, NULL, 0) < 0) die("unable to stream %s to stdout", sha1_to_hex(sha1)); } else { - enum object_type rtype; - unsigned long rsize; + enum object_type type; + unsigned long size; void *contents; - contents = read_sha1_file(sha1, &rtype, &rsize); + contents = read_sha1_file(sha1, &type, &size); if (!contents) die("object %s disappeared", sha1_to_hex(sha1)); - if (rtype != type) + if (type != data->type) die("object %s changed type!?", sha1_to_hex(sha1)); - if (rsize != size) - die("object %s change size!?", sha1_to_hex(sha1)); + if (data->info.sizep && size != data->size) + die("object %s changed size!?", sha1_to_hex(sha1)); write_or_die(fd, contents, size); free(contents); @@ -240,7 +248,7 @@ static int batch_one_object(const char *obj_name, struct batch_options *opt, return 0; } - if (sha1_object_info_extended(data->sha1, &data->info) < 0) { + if (sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) { printf("%s missing\n", obj_name); fflush(stdout); return 0; @@ -252,7 +260,7 @@ static int batch_one_object(const char *obj_name, struct batch_options *opt, strbuf_release(&buf); if (opt->print_contents) { - print_object_or_die(1, data->sha1, data->type, data->size); + print_object_or_die(1, data); write_or_die(1, "\n", 1); } return 0; @@ -262,6 +270,8 @@ static int batch_objects(struct batch_options *opt) { struct strbuf buf = STRBUF_INIT; struct expand_data data; + int save_warning; + int retval = 0; if (!opt->format) opt->format = "%(objectname) %(objecttype) %(objectsize)"; @@ -277,17 +287,23 @@ static int batch_objects(struct batch_options *opt) data.mark_query = 0; /* + * If we are printing out the object, then always fill in the type, + * since we will want to decide whether or not to stream. + */ + if (opt->print_contents) + data.info.typep = &data.type; + + /* * We are going to call get_sha1 on a potentially very large number of * objects. In most large cases, these will be actual object sha1s. The * cost to double-check that each one is not also a ref (just so we can * warn) ends up dwarfing the actual cost of the object lookups * themselves. We can work around it by just turning off the warning. */ + save_warning = warn_on_object_refname_ambiguity; warn_on_object_refname_ambiguity = 0; while (strbuf_getline(&buf, stdin, '\n') != EOF) { - int error; - if (data.split_on_whitespace) { /* * Split at first whitespace, tying off the beginning @@ -302,12 +318,14 @@ static int batch_objects(struct batch_options *opt) data.rest = p; } - error = batch_one_object(buf.buf, opt, &data); - if (error) - return error; + retval = batch_one_object(buf.buf, opt, &data); + if (retval) + break; } - return 0; + strbuf_release(&buf); + warn_on_object_refname_ambiguity = save_warning; + return retval; } static const char * const cat_file_usage[] = { |