sha1_file.c: cleanup hdr usage
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index fad13ab44b5e8e4719ba24e0d059127dbd34ec69..d1eae7214d863d5a87735059d509afcdf60507d7 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -77,7 +77,7 @@ int git_diff_ui_config(const char *var, const char *value)
                        diff_detect_rename_default = DIFF_DETECT_RENAME;
                return 0;
        }
-       if (!prefixcmp(var, "diff.color.") || !strncmp(var, "color.diff.", 11)) {
+       if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
                int slot = parse_diff_color_slot(var, 11);
                color_parse(value, var, diff_colors[slot]);
                return 0;
@@ -184,31 +184,43 @@ static void print_line_count(int count)
        }
 }
 
-static void copy_file(int prefix, const char *data, int size)
+static void copy_file(int prefix, const char *data, int size,
+               const char *set, const char *reset)
 {
        int ch, nl_just_seen = 1;
        while (0 < size--) {
                ch = *data++;
-               if (nl_just_seen)
+               if (nl_just_seen) {
+                       fputs(set, stdout);
                        putchar(prefix);
-               putchar(ch);
-               if (ch == '\n')
+               }
+               if (ch == '\n') {
                        nl_just_seen = 1;
-               else
+                       fputs(reset, stdout);
+               } else
                        nl_just_seen = 0;
+               putchar(ch);
        }
        if (!nl_just_seen)
-               printf("\n\\ No newline at end of file\n");
+               printf("%s\n\\ No newline at end of file\n", reset);
 }
 
 static void emit_rewrite_diff(const char *name_a,
                              const char *name_b,
                              struct diff_filespec *one,
-                             struct diff_filespec *two)
+                             struct diff_filespec *two,
+                             int color_diff)
 {
        int lc_a, lc_b;
        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);
+
+       name_a += (*name_a == '/');
+       name_b += (*name_b == '/');
        name_a_tab = strchr(name_a, ' ') ? "\t" : "";
        name_b_tab = strchr(name_b, ' ') ? "\t" : "";
 
@@ -216,17 +228,17 @@ static void emit_rewrite_diff(const char *name_a,
        diff_populate_filespec(two, 0);
        lc_a = count_lines(one->data, one->size);
        lc_b = count_lines(two->data, two->size);
-       printf("--- a/%s%s\n+++ b/%s%s\n@@ -",
-              name_a, name_a_tab,
-              name_b, name_b_tab);
+       printf("%s--- a/%s%s%s\n%s+++ b/%s%s%s\n%s@@ -",
+              metainfo, name_a, name_a_tab, reset,
+              metainfo, name_b, name_b_tab, reset, fraginfo);
        print_line_count(lc_a);
        printf(" +");
        print_line_count(lc_b);
-       printf(" @@\n");
+       printf(" @@%s\n", reset);
        if (lc_a)
-               copy_file('-', one->data, one->size);
+               copy_file('-', one->data, one->size, old, reset);
        if (lc_b)
-               copy_file('+', two->data, two->size);
+               copy_file('+', two->data, two->size, new, reset);
 }
 
 static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
@@ -1054,8 +1066,8 @@ static void builtin_diff(const char *name_a,
        const char *set = diff_get_color(o->color_diff, DIFF_METAINFO);
        const char *reset = diff_get_color(o->color_diff, DIFF_RESET);
 
-       a_one = quote_two("a/", name_a);
-       b_two = quote_two("b/", name_b);
+       a_one = quote_two("a/", name_a + (*name_a == '/'));
+       b_two = quote_two("b/", name_b + (*name_b == '/'));
        lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
        lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
        printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset);
@@ -1084,7 +1096,8 @@ static void builtin_diff(const char *name_a,
                if ((one->mode ^ two->mode) & S_IFMT)
                        goto free_ab_and_return;
                if (complete_rewrite) {
-                       emit_rewrite_diff(name_a, name_b, one, two);
+                       emit_rewrite_diff(name_a, name_b, one, two,
+                                       o->color_diff);
                        goto free_ab_and_return;
                }
        }
@@ -1367,6 +1380,9 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
            reuse_worktree_file(s->path, s->sha1, 0)) {
                struct stat st;
                int fd;
+               char *buf;
+               unsigned long size;
+
                if (lstat(s->path, &st) < 0) {
                        if (errno == ENOENT) {
                        err_empty:
@@ -1399,7 +1415,19 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
                s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
                close(fd);
                s->should_munmap = 1;
-               /* FIXME! CRLF -> LF conversion goes here, based on "s->path" */
+
+               /*
+                * Convert from working tree format to canonical git format
+                */
+               buf = s->data;
+               size = s->size;
+               if (convert_to_git(s->path, &buf, &size)) {
+                       munmap(s->data, s->size);
+                       s->should_munmap = 0;
+                       s->data = buf;
+                       s->size = size;
+                       s->should_free = 1;
+               }
        }
        else {
                char type[20];