@@ -10,6 +10,7 @@ SYNOPSIS
--------
[verse]
'git diff-blob' <blob> <blob>
+'git diff-blob' --stdin
DESCRIPTION
-----------
@@ -20,6 +21,11 @@ OPTIONS
<blob>::
The id of a blob object or path-scoped revision that resolves to a blob.
+--stdin::
+ When `--stdin` is specified, the command does not take <blob> arguments
+ from the command line. Instead, it reads lines containing two <blob>
+ from its standard input. (Use a single space as separator.)
+
include::pretty-formats.txt[]
include::diff-format.txt[]
@@ -4,9 +4,12 @@
#include "diffcore.h"
#include "gettext.h"
#include "hash.h"
+#include "object-name.h"
#include "object.h"
#include "parse-options.h"
#include "revision.h"
+#include "strbuf.h"
+#include "string-list.h"
static void diff_blobs(struct object_array_entry *old_blob,
struct object_array_entry *new_blob,
@@ -59,18 +62,66 @@ static void diff_blobs(struct object_array_entry *old_blob,
diff_flush(opts);
}
+static void parse_blob_stdin(struct object_array *blob_pair,
+ struct repository *repo, const char *name)
+{
+ int flags = GET_OID_BLOB | GET_OID_RECORD_PATH;
+ struct object_context oc;
+ struct object_id oid;
+ struct object *obj;
+
+ if (get_oid_with_context(repo, name, flags, &oid, &oc))
+ die("invalid object %s given", name);
+
+ obj = parse_object_or_die(&oid, name);
+ if (obj->type != OBJ_BLOB)
+ die("object %s is not a blob", name);
+
+ add_object_array_with_path(obj, name, blob_pair, oc.mode, oc.path);
+ object_context_release(&oc);
+}
+
+static void diff_blob_stdin(struct repository *repo, struct diff_options *opts)
+{
+ struct strbuf sb = STRBUF_INIT;
+ struct string_list_item *item;
+
+ while (strbuf_getline(&sb, stdin) != EOF) {
+ struct object_array blob_pair = OBJECT_ARRAY_INIT;
+ struct string_list list = STRING_LIST_INIT_NODUP;
+
+ if (string_list_split_in_place(&list, sb.buf, " ", -1) != 2)
+ die("two blobs not provided");
+
+ for_each_string_list_item(item, &list) {
+ parse_blob_stdin(&blob_pair, repo, item->string);
+ }
+
+ diff_blobs(&blob_pair.objects[0], &blob_pair.objects[1], opts);
+
+ string_list_clear(&list, 1);
+ object_array_clear(&blob_pair);
+ }
+
+ strbuf_release(&sb);
+}
+
int cmd_diff_blob(int argc, const char **argv, const char *prefix,
struct repository *repo)
{
struct object_array_entry *old_blob, *new_blob;
struct rev_info revs;
+ int read_stdin = 0;
int ret;
const char * const usage[] = {
N_("git diff-blob <blob> <blob>"),
+ N_("git diff-blob --stdin"),
NULL
};
struct option options[] = {
+ OPT_BOOL(0, "stdin", &read_stdin,
+ N_("read blob pairs from stdin")),
OPT_END()
};
@@ -93,7 +144,20 @@ int cmd_diff_blob(int argc, const char **argv, const char *prefix,
revs.diffopt.output_format = DIFF_FORMAT_PATCH;
switch (revs.pending.nr) {
+ case 0:
+ if (!read_stdin)
+ usage_with_options(usage, options);
+
+ revs.diffopt.no_free = 1;
+ diff_blob_stdin(repo, &revs.diffopt);
+ revs.diffopt.no_free = 0;
+ diff_free(&revs.diffopt);
+
+ break;
case 2:
+ if (read_stdin)
+ usage_with_options(usage, options);
+
old_blob = &revs.pending.objects[0];
new_blob = &revs.pending.objects[1];
@@ -98,4 +98,18 @@ for cmd in $commands; do
'
done
+test_expect_success 'diff-blob --stdin with blob ID' '
+ echo $sha1_one $sha1_two | git diff-blob --full-index --stdin >diff &&
+ check_index $sha1_one $sha1_two &&
+ check_paths $sha1_one $sha1_two &&
+ ! grep mode diff
+'
+
+test_expect_success 'diff-blob --stdin with revision' '
+ echo HEAD:one HEAD:two | git diff-blob --full-index --stdin >diff &&
+ check_index $sha1_one $sha1_two &&
+ check_paths one two &&
+ check_mode 100644 100755
+'
+
test_done
There is not a way to generate multiple blob diffs from a single process. Similar to git-diff-tree(1) with its "--stdin" option, it would be useful if multiple blob pairs could be provided to git-diff-blob(1) to compute blob diffs for. Teach git-diff-blob(1) the "--stdin" option to allow a pair of blobs to be read from each line of stdin instead of relying on the single blob pair provided as arguments. When this option is specified, each valid line of input computes a blob diff thus allowing multiple blob diffs in a single process. A blob may be specified by its ID or a path-scoped revision that resolve to a blob. When a path-scoped revision is used, path and mode information is also extracted and presented in the resulting diff header. Signed-off-by: Justin Tobler <jltobler@gmail.com> --- Documentation/git-diff-blob.txt | 6 ++++ builtin/diff-blob.c | 64 +++++++++++++++++++++++++++++++++ t/t4063-diff-blobs.sh | 14 ++++++++ 3 files changed, 84 insertions(+)