mirror of
https://github.com/git/git.git
synced 2024-11-24 18:33:43 +08:00
b46f0b6dfd
This patch optimizes "diff-cache -p --cached" by avoiding to inflate blobs into temporary files when the blob recorded in the cache matches the corresponding file in the work tree. The file in the work tree is passed as the comparison source in such a case instead. This optimization kicks in only when we have already read the cache this optimization and this is deliberate. Especially, diff-tree does not use this code, because changes are contained in small number of files relative to the project size most of the time, and reading cache is so expensive for a large project that the cost of reading it outweighs the savings by not inflating blobs. Also this patch cleans up the structure passed from diff clients by removing one unused structure member. Signed-off-by: Junio C Hamano <junkio@cox.net>
143 lines
2.8 KiB
C
143 lines
2.8 KiB
C
/*
|
|
* Copyright (C) 2005 Junio C Hamano
|
|
*/
|
|
#include "cache.h"
|
|
#include "strbuf.h"
|
|
#include "diff.h"
|
|
|
|
static int matches_pathspec(const char *name, const char **spec, int cnt)
|
|
{
|
|
int i;
|
|
int namelen = strlen(name);
|
|
for (i = 0; i < cnt; i++) {
|
|
int speclen = strlen(spec[i]);
|
|
if (! strncmp(spec[i], name, speclen) &&
|
|
speclen <= namelen &&
|
|
(name[speclen] == 0 ||
|
|
name[speclen] == '/'))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int parse_oneside_change(const char *cp, struct diff_spec *one,
|
|
char *path)
|
|
{
|
|
int ch;
|
|
|
|
one->file_valid = one->sha1_valid = 1;
|
|
one->mode = 0;
|
|
while ((ch = *cp) && '0' <= ch && ch <= '7') {
|
|
one->mode = (one->mode << 3) | (ch - '0');
|
|
cp++;
|
|
}
|
|
|
|
if (strncmp(cp, "\tblob\t", 6))
|
|
return -1;
|
|
cp += 6;
|
|
if (get_sha1_hex(cp, one->blob_sha1))
|
|
return -1;
|
|
cp += 40;
|
|
if (*cp++ != '\t')
|
|
return -1;
|
|
strcpy(path, cp);
|
|
return 0;
|
|
}
|
|
|
|
static int parse_diff_tree_output(const char *buf,
|
|
const char **spec, int cnt, int reverse)
|
|
{
|
|
struct diff_spec old, new;
|
|
char path[PATH_MAX];
|
|
const char *cp = buf;
|
|
int ch;
|
|
|
|
switch (*cp++) {
|
|
case 'U':
|
|
if (!cnt || matches_pathspec(cp + 1, spec, cnt))
|
|
diff_unmerge(cp + 1);
|
|
return 0;
|
|
case '+':
|
|
old.file_valid = 0;
|
|
parse_oneside_change(cp, &new, path);
|
|
break;
|
|
case '-':
|
|
new.file_valid = 0;
|
|
parse_oneside_change(cp, &old, path);
|
|
break;
|
|
case '*':
|
|
old.file_valid = old.sha1_valid =
|
|
new.file_valid = new.sha1_valid = 1;
|
|
old.mode = new.mode = 0;
|
|
while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
|
|
old.mode = (old.mode << 3) | (ch - '0');
|
|
cp++;
|
|
}
|
|
if (strncmp(cp, "->", 2))
|
|
return -1;
|
|
cp += 2;
|
|
while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
|
|
new.mode = (new.mode << 3) | (ch - '0');
|
|
cp++;
|
|
}
|
|
if (strncmp(cp, "\tblob\t", 6))
|
|
return -1;
|
|
cp += 6;
|
|
if (get_sha1_hex(cp, old.blob_sha1))
|
|
return -1;
|
|
cp += 40;
|
|
if (strncmp(cp, "->", 2))
|
|
return -1;
|
|
cp += 2;
|
|
if (get_sha1_hex(cp, new.blob_sha1))
|
|
return -1;
|
|
cp += 40;
|
|
if (*cp++ != '\t')
|
|
return -1;
|
|
strcpy(path, cp);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
if (!cnt || matches_pathspec(path, spec, cnt)) {
|
|
if (reverse)
|
|
run_external_diff(path, &new, &old);
|
|
else
|
|
run_external_diff(path, &old, &new);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static const char *diff_tree_helper_usage =
|
|
"diff-tree-helper [-R] [-z] paths...";
|
|
|
|
int main(int ac, const char **av) {
|
|
struct strbuf sb;
|
|
int reverse = 0;
|
|
int line_termination = '\n';
|
|
|
|
strbuf_init(&sb);
|
|
|
|
while (1 < ac && av[1][0] == '-') {
|
|
if (av[1][1] == 'R')
|
|
reverse = 1;
|
|
else if (av[1][1] == 'z')
|
|
line_termination = 0;
|
|
else
|
|
usage(diff_tree_helper_usage);
|
|
ac--; av++;
|
|
}
|
|
/* the remaining parameters are paths patterns */
|
|
|
|
while (1) {
|
|
int status;
|
|
read_line(&sb, stdin, line_termination);
|
|
if (sb.eof)
|
|
break;
|
|
status = parse_diff_tree_output(sb.buf, av+1, ac-1, reverse);
|
|
if (status)
|
|
fprintf(stderr, "cannot parse %s\n", sb.buf);
|
|
}
|
|
return 0;
|
|
}
|