You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.7 KiB
106 lines
2.7 KiB
#include "cache.h" |
|
#include "diff.h" |
|
|
|
static char *diff_cmd = "diff -L 'k/%s' -L 'l/%s' "; |
|
static char *diff_opts = "-p -u"; |
|
static char *diff_arg_forward = " - '%s'"; |
|
static char *diff_arg_reverse = " '%s' -"; |
|
|
|
void prepare_diff_cmd(void) |
|
{ |
|
/* |
|
* Default values above are meant to match the |
|
* Linux kernel development style. Examples of |
|
* alternative styles you can specify via environment |
|
* variables are: |
|
* |
|
* GIT_DIFF_CMD="diff -L '%s' -L '%s'" |
|
* GIT_DIFF_OPTS="-c"; |
|
*/ |
|
diff_cmd = getenv("GIT_DIFF_CMD") ? : diff_cmd; |
|
diff_opts = getenv("GIT_DIFF_OPTS") ? : diff_opts; |
|
} |
|
|
|
/* Help to copy the thing properly quoted for the shell safety. |
|
* any single quote is replaced with '\'', and the caller is |
|
* expected to enclose the result within a single quote pair. |
|
* |
|
* E.g. |
|
* original sq_expand result |
|
* name ==> name ==> 'name' |
|
* a b ==> a b ==> 'a b' |
|
* a'b ==> a'\''b ==> 'a'\''b' |
|
*/ |
|
static char *sq_expand(const char *src) |
|
{ |
|
static char *buf = NULL; |
|
int cnt, c; |
|
const char *cp; |
|
char *bp; |
|
|
|
/* count bytes needed to store the quoted string. */ |
|
for (cnt = 1, cp = src; *cp; cnt++, cp++) |
|
if (*cp == '\'') |
|
cnt += 3; |
|
|
|
if (! (buf = malloc(cnt))) |
|
return buf; |
|
bp = buf; |
|
while ((c = *src++)) { |
|
if (c != '\'') |
|
*bp++ = c; |
|
else { |
|
bp = strcpy(bp, "'\\''"); |
|
bp += 4; |
|
} |
|
} |
|
*bp = 0; |
|
return buf; |
|
} |
|
|
|
void show_differences(const char *name, /* filename on the filesystem */ |
|
const char *label, /* diff label to use */ |
|
void *old_contents, /* contents in core */ |
|
unsigned long long old_size, /* size in core */ |
|
int reverse /* 0: diff core file |
|
1: diff file core */) |
|
{ |
|
FILE *f; |
|
char *name_sq = sq_expand(name); |
|
const char *label_sq = (name != label) ? sq_expand(label) : name_sq; |
|
char *diff_arg = reverse ? diff_arg_reverse : diff_arg_forward; |
|
int cmd_size = strlen(name_sq) + strlen(label_sq) * 2 + |
|
strlen(diff_cmd) + strlen(diff_opts) + strlen(diff_arg); |
|
char *cmd = malloc(cmd_size); |
|
int next_at; |
|
|
|
fflush(stdout); |
|
next_at = snprintf(cmd, cmd_size, diff_cmd, label_sq, label_sq); |
|
next_at += snprintf(cmd+next_at, cmd_size-next_at, "%s", diff_opts); |
|
next_at += snprintf(cmd+next_at, cmd_size-next_at, diff_arg, name_sq); |
|
f = popen(cmd, "w"); |
|
if (old_size) |
|
fwrite(old_contents, old_size, 1, f); |
|
pclose(f); |
|
if (label_sq != name_sq) |
|
free((void*)label_sq); /* constness */ |
|
free(name_sq); |
|
free(cmd); |
|
} |
|
|
|
void show_diff_empty(const unsigned char *sha1, |
|
const char *name, |
|
int reverse) |
|
{ |
|
char *old; |
|
unsigned long int size; |
|
unsigned char type[20]; |
|
|
|
old = read_sha1_file(sha1, type, &size); |
|
if (! old) { |
|
error("unable to read blob object for %s (%s)", name, |
|
sha1_to_hex(sha1)); |
|
return; |
|
} |
|
show_differences("/dev/null", name, old, size, reverse); |
|
}
|
|
|