diff.c: emit_diff_symbol learns DIFF_SYMBOL_CONTEXT_MARKER
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 41295d4ea9ff5564fa73d45aaa3afaab20103d87..75b996c4cf17d712d7430c24869208263d05f064 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -560,6 +560,31 @@ static void emit_line(struct diff_options *o, const char *set, const char *reset
        emit_line_0(o, set, reset, line[0], line+1, len-1);
 }
 
+enum diff_symbol {
+       DIFF_SYMBOL_CONTEXT_MARKER,
+       DIFF_SYMBOL_SEPARATOR
+};
+
+static void emit_diff_symbol(struct diff_options *o, enum diff_symbol s,
+                            const char *line, int len)
+{
+       const char *context, *reset;
+       switch (s) {
+       case DIFF_SYMBOL_CONTEXT_MARKER:
+               context = diff_get_color_opt(o, DIFF_CONTEXT);
+               reset = diff_get_color_opt(o, DIFF_RESET);
+               emit_line(o, context, reset, line, len);
+               break;
+       case DIFF_SYMBOL_SEPARATOR:
+               fprintf(o->file, "%s%c",
+                       diff_line_prefix(o),
+                       o->line_termination);
+               break;
+       default:
+               die("BUG: unknown diff symbol");
+       }
+}
+
 static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)
 {
        if (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&
@@ -644,7 +669,8 @@ static void emit_hunk_header(struct emit_callback *ecbdata,
        if (len < 10 ||
            memcmp(line, atat, 2) ||
            !(ep = memmem(line + 2, len - 2, atat, 2))) {
-               emit_line(ecbdata->opt, context, reset, line, len);
+               emit_diff_symbol(ecbdata->opt,
+                                DIFF_SYMBOL_CONTEXT_MARKER, line, len);
                return;
        }
        ep += 2; /* skip over @@ */
@@ -678,6 +704,8 @@ static void emit_hunk_header(struct emit_callback *ecbdata,
        }
 
        strbuf_add(&msgbuf, line + len, org_len - len);
+       strbuf_complete_line(&msgbuf);
+
        emit_line(ecbdata->opt, "", "", msgbuf.buf, msgbuf.len);
        strbuf_release(&msgbuf);
 }
@@ -1219,8 +1247,7 @@ static void free_diff_words_data(struct emit_callback *ecbdata)
                        regfree(ecbdata->diff_words->word_regex);
                        free(ecbdata->diff_words->word_regex);
                }
-               free(ecbdata->diff_words);
-               ecbdata->diff_words = NULL;
+               FREE_AND_NULL(ecbdata->diff_words);
        }
 }
 
@@ -1316,8 +1343,6 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                len = sane_truncate_line(ecbdata, line, len);
                find_lno(line, ecbdata);
                emit_hunk_header(ecbdata, line, len);
-               if (line[len-1] != '\n')
-                       putc('\n', o->file);
                return;
        }
 
@@ -2952,8 +2977,7 @@ void diff_free_filespec_blob(struct diff_filespec *s)
 void diff_free_filespec_data(struct diff_filespec *s)
 {
        diff_free_filespec_blob(s);
-       free(s->cnt_data);
-       s->cnt_data = NULL;
+       FREE_AND_NULL(s->cnt_data);
 }
 
 static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
@@ -3284,8 +3308,8 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
        const char *other;
        const char *attr_path;
 
-       name  = p->one->path;
-       other = (strcmp(name, p->two->path) ? p->two->path : NULL);
+       name  = one->path;
+       other = (strcmp(name, two->path) ? two->path : NULL);
        attr_path = name;
        if (o->prefix_length)
                strip_prefix(o->prefix_length, &name, &other);
@@ -4736,6 +4760,17 @@ void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc)
                warning(_(rename_limit_advice), varname, needed);
 }
 
+static void diff_flush_patch_all_file_pairs(struct diff_options *o)
+{
+       int i;
+       struct diff_queue_struct *q = &diff_queued_diff;
+       for (i = 0; i < q->nr; i++) {
+               struct diff_filepair *p = q->queue[i];
+               if (check_pair_status(p))
+                       diff_flush_patch(p, o);
+       }
+}
+
 void diff_flush(struct diff_options *options)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
@@ -4819,20 +4854,14 @@ void diff_flush(struct diff_options *options)
 
        if (output_format & DIFF_FORMAT_PATCH) {
                if (separator) {
-                       fprintf(options->file, "%s%c",
-                               diff_line_prefix(options),
-                               options->line_termination);
+                       emit_diff_symbol(options, DIFF_SYMBOL_SEPARATOR, NULL, 0);
                        if (options->stat_sep) {
                                /* attach patch instead of inline */
                                fputs(options->stat_sep, options->file);
                        }
                }
 
-               for (i = 0; i < q->nr; i++) {
-                       struct diff_filepair *p = q->queue[i];
-                       if (check_pair_status(p))
-                               diff_flush_patch(p, options);
-               }
+               diff_flush_patch_all_file_pairs(options);
        }
 
        if (output_format & DIFF_FORMAT_CALLBACK)