aboutsummaryrefslogtreecommitdiff
path: root/diff.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2009-01-31 17:43:56 -0800
committerJunio C Hamano <gitster@pobox.com>2009-01-31 17:43:56 -0800
commitfa5bc8abb35e34f673c41cb5c66d0a2f21536861 (patch)
treee76e7f9d8d64db34f148f7ddfa6bca928c194d65 /diff.c
parent2edefe38a813deb4dfbd62dcf47520aeb1af15fc (diff)
parent0ea8039644968e53d79a8dfbf739c87af4261d46 (diff)
downloadgit-fa5bc8abb35e34f673c41cb5c66d0a2f21536861.tar.gz
git-fa5bc8abb35e34f673c41cb5c66d0a2f21536861.tar.xz
Merge branch 'jk/signal-cleanup'
* jk/signal-cleanup: t0005: use SIGTERM for sigchain test pager: do wait_for_pager on signal death refactor signal handling for cleanup functions chain kill signals for cleanup functions diff: refactor tempfile cleanup handling Windows: Fix signal numbers
Diffstat (limited to 'diff.c')
-rw-r--r--diff.c108
1 files changed, 56 insertions, 52 deletions
diff --git a/diff.c b/diff.c
index 972b3daa6..d8b1c22d5 100644
--- a/diff.c
+++ b/diff.c
@@ -12,6 +12,7 @@
#include "run-command.h"
#include "utf8.h"
#include "userdiff.h"
+#include "sigchain.h"
#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
@@ -170,6 +171,33 @@ static struct diff_tempfile {
char tmp_path[PATH_MAX];
} diff_temp[2];
+static struct diff_tempfile *claim_diff_tempfile(void) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
+ if (!diff_temp[i].name)
+ return diff_temp + i;
+ die("BUG: diff is failing to clean up its tempfiles");
+}
+
+static int remove_tempfile_installed;
+
+static void remove_tempfile(void)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
+ if (diff_temp[i].name == diff_temp[i].tmp_path) {
+ unlink(diff_temp[i].name);
+ diff_temp[i].name = NULL;
+ }
+}
+
+static void remove_tempfile_on_signal(int signo)
+{
+ remove_tempfile();
+ sigchain_pop(signo);
+ raise(signo);
+}
+
static int count_lines(const char *data, int size)
{
int count, ch, completely_empty = 1, nl_just_seen = 0;
@@ -1940,10 +1968,11 @@ static void prep_temp_blob(struct diff_tempfile *temp,
sprintf(temp->mode, "%06o", mode);
}
-static void prepare_temp_file(const char *name,
- struct diff_tempfile *temp,
- struct diff_filespec *one)
+static struct diff_tempfile *prepare_temp_file(const char *name,
+ struct diff_filespec *one)
{
+ struct diff_tempfile *temp = claim_diff_tempfile();
+
if (!DIFF_FILE_VALID(one)) {
not_a_valid_file:
/* A '-' entry produces this for file-2, and
@@ -1952,7 +1981,13 @@ static void prepare_temp_file(const char *name,
temp->name = "/dev/null";
strcpy(temp->hex, ".");
strcpy(temp->mode, ".");
- return;
+ return temp;
+ }
+
+ if (!remove_tempfile_installed) {
+ atexit(remove_tempfile);
+ sigchain_push_common(remove_tempfile_on_signal);
+ remove_tempfile_installed = 1;
}
if (!one->sha1_valid ||
@@ -1992,7 +2027,7 @@ static void prepare_temp_file(const char *name,
*/
sprintf(temp->mode, "%06o", one->mode);
}
- return;
+ return temp;
}
else {
if (diff_populate_filespec(one, 0))
@@ -2000,24 +2035,7 @@ static void prepare_temp_file(const char *name,
prep_temp_blob(temp, one->data, one->size,
one->sha1, one->mode);
}
-}
-
-static void remove_tempfile(void)
-{
- int i;
-
- for (i = 0; i < 2; i++)
- if (diff_temp[i].name == diff_temp[i].tmp_path) {
- unlink(diff_temp[i].name);
- diff_temp[i].name = NULL;
- }
-}
-
-static void remove_tempfile_on_signal(int signo)
-{
- remove_tempfile();
- signal(SIGINT, SIG_DFL);
- raise(signo);
+ return temp;
}
/* An external diff command takes:
@@ -2035,34 +2053,22 @@ static void run_external_diff(const char *pgm,
int complete_rewrite)
{
const char *spawn_arg[10];
- struct diff_tempfile *temp = diff_temp;
int retval;
- static int atexit_asked = 0;
- const char *othername;
const char **arg = &spawn_arg[0];
- othername = (other? other : name);
- if (one && two) {
- prepare_temp_file(name, &temp[0], one);
- prepare_temp_file(othername, &temp[1], two);
- if (! atexit_asked &&
- (temp[0].name == temp[0].tmp_path ||
- temp[1].name == temp[1].tmp_path)) {
- atexit_asked = 1;
- atexit(remove_tempfile);
- }
- signal(SIGINT, remove_tempfile_on_signal);
- }
-
if (one && two) {
+ struct diff_tempfile *temp_one, *temp_two;
+ const char *othername = (other ? other : name);
+ temp_one = prepare_temp_file(name, one);
+ temp_two = prepare_temp_file(othername, two);
*arg++ = pgm;
*arg++ = name;
- *arg++ = temp[0].name;
- *arg++ = temp[0].hex;
- *arg++ = temp[0].mode;
- *arg++ = temp[1].name;
- *arg++ = temp[1].hex;
- *arg++ = temp[1].mode;
+ *arg++ = temp_one->name;
+ *arg++ = temp_one->hex;
+ *arg++ = temp_one->mode;
+ *arg++ = temp_two->name;
+ *arg++ = temp_two->hex;
+ *arg++ = temp_two->mode;
if (other) {
*arg++ = other;
*arg++ = xfrm_msg;
@@ -3537,15 +3543,15 @@ void diff_unmerge(struct diff_options *options,
static char *run_textconv(const char *pgm, struct diff_filespec *spec,
size_t *outsize)
{
- struct diff_tempfile temp;
+ struct diff_tempfile *temp;
const char *argv[3];
const char **arg = argv;
struct child_process child;
struct strbuf buf = STRBUF_INIT;
- prepare_temp_file(spec->path, &temp, spec);
+ temp = prepare_temp_file(spec->path, spec);
*arg++ = pgm;
- *arg++ = temp.name;
+ *arg++ = temp->name;
*arg = NULL;
memset(&child, 0, sizeof(child));
@@ -3554,13 +3560,11 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
if (start_command(&child) != 0 ||
strbuf_read(&buf, child.out, 0) < 0 ||
finish_command(&child) != 0) {
- if (temp.name == temp.tmp_path)
- unlink(temp.name);
+ remove_tempfile();
error("error running textconv command '%s'", pgm);
return NULL;
}
- if (temp.name == temp.tmp_path)
- unlink(temp.name);
+ remove_tempfile();
return strbuf_detach(&buf, outsize);
}