Skip to content

Commit 52e9578

Browse files
Junio C HamanoLinus Torvalds
authored andcommitted
[PATCH] Introducing software archaeologist's tool "pickaxe".
This steals the "pickaxe" feature from JIT and make it available to the bare Plumbing layer. From the command line, the user gives a string he is intersted in. Using the diff-core infrastructure previously introduced, it filters the differences to limit the output only to the diffs between <src> and <dst> where the string appears only in one but not in the other. For example: $ ./git-rev-list HEAD | ./git-diff-tree -Sdiff-tree-helper --stdin -M would show the diffs that touch the string "diff-tree-helper". In real software-archaeologist application, you would typically look for a few to several lines of code and see where that code came from. The "pickaxe" module runs after "rename/copy detection" module, so it even crosses the file rename boundary, as the above example demonstrates. Signed-off-by: Junio C Hamano <junkio@cox.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
1 parent 427dcb4 commit 52e9578

File tree

14 files changed

+140
-51
lines changed

14 files changed

+140
-51
lines changed

Documentation/git-diff-cache.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-diff-cache - Compares content and mode of blobs between the cache and reposi
99

1010
SYNOPSIS
1111
--------
12-
'git-diff-cache' [-p] [-r] [-z] [-m] [-M] [-R] [-C] [--cached] <tree-ish>
12+
'git-diff-cache' [-p] [-r] [-z] [-m] [-M] [-R] [-C] [-S<string>] [--cached] <tree-ish>
1313

1414
DESCRIPTION
1515
-----------
@@ -39,6 +39,10 @@ OPTIONS
3939
-C::
4040
Detect copies as well as renames; implies -p.
4141

42+
-S<string>::
43+
Look for differences that contains the change in <string>.
44+
45+
4246
-R::
4347
Output diff in reverse.
4448

Documentation/git-diff-files.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-diff-files - Compares files in the working tree and the cache
99

1010
SYNOPSIS
1111
--------
12-
'git-diff-files' [-p] [-q] [-r] [-z] [-M] [-C] [-R] [<pattern>...]
12+
'git-diff-files' [-p] [-q] [-r] [-z] [-M] [-C] [-R] [-S<string>] [<pattern>...]
1313

1414
DESCRIPTION
1515
-----------
@@ -35,6 +35,10 @@ OPTIONS
3535
-C::
3636
Detect copies as well as renames; implies -p.
3737

38+
-S<string>::
39+
Look for differences that contains the change in <string>.
40+
41+
3842
-r::
3943
This flag does not mean anything. It is there only to match
4044
git-diff-tree. Unlike git-diff-tree, git-diff-files always looks

Documentation/git-diff-helper.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-diff-helper - Generates patch format output for git-diff-*
99

1010
SYNOPSIS
1111
--------
12-
'git-diff-helper' [-z] [-R] [-M] [-C]
12+
'git-diff-helper' [-z] [-R] [-M] [-C] [-S<string>]
1313

1414
DESCRIPTION
1515
-----------
@@ -37,6 +37,10 @@ OPTIONS
3737
-C::
3838
Detect copies as well as renames.
3939

40+
-S<string>::
41+
Look for differences that contains the change in <string>.
42+
43+
4044
See Also
4145
--------
4246
The section on generating patches in link:git-diff-cache.html[git-diff-cache]

Documentation/git-diff-tree.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-diff-tree - Compares the content and mode of blobs found via two tree object
99

1010
SYNOPSIS
1111
--------
12-
'git-diff-tree' [-p] [-r] [-z] [--stdin] [-M] [-R] [-C] [-m] [-s] [-v] <tree-ish> <tree-ish> [<pattern>]\*
12+
'git-diff-tree' [-p] [-r] [-z] [--stdin] [-M] [-R] [-C] [-S<string>] [-m] [-s] [-v] <tree-ish> <tree-ish> [<pattern>]\*
1313

1414
DESCRIPTION
1515
-----------
@@ -43,6 +43,9 @@ OPTIONS
4343
-R::
4444
Output diff in reverse.
4545

