summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2017-11-13 15:37:50 +0900
committerJunio C Hamano <gitster@pobox.com>2017-11-14 09:48:01 +0900
commit5b877eb77530f92d7f4e4dc3fcc30b5788cc8622 (patch)
treed3a47f11a8c97319f6d875c602ba9443e43fed59
parentd8df70f2739af78cab6d7f9b942e890da6fbd01d (diff)
downloadgit-jc/diff-blobfind.tar.gz
-rw-r--r--Makefile1
-rw-r--r--diff.c20
-rw-r--r--diff.h3
-rw-r--r--diffcore-blobfind.c31
-rw-r--r--diffcore.h1
5 files changed, 55 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index ee9d5eb11e..fdfa8f38f6 100644
--- a/Makefile
+++ b/Makefile
@@ -775,6 +775,7 @@ LIB_OBJS += date.o
LIB_OBJS += decorate.o
LIB_OBJS += diffcore-break.o
LIB_OBJS += diffcore-delta.o
+LIB_OBJS += diffcore-blobfind.o
LIB_OBJS += diffcore-order.o
LIB_OBJS += diffcore-pickaxe.o
LIB_OBJS += diffcore-rename.o
diff --git a/diff.c b/diff.c
index 0763e89263..8861f89ab1 100644
--- a/diff.c
+++ b/diff.c
@@ -4082,6 +4082,7 @@ void diff_setup(struct diff_options *options)
options->interhunkcontext = diff_interhunk_context_default;
options->ws_error_highlight = ws_error_highlight_default;
options->flags.rename_empty = 1;
+ options->blobfind = NULL;
/* pathchange left =NULL by default */
options->change = diff_change;
@@ -4487,6 +4488,19 @@ static int parse_ws_error_highlight_opt(struct diff_options *opt, const char *ar
return 1;
}
+static int parse_blobfind_opt(struct diff_options *opt, const char *arg)
+{
+ struct object_id oid;
+
+ if (get_oid_blob(arg, &oid) || sha1_object_info(oid.hash, NULL) != OBJ_BLOB)
+ return error("object '%s' is not a blob", arg);
+
+ if (!opt->blobfind)
+ opt->blobfind = xcalloc(1, sizeof(*opt->blobfind));
+ oidset_insert(opt->blobfind, &oid);
+ return 1;
+}
+
int diff_opt_parse(struct diff_options *options,
const char **av, int ac, const char *prefix)
{
@@ -4736,7 +4750,8 @@ int diff_opt_parse(struct diff_options *options,
else if ((argcount = short_opt('O', av, &optarg))) {
options->orderfile = prefix_filename(prefix, optarg);
return argcount;
- }
+ } else if (skip_prefix(arg, "--blobfind=", &arg))
+ return parse_blobfind_opt(options, arg);
else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
int offending = parse_diff_filter_opt(optarg, options);
if (offending)
@@ -5770,6 +5785,9 @@ void diffcore_std(struct diff_options *options)
diffcore_skip_stat_unmatch(options);
if (!options->found_follow) {
/* See try_to_follow_renames() in tree-diff.c */
+
+ if (options->blobfind)
+ diffcore_blobfind(options);
if (options->break_opt != -1)
diffcore_break(options->break_opt);
if (options->detect_rename)
diff --git a/diff.h b/diff.h
index 0fb18dd735..9178e498fa 100644
--- a/diff.h
+++ b/diff.h
@@ -7,6 +7,7 @@
#include "tree-walk.h"
#include "pathspec.h"
#include "object.h"
+#include "oidset.h"
struct rev_info;
struct diff_options;
@@ -174,6 +175,8 @@ struct diff_options {
enum diff_words_type word_diff;
enum diff_submodule_format submodule_format;
+ struct oidset *blobfind;
+
/* this is set by diffcore for DIFF_FORMAT_PATCH */
int found_changes;
diff --git a/diffcore-blobfind.c b/diffcore-blobfind.c
new file mode 100644
index 0000000000..64bf6922b0
--- /dev/null
+++ b/diffcore-blobfind.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Google Inc.
+ */
+#include "cache.h"
+#include "diff.h"
+#include "diffcore.h"
+
+void diffcore_blobfind(struct diff_options *options)
+{
+ struct diff_queue_struct *q = &diff_queued_diff;
+ struct diff_queue_struct outq;
+ int i;
+
+ if (!options->blobfind)
+ BUG("blobfind oidset not initialized???");
+
+ DIFF_QUEUE_CLEAR(&outq);
+ for (i = 0; i < q->nr; i++) {
+ struct diff_filepair *p = q->queue[i];
+
+ if (!DIFF_PAIR_UNMERGED(p) &&
+ ((DIFF_FILE_VALID(p->one) &&
+ oidset_contains(options->blobfind, &p->one->oid)) ||
+ (DIFF_FILE_VALID(p->two) &&
+ oidset_contains(options->blobfind, &p->two->oid))))
+ diff_q(&outq, p);
+ else
+ diff_free_filepair(p);
+ }
+ *q = outq;
+}
diff --git a/diffcore.h b/diffcore.h
index a30da161da..431917672f 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -107,6 +107,7 @@ extern struct diff_filepair *diff_queue(struct diff_queue_struct *,
struct diff_filespec *);
extern void diff_q(struct diff_queue_struct *, struct diff_filepair *);
+extern void diffcore_blobfind(struct diff_options *);
extern void diffcore_break(int);
extern void diffcore_rename(struct diff_options *);
extern void diffcore_merge_broken(void);