Browse Source
With this patch, the non-core'ish part of show-diff command that invokes an external "diff" comand to obtain patches is split into a separate file. The next patch will introduce a new command, diff-tree-helper, which uses this common diff interface to format diff-tree and diff-cache output into a patch form. Signed-off-by: Junio C Hamano <junkio@cox.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>maint
Junio C Hamano
20 years ago
committed by
Linus Torvalds
4 changed files with 130 additions and 98 deletions
@ -0,0 +1,106 @@
@@ -0,0 +1,106 @@
|
||||
#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); |
||||
} |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
#ifndef DIFF_H |
||||
#define DIFF_H |
||||
|
||||
extern void prepare_diff_cmd(void); |
||||
|
||||
extern 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 */); |
||||
|
||||
extern void show_diff_empty(const unsigned char *sha1, |
||||
const char *name, |
||||
int reverse); |
||||
|
||||
#endif /* DIFF_H */ |
Loading…
Reference in new issue