fix typo in git-am manpage
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index f14288bb8a100c43c6709f658b9a9ca44832fd7f..b8a90e91a9af75e1e5f5d69ce45c2a59e64071d1 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -211,6 +211,8 @@ 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);
+       name_a += (*name_a == '/');
+       name_b += (*name_b == '/');
        printf("--- a/%s\n+++ b/%s\n@@ -", name_a, name_b);
        print_line_count(lc_a);
        printf(" +");
@@ -545,6 +547,24 @@ static char *pprint_rename(const char *a, const char *b)
        int pfx_length, sfx_length;
        int len_a = strlen(a);
        int len_b = strlen(b);
+       int qlen_a = quote_c_style(a, NULL, NULL, 0);
+       int qlen_b = quote_c_style(b, NULL, NULL, 0);
+
+       if (qlen_a || qlen_b) {
+               if (qlen_a) len_a = qlen_a;
+               if (qlen_b) len_b = qlen_b;
+               name = xmalloc( len_a + len_b + 5 );
+               if (qlen_a)
+                       quote_c_style(a, name, NULL, 0);
+               else
+                       memcpy(name, a, len_a);
+               memcpy(name + len_a, " => ", 4);
+               if (qlen_b)
+                       quote_c_style(b, name + len_a + 4, NULL, 0);
+               else
+                       memcpy(name + len_a + 4, b, len_b + 1);
+               return name;
+       }
 
        /* Find common prefix */
        pfx_length = 0;
@@ -701,12 +721,14 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
                struct diffstat_file *file = data->files[i];
                int change = file->added + file->deleted;
 
-               len = quote_c_style(file->name, NULL, NULL, 0);
-               if (len) {
-                       char *qname = xmalloc(len + 1);
-                       quote_c_style(file->name, qname, NULL, 0);
-                       free(file->name);
-                       file->name = qname;
+               if (!file->is_renamed) {  /* renames are already quoted by pprint_rename */
+                       len = quote_c_style(file->name, NULL, NULL, 0);
+                       if (len) {
+                               char *qname = xmalloc(len + 1);
+                               quote_c_style(file->name, qname, NULL, 0);
+                               free(file->name);
+                               file->name = qname;
+                       }
                }
 
                len = strlen(file->name);
@@ -838,7 +860,7 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options)
                        printf("-\t-\t");
                else
                        printf("%d\t%d\t", file->added, file->deleted);
-               if (options->line_termination &&
+               if (options->line_termination && !file->is_renamed &&
                    quote_c_style(file->name, NULL, NULL, 0))
                        quote_c_style(file->name, NULL, stdout, 0);
                else
@@ -1000,8 +1022,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);
@@ -1341,11 +1363,10 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
                fd = open(s->path, O_RDONLY);
                if (fd < 0)
                        goto err_empty;
-               s->data = mmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
+               s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
                close(fd);
-               if (s->data == MAP_FAILED)
-                       goto err_empty;
                s->should_munmap = 1;
+               /* FIXME! CRLF -> LF conversion goes here, based on "s->path" */
        }
        else {
                char type[20];
@@ -1391,7 +1412,7 @@ static void prep_temp_blob(struct diff_tempfile *temp,
        fd = git_mkstemp(temp->tmp_path, TEMPFILE_PATH_LEN, ".diff_XXXXXX");
        if (fd < 0)
                die("unable to create temp-file");
-       if (write(fd, blob, size) != size)
+       if (write_in_full(fd, blob, size) != size)
                die("unable to write temp-file");
        close(fd);
        temp->name = temp->tmp_path;
@@ -2193,13 +2214,13 @@ static void diff_flush_raw(struct diff_filepair *p,
                free((void*)path_two);
 }
 
-static void diff_flush_name(struct diff_filepair *p, int line_termination)
+static void diff_flush_name(struct diff_filepair *p, struct diff_options *opt)
 {
        char *path = p->two->path;
 
-       if (line_termination)
+       if (opt->line_termination)
                path = quote_one(p->two->path);
-       printf("%s%c", path, line_termination);
+       printf("%s%c", path, opt->line_termination);
        if (p->two->path != path)
                free(path);
 }
@@ -2406,24 +2427,29 @@ static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
        else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS))
                diff_flush_raw(p, opt);
        else if (fmt & DIFF_FORMAT_NAME)
