From: Junio C Hamano Date: Wed, 21 Sep 2016 22:15:18 +0000 (-0700) Subject: Merge branch 'js/cat-file-filters' X-Git-Tag: v2.11.0-rc0~138 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/7889ed25ac709624446b0b4d887dd3633e81f44a?hp=--cc Merge branch 'js/cat-file-filters' Even though "git hash-objects", which is a tool to take an on-filesystem data stream and put it into the Git object store, allowed to perform the "outside-world-to-Git" conversions (e.g. end-of-line conversions and application of the clean-filter), and it had the feature on by default from very early days, its reverse operation "git cat-file", which takes an object from the Git object store and externalize for the consumption by the outside world, lacked an equivalent mechanism to run the "Git-to-outside-world" conversion. The command learned the "--filters" option to do so. * js/cat-file-filters: cat-file: support --textconv/--filters in batch mode cat-file --textconv/--filters: allow specifying the path separately cat-file: introduce the --filters option cat-file: fix a grammo in the man page --- 7889ed25ac709624446b0b4d887dd3633e81f44a diff --cc builtin/cat-file.c index 3ee9bc9ad1,59dea48dae..94e67ebb7e --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@@ -20,6 -21,30 +21,30 @@@ struct batch_options const char *format; }; + static const char *force_path; + + static int filter_object(const char *path, unsigned mode, - const unsigned char *sha1, ++ const struct object_id *oid, + char **buf, unsigned long *size) + { + enum object_type type; + - *buf = read_sha1_file(sha1, &type, size); ++ *buf = read_sha1_file(oid->hash, &type, size); + if (!*buf) + return error(_("cannot read object %s '%s'"), - sha1_to_hex(sha1), path); ++ oid_to_hex(oid), path); + if ((type == OBJ_BLOB) && S_ISREG(mode)) { + struct strbuf strbuf = STRBUF_INIT; + if (convert_to_working_tree(path, *buf, *size, &strbuf)) { + free(*buf); + *size = strbuf.len; + *buf = strbuf_detach(&strbuf, NULL); + } + } + + return 0; + } + static int cat_one_file(int opt, const char *exp_type, const char *obj_name, int unknown_type) { @@@ -35,9 -61,14 +61,14 @@@ if (unknown_type) flags |= LOOKUP_UNKNOWN_OBJECT; - if (get_sha1_with_context(obj_name, 0, sha1, &obj_context)) + if (get_sha1_with_context(obj_name, 0, oid.hash, &obj_context)) die("Not a valid object name %s", obj_name); + if (!path) + path = obj_context.path; + if (obj_context.mode == S_IFINVALID) + obj_context.mode = 0100644; + buf = NULL; switch (opt) { case 't': @@@ -59,14 -90,25 +90,24 @@@ return 0; case 'e': - return !has_sha1_file(sha1); + return !has_object_file(&oid); + case 'w': + if (!path[0]) + die("git cat-file --filters %s: must be " + "", obj_name); + + if (filter_object(path, obj_context.mode, - sha1, &buf, &size)) ++ &oid, &buf, &size)) + return -1; + break; + case 'c': - if (!obj_context.path[0]) + if (!path[0]) die("git cat-file --textconv %s: must be ", obj_name); - if (textconv_object(obj_context.path, obj_context.mode, &oid, 1, &buf, &size)) - if (textconv_object(path, obj_context.mode, - sha1, 1, &buf, &size)) ++ if (textconv_object(path, obj_context.mode, &oid, 1, &buf, &size)) break; case 'p': @@@ -240,8 -281,33 +281,33 @@@ static void print_object_or_die(struct if (data->type == OBJ_BLOB) { if (opt->buffer_output) fflush(stdout); - if (stream_blob_to_fd(1, oid, NULL, 0) < 0) + if (opt->cmdmode) { + char *contents; + unsigned long size; + + if (!data->rest) - die("missing path for '%s'", sha1_to_hex(sha1)); ++ die("missing path for '%s'", oid_to_hex(oid)); + + if (opt->cmdmode == 'w') { - if (filter_object(data->rest, 0100644, sha1, ++ if (filter_object(data->rest, 0100644, oid, + &contents, &size)) + die("could not convert '%s' %s", - sha1_to_hex(sha1), data->rest); ++ oid_to_hex(oid), data->rest); + } else if (opt->cmdmode == 'c') { + enum object_type type; - if (!textconv_object(data->rest, 0100644, sha1, ++ if (!textconv_object(data->rest, 0100644, oid, + 1, &contents, &size)) - contents = read_sha1_file(sha1, &type, ++ contents = read_sha1_file(oid->hash, &type, + &size); + if (!contents) + die("could not convert '%s' %s", - sha1_to_hex(sha1), data->rest); ++ oid_to_hex(oid), data->rest); + } else + die("BUG: invalid cmdmode: %c", opt->cmdmode); + batch_write(opt, contents, size); + free(contents); - } else if (stream_blob_to_fd(1, sha1, NULL, 0) < 0) - die("unable to stream %s to stdout", sha1_to_hex(sha1)); ++ } else if (stream_blob_to_fd(1, oid, NULL, 0) < 0) + die("unable to stream %s to stdout", oid_to_hex(oid)); } else { enum object_type type; @@@ -442,8 -509,8 +510,8 @@@ static int batch_objects(struct batch_o } static const char * const cat_file_usage[] = { - N_("git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | | --textconv) "), - N_("git cat-file (--batch | --batch-check) [--follow-symlinks]"), - N_("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p||--textconv|--filters) [--path=] "), - N_("git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv|--filters]"), ++ N_("git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | | --textconv | --filters) [--path=] "), ++ N_("git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv | --filters]"), NULL };