6145ee8b36
This changes the way how pathspec is used in the three diff-* brothers. Earlier, they tried to grab as much information from the original input and used pathspec to limit the output. This version uses pathspec upfront to narrow the world diffcore operates in, so "git-diff-* <arguments> some-directory" does not look at things outside the specified subtree when finding rename/copy or running pickaxe. Since diff-tree already takes this view and does not feed anything outside the specified directotires to begin with, this patch does not have to touch that command. Signed-off-by: Junio C Hamano <junkio@cox.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
146 lines
3.0 KiB
C
146 lines
3.0 KiB
C
/*
|
|
* Copyright (C) 2005 Junio C Hamano
|
|
*/
|
|
#include "cache.h"
|
|
#include "strbuf.h"
|
|
#include "diff.h"
|
|
|
|
static const char *pickaxe = NULL;
|
|
static int pickaxe_opts = 0;
|
|
static int line_termination = '\n';
|
|
static int inter_name_termination = '\t';
|
|
|
|
static const char *diff_helper_usage =
|
|
"git-diff-helper [-z] [-S<string>] paths...";
|
|
|
|
int main(int ac, const char **av) {
|
|
struct strbuf sb;
|
|
|
|
strbuf_init(&sb);
|
|
|
|
while (1 < ac && av[1][0] == '-') {
|
|
if (av[1][1] == 'z')
|
|
line_termination = inter_name_termination = 0;
|
|
else if (av[1][1] == 'S') {
|
|
pickaxe = av[1] + 2;
|
|
}
|
|
else if (!strcmp(av[1], "--pickaxe-all"))
|
|
pickaxe_opts = DIFF_PICKAXE_ALL;
|
|
else
|
|
usage(diff_helper_usage);
|
|
ac--; av++;
|
|
}
|
|
/* the remaining parameters are paths patterns */
|
|
|
|
diff_setup(0);
|
|
while (1) {
|
|
unsigned old_mode, new_mode;
|
|
unsigned char old_sha1[20], new_sha1[20];
|
|
char old_path[PATH_MAX];
|
|
int status, score, two_paths;
|
|
char new_path[PATH_MAX];
|
|
|
|
int ch;
|
|
char *cp, *ep;
|
|
|
|
read_line(&sb, stdin, line_termination);
|
|
if (sb.eof)
|
|
break;
|
|
switch (sb.buf[0]) {
|
|
case ':':
|
|
/* parse the first part up to the status */
|
|
cp = sb.buf + 1;
|
|
old_mode = new_mode = 0;
|
|
while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
|
|
old_mode = (old_mode << 3) | (ch - '0');
|
|
cp++;
|
|
}
|
|
if (*cp++ != ' ')
|
|
break;
|
|
while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
|
|
new_mode = (new_mode << 3) | (ch - '0');
|
|
cp++;
|
|
}
|
|
if (*cp++ != ' ')
|
|
break;
|
|
if (get_sha1_hex(cp, old_sha1))
|
|
break;
|
|
cp += 40;
|
|
if (*cp++ != ' ')
|
|
break;
|
|
if (get_sha1_hex(cp, new_sha1))
|
|
break;
|
|
cp += 40;
|
|
if (*cp++ != ' ')
|
|
break;
|
|
status = *cp++;
|
|
if (!strchr("MCRNDU", status))
|
|
break;
|
|
two_paths = score = 0;
|
|
if (status == 'R' || status == 'C') {
|
|
two_paths = 1;
|
|
sscanf(cp, "%d", &score);
|
|
if (line_termination) {
|
|
cp = strchr(cp,
|
|
inter_name_termination);
|
|
if (!cp)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*cp++ != inter_name_termination)
|
|
break;
|
|
|
|
/* first pathname */
|
|
if (!line_termination) {
|
|
read_line(&sb, stdin, line_termination);
|
|
if (sb.eof)
|
|
break;
|
|
strcpy(old_path, sb.buf);
|
|
}
|
|
else if (!two_paths)
|
|
strcpy(old_path, cp);
|
|
else {
|
|
ep = strchr(cp, inter_name_termination);
|
|
if (!ep)
|
|
break;
|
|
strncpy(old_path, cp, ep-cp);
|
|
old_path[ep-cp] = 0;
|
|
cp = ep + 1;
|
|
}
|
|
|
|
/* second pathname */
|
|
if (!two_paths)
|
|
strcpy(new_path, old_path);
|
|
else {
|
|
if (!line_termination) {
|
|
read_line(&sb, stdin,
|
|
line_termination);
|
|
if (sb.eof)
|
|
break;
|
|
strcpy(new_path, sb.buf);
|
|
}
|
|
else
|
|
strcpy(new_path, cp);
|
|
}
|
|
diff_helper_input(old_mode, new_mode,
|
|
old_sha1, new_sha1,
|
|
old_path, status, score,
|
|
new_path);
|
|
continue;
|
|
}
|
|
if (1 < ac)
|
|
diffcore_pathspec(av + 1);
|
|
if (pickaxe)
|
|
diffcore_pickaxe(pickaxe, pickaxe_opts);
|
|
diff_flush(DIFF_FORMAT_PATCH, 0);
|
|
printf("%s\n", sb.buf);
|
|
}
|
|
if (1 < ac)
|
|
diffcore_pathspec(av + 1);
|
|
if (pickaxe)
|
|
diffcore_pickaxe(pickaxe, pickaxe_opts);
|
|
diff_flush(DIFF_FORMAT_PATCH, 0);
|
|
return 0;
|
|
}
|