X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=diff.c;h=65110333f2a71b0f4ff13094b431380089b79ffe;hb=c983370e5e208cca4deda82184478ba445a156e6;hp=c064e10580d5e1f7185f3f32ee19319292f6b43d;hpb=2f97813870c73a89b673ea7882f2a078d25c2dcd;p=git.git diff --git a/diff.c b/diff.c index c064e105..65110333 100644 --- a/diff.c +++ b/diff.c @@ -3,6 +3,7 @@ */ #include #include +#include #include "cache.h" #include "diff.h" @@ -81,35 +82,32 @@ static void builtin_diff(const char *name, struct diff_tempfile *temp) { int i, next_at; - const char *diff_cmd = "diff -L'%s%s%s' -L'%s%s%s'"; + const char *diff_cmd = "diff -L'%s%s' -L'%s%s'"; const char *diff_arg = "'%s' '%s'"; const char *input_name_sq[2]; const char *path0[2]; const char *path1[2]; - char mode[2][20]; const char *name_sq = sq_expand(name); char *cmd; - /* diff_cmd and diff_arg have 8 %s in total which makes - * the sum of these strings 16 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 - * terminating NUL, so we subtract 13 here. + * terminating NUL, so we subtract 9 here. */ int cmd_size = (strlen(diff_cmd) + strlen(diff_opts) + - strlen(diff_arg) - 13); + strlen(diff_arg) - 9); for (i = 0; i < 2; i++) { input_name_sq[i] = sq_expand(temp[i].name); if (!strcmp(temp[i].name, "/dev/null")) { path0[i] = "/dev/null"; path1[i] = ""; - mode[i][0] = 0; } else { path0[i] = i ? "l/" : "k/"; path1[i] = name_sq; - sprintf(mode[i], " (mode:%s)", temp[i].mode); } cmd_size += (strlen(path0[i]) + strlen(path1[i]) + - strlen(mode[i]) + strlen(input_name_sq[i])); + strlen(input_name_sq[i])); } cmd = xmalloc(cmd_size); @@ -117,13 +115,20 @@ static void builtin_diff(const char *name, next_at = 0; next_at += snprintf(cmd+next_at, cmd_size-next_at, diff_cmd, - path0[0], path1[0], mode[0], - path0[1], path1[1], mode[1]); + path0[0], path1[0], path0[1], path1[1]); 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, input_name_sq[0], input_name_sq[1]); + if (!path1[0][0]) + printf("Created: %s (mode:%s)\n", name, temp[1].mode); + else if (!path1[1][0]) + printf("Deleted: %s\n", name); + else if (strcmp(temp[0].mode, temp[1].mode)) + printf("Mode changed: %s (%s->%s)\n", name, + temp[0].mode, temp[1].mode); + fflush(NULL); execlp("/bin/sh","sh", "-c", cmd, NULL); } @@ -135,6 +140,9 @@ static void prepare_temp_file(const char *name, if (!one->file_valid) { not_a_valid_file: + /* A '-' entry produces this for file-2, and + * a '+' entry produces this for file-1. + */ temp->name = "/dev/null"; strcpy(temp->hex, "."); strcpy(temp->mode, "."); @@ -155,7 +163,7 @@ static void prepare_temp_file(const char *name, goto not_a_valid_file; die("stat(%s): %s", temp->name, strerror(errno)); } - strcpy(temp->hex, "."); + strcpy(temp->hex, sha1_to_hex(null_sha1)); sprintf(temp->mode, "%06o", S_IFREG |ce_permissions(st.st_mode)); } @@ -196,6 +204,11 @@ static void remove_tempfile(void) } } +static void remove_tempfile_on_signal(int signo) +{ + remove_tempfile(); +} + /* An external diff command takes: * * diff-cmd name infile1 infile1-sha1 infile1-mode \ @@ -207,7 +220,8 @@ void run_external_diff(const char *name, struct diff_spec *two) { struct diff_tempfile *temp = diff_temp; - int pid, status; + pid_t pid; + int status; static int atexit_asked = 0; if (one && two) { @@ -219,6 +233,7 @@ void run_external_diff(const char *name, atexit_asked = 1; atexit(remove_tempfile); } + signal(SIGINT, remove_tempfile_on_signal); } fflush(NULL); @@ -246,9 +261,17 @@ void run_external_diff(const char *name, printf("* Unmerged path %s\n", name); exit(0); } - if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status)) - die("diff program failed"); - + if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status)) { + /* We do not check the exit status because typically + * diff exits non-zero if files are different, and + * we are not interested in knowing that. We *knew* + * they are different and that's why we ran diff + * in the first place! However if it dies by a signal, + * we stop processing immediately. + */ + remove_tempfile(); + die("external diff died unexpectedly.\n"); + } remove_tempfile(); }