}
}
- static void copy_file_with_prefix(FILE *file,
- int prefix, const char *data, int size,
- const char *set, const char *reset)
+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_or_warn(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 void print_line_count(FILE *file, int count)
+{
+ switch (count) {
+ case 0:
+ fprintf(file, "0,0");
+ break;
+ case 1:
+ fprintf(file, "1");
+ break;
+ default:
+ fprintf(file, "1,%d", count);
+ break;
+ }
+}
+
+ static void emit_rewrite_lines(struct emit_callback *ecb,
+ int prefix, const char *data, int size)
{
- int ch, nl_just_seen = 1;
- while (0 < size--) {
- ch = *data++;
- if (nl_just_seen) {
- fputs(set, file);
- putc(prefix, file);
+ const char *endp = NULL;
+ static const char *nneof = " No newline at end of file\n";
+ const char *old = diff_get_color(ecb->color_diff, DIFF_FILE_OLD);
+ const char *reset = diff_get_color(ecb->color_diff, DIFF_RESET);
+
+ while (0 < size) {
+ int len;
+
+ endp = memchr(data, '\n', size);
+ len = endp ? (endp - data + 1) : size;
+ if (prefix != '+') {
+ ecb->lno_in_preimage++;
+ emit_line_0(ecb->file, old, reset, '-',
+ data, len);
+ } else {
+ ecb->lno_in_postimage++;
+ emit_add_line(reset, ecb, data, len);
}
- if (ch == '\n') {
- nl_just_seen = 1;
- fputs(reset, file);
- } else
- nl_just_seen = 0;
- putc(ch, file);
+ size -= len;
+ data += len;
+ }
+ if (!endp) {
+ const char *plain = diff_get_color(ecb->color_diff,
+ DIFF_PLAIN);
+ emit_line_0(ecb->file, plain, reset, '\\',
+ nneof, strlen(nneof));
}
- if (!nl_just_seen)
- fprintf(file, "%s\n\\ No newline at end of file\n", reset);
}
static void emit_rewrite_diff(const char *name_a,
const char *name_a_tab, *name_b_tab;
const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
- const char *old = diff_get_color(color_diff, DIFF_FILE_OLD);
- const char *new = diff_get_color(color_diff, DIFF_FILE_NEW);
const char *reset = diff_get_color(color_diff, DIFF_RESET);
static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
+ const char *a_prefix, *b_prefix;
+ const char *data_one, *data_two;
+ size_t size_one, size_two;
+ struct emit_callback ecbdata;
- memset(&ecbdata, 0, sizeof(ecbdata));
- ecbdata.color_diff = color_diff;
- ecbdata.found_changesp = &o->found_changes;
- ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
- ecbdata.file = o->file;
- if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
- mmfile_t mf1, mf2;
- fill_mmfile(&mf1, one);
- fill_mmfile(&mf2, two);
- check_blank_at_eof(&mf1, &mf2, &ecbdata);
+ if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) {
+ a_prefix = o->b_prefix;
+ b_prefix = o->a_prefix;
+ } else {
+ a_prefix = o->a_prefix;
+ b_prefix = o->b_prefix;
}
- ecbdata.lno_in_preimage = 1;
- ecbdata.lno_in_postimage = 1;
name_a += (*name_a == '/');
name_b += (*name_b == '/');
diff_populate_filespec(one, 0);
diff_populate_filespec(two, 0);
- lc_a = count_lines(one->data, one->size);
- lc_b = count_lines(two->data, two->size);
+ if (textconv_one) {
+ data_one = run_textconv(textconv_one, one, &size_one);
+ if (!data_one)
+ die("unable to read files to diff");
+ }
+ else {
+ data_one = one->data;
+ size_one = one->size;
+ }
+ if (textconv_two) {
+ data_two = run_textconv(textconv_two, two, &size_two);
+ if (!data_two)
+ die("unable to read files to diff");
+ }
+ else {
+ data_two = two->data;
+ size_two = two->size;
+ }
+
++ memset(&ecbdata, 0, sizeof(ecbdata));
++ ecbdata.color_diff = color_diff;
++ ecbdata.found_changesp = &o->found_changes;
++ ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
++ ecbdata.file = o->file;
++ if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
++ mmfile_t mf1, mf2;
++ mf1.ptr = (char *)data_one;
++ mf2.ptr = (char *)data_two;
++ mf1.size = size_one;
++ mf2.size = size_two;
++ check_blank_at_eof(&mf1, &mf2, &ecbdata);
++ }
++ ecbdata.lno_in_preimage = 1;
++ ecbdata.lno_in_postimage = 1;
++
+ lc_a = count_lines(data_one, size_one);
+ lc_b = count_lines(data_two, size_two);
fprintf(o->file,
"%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -",
metainfo, a_name.buf, name_a_tab, reset,
print_line_count(o->file, lc_b);
fprintf(o->file, " @@%s\n", reset);
if (lc_a)
- copy_file_with_prefix(o->file, '-', data_one, size_one, old, reset);
- emit_rewrite_lines(&ecbdata, '-', one->data, one->size);
++ emit_rewrite_lines(&ecbdata, '-', data_one, size_one);
if (lc_b)
- copy_file_with_prefix(o->file, '+', data_two, size_two, new, reset);
- emit_rewrite_lines(&ecbdata, '+', two->data, two->size);
++ emit_rewrite_lines(&ecbdata, '+', data_two, size_two);
}
struct diff_words_buffer {