46+
-S<string>::
47+
Look for differences that contains the change in <string>.
48+
4649
-r::
4750
recurse
4851

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ LIB_H += strbuf.h
4545
LIB_OBJS += strbuf.o
4646

4747
LIB_H += diff.h
48-
LIB_OBJS += diff.o diffcore-rename.o
48+
LIB_OBJS += diff.o diffcore-rename.o diffcore-pickaxe.o
4949

5050
LIB_OBJS += gitenv.o
5151

@@ -125,6 +125,7 @@ strbuf.o: $(LIB_H)
125125
gitenv.o: $(LIB_H)
126126
diff.o: $(LIB_H)
127127
diffcore-rename.o : $(LIB_H)
128+
diffcore-pickaxe.o : $(LIB_H)
128129

129130
test: all
130131
make -C t/ all

diff-cache.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ static int line_termination = '\n';
88
static int detect_rename = 0;
99
static int reverse_diff = 0;
1010
static int diff_score_opt = 0;
11+
static char *pickaxe = 0;
1112

1213
/* A file entry went away or appeared */
1314
static void show_file(const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode)
@@ -153,7 +154,7 @@ static void mark_merge_entries(void)
153154
}
154155

155156
static char *diff_cache_usage =
156-
"git-diff-cache [-p] [-r] [-z] [-m] [-M] [-C] [-R] [--cached] <tree-ish>";
157+
"git-diff-cache [-p] [-r] [-z] [-m] [-M] [-C] [-R] [-S<string>] [--cached] <tree-ish>";
157158

