Update git-diff-* to use C-style quoting for funny pathnames.
Signed-off-by: Junio C Hamano <junkio@cox.net>maint
parent
caf4f582b2
commit
cf9dfc669e
135
diff.c
135
diff.c
|
@ -13,6 +13,46 @@ static const char *diff_opts = "-pu";
|
||||||
|
|
||||||
static int use_size_cache;
|
static int use_size_cache;
|
||||||
|
|
||||||
|
static char *quote_one(const char *str)
|
||||||
|
{
|
||||||
|
int needlen;
|
||||||
|
char *xp;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return NULL;
|
||||||
|
needlen = quote_c_style(str, NULL, NULL, 0);
|
||||||
|
if (!needlen)
|
||||||
|
return strdup(str);
|
||||||
|
xp = xmalloc(needlen + 1);
|
||||||
|
quote_c_style(str, xp, NULL, 0);
|
||||||
|
return xp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *quote_two(const char *one, const char *two)
|
||||||
|
{
|
||||||
|
int need_one = quote_c_style(one, NULL, NULL, 1);
|
||||||
|
int need_two = quote_c_style(two, NULL, NULL, 1);
|
||||||
|
char *xp;
|
||||||
|
|
||||||
|
if (need_one + need_two) {
|
||||||
|
if (!need_one) need_one = strlen(one);
|
||||||
|
if (!need_two) need_one = strlen(two);
|
||||||
|
|
||||||
|
xp = xmalloc(need_one + need_two + 3);
|
||||||
|
xp[0] = '"';
|
||||||
|
quote_c_style(one, xp + 1, NULL, 1);
|
||||||
|
quote_c_style(two, xp + need_one + 1, NULL, 1);
|
||||||
|
strcpy(xp + need_one + need_two + 1, "\"");
|
||||||
|
return xp;
|
||||||
|
}
|
||||||
|
need_one = strlen(one);
|
||||||
|
need_two = strlen(two);
|
||||||
|
xp = xmalloc(need_one + need_two + 1);
|
||||||
|
strcpy(xp, one);
|
||||||
|
strcpy(xp + need_one, two);
|
||||||
|
return xp;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *external_diff(void)
|
static const char *external_diff(void)
|
||||||
{
|
{
|
||||||
static const char *external_diff_cmd = NULL;
|
static const char *external_diff_cmd = NULL;
|
||||||
|
@ -133,55 +173,52 @@ static void builtin_diff(const char *name_a,
|
||||||
int complete_rewrite)
|
int complete_rewrite)
|
||||||
{
|
{
|
||||||
int i, next_at, cmd_size;
|
int i, next_at, cmd_size;
|
||||||
const char *const diff_cmd = "diff -L%s%s -L%s%s";
|
const char *const diff_cmd = "diff -L%s -L%s";
|
||||||
const char *const diff_arg = "%s %s||:"; /* "||:" is to return 0 */
|
const char *const diff_arg = "%s %s||:"; /* "||:" is to return 0 */
|
||||||
const char *input_name_sq[2];
|
const char *input_name_sq[2];
|
||||||
const char *path0[2];
|
const char *label_path[2];
|
||||||
const char *path1[2];
|
|
||||||
const char *name_sq[2];
|
|
||||||
char *cmd;
|
char *cmd;
|
||||||
|
|
||||||
name_sq[0] = sq_quote(name_a);
|
/* diff_cmd and diff_arg have 4 %s in total which makes
|
||||||
name_sq[1] = sq_quote(name_b);
|
* the sum of these strings 8 bytes larger than required.
|
||||||
|
|
||||||
/* diff_cmd and diff_arg have 6 %s in total which makes
|
|
||||||
* the sum of these strings 12 bytes larger than required.
|
|
||||||
* we use 2 spaces around diff-opts, and we need to count
|
* we use 2 spaces around diff-opts, and we need to count
|
||||||
* terminating NUL, so we subtract 9 here.
|
* terminating NUL; we used to subtract 5 here, but we do not
|
||||||
|
* care about small leaks in this subprocess that is about
|
||||||
|
* to exec "diff" anymore.
|
||||||
*/
|
*/
|
||||||
cmd_size = (strlen(diff_cmd) + strlen(diff_opts) +
|
cmd_size = (strlen(diff_cmd) + strlen(diff_opts) + strlen(diff_arg)
|
||||||
strlen(diff_arg) - 9);
|
+ 128);
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
input_name_sq[i] = sq_quote(temp[i].name);
|
input_name_sq[i] = sq_quote(temp[i].name);
|
||||||
if (!strcmp(temp[i].name, "/dev/null")) {
|
if (!strcmp(temp[i].name, "/dev/null"))
|
||||||
path0[i] = "/dev/null";
|
label_path[i] = "/dev/null";
|
||||||
path1[i] = "";
|
else if (!i)
|
||||||
} else {
|
label_path[i] = sq_quote(quote_two("a/", name_a));
|
||||||
path0[i] = i ? "b/" : "a/";
|
else
|
||||||
path1[i] = name_sq[i];
|
label_path[i] = sq_quote(quote_two("b/", name_b));
|
||||||
}
|
cmd_size += (strlen(label_path[i]) + strlen(input_name_sq[i]));
|
||||||
cmd_size += (strlen(path0[i]) + strlen(path1[i]) +
|
|
||||||
strlen(input_name_sq[i]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = xmalloc(cmd_size);
|
cmd = xmalloc(cmd_size);
|
||||||
|
|
||||||
next_at = 0;
|
next_at = 0;
|
||||||
next_at += snprintf(cmd+next_at, cmd_size-next_at,
|
next_at += snprintf(cmd+next_at, cmd_size-next_at,
|
||||||
diff_cmd,
|
diff_cmd, label_path[0], label_path[1]);
|
||||||
path0[0], path1[0], path0[1], path1[1]);
|
|
||||||
next_at += snprintf(cmd+next_at, cmd_size-next_at,
|
next_at += snprintf(cmd+next_at, cmd_size-next_at,
|
||||||
" %s ", diff_opts);
|
" %s ", diff_opts);
|
||||||
next_at += snprintf(cmd+next_at, cmd_size-next_at,
|
next_at += snprintf(cmd+next_at, cmd_size-next_at,
|
||||||
diff_arg, input_name_sq[0], input_name_sq[1]);
|
diff_arg, input_name_sq[0], input_name_sq[1]);
|
||||||
|
|
||||||
printf("diff --git a/%s b/%s\n", name_a, name_b);
|
printf("diff --git %s %s\n",
|
||||||
if (!path1[0][0]) {
|
quote_two("a/", name_a), quote_two("b/", name_b));
|
||||||
|
if (label_path[0][0] == '/') {
|
||||||
|
/* dev/null */
|
||||||
printf("new file mode %s\n", temp[1].mode);
|
printf("new file mode %s\n", temp[1].mode);
|
||||||
if (xfrm_msg && xfrm_msg[0])
|
if (xfrm_msg && xfrm_msg[0])
|
||||||
puts(xfrm_msg);
|
puts(xfrm_msg);
|
||||||
}
|
}
|
||||||
else if (!path1[1][0]) {
|
else if (label_path[1][0] == '/') {
|
||||||
printf("deleted file mode %s\n", temp[0].mode);
|
printf("deleted file mode %s\n", temp[0].mode);
|
||||||
if (xfrm_msg && xfrm_msg[0])
|
if (xfrm_msg && xfrm_msg[0])
|
||||||
puts(xfrm_msg);
|
puts(xfrm_msg);
|
||||||
|
@ -619,6 +656,7 @@ static void run_diff(struct diff_filepair *p)
|
||||||
struct diff_filespec *two;
|
struct diff_filespec *two;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *other;
|
const char *other;
|
||||||
|
char *name_munged, *other_munged;
|
||||||
int complete_rewrite = 0;
|
int complete_rewrite = 0;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -631,6 +669,8 @@ static void run_diff(struct diff_filepair *p)
|
||||||
|
|
||||||
name = p->one->path;
|
name = p->one->path;
|
||||||
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
|
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
|
||||||
|
name_munged = quote_one(name);
|
||||||
|
other_munged = quote_one(other);
|
||||||
one = p->one; two = p->two;
|
one = p->one; two = p->two;
|
||||||
|
|
||||||
diff_fill_sha1_info(one);
|
diff_fill_sha1_info(one);
|
||||||
|
@ -644,7 +684,7 @@ static void run_diff(struct diff_filepair *p)
|
||||||
"copy from %s\n"
|
"copy from %s\n"
|
||||||
"copy to %s\n",
|
"copy to %s\n",
|
||||||
(int)(0.5 + p->score * 100.0/MAX_SCORE),
|
(int)(0.5 + p->score * 100.0/MAX_SCORE),
|
||||||
name, other);
|
name_munged, other_munged);
|
||||||
break;
|
break;
|
||||||
case DIFF_STATUS_RENAMED:
|
case DIFF_STATUS_RENAMED:
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
len += snprintf(msg + len, sizeof(msg) - len,
|
||||||
|
@ -652,7 +692,7 @@ static void run_diff(struct diff_filepair *p)
|
||||||
"rename from %s\n"
|
"rename from %s\n"
|
||||||
"rename to %s\n",
|
"rename to %s\n",
|
||||||
(int)(0.5 + p->score * 100.0/MAX_SCORE),
|
(int)(0.5 + p->score * 100.0/MAX_SCORE),
|
||||||
name, other);
|
name_munged, other_munged);
|
||||||
break;
|
break;
|
||||||
case DIFF_STATUS_MODIFIED:
|
case DIFF_STATUS_MODIFIED:
|
||||||
if (p->score) {
|
if (p->score) {
|
||||||
|
@ -702,6 +742,9 @@ static void run_diff(struct diff_filepair *p)
|
||||||
else
|
else
|
||||||
run_external_diff(pgm, name, other, one, two, xfrm_msg,
|
run_external_diff(pgm, name, other, one, two, xfrm_msg,
|
||||||
complete_rewrite);
|
complete_rewrite);
|
||||||
|
|
||||||
|
free(name_munged);
|
||||||
|
free(other_munged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void diff_setup(struct diff_options *options)
|
void diff_setup(struct diff_options *options)
|
||||||
|
@ -878,16 +921,13 @@ static void diff_flush_raw(struct diff_filepair *p,
|
||||||
{
|
{
|
||||||
int two_paths;
|
int two_paths;
|
||||||
char status[10];
|
char status[10];
|
||||||
|
const char *path_one, *path_two;
|
||||||
|
|
||||||
|
path_one = p->one->path;
|
||||||
|
path_two = p->two->path;
|
||||||
if (line_termination) {
|
if (line_termination) {
|
||||||
const char *const err =
|
path_one = quote_one(path_one);
|
||||||
"path %s cannot be expressed without -z";
|
path_two = quote_one(path_two);
|
||||||
if (strchr(p->one->path, line_termination) ||
|
|
||||||
strchr(p->one->path, inter_name_termination))
|
|
||||||
die(err, p->one->path);
|
|
||||||
if (strchr(p->two->path, line_termination) ||
|
|
||||||
strchr(p->two->path, inter_name_termination))
|
|
||||||
die(err, p->two->path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->score)
|
if (p->score)
|
||||||
|
@ -915,16 +955,29 @@ static void diff_flush_raw(struct diff_filepair *p,
|
||||||
p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
|
p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
|
||||||
printf("%s ", sha1_to_hex(p->two->sha1));
|
printf("%s ", sha1_to_hex(p->two->sha1));
|
||||||
}
|
}
|
||||||
printf("%s%c%s",status, inter_name_termination, p->one->path);
|
printf("%s%c%s", status, inter_name_termination, path_one);
|
||||||
if (two_paths)
|
if (two_paths)
|
||||||
printf("%c%s", inter_name_termination, p->two->path);
|
printf("%c%s", inter_name_termination, path_two);
|
||||||
putchar(line_termination);
|
putchar(line_termination);
|
||||||
|
if (path_one != p->one->path)
|
||||||
|
free((void*)path_one);
|
||||||
|
if (path_two != p->two->path)
|
||||||
|
free((void*)path_two);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diff_flush_name(struct diff_filepair *p,
|
static void diff_flush_name(struct diff_filepair *p,
|
||||||
|
int inter_name_termination,
|
||||||
int line_termination)
|
int line_termination)
|
||||||
{
|
{
|
||||||
printf("%s%c", p->two->path, line_termination);
|
char *path = p->two->path;
|
||||||
|
|
||||||
|
if (line_termination)
|
||||||
|
path = quote_one(p->two->path);
|
||||||
|
else
|
||||||
|
path = p->two->path;
|
||||||
|
printf("%s%c", path, line_termination);
|
||||||
|
if (p->two->path != path)
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int diff_unmodified_pair(struct diff_filepair *p)
|
int diff_unmodified_pair(struct diff_filepair *p)
|
||||||
|
@ -1111,7 +1164,9 @@ void diff_flush(struct diff_options *options)
|
||||||
diff_output_format);
|
diff_output_format);
|
||||||
break;
|
break;
|
||||||
case DIFF_FORMAT_NAME:
|
case DIFF_FORMAT_NAME:
|
||||||
diff_flush_name(p, line_termination);
|
diff_flush_name(p,
|
||||||
|
inter_name_termination,
|
||||||
|
line_termination);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
diff_free_filepair(q->queue[i]);
|
diff_free_filepair(q->queue[i]);
|
||||||
|
|
Loading…
Reference in New Issue