-               diff_flush_name(p, opt->line_termination);
+               diff_flush_name(p, opt);
 }
 
 static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs)
 {
+       char *name = quote_one(fs->path);
        if (fs->mode)
-               printf(" %s mode %06o %s\n", newdelete, fs->mode, fs->path);
+               printf(" %s mode %06o %s\n", newdelete, fs->mode, name);
        else
-               printf(" %s %s\n", newdelete, fs->path);
+               printf(" %s %s\n", newdelete, name);
+       free(name);
 }
 
 
 static void show_mode_change(struct diff_filepair *p, int show_name)
 {
        if (p->one->mode && p->two->mode && p->one->mode != p->two->mode) {
-               if (show_name)
+               if (show_name) {
+                       char *name = quote_one(p->two->path);
                        printf(" mode change %06o => %06o %s\n",
-                              p->one->mode, p->two->mode, p->two->path);
+                              p->one->mode, p->two->mode, name);
+                       free(name);
+               }
                else
                        printf(" mode change %06o => %06o\n",
                               p->one->mode, p->two->mode);
@@ -2432,34 +2458,11 @@ static void show_mode_change(struct diff_filepair *p, int show_name)
 
 static void show_rename_copy(const char *renamecopy, struct diff_filepair *p)
 {
-       const char *old, *new;
+       char *names = pprint_rename(p->one->path, p->two->path);
 
-       /* Find common prefix */
-       old = p->one->path;
-       new = p->two->path;
-       while (1) {
-               const char *slash_old, *slash_new;
-               slash_old = strchr(old, '/');
-               slash_new = strchr(new, '/');
-               if (!slash_old ||
-                   !slash_new ||
-                   slash_old - old != slash_new - new ||
-                   memcmp(old, new, slash_new - new))
-                       break;
-               old = slash_old + 1;
-               new = slash_new + 1;
-       }
-       /* p->one->path thru old is the common prefix, and old and new
-        * through the end of names are renames
-        */
-       if (old != p->one->path)
-               printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy,
-                      (int)(old - p->one->path), p->one->path,
-                      old, new, (int)(0.5 + p->score * 100.0/MAX_SCORE));
-       else
-               printf(" %s %s => %s (%d%%)\n", renamecopy,
-                      p->one->path, p->two->path,
-                      (int)(0.5 + p->score * 100.0/MAX_SCORE));
+       printf(" %s %s (%d%%)\n", renamecopy, names,
+              (int)(0.5 + p->score * 100.0/MAX_SCORE));
+       free(names);
        show_mode_change(p, 0);
 }
 
@@ -2480,8 +2483,10 @@ static void diff_summary(struct diff_filepair *p)
                break;
        default:
                if (p->score) {
-                       printf(" rewrite %s (%d%%)\n", p->two->path,
+                       char *name = quote_one(p->two->path);
+                       printf(" rewrite %s (%d%%)\n", name,
                                (int)(0.5 + p->score * 100.0/MAX_SCORE));
+                       free(name);
                        show_mode_change(p, 0);
                } else  show_mode_change(p, 1);
                break;
@@ -2875,10 +2880,12 @@ void diff_change(struct diff_options *options,
 }
 
 void diff_unmerge(struct diff_options *options,
-                 const char *path)
+                 const char *path,
+                 unsigned mode, const unsigned char *sha1)
 {
        struct diff_filespec *one, *two;
        one = alloc_filespec(path);
        two = alloc_filespec(path);
-       diff_queue(&diff_queued_diff, one, two);
+       fill_filespec(one, sha1, mode);
+       diff_queue(&diff_queued_diff, one, two)->is_unmerged = 1;
 }