Merge branch 'jk/diff-color-moved-fix'
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 24bec41114de0364c7b1ea6e2c692dd94e17eea2..c4a669ffa8690f7640294f717e817352265a8bf6 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -21,6 +21,7 @@
 #include "string-list.h"
 #include "argv-array.h"
 #include "graph.h"
+#include "packfile.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -357,6 +358,9 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
+       if (git_color_config(var, value, cb) < 0)
+               return -1;
+
        return git_diff_basic_config(var, value, cb);
 }
 
@@ -401,9 +405,6 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       if (starts_with(var, "submodule."))
-               return parse_submodule_config_option(var, value);
-
        if (git_diff_heuristic_config(var, value, cb) < 0)
                return -1;
 
@@ -461,7 +462,7 @@ static struct diff_tempfile {
         * If this diff_tempfile instance refers to a temporary file,
         * this tempfile object is used to manage its lifetime.
         */
-       struct tempfile tempfile;
+       struct tempfile *tempfile;
 } diff_temp[2];
 
 struct emit_callback {
@@ -711,23 +712,30 @@ static int next_byte(const char **cp, const char **endp,
 {
        int retval;
 
-       if (*cp > *endp)
+       if (*cp >= *endp)
                return -1;
 
-       if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE_CHANGE)) {
-               while (*cp < *endp && isspace(**cp))
-                       (*cp)++;
-               /*
-                * After skipping a couple of whitespaces, we still have to
-                * account for one space.
-                */
-               return (int)' ';
-       }
+       if (isspace(**cp)) {
+               if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE_CHANGE)) {
+                       while (*cp < *endp && isspace(**cp))
+                               (*cp)++;
+                       /*
+                        * After skipping a couple of whitespaces,
+                        * we still have to account for one space.
+                        */
+                       return (int)' ';
+               }
 
-       if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE)) {
-               while (*cp < *endp && isspace(**cp))
-                       (*cp)++;
-               /* return the first non-ws character via the usual below */
+               if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE)) {
+                       while (*cp < *endp && isspace(**cp))
+                               (*cp)++;
+                       /*
+                        * return the first non-ws character via the usual
+                        * below, unless we ate all of the bytes
+                        */
+                       if (*cp >= *endp)
+                               return -1;
+               }
        }
 
        retval = (unsigned char)(**cp);
@@ -747,9 +755,9 @@ static int moved_entry_cmp(const struct diff_options *diffopt,
                return a->es->len != b->es->len  || memcmp(ap, bp, a->es->len);
 
        if (DIFF_XDL_TST(diffopt, IGNORE_WHITESPACE_AT_EOL)) {
-               while (ae > ap && isspace(*ae))
+               while (ae > ap && isspace(ae[-1]))
                        ae--;
-               while (be > bp && isspace(*be))
+               while (be > bp && isspace(be[-1]))
                        be--;
        }
 
@@ -772,9 +780,9 @@ static unsigned get_string_hash(struct emitted_diff_symbol *es, struct diff_opti
                int c;
 
                strbuf_reset(&sb);
-               while (ae > ap && isspace(*ae))
+               while (ae > ap && isspace(ae[-1]))
                        ae--;
-               while ((c = next_byte(&ap, &ae, o)) > 0)
+               while ((c = next_byte(&ap, &ae, o)) >= 0)
                        strbuf_addch(&sb, c);
 
                return memhash(sb.buf, sb.len);
@@ -1416,7 +1424,7 @@ static void remove_tempfile(void)
 {
        int i;
        for (i = 0; i < ARRAY_SIZE(diff_temp); i++) {
-               if (is_tempfile_active(&diff_temp[i].tempfile))
+               if (is_tempfile_active(diff_temp[i].tempfile))
                        delete_tempfile(&diff_temp[i].tempfile);
                diff_temp[i].name = NULL;
        }
@@ -1543,7 +1551,7 @@ static void emit_rewrite_diff(const char *name_a,
 
 struct diff_words_buffer {
        mmfile_t text;
-       long alloc;
+       unsigned long alloc;
        struct diff_words_orig {
                const char *begin, *end;
        } *orig;
@@ -2585,6 +2593,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
        }
 
        print_stat_summary_inserts_deletes(options, total_files, adds, dels);
+       strbuf_release(&out);
 }
 
 static void show_shortstats(struct diffstat_t *data, struct diff_options *options)
@@ -3722,7 +3731,6 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
                           const struct object_id *oid,
                           int mode)
 {
-       int fd;
        struct strbuf buf = STRBUF_INIT;
        struct strbuf template = STRBUF_INIT;
        char *path_dup = xstrdup(path);
@@ -3732,18 +3740,18 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
        strbuf_addstr(&template, "XXXXXX_");
        strbuf_addstr(&template, base);
 
-       fd = mks_tempfile_ts(&temp->tempfile, template.buf, strlen(base) + 1);
-       if (fd < 0)
+       temp->tempfile = mks_tempfile_ts(template.buf, strlen(base) + 1);
+       if (!temp->tempfile)
                die_errno("unable to create temp-file");
        if (convert_to_working_tree(path,
                        (const char *)blob, (size_t)size, &buf)) {
                blob = buf.buf;
                size = buf.len;
        }
-       if (write_in_full(fd, blob, size) != size)
+       if (write_in_full(temp->tempfile->fd, blob, size) < 0 ||
+           close_tempfile_gently(temp->tempfile))
                die_errno("unable to write temp-file");
-       close_tempfile(&temp->tempfile);
-       temp->name = get_tempfile_path(&temp->tempfile);
+       temp->name = get_tempfile_path(temp->tempfile);
        oid_to_hex_r(temp->hex, oid);
        xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode);
        strbuf_release(&buf);
@@ -5274,6 +5282,7 @@ static void show_mode_change(struct diff_options *opt, struct diff_filepair *p,
                        strbuf_addch(&sb, ' ');
                        quote_c_style(p->two->path, &sb, NULL, 0);
                }
+               strbuf_addch(&sb, '\n');
                emit_diff_symbol(opt, DIFF_SYMBOL_SUMMARY,
                                 sb.buf, sb.len, 0);
                strbuf_release(&sb);
@@ -5291,6 +5300,7 @@ static void show_rename_copy(struct diff_options *opt, const char *renamecopy,
        emit_diff_symbol(opt, DIFF_SYMBOL_SUMMARY,
                                 sb.buf, sb.len, 0);
        show_mode_change(opt, p, 0);
+       strbuf_release(&sb);
 }
 
 static void diff_summary(struct diff_options *opt, struct diff_filepair *p)
@@ -5316,6 +5326,7 @@ static void diff_summary(struct diff_options *opt, struct diff_filepair *p)
                        strbuf_addf(&sb, " (%d%%)\n", similarity_index(p));
                        emit_diff_symbol(opt, DIFF_SYMBOL_SUMMARY,
                                         sb.buf, sb.len, 0);
+                       strbuf_release(&sb);
                }
                show_mode_change(opt, p, !p->score);
                break;