Merge branch 'jc/maint-1.6.0-blank-at-eof' into jc/maint-blank-at-eof
authorJunio C Hamano <gitster@pobox.com>
Tue, 15 Sep 2009 18:21:10 +0000 (11:21 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 15 Sep 2009 18:21:10 +0000 (11:21 -0700)
* jc/maint-1.6.0-blank-at-eof:
diff -B: colour whitespace errors

1  2 
diff.c
diff --cc diff.c
index 2046290e1a1d245e5aa0090194d3f5df60ab3f72,8414478032632c2b9b877c65ddcf955451083934..ce2b758a8d68cccb51e9dcea8892c506630d7505
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -343,68 -425,36 +343,78 @@@ static void emit_add_line(const char *r
        }
  }
  
- 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 {