158159
int main(int argc, char **argv)
159160
{
@@ -194,6 +195,10 @@ int main(int argc, char **argv)
194195
reverse_diff = 1;
195196
continue;
196197
}
198+
if (!strcmp(arg, "-S")) {
199+
pickaxe = arg + 2;
200+
continue;
201+
}
197202
if (!strcmp(arg, "-m")) {
198203
match_nonexisting = 1;
199204
continue;
@@ -208,8 +213,8 @@ int main(int argc, char **argv)
208213
if (argc != 2 || get_sha1(argv[1], tree_sha1))
209214
usage(diff_cache_usage);
210215

211-
diff_setup(detect_rename, diff_score_opt, reverse_diff,
212-
(generate_patch ? -1 : line_termination),
216+
diff_setup(detect_rename, diff_score_opt, pickaxe,
217+
reverse_diff, (generate_patch ? -1 : line_termination),
213218
NULL, 0);
214219

215220
mark_merge_entries();

diff-files.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
#include "diff.h"
88

99
static const char *diff_files_usage =
10-
"git-diff-files [-p] [-q] [-r] [-z] [-M] [-C] [-R] [paths...]";
10+
"git-diff-files [-p] [-q] [-r] [-z] [-M] [-C] [-R] [-S<string>] [paths...]";
1111

1212
static int generate_patch = 0;
1313
static int line_termination = '\n';
1414
static int detect_rename = 0;
1515
static int reverse_diff = 0;
1616
static int diff_score_opt = 0;
17+
static char *pickaxe = 0;
1718
static int silent = 0;
1819

1920
static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt)
@@ -67,6 +68,8 @@ int main(int argc, char **argv)
6768
line_termination = 0;
6869
else if (!strcmp(argv[1], "-R"))
6970
reverse_diff = 1;
71+
else if (!strcmp(argv[1], "-S"))
72+
pickaxe = argv[1] + 2;
7073
else if (!strncmp(argv[1], "-M", 2)) {
7174
diff_score_opt = diff_scoreopt_parse(argv[1]);
7275
detect_rename = generate_patch = 1;
@@ -89,8 +92,8 @@ int main(int argc, char **argv)
8992
exit(1);
9093
}
9194

92-
diff_setup(detect_rename, diff_score_opt, reverse_diff,
93-
(generate_patch ? -1 : line_termination),
95+
diff_setup(detect_rename, diff_score_opt, pickaxe,
96+
reverse_diff, (generate_patch ? -1 : line_termination),
9497
NULL, 0);
9598

9699
for (i = 0; i < entries; i++) {

diff-helper.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
static int detect_rename = 0;
1010
static int diff_score_opt = 0;
1111
static int generate_patch = 1;
12+
static char *pickaxe = 0;
1213

1314
static int parse_oneside_change(const char *cp, int *mode,
1415
unsigned char *sha1, char *path)
@@ -93,7 +94,7 @@ static int parse_diff_raw_output(const char *buf)
9394
}
9495

9596
static const char *diff_helper_usage =
96-
"git-diff-helper [-z] [-R] [-M] [-C] paths...";
97+
"git-diff-helper [-z] [-R] [-M] [-C] [-S<string>] paths...";
9798

9899
int main(int ac, const char **av) {
99100
struct strbuf sb;
@@ -117,14 +118,17 @@ int main(int ac, const char **av) {
117118
detect_rename = 2;
118119
diff_score_opt = diff_scoreopt_parse(av[1]);
119120
}
121+
else if (av[1][1] == 'S') {
122+
pickaxe = av[1] + 2;
123+
}
120124
else
121125
usage(diff_helper_usage);
122126
ac--; av++;
123127
}
124128
/* the remaining parameters are paths patterns */
125129

126-
diff_setup(detect_rename, diff_score_opt, reverse,
127-
(generate_patch ? -1 : line_termination),
130+
diff_setup(detect_rename, diff_score_opt, pickaxe,
131+
reverse, (generate_patch ? -1 : line_termination),
128132
av+1, ac-1);
129133

130134
while (1) {

diff-tree.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ static int generate_patch = 0;
1313
static int detect_rename = 0;
1414
static int reverse_diff = 0;
1515
static int diff_score_opt = 0;
16+
static char *pickaxe = 0;
1617
static const char *header = NULL;
1718
static const char *header_prefix = "";
1819

@@ -271,8 +272,8 @@ static int diff_tree_sha1_top(const unsigned char *old,
271272
{
272273
int ret;
273274

274-
diff_setup(detect_rename, diff_score_opt, reverse_diff,
275-
(generate_patch ? -1 : line_termination),
275+
diff_setup(detect_rename, diff_score_opt, pickaxe,
276+
reverse_diff, (generate_patch ? -1 : line_termination),
276277
NULL, 0);
277278
ret = diff_tree_sha1(old, new, base);
278279
diff_flush();
@@ -285,8 +286,8 @@ static int diff_root_tree(const unsigned char *new, const char *base)
285286
void *tree;
286287
unsigned long size;
287288

288-
diff_setup(detect_rename, diff_score_opt, reverse_diff,
289-
(generate_patch ? -1 : line_termination),
289+
diff_setup(detect_rename, diff_score_opt, pickaxe,
290+
reverse_diff, (generate_patch ? -1 : line_termination),
290291
NULL, 0);
291292
tree = read_object_with_reference(new, "tree", &size, NULL);
292293
if (!tree)
@@ -430,7 +431,7 @@ static int diff_tree_stdin(char *line)
430431
}
431432

432433
static char *diff_tree_usage =
433-
"git-diff-tree [-p] [-r] [-z] [--stdin] [-M] [-C] [-R] [-m] [-s] [-v] <tree-ish> <tree-ish>";
434+
"git-diff-tree [-p] [-r] [-z] [--stdin] [-M] [-C] [-R] [-S<string>] [-m] [-s] [-v] <tree-ish> <tree-ish>";
434435

435436
int main(int argc, char **argv)
436437
{
@@ -473,6 +474,10 @@ int main(int argc, char **argv)
473474
recursive = generate_patch = 1;
474475
continue;
475476
}
477+
if (!strncmp(arg, "-S", 2)) {
478+
pickaxe = arg + 2;
479+
continue;
480+
}
476481
if (!strncmp(arg, "-M", 2)) {
477482
detect_rename = recursive = generate_patch = 1;
478483
diff_score_opt = diff_scoreopt_parse(arg);

diff.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ static int reverse_diff;
1717
static int diff_raw_output = -1;
1818
static const char **pathspec;
1919
static int speccnt;
20+
static const char *pickaxe;
2021
static int minimum_score;
2122

2223
static const char *external_diff(void)
@@ -511,8 +512,9 @@ int diff_scoreopt_parse(const char *opt)
511512
return MAX_SCORE * num / scale;
512513
}
513514

514-
void diff_setup(int detect_rename_, int minimum_score_, int reverse_diff_,
515-
int diff_raw_output_,
515+
void diff_setup(int detect_rename_, int minimum_score_,
516+
char *pickaxe_,
517+
int reverse_diff_, int diff_raw_output_,
516518
const char **pathspec_, int speccnt_)
517519
{
518520
detect_rename = detect_rename_;
@@ -521,15 +523,16 @@ void diff_setup(int detect_rename_, int minimum_score_, int reverse_diff_,
521523
diff_raw_output = diff_raw_output_;
522524
speccnt = speccnt_;
523525
minimum_score = minimum_score_ ? : DEFAULT_MINIMUM_SCORE;
526+
pickaxe = pickaxe_;
524527
}
525528

526529
static struct diff_queue_struct queued_diff;
527530

528-
struct diff_file_pair *diff_queue(struct diff_queue_struct *queue,
531+
struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
529532
struct diff_filespec *one,
530533
struct diff_filespec *two)
531534
{
532-
struct diff_file_pair *dp = xmalloc(sizeof(*dp));
535+
struct diff_filepair *dp = xmalloc(sizeof(*dp));
533536
dp->one = one;
534537
dp->two = two;
535538
dp->xfrm_msg = 0;
@@ -549,7 +552,7 @@ static const char *git_object_type(unsigned mode)
549552
return S_ISDIR(mode) ? "tree" : "blob";
550553
}
551554

552-
static void diff_flush_raw(struct diff_file_pair *p)
555+
static void diff_flush_raw(struct diff_filepair *p)
553556
{
554557
struct diff_filespec *it;
555558
int addremove;
@@ -583,7 +586,7 @@ static void diff_flush_raw(struct diff_file_pair *p)
583586
sha1_to_hex(it->sha1), it->path, diff_raw_output);
584587
}
585588

586-
static void diff_flush_patch(struct diff_file_pair *p)
589+
static void diff_flush_patch(struct diff_filepair *p)
587590
{
588591
const char *name, *other;
589592

@@ -600,7 +603,7 @@ static int identical(struct diff_filespec *one, struct diff_filespec *two)
600603
{
601604
/* This function is written stricter than necessary to support
602605
* the currently implemented transformers, but the idea is to
603-
* let transformers to produce diff_file_pairs any way they want,
606+
* let transformers to produce diff_filepairs any way they want,
604607
* and filter and clean them up here before producing the output.
605608
*/
606609

@@ -623,7 +626,7 @@ static int identical(struct diff_filespec *one, struct diff_filespec *two)
623626
return 0;
624627
}
625628

626-
static void diff_flush_one(struct diff_file_pair *p)
629+
static void diff_flush_one(struct diff_filepair *p)
627630
{
628631
if (identical(p->one, p->two))
629632
return;
@@ -640,11 +643,13 @@ void diff_flush(void)
640643

641644
if (detect_rename)
642645
diff_detect_rename(q, detect_rename, minimum_score);
646+
if (pickaxe)
647+
diff_pickaxe(q, pickaxe);
643648
for (i = 0; i < q->nr; i++)
644649
diff_flush_one(q->queue[i]);
645650

646651
for (i = 0; i < q->nr; i++) {
647-
struct diff_file_pair *p = q->queue[i];
652+
struct diff_filepair *p = q->queue[i];
648653
diff_free_filespec_data(p->one);
649654
diff_free_filespec_data(p->two);
650655
free(p->xfrm_msg);

0 commit comments

Comments
 (0)