refs: minor restructuring of cached refs data.
[git] / diff.c
1 /*
2  * Copyright (C) 2005 Junio C Hamano
3  */
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <signal.h>
7 #include "cache.h"
8 #include "quote.h"
9 #include "diff.h"
10 #include "diffcore.h"
11 #include "delta.h"
12 #include "xdiff-interface.h"
13 #include "color.h"
14
15 static int use_size_cache;
16
17 static int diff_detect_rename_default;
18 static int diff_rename_limit_default = -1;
19 static int diff_use_color_default;
20
21 static char diff_colors[][COLOR_MAXLEN] = {
22         "\033[m",       /* reset */
23         "",             /* PLAIN (normal) */
24         "\033[1m",      /* METAINFO (bold) */
25         "\033[36m",     /* FRAGINFO (cyan) */
26         "\033[31m",     /* OLD (red) */
27         "\033[32m",     /* NEW (green) */
28         "\033[33m",     /* COMMIT (yellow) */
29         "\033[41m",     /* WHITESPACE (red background) */
30 };
31
32 static int parse_diff_color_slot(const char *var, int ofs)
33 {
34         if (!strcasecmp(var+ofs, "plain"))
35                 return DIFF_PLAIN;
36         if (!strcasecmp(var+ofs, "meta"))
37                 return DIFF_METAINFO;
38         if (!strcasecmp(var+ofs, "frag"))
39                 return DIFF_FRAGINFO;
40         if (!strcasecmp(var+ofs, "old"))
41                 return DIFF_FILE_OLD;
42         if (!strcasecmp(var+ofs, "new"))
43                 return DIFF_FILE_NEW;
44         if (!strcasecmp(var+ofs, "commit"))
45                 return DIFF_COMMIT;
46         if (!strcasecmp(var+ofs, "whitespace"))
47                 return DIFF_WHITESPACE;
48         die("bad config variable '%s'", var);
49 }
50
51 /*
52  * These are to give UI layer defaults.
53  * The core-level commands such as git-diff-files should
54  * never be affected by the setting of diff.renames
55  * the user happens to have in the configuration file.
56  */
57 int git_diff_ui_config(const char *var, const char *value)
58 {
59         if (!strcmp(var, "diff.renamelimit")) {
60                 diff_rename_limit_default = git_config_int(var, value);
61                 return 0;
62         }
63         if (!strcmp(var, "diff.color")) {
64                 diff_use_color_default = git_config_colorbool(var, value);
65                 return 0;
66         }
67         if (!strcmp(var, "diff.renames")) {
68                 if (!value)
69                         diff_detect_rename_default = DIFF_DETECT_RENAME;
70                 else if (!strcasecmp(value, "copies") ||
71                          !strcasecmp(value, "copy"))
72                         diff_detect_rename_default = DIFF_DETECT_COPY;
73                 else if (git_config_bool(var,value))
74                         diff_detect_rename_default = DIFF_DETECT_RENAME;
75                 return 0;
76         }
77         if (!strncmp(var, "diff.color.", 11)) {
78                 int slot = parse_diff_color_slot(var, 11);
79                 color_parse(value, var, diff_colors[slot]);
80                 return 0;
81         }
82         return git_default_config(var, value);
83 }
84
85 static char *quote_one(const char *str)
86 {
87         int needlen;
88         char *xp;
89
90         if (!str)
91                 return NULL;
92         needlen = quote_c_style(str, NULL, NULL, 0);
93         if (!needlen)
94                 return xstrdup(str);
95         xp = xmalloc(needlen + 1);
96         quote_c_style(str, xp, NULL, 0);
97         return xp;
98 }
99
100 static char *quote_two(const char *one, const char *two)
101 {
102         int need_one = quote_c_style(one, NULL, NULL, 1);
103         int need_two = quote_c_style(two, NULL, NULL, 1);
104         char *xp;
105
106         if (need_one + need_two) {
107                 if (!need_one) need_one = strlen(one);
108                 if (!need_two) need_one = strlen(two);
109
110                 xp = xmalloc(need_one + need_two + 3);
111                 xp[0] = '"';
112                 quote_c_style(one, xp + 1, NULL, 1);
113                 quote_c_style(two, xp + need_one + 1, NULL, 1);
114                 strcpy(xp + need_one + need_two + 1, "\"");
115                 return xp;
116         }
117         need_one = strlen(one);
118         need_two = strlen(two);
119         xp = xmalloc(need_one + need_two + 1);
120         strcpy(xp, one);
121         strcpy(xp + need_one, two);
122         return xp;
123 }
124
125 static const char *external_diff(void)
126 {
127         static const char *external_diff_cmd = NULL;
128         static int done_preparing = 0;
129
130         if (done_preparing)
131                 return external_diff_cmd;
132         external_diff_cmd = getenv("GIT_EXTERNAL_DIFF");
133         done_preparing = 1;
134         return external_diff_cmd;
135 }
136
137 #define TEMPFILE_PATH_LEN               50
138
139 static struct diff_tempfile {
140         const char *name; /* filename external diff should read from */
141         char hex[41];
142         char mode[10];
143         char tmp_path[TEMPFILE_PATH_LEN];
144 } diff_temp[2];
145
146 static int count_lines(const char *data, int size)
147 {
148         int count, ch, completely_empty = 1, nl_just_seen = 0;
149         count = 0;
150         while (0 < size--) {
151                 ch = *data++;
152                 if (ch == '\n') {
153                         count++;
154                         nl_just_seen = 1;
155                         completely_empty = 0;
156                 }
157                 else {
158                         nl_just_seen = 0;
159                         completely_empty = 0;
160                 }
161         }
162         if (completely_empty)
163                 return 0;
164         if (!nl_just_seen)
165                 count++; /* no trailing newline */
166         return count;
167 }
168
169 static void print_line_count(int count)
170 {
171         switch (count) {
172         case 0:
173                 printf("0,0");
174                 break;
175         case 1:
176                 printf("1");
177                 break;
178         default:
179                 printf("1,%d", count);
180                 break;
181         }
182 }
183
184 static void copy_file(int prefix, const char *data, int size)
185 {
186         int ch, nl_just_seen = 1;
187         while (0 < size--) {
188                 ch = *data++;
189                 if (nl_just_seen)
190                         putchar(prefix);
191                 putchar(ch);
192                 if (ch == '\n')
193                         nl_just_seen = 1;
194                 else
195                         nl_just_seen = 0;
196         }
197         if (!nl_just_seen)
198                 printf("\n\\ No newline at end of file\n");
199 }
200
201 static void emit_rewrite_diff(const char *name_a,
202                               const char *name_b,
203                               struct diff_filespec *one,
204                               struct diff_filespec *two)
205 {
206         int lc_a, lc_b;
207         diff_populate_filespec(one, 0);
208         diff_populate_filespec(two, 0);
209         lc_a = count_lines(one->data, one->size);
210         lc_b = count_lines(two->data, two->size);
211         printf("--- %s\n+++ %s\n@@ -", name_a, name_b);
212         print_line_count(lc_a);
213         printf(" +");
214         print_line_count(lc_b);
215         printf(" @@\n");
216         if (lc_a)
217                 copy_file('-', one->data, one->size);
218         if (lc_b)
219                 copy_file('+', two->data, two->size);
220 }
221
222 static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
223 {
224         if (!DIFF_FILE_VALID(one)) {
225                 mf->ptr = (char *)""; /* does not matter */
226                 mf->size = 0;
227                 return 0;
228         }
229         else if (diff_populate_filespec(one, 0))
230                 return -1;
231         mf->ptr = one->data;
232         mf->size = one->size;
233         return 0;
234 }
235
236 struct diff_words_buffer {
237         mmfile_t text;
238         long alloc;
239         long current; /* output pointer */
240         int suppressed_newline;
241 };
242
243 static void diff_words_append(char *line, unsigned long len,
244                 struct diff_words_buffer *buffer)
245 {
246         if (buffer->text.size + len > buffer->alloc) {
247                 buffer->alloc = (buffer->text.size + len) * 3 / 2;
248                 buffer->text.ptr = xrealloc(buffer->text.ptr, buffer->alloc);
249         }
250         line++;
251         len--;
252         memcpy(buffer->text.ptr + buffer->text.size, line, len);
253         buffer->text.size += len;
254 }
255
256 struct diff_words_data {
257         struct xdiff_emit_state xm;
258         struct diff_words_buffer minus, plus;
259 };
260
261 static void print_word(struct diff_words_buffer *buffer, int len, int color,
262                 int suppress_newline)
263 {
264         const char *ptr;
265         int eol = 0;
266
267         if (len == 0)
268                 return;
269
270         ptr  = buffer->text.ptr + buffer->current;
271         buffer->current += len;
272
273         if (ptr[len - 1] == '\n') {
274                 eol = 1;
275                 len--;
276         }
277
278         fputs(diff_get_color(1, color), stdout);
279         fwrite(ptr, len, 1, stdout);
280         fputs(diff_get_color(1, DIFF_RESET), stdout);
281
282         if (eol) {
283                 if (suppress_newline)
284                         buffer->suppressed_newline = 1;
285                 else
286                         putchar('\n');
287         }
288 }
289
290 static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
291 {
292         struct diff_words_data *diff_words = priv;
293
294         if (diff_words->minus.suppressed_newline) {
295                 if (line[0] != '+')
296                         putchar('\n');
297                 diff_words->minus.suppressed_newline = 0;
298         }
299
300         len--;
301         switch (line[0]) {
302                 case '-':
303                         print_word(&diff_words->minus, len, DIFF_FILE_OLD, 1);
304                         break;
305                 case '+':
306                         print_word(&diff_words->plus, len, DIFF_FILE_NEW, 0);
307                         break;
308                 case ' ':
309                         print_word(&diff_words->plus, len, DIFF_PLAIN, 0);
310                         diff_words->minus.current += len;
311                         break;
312         }
313 }
314
315 /* this executes the word diff on the accumulated buffers */
316 static void diff_words_show(struct diff_words_data *diff_words)
317 {
318         xpparam_t xpp;
319         xdemitconf_t xecfg;
320         xdemitcb_t ecb;
321         mmfile_t minus, plus;
322         int i;
323
324         minus.size = diff_words->minus.text.size;
325         minus.ptr = xmalloc(minus.size);
326         memcpy(minus.ptr, diff_words->minus.text.ptr, minus.size);
327         for (i = 0; i < minus.size; i++)
328                 if (isspace(minus.ptr[i]))
329                         minus.ptr[i] = '\n';
330         diff_words->minus.current = 0;
331
332         plus.size = diff_words->plus.text.size;
333         plus.ptr = xmalloc(plus.size);
334         memcpy(plus.ptr, diff_words->plus.text.ptr, plus.size);
335         for (i = 0; i < plus.size; i++)
336                 if (isspace(plus.ptr[i]))
337                         plus.ptr[i] = '\n';
338         diff_words->plus.current = 0;
339
340         xpp.flags = XDF_NEED_MINIMAL;
341         xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc;
342         xecfg.flags = 0;
343         ecb.outf = xdiff_outf;
344         ecb.priv = diff_words;
345         diff_words->xm.consume = fn_out_diff_words_aux;
346         xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb);
347
348         free(minus.ptr);
349         free(plus.ptr);
350         diff_words->minus.text.size = diff_words->plus.text.size = 0;
351
352         if (diff_words->minus.suppressed_newline) {
353                 putchar('\n');
354                 diff_words->minus.suppressed_newline = 0;
355         }
356 }
357
358 struct emit_callback {
359         struct xdiff_emit_state xm;
360         int nparents, color_diff;
361         const char **label_path;
362         struct diff_words_data *diff_words;
363 };
364
365 static void free_diff_words_data(struct emit_callback *ecbdata)
366 {
367         if (ecbdata->diff_words) {
368                 /* flush buffers */
369                 if (ecbdata->diff_words->minus.text.size ||
370                                 ecbdata->diff_words->plus.text.size)
371                         diff_words_show(ecbdata->diff_words);
372
373                 if (ecbdata->diff_words->minus.text.ptr)
374                         free (ecbdata->diff_words->minus.text.ptr);
375                 if (ecbdata->diff_words->plus.text.ptr)
376                         free (ecbdata->diff_words->plus.text.ptr);
377                 free(ecbdata->diff_words);
378                 ecbdata->diff_words = NULL;
379         }
380 }
381
382 const char *diff_get_color(int diff_use_color, enum color_diff ix)
383 {
384         if (diff_use_color)
385                 return diff_colors[ix];
386         return "";
387 }
388
389 static void emit_line(const char *set, const char *reset, const char *line, int len)
390 {
391         if (len > 0 && line[len-1] == '\n')
392                 len--;
393         fputs(set, stdout);
394         fwrite(line, len, 1, stdout);
395         puts(reset);
396 }
397
398 static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
399 {
400         int col0 = ecbdata->nparents;
401         int last_tab_in_indent = -1;
402         int last_space_in_indent = -1;
403         int i;
404         int tail = len;
405         int need_highlight_leading_space = 0;
406         const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
407         const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
408
409         if (!*ws) {
410                 emit_line(set, reset, line, len);
411                 return;
412         }
413
414         /* The line is a newly added line.  Does it have funny leading
415          * whitespaces?  In indent, SP should never precede a TAB.
416          */
417         for (i = col0; i < len; i++) {
418                 if (line[i] == '\t') {
419                         last_tab_in_indent = i;
420                         if (0 <= last_space_in_indent)
421                                 need_highlight_leading_space = 1;
422                 }
423                 else if (line[i] == ' ')
424                         last_space_in_indent = i;
425                 else
426                         break;
427         }
428         fputs(set, stdout);
429         fwrite(line, col0, 1, stdout);
430         fputs(reset, stdout);
431         if (((i == len) || line[i] == '\n') && i != col0) {
432                 /* The whole line was indent */
433                 emit_line(ws, reset, line + col0, len - col0);
434                 return;
435         }
436         i = col0;
437         if (need_highlight_leading_space) {
438                 while (i < last_tab_in_indent) {
439                         if (line[i] == ' ') {
440                                 fputs(ws, stdout);
441                                 putchar(' ');
442                                 fputs(reset, stdout);
443                         }
444                         else
445                                 putchar(line[i]);
446                         i++;
447                 }
448         }
449         tail = len - 1;
450         if (line[tail] == '\n' && i < tail)
451                 tail--;
452         while (i < tail) {
453                 if (!isspace(line[tail]))
454                         break;
455                 tail--;
456         }
457         if ((i < tail && line[tail + 1] != '\n')) {
458                 /* This has whitespace between tail+1..len */
459                 fputs(set, stdout);
460                 fwrite(line + i, tail - i + 1, 1, stdout);
461                 fputs(reset, stdout);
462                 emit_line(ws, reset, line + tail + 1, len - tail - 1);
463         }
464         else
465                 emit_line(set, reset, line + i, len - i);
466 }
467
468 static void fn_out_consume(void *priv, char *line, unsigned long len)
469 {
470         int i;
471         int color;
472         struct emit_callback *ecbdata = priv;
473         const char *set = diff_get_color(ecbdata->color_diff, DIFF_METAINFO);
474         const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
475
476         if (ecbdata->label_path[0]) {
477                 printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset);
478                 printf("%s+++ %s%s\n", set, ecbdata->label_path[1], reset);
479                 ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
480         }
481
482         /* This is not really necessary for now because
483          * this codepath only deals with two-way diffs.
484          */
485         for (i = 0; i < len && line[i] == '@'; i++)
486                 ;
487         if (2 <= i && i < len && line[i] == ' ') {
488                 ecbdata->nparents = i - 1;
489                 emit_line(diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO),
490                           reset, line, len);
491                 return;
492         }
493
494         if (len < ecbdata->nparents) {
495                 set = reset;
496                 emit_line(reset, reset, line, len);
497                 return;
498         }
499
500         color = DIFF_PLAIN;
501         if (ecbdata->diff_words && ecbdata->nparents != 1)
502                 /* fall back to normal diff */
503                 free_diff_words_data(ecbdata);
504         if (ecbdata->diff_words) {
505                 if (line[0] == '-') {
506                         diff_words_append(line, len,
507                                           &ecbdata->diff_words->minus);
508                         return;
509                 } else if (line[0] == '+') {
510                         diff_words_append(line, len,
511                                           &ecbdata->diff_words->plus);
512                         return;
513                 }
514                 if (ecbdata->diff_words->minus.text.size ||
515                     ecbdata->diff_words->plus.text.size)
516                         diff_words_show(ecbdata->diff_words);
517                 line++;
518                 len--;
519                 emit_line(set, reset, line, len);
520                 return;
521         }
522         for (i = 0; i < ecbdata->nparents && len; i++) {
523                 if (line[i] == '-')
524                         color = DIFF_FILE_OLD;
525                 else if (line[i] == '+')
526                         color = DIFF_FILE_NEW;
527         }
528
529         if (color != DIFF_FILE_NEW) {
530                 emit_line(diff_get_color(ecbdata->color_diff, color),
531                           reset, line, len);
532                 return;
533         }
534         emit_add_line(reset, ecbdata, line, len);
535 }
536
537 static char *pprint_rename(const char *a, const char *b)
538 {
539         const char *old = a;
540         const char *new = b;
541         char *name = NULL;
542         int pfx_length, sfx_length;
543         int len_a = strlen(a);
544         int len_b = strlen(b);
545
546         /* Find common prefix */
547         pfx_length = 0;
548         while (*old && *new && *old == *new) {
549                 if (*old == '/')
550                         pfx_length = old - a + 1;
551                 old++;
552                 new++;
553         }
554
555         /* Find common suffix */
556         old = a + len_a;
557         new = b + len_b;
558         sfx_length = 0;
559         while (a <= old && b <= new && *old == *new) {
560                 if (*old == '/')
561                         sfx_length = len_a - (old - a);
562                 old--;
563                 new--;
564         }
565
566         /*
567          * pfx{mid-a => mid-b}sfx
568          * {pfx-a => pfx-b}sfx
569          * pfx{sfx-a => sfx-b}
570          * name-a => name-b
571          */
572         if (pfx_length + sfx_length) {
573                 int a_midlen = len_a - pfx_length - sfx_length;
574                 int b_midlen = len_b - pfx_length - sfx_length;
575                 if (a_midlen < 0) a_midlen = 0;
576                 if (b_midlen < 0) b_midlen = 0;
577
578                 name = xmalloc(pfx_length + a_midlen + b_midlen + sfx_length + 7);
579                 sprintf(name, "%.*s{%.*s => %.*s}%s",
580                         pfx_length, a,
581                         a_midlen, a + pfx_length,
582                         b_midlen, b + pfx_length,
583                         a + len_a - sfx_length);
584         }
585         else {
586                 name = xmalloc(len_a + len_b + 5);
587                 sprintf(name, "%s => %s", a, b);
588         }
589         return name;
590 }
591
592 struct diffstat_t {
593         struct xdiff_emit_state xm;
594
595         int nr;
596         int alloc;
597         struct diffstat_file {
598                 char *name;
599                 unsigned is_unmerged:1;
600                 unsigned is_binary:1;
601                 unsigned is_renamed:1;
602                 unsigned int added, deleted;
603         } **files;
604 };
605
606 static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,
607                                           const char *name_a,
608                                           const char *name_b)
609 {
610         struct diffstat_file *x;
611         x = xcalloc(sizeof (*x), 1);
612         if (diffstat->nr == diffstat->alloc) {
613                 diffstat->alloc = alloc_nr(diffstat->alloc);
614                 diffstat->files = xrealloc(diffstat->files,
615                                 diffstat->alloc * sizeof(x));
616         }
617         diffstat->files[diffstat->nr++] = x;
618         if (name_b) {
619                 x->name = pprint_rename(name_a, name_b);
620                 x->is_renamed = 1;
621         }
622         else
623                 x->name = xstrdup(name_a);
624         return x;
625 }
626
627 static void diffstat_consume(void *priv, char *line, unsigned long len)
628 {
629         struct diffstat_t *diffstat = priv;
630         struct diffstat_file *x = diffstat->files[diffstat->nr - 1];
631
632         if (line[0] == '+')
633                 x->added++;
634         else if (line[0] == '-')
635                 x->deleted++;
636 }
637
638 static const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
639 static const char minuses[]= "----------------------------------------------------------------------";
640 const char mime_boundary_leader[] = "------------";
641
642 static void show_stats(struct diffstat_t* data)
643 {
644         int i, len, add, del, total, adds = 0, dels = 0;
645         int max, max_change = 0, max_len = 0;
646         int total_files = data->nr;
647
648         if (data->nr == 0)
649                 return;
650
651         for (i = 0; i < data->nr; i++) {
652                 struct diffstat_file *file = data->files[i];
653
654                 len = strlen(file->name);
655                 if (max_len < len)
656                         max_len = len;
657
658                 if (file->is_binary || file->is_unmerged)
659                         continue;
660                 if (max_change < file->added + file->deleted)
661                         max_change = file->added + file->deleted;
662         }
663
664         for (i = 0; i < data->nr; i++) {
665                 const char *prefix = "";
666                 char *name = data->files[i]->name;
667                 int added = data->files[i]->added;
668                 int deleted = data->files[i]->deleted;
669
670                 if (0 < (len = quote_c_style(name, NULL, NULL, 0))) {
671                         char *qname = xmalloc(len + 1);
672                         quote_c_style(name, qname, NULL, 0);
673                         free(name);
674                         data->files[i]->name = name = qname;
675                 }
676
677                 /*
678                  * "scale" the filename
679                  */
680                 len = strlen(name);
681                 max = max_len;
682                 if (max > 50)
683                         max = 50;
684                 if (len > max) {
685                         char *slash;
686                         prefix = "...";
687                         max -= 3;
688                         name += len - max;
689                         slash = strchr(name, '/');
690                         if (slash)
691                                 name = slash;
692                 }
693                 len = max;
694
695                 /*
696                  * scale the add/delete
697                  */
698                 max = max_change;
699                 if (max + len > 70)
700                         max = 70 - len;
701
702                 if (data->files[i]->is_binary) {
703                         printf(" %s%-*s |  Bin\n", prefix, len, name);
704                         goto free_diffstat_file;
705                 }
706                 else if (data->files[i]->is_unmerged) {
707                         printf(" %s%-*s |  Unmerged\n", prefix, len, name);
708                         goto free_diffstat_file;
709                 }
710                 else if (!data->files[i]->is_renamed &&
711                          (added + deleted == 0)) {
712                         total_files--;
713                         goto free_diffstat_file;
714                 }
715
716                 add = added;
717                 del = deleted;
718                 total = add + del;
719                 adds += add;
720                 dels += del;
721
722                 if (max_change > 0) {
723                         total = (total * max + max_change / 2) / max_change;
724                         add = (add * max + max_change / 2) / max_change;
725                         del = total - add;
726                 }
727                 printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
728                                 len, name, added + deleted,
729                                 add, pluses, del, minuses);
730         free_diffstat_file:
731                 free(data->files[i]->name);
732                 free(data->files[i]);
733         }
734         free(data->files);
735         printf(" %d files changed, %d insertions(+), %d deletions(-)\n",
736                         total_files, adds, dels);
737 }
738
739 struct checkdiff_t {
740         struct xdiff_emit_state xm;
741         const char *filename;
742         int lineno;
743 };
744
745 static void checkdiff_consume(void *priv, char *line, unsigned long len)
746 {
747         struct checkdiff_t *data = priv;
748
749         if (line[0] == '+') {
750                 int i, spaces = 0;
751
752                 data->lineno++;
753
754                 /* check space before tab */
755                 for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++)
756                         if (line[i] == ' ')
757                                 spaces++;
758                 if (line[i - 1] == '\t' && spaces)
759                         printf("%s:%d: space before tab:%.*s\n",
760                                 data->filename, data->lineno, (int)len, line);
761
762                 /* check white space at line end */
763                 if (line[len - 1] == '\n')
764                         len--;
765                 if (isspace(line[len - 1]))
766                         printf("%s:%d: white space at end: %.*s\n",
767                                 data->filename, data->lineno, (int)len, line);
768         } else if (line[0] == ' ')
769                 data->lineno++;
770         else if (line[0] == '@') {
771                 char *plus = strchr(line, '+');
772                 if (plus)
773                         data->lineno = strtol(plus, NULL, 10);
774                 else
775                         die("invalid diff");
776         }
777 }
778
779 static unsigned char *deflate_it(char *data,
780                                  unsigned long size,
781                                  unsigned long *result_size)
782 {
783         int bound;
784         unsigned char *deflated;
785         z_stream stream;
786
787         memset(&stream, 0, sizeof(stream));
788         deflateInit(&stream, zlib_compression_level);
789         bound = deflateBound(&stream, size);
790         deflated = xmalloc(bound);
791         stream.next_out = deflated;
792         stream.avail_out = bound;
793
794         stream.next_in = (unsigned char *)data;
795         stream.avail_in = size;
796         while (deflate(&stream, Z_FINISH) == Z_OK)
797                 ; /* nothing */
798         deflateEnd(&stream);
799         *result_size = stream.total_out;
800         return deflated;
801 }
802
803 static void emit_binary_diff_body(mmfile_t *one, mmfile_t *two)
804 {
805         void *cp;
806         void *delta;
807         void *deflated;
808         void *data;
809         unsigned long orig_size;
810         unsigned long delta_size;
811         unsigned long deflate_size;
812         unsigned long data_size;
813
814         /* We could do deflated delta, or we could do just deflated two,
815          * whichever is smaller.
816          */
817         delta = NULL;
818         deflated = deflate_it(two->ptr, two->size, &deflate_size);
819         if (one->size && two->size) {
820                 delta = diff_delta(one->ptr, one->size,
821                                    two->ptr, two->size,
822                                    &delta_size, deflate_size);
823                 if (delta) {
824                         void *to_free = delta;
825                         orig_size = delta_size;
826                         delta = deflate_it(delta, delta_size, &delta_size);
827                         free(to_free);
828                 }
829         }
830
831         if (delta && delta_size < deflate_size) {
832                 printf("delta %lu\n", orig_size);
833                 free(deflated);
834                 data = delta;
835                 data_size = delta_size;
836         }
837         else {
838                 printf("literal %lu\n", two->size);
839                 free(delta);
840                 data = deflated;
841                 data_size = deflate_size;
842         }
843
844         /* emit data encoded in base85 */
845         cp = data;
846         while (data_size) {
847                 int bytes = (52 < data_size) ? 52 : data_size;
848                 char line[70];
849                 data_size -= bytes;
850                 if (bytes <= 26)
851                         line[0] = bytes + 'A' - 1;
852                 else
853                         line[0] = bytes - 26 + 'a' - 1;
854                 encode_85(line + 1, cp, bytes);
855                 cp = (char *) cp + bytes;
856                 puts(line);
857         }
858         printf("\n");
859         free(data);
860 }
861
862 static void emit_binary_diff(mmfile_t *one, mmfile_t *two)
863 {
864         printf("GIT binary patch\n");
865         emit_binary_diff_body(one, two);
866         emit_binary_diff_body(two, one);
867 }
868
869 #define FIRST_FEW_BYTES 8000
870 static int mmfile_is_binary(mmfile_t *mf)
871 {
872         long sz = mf->size;
873         if (FIRST_FEW_BYTES < sz)
874                 sz = FIRST_FEW_BYTES;
875         return !!memchr(mf->ptr, 0, sz);
876 }
877
878 static void builtin_diff(const char *name_a,
879                          const char *name_b,
880                          struct diff_filespec *one,
881                          struct diff_filespec *two,
882                          const char *xfrm_msg,
883                          struct diff_options *o,
884                          int complete_rewrite)
885 {
886         mmfile_t mf1, mf2;
887         const char *lbl[2];
888         char *a_one, *b_two;
889         const char *set = diff_get_color(o->color_diff, DIFF_METAINFO);
890         const char *reset = diff_get_color(o->color_diff, DIFF_RESET);
891
892         a_one = quote_two("a/", name_a);
893         b_two = quote_two("b/", name_b);
894         lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
895         lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
896         printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset);
897         if (lbl[0][0] == '/') {
898                 /* /dev/null */
899                 printf("%snew file mode %06o%s\n", set, two->mode, reset);
900                 if (xfrm_msg && xfrm_msg[0])
901                         printf("%s%s%s\n", set, xfrm_msg, reset);
902         }
903         else if (lbl[1][0] == '/') {
904                 printf("%sdeleted file mode %06o%s\n", set, one->mode, reset);
905                 if (xfrm_msg && xfrm_msg[0])
906                         printf("%s%s%s\n", set, xfrm_msg, reset);
907         }
908         else {
909                 if (one->mode != two->mode) {
910                         printf("%sold mode %06o%s\n", set, one->mode, reset);
911                         printf("%snew mode %06o%s\n", set, two->mode, reset);
912                 }
913                 if (xfrm_msg && xfrm_msg[0])
914                         printf("%s%s%s\n", set, xfrm_msg, reset);
915                 /*
916                  * we do not run diff between different kind
917                  * of objects.
918                  */
919                 if ((one->mode ^ two->mode) & S_IFMT)
920                         goto free_ab_and_return;
921                 if (complete_rewrite) {
922                         emit_rewrite_diff(name_a, name_b, one, two);
923                         goto free_ab_and_return;
924                 }
925         }
926
927         if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
928                 die("unable to read files to diff");
929
930         if (!o->text && (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))) {
931                 /* Quite common confusing case */
932                 if (mf1.size == mf2.size &&
933                     !memcmp(mf1.ptr, mf2.ptr, mf1.size))
934                         goto free_ab_and_return;
935                 if (o->binary)
936                         emit_binary_diff(&mf1, &mf2);
937                 else
938                         printf("Binary files %s and %s differ\n",
939                                lbl[0], lbl[1]);
940         }
941         else {
942                 /* Crazy xdl interfaces.. */
943                 const char *diffopts = getenv("GIT_DIFF_OPTS");
944                 xpparam_t xpp;
945                 xdemitconf_t xecfg;
946                 xdemitcb_t ecb;
947                 struct emit_callback ecbdata;
948
949                 memset(&ecbdata, 0, sizeof(ecbdata));
950                 ecbdata.label_path = lbl;
951                 ecbdata.color_diff = o->color_diff;
952                 xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
953                 xecfg.ctxlen = o->context;
954                 xecfg.flags = XDL_EMIT_FUNCNAMES;
955                 if (!diffopts)
956                         ;
957                 else if (!strncmp(diffopts, "--unified=", 10))
958                         xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
959                 else if (!strncmp(diffopts, "-u", 2))
960                         xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
961                 ecb.outf = xdiff_outf;
962                 ecb.priv = &ecbdata;
963                 ecbdata.xm.consume = fn_out_consume;
964                 if (o->color_diff_words)
965                         ecbdata.diff_words =
966                                 xcalloc(1, sizeof(struct diff_words_data));
967                 xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
968                 if (o->color_diff_words)
969                         free_diff_words_data(&ecbdata);
970         }
971
972  free_ab_and_return:
973         free(a_one);
974         free(b_two);
975         return;
976 }
977
978 static void builtin_diffstat(const char *name_a, const char *name_b,
979                              struct diff_filespec *one,
980                              struct diff_filespec *two,
981                              struct diffstat_t *diffstat,
982                              struct diff_options *o,
983                              int complete_rewrite)
984 {
985         mmfile_t mf1, mf2;
986         struct diffstat_file *data;
987
988         data = diffstat_add(diffstat, name_a, name_b);
989
990         if (!one || !two) {
991                 data->is_unmerged = 1;
992                 return;
993         }
994         if (complete_rewrite) {
995                 diff_populate_filespec(one, 0);
996                 diff_populate_filespec(two, 0);
997                 data->deleted = count_lines(one->data, one->size);
998                 data->added = count_lines(two->data, two->size);
999                 return;
1000         }
1001         if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
1002                 die("unable to read files to diff");
1003
1004         if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
1005                 data->is_binary = 1;
1006         else {
1007                 /* Crazy xdl interfaces.. */
1008                 xpparam_t xpp;
1009                 xdemitconf_t xecfg;
1010                 xdemitcb_t ecb;
1011
1012                 xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
1013                 xecfg.ctxlen = 0;
1014                 xecfg.flags = 0;
1015                 ecb.outf = xdiff_outf;
1016                 ecb.priv = diffstat;
1017                 xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
1018         }
1019 }
1020
1021 static void builtin_checkdiff(const char *name_a, const char *name_b,
1022                              struct diff_filespec *one,
1023                              struct diff_filespec *two)
1024 {
1025         mmfile_t mf1, mf2;
1026         struct checkdiff_t data;
1027
1028         if (!two)
1029                 return;
1030
1031         memset(&data, 0, sizeof(data));
1032         data.xm.consume = checkdiff_consume;
1033         data.filename = name_b ? name_b : name_a;
1034         data.lineno = 0;
1035
1036         if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
1037                 die("unable to read files to diff");
1038
1039         if (mmfile_is_binary(&mf2))
1040                 return;
1041         else {
1042                 /* Crazy xdl interfaces.. */
1043                 xpparam_t xpp;
1044                 xdemitconf_t xecfg;
1045                 xdemitcb_t ecb;
1046
1047                 xpp.flags = XDF_NEED_MINIMAL;
1048                 xecfg.ctxlen = 0;
1049                 xecfg.flags = 0;
1050                 ecb.outf = xdiff_outf;
1051                 ecb.priv = &data;
1052                 xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
1053         }
1054 }
1055
1056 struct diff_filespec *alloc_filespec(const char *path)
1057 {
1058         int namelen = strlen(path);
1059         struct diff_filespec *spec = xmalloc(sizeof(*spec) + namelen + 1);
1060
1061         memset(spec, 0, sizeof(*spec));
1062         spec->path = (char *)(spec + 1);
1063         memcpy(spec->path, path, namelen+1);
1064         return spec;
1065 }
1066
1067 void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
1068                    unsigned short mode)
1069 {
1070         if (mode) {
1071                 spec->mode = canon_mode(mode);
1072                 hashcpy(spec->sha1, sha1);
1073                 spec->sha1_valid = !is_null_sha1(sha1);
1074         }
1075 }
1076
1077 /*
1078  * Given a name and sha1 pair, if the dircache tells us the file in
1079  * the work tree has that object contents, return true, so that
1080  * prepare_temp_file() does not have to inflate and extract.
1081  */
1082 static int work_tree_matches(const char *name, const unsigned char *sha1)
1083 {
1084         struct cache_entry *ce;
1085         struct stat st;
1086         int pos, len;
1087
1088         /* We do not read the cache ourselves here, because the
1089          * benchmark with my previous version that always reads cache
1090          * shows that it makes things worse for diff-tree comparing
1091          * two linux-2.6 kernel trees in an already checked out work
1092          * tree.  This is because most diff-tree comparisons deal with
1093          * only a small number of files, while reading the cache is
1094          * expensive for a large project, and its cost outweighs the
1095          * savings we get by not inflating the object to a temporary
1096          * file.  Practically, this code only helps when we are used
1097          * by diff-cache --cached, which does read the cache before
1098          * calling us.
1099          */
1100         if (!active_cache)
1101                 return 0;
1102
1103         len = strlen(name);
1104         pos = cache_name_pos(name, len);
1105         if (pos < 0)
1106                 return 0;
1107         ce = active_cache[pos];
1108         if ((lstat(name, &st) < 0) ||
1109             !S_ISREG(st.st_mode) || /* careful! */
1110             ce_match_stat(ce, &st, 0) ||
1111             hashcmp(sha1, ce->sha1))
1112                 return 0;
1113         /* we return 1 only when we can stat, it is a regular file,
1114          * stat information matches, and sha1 recorded in the cache
1115          * matches.  I.e. we know the file in the work tree really is
1116          * the same as the <name, sha1> pair.
1117          */
1118         return 1;
1119 }
1120
1121 static struct sha1_size_cache {
1122         unsigned char sha1[20];
1123         unsigned long size;
1124 } **sha1_size_cache;
1125 static int sha1_size_cache_nr, sha1_size_cache_alloc;
1126
1127 static struct sha1_size_cache *locate_size_cache(unsigned char *sha1,
1128                                                  int find_only,
1129                                                  unsigned long size)
1130 {
1131         int first, last;
1132         struct sha1_size_cache *e;
1133
1134         first = 0;
1135         last = sha1_size_cache_nr;
1136         while (last > first) {
1137                 int cmp, next = (last + first) >> 1;
1138                 e = sha1_size_cache[next];
1139                 cmp = hashcmp(e->sha1, sha1);
1140                 if (!cmp)
1141                         return e;
1142                 if (cmp < 0) {
1143                         last = next;
1144                         continue;
1145                 }
1146                 first = next+1;
1147         }
1148         /* not found */
1149         if (find_only)
1150                 return NULL;
1151         /* insert to make it at "first" */
1152         if (sha1_size_cache_alloc <= sha1_size_cache_nr) {
1153                 sha1_size_cache_alloc = alloc_nr(sha1_size_cache_alloc);
1154                 sha1_size_cache = xrealloc(sha1_size_cache,
1155                                            sha1_size_cache_alloc *
1156                                            sizeof(*sha1_size_cache));
1157         }
1158         sha1_size_cache_nr++;
1159         if (first < sha1_size_cache_nr)
1160                 memmove(sha1_size_cache + first + 1, sha1_size_cache + first,
1161                         (sha1_size_cache_nr - first - 1) *
1162                         sizeof(*sha1_size_cache));
1163         e = xmalloc(sizeof(struct sha1_size_cache));
1164         sha1_size_cache[first] = e;
1165         hashcpy(e->sha1, sha1);
1166         e->size = size;
1167         return e;
1168 }
1169
1170 /*
1171  * While doing rename detection and pickaxe operation, we may need to
1172  * grab the data for the blob (or file) for our own in-core comparison.
1173  * diff_filespec has data and size fields for this purpose.
1174  */
1175 int diff_populate_filespec(struct diff_filespec *s, int size_only)
1176 {
1177         int err = 0;
1178         if (!DIFF_FILE_VALID(s))
1179                 die("internal error: asking to populate invalid file.");
1180         if (S_ISDIR(s->mode))
1181                 return -1;
1182
1183         if (!use_size_cache)
1184                 size_only = 0;
1185
1186         if (s->data)
1187                 return err;
1188         if (!s->sha1_valid ||
1189             work_tree_matches(s->path, s->sha1)) {
1190                 struct stat st;
1191                 int fd;
1192                 if (lstat(s->path, &st) < 0) {
1193                         if (errno == ENOENT) {
1194                         err_empty:
1195                                 err = -1;
1196                         empty:
1197                                 s->data = (char *)"";
1198                                 s->size = 0;
1199                                 return err;
1200                         }
1201                 }
1202                 s->size = st.st_size;
1203                 if (!s->size)
1204                         goto empty;
1205                 if (size_only)
1206                         return 0;
1207                 if (S_ISLNK(st.st_mode)) {
1208                         int ret;
1209                         s->data = xmalloc(s->size);
1210                         s->should_free = 1;
1211                         ret = readlink(s->path, s->data, s->size);
1212                         if (ret < 0) {
1213                                 free(s->data);
1214                                 goto err_empty;
1215                         }
1216                         return 0;
1217                 }
1218                 fd = open(s->path, O_RDONLY);
1219                 if (fd < 0)
1220                         goto err_empty;
1221                 s->data = mmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
1222                 close(fd);
1223                 if (s->data == MAP_FAILED)
1224                         goto err_empty;
1225                 s->should_munmap = 1;
1226         }
1227         else {
1228                 char type[20];
1229                 struct sha1_size_cache *e;
1230
1231                 if (size_only) {
1232                         e = locate_size_cache(s->sha1, 1, 0);
1233                         if (e) {
1234                                 s->size = e->size;
1235                                 return 0;
1236                         }
1237                         if (!sha1_object_info(s->sha1, type, &s->size))
1238                                 locate_size_cache(s->sha1, 0, s->size);
1239                 }
1240                 else {
1241                         s->data = read_sha1_file(s->sha1, type, &s->size);
1242                         s->should_free = 1;
1243                 }
1244         }
1245         return 0;
1246 }
1247
1248 void diff_free_filespec_data(struct diff_filespec *s)
1249 {
1250         if (s->should_free)
1251                 free(s->data);
1252         else if (s->should_munmap)
1253                 munmap(s->data, s->size);
1254         s->should_free = s->should_munmap = 0;
1255         s->data = NULL;
1256         free(s->cnt_data);
1257         s->cnt_data = NULL;
1258 }
1259
1260 static void prep_temp_blob(struct diff_tempfile *temp,
1261                            void *blob,
1262                            unsigned long size,
1263                            const unsigned char *sha1,
1264                            int mode)
1265 {
1266         int fd;
1267
1268         fd = git_mkstemp(temp->tmp_path, TEMPFILE_PATH_LEN, ".diff_XXXXXX");
1269         if (fd < 0)
1270                 die("unable to create temp-file");
1271         if (write(fd, blob, size) != size)
1272                 die("unable to write temp-file");
1273         close(fd);
1274         temp->name = temp->tmp_path;
1275         strcpy(temp->hex, sha1_to_hex(sha1));
1276         temp->hex[40] = 0;
1277         sprintf(temp->mode, "%06o", mode);
1278 }
1279
1280 static void prepare_temp_file(const char *name,
1281                               struct diff_tempfile *temp,
1282                               struct diff_filespec *one)
1283 {
1284         if (!DIFF_FILE_VALID(one)) {
1285         not_a_valid_file:
1286                 /* A '-' entry produces this for file-2, and
1287                  * a '+' entry produces this for file-1.
1288                  */
1289                 temp->name = "/dev/null";
1290                 strcpy(temp->hex, ".");
1291                 strcpy(temp->mode, ".");
1292                 return;
1293         }
1294
1295         if (!one->sha1_valid ||
1296             work_tree_matches(name, one->sha1)) {
1297                 struct stat st;
1298                 if (lstat(name, &st) < 0) {
1299                         if (errno == ENOENT)
1300                                 goto not_a_valid_file;
1301                         die("stat(%s): %s", name, strerror(errno));
1302                 }
1303                 if (S_ISLNK(st.st_mode)) {
1304                         int ret;
1305                         char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
1306                         if (sizeof(buf) <= st.st_size)
1307                                 die("symlink too long: %s", name);
1308                         ret = readlink(name, buf, st.st_size);
1309                         if (ret < 0)
1310                                 die("readlink(%s)", name);
1311                         prep_temp_blob(temp, buf, st.st_size,
1312                                        (one->sha1_valid ?
1313                                         one->sha1 : null_sha1),
1314                                        (one->sha1_valid ?
1315                                         one->mode : S_IFLNK));
1316                 }
1317                 else {
1318                         /* we can borrow from the file in the work tree */
1319                         temp->name = name;
1320                         if (!one->sha1_valid)
1321                                 strcpy(temp->hex, sha1_to_hex(null_sha1));
1322                         else
1323                                 strcpy(temp->hex, sha1_to_hex(one->sha1));
1324                         /* Even though we may sometimes borrow the
1325                          * contents from the work tree, we always want
1326                          * one->mode.  mode is trustworthy even when
1327                          * !(one->sha1_valid), as long as
1328                          * DIFF_FILE_VALID(one).
1329                          */
1330                         sprintf(temp->mode, "%06o", one->mode);
1331                 }
1332                 return;
1333         }
1334         else {
1335                 if (diff_populate_filespec(one, 0))
1336                         die("cannot read data blob for %s", one->path);
1337                 prep_temp_blob(temp, one->data, one->size,
1338                                one->sha1, one->mode);
1339         }
1340 }
1341
1342 static void remove_tempfile(void)
1343 {
1344         int i;
1345
1346         for (i = 0; i < 2; i++)
1347                 if (diff_temp[i].name == diff_temp[i].tmp_path) {
1348                         unlink(diff_temp[i].name);
1349                         diff_temp[i].name = NULL;
1350                 }
1351 }
1352
1353 static void remove_tempfile_on_signal(int signo)
1354 {
1355         remove_tempfile();
1356         signal(SIGINT, SIG_DFL);
1357         raise(signo);
1358 }
1359
1360 static int spawn_prog(const char *pgm, const char **arg)
1361 {
1362         pid_t pid;
1363         int status;
1364
1365         fflush(NULL);
1366         pid = fork();
1367         if (pid < 0)
1368                 die("unable to fork");
1369         if (!pid) {
1370                 execvp(pgm, (char *const*) arg);
1371                 exit(255);
1372         }
1373
1374         while (waitpid(pid, &status, 0) < 0) {
1375                 if (errno == EINTR)
1376                         continue;
1377                 return -1;
1378         }
1379
1380         /* Earlier we did not check the exit status because
1381          * diff exits non-zero if files are different, and
1382          * we are not interested in knowing that.  It was a
1383          * mistake which made it harder to quit a diff-*
1384          * session that uses the git-apply-patch-script as
1385          * the GIT_EXTERNAL_DIFF.  A custom GIT_EXTERNAL_DIFF
1386          * should also exit non-zero only when it wants to
1387          * abort the entire diff-* session.
1388          */
1389         if (WIFEXITED(status) && !WEXITSTATUS(status))
1390                 return 0;
1391         return -1;
1392 }
1393
1394 /* An external diff command takes:
1395  *
1396  * diff-cmd name infile1 infile1-sha1 infile1-mode \
1397  *               infile2 infile2-sha1 infile2-mode [ rename-to ]
1398  *
1399  */
1400 static void run_external_diff(const char *pgm,
1401                               const char *name,
1402                               const char *other,
1403                               struct diff_filespec *one,
1404                               struct diff_filespec *two,
1405                               const char *xfrm_msg,
1406                               int complete_rewrite)
1407 {
1408         const char *spawn_arg[10];
1409         struct diff_tempfile *temp = diff_temp;
1410         int retval;
1411         static int atexit_asked = 0;
1412         const char *othername;
1413         const char **arg = &spawn_arg[0];
1414
1415         othername = (other? other : name);
1416         if (one && two) {
1417                 prepare_temp_file(name, &temp[0], one);
1418                 prepare_temp_file(othername, &temp[1], two);
1419                 if (! atexit_asked &&
1420                     (temp[0].name == temp[0].tmp_path ||
1421                      temp[1].name == temp[1].tmp_path)) {
1422                         atexit_asked = 1;
1423                         atexit(remove_tempfile);
1424                 }
1425                 signal(SIGINT, remove_tempfile_on_signal);
1426         }
1427
1428         if (one && two) {
1429                 *arg++ = pgm;
1430                 *arg++ = name;
1431                 *arg++ = temp[0].name;
1432                 *arg++ = temp[0].hex;
1433                 *arg++ = temp[0].mode;
1434                 *arg++ = temp[1].name;
1435                 *arg++ = temp[1].hex;
1436                 *arg++ = temp[1].mode;
1437                 if (other) {
1438                         *arg++ = other;
1439                         *arg++ = xfrm_msg;
1440                 }
1441         } else {
1442                 *arg++ = pgm;
1443                 *arg++ = name;
1444         }
1445         *arg = NULL;
1446         retval = spawn_prog(pgm, spawn_arg);
1447         remove_tempfile();
1448         if (retval) {
1449                 fprintf(stderr, "external diff died, stopping at %s.\n", name);
1450                 exit(1);
1451         }
1452 }
1453
1454 static void run_diff_cmd(const char *pgm,
1455                          const char *name,
1456                          const char *other,
1457                          struct diff_filespec *one,
1458                          struct diff_filespec *two,
1459                          const char *xfrm_msg,
1460                          struct diff_options *o,
1461                          int complete_rewrite)
1462 {
1463         if (pgm) {
1464                 run_external_diff(pgm, name, other, one, two, xfrm_msg,
1465                                   complete_rewrite);
1466                 return;
1467         }
1468         if (one && two)
1469                 builtin_diff(name, other ? other : name,
1470                              one, two, xfrm_msg, o, complete_rewrite);
1471         else
1472                 printf("* Unmerged path %s\n", name);
1473 }
1474
1475 static void diff_fill_sha1_info(struct diff_filespec *one)
1476 {
1477         if (DIFF_FILE_VALID(one)) {
1478                 if (!one->sha1_valid) {
1479                         struct stat st;
1480                         if (lstat(one->path, &st) < 0)
1481                                 die("stat %s", one->path);
1482                         if (index_path(one->sha1, one->path, &st, 0))
1483                                 die("cannot hash %s\n", one->path);
1484                 }
1485         }
1486         else
1487                 hashclr(one->sha1);
1488 }
1489
1490 static void run_diff(struct diff_filepair *p, struct diff_options *o)
1491 {
1492         const char *pgm = external_diff();
1493         char msg[PATH_MAX*2+300], *xfrm_msg;
1494         struct diff_filespec *one;
1495         struct diff_filespec *two;
1496         const char *name;
1497         const char *other;
1498         char *name_munged, *other_munged;
1499         int complete_rewrite = 0;
1500         int len;
1501
1502         if (DIFF_PAIR_UNMERGED(p)) {
1503                 /* unmerged */
1504                 run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, o, 0);
1505                 return;
1506         }
1507
1508         name = p->one->path;
1509         other = (strcmp(name, p->two->path) ? p->two->path : NULL);
1510         name_munged = quote_one(name);
1511         other_munged = quote_one(other);
1512         one = p->one; two = p->two;
1513
1514         diff_fill_sha1_info(one);
1515         diff_fill_sha1_info(two);
1516
1517         len = 0;
1518         switch (p->status) {
1519         case DIFF_STATUS_COPIED:
1520                 len += snprintf(msg + len, sizeof(msg) - len,
1521                                 "similarity index %d%%\n"
1522                                 "copy from %s\n"
1523                                 "copy to %s\n",
1524                                 (int)(0.5 + p->score * 100.0/MAX_SCORE),
1525                                 name_munged, other_munged);
1526                 break;
1527         case DIFF_STATUS_RENAMED:
1528                 len += snprintf(msg + len, sizeof(msg) - len,
1529                                 "similarity index %d%%\n"
1530                                 "rename from %s\n"
1531                                 "rename to %s\n",
1532                                 (int)(0.5 + p->score * 100.0/MAX_SCORE),
1533                                 name_munged, other_munged);
1534                 break;
1535         case DIFF_STATUS_MODIFIED:
1536                 if (p->score) {
1537                         len += snprintf(msg + len, sizeof(msg) - len,
1538                                         "dissimilarity index %d%%\n",
1539                                         (int)(0.5 + p->score *
1540                                               100.0/MAX_SCORE));
1541                         complete_rewrite = 1;
1542                         break;
1543                 }
1544                 /* fallthru */
1545         default:
1546                 /* nothing */
1547                 ;
1548         }
1549
1550         if (hashcmp(one->sha1, two->sha1)) {
1551                 int abbrev = o->full_index ? 40 : DEFAULT_ABBREV;
1552
1553                 if (o->binary) {
1554                         mmfile_t mf;
1555                         if ((!fill_mmfile(&mf, one) && mmfile_is_binary(&mf)) ||
1556                             (!fill_mmfile(&mf, two) && mmfile_is_binary(&mf)))
1557                                 abbrev = 40;
1558                 }
1559                 len += snprintf(msg + len, sizeof(msg) - len,
1560                                 "index %.*s..%.*s",
1561                                 abbrev, sha1_to_hex(one->sha1),
1562                                 abbrev, sha1_to_hex(two->sha1));
1563                 if (one->mode == two->mode)
1564                         len += snprintf(msg + len, sizeof(msg) - len,
1565                                         " %06o", one->mode);
1566                 len += snprintf(msg + len, sizeof(msg) - len, "\n");
1567         }
1568
1569         if (len)
1570                 msg[--len] = 0;
1571         xfrm_msg = len ? msg : NULL;
1572
1573         if (!pgm &&
1574             DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
1575             (S_IFMT & one->mode) != (S_IFMT & two->mode)) {
1576                 /* a filepair that changes between file and symlink
1577                  * needs to be split into deletion and creation.
1578                  */
1579                 struct diff_filespec *null = alloc_filespec(two->path);
1580                 run_diff_cmd(NULL, name, other, one, null, xfrm_msg, o, 0);
1581                 free(null);
1582                 null = alloc_filespec(one->path);
1583                 run_diff_cmd(NULL, name, other, null, two, xfrm_msg, o, 0);
1584                 free(null);
1585         }
1586         else
1587                 run_diff_cmd(pgm, name, other, one, two, xfrm_msg, o,
1588                              complete_rewrite);
1589
1590         free(name_munged);
1591         free(other_munged);
1592 }
1593
1594 static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
1595                          struct diffstat_t *diffstat)
1596 {
1597         const char *name;
1598         const char *other;
1599         int complete_rewrite = 0;
1600
1601         if (DIFF_PAIR_UNMERGED(p)) {
1602                 /* unmerged */
1603                 builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, 0);
1604                 return;
1605         }
1606
1607         name = p->one->path;
1608         other = (strcmp(name, p->two->path) ? p->two->path : NULL);
1609
1610         diff_fill_sha1_info(p->one);
1611         diff_fill_sha1_info(p->two);
1612
1613         if (p->status == DIFF_STATUS_MODIFIED && p->score)
1614                 complete_rewrite = 1;
1615         builtin_diffstat(name, other, p->one, p->two, diffstat, o, complete_rewrite);
1616 }
1617
1618 static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
1619 {
1620         const char *name;
1621         const char *other;
1622
1623         if (DIFF_PAIR_UNMERGED(p)) {
1624                 /* unmerged */
1625                 return;
1626         }
1627
1628         name = p->one->path;
1629         other = (strcmp(name, p->two->path) ? p->two->path : NULL);
1630
1631         diff_fill_sha1_info(p->one);
1632         diff_fill_sha1_info(p->two);
1633
1634         builtin_checkdiff(name, other, p->one, p->two);
1635 }
1636
1637 void diff_setup(struct diff_options *options)
1638 {
1639         memset(options, 0, sizeof(*options));
1640         options->line_termination = '\n';
1641         options->break_opt = -1;
1642         options->rename_limit = -1;
1643         options->context = 3;
1644         options->msg_sep = "";
1645
1646         options->change = diff_change;
1647         options->add_remove = diff_addremove;
1648         options->color_diff = diff_use_color_default;
1649         options->detect_rename = diff_detect_rename_default;
1650 }
1651
1652 int diff_setup_done(struct diff_options *options)
1653 {
1654         int count = 0;
1655
1656         if (options->output_format & DIFF_FORMAT_NAME)
1657                 count++;
1658         if (options->output_format & DIFF_FORMAT_NAME_STATUS)
1659                 count++;
1660         if (options->output_format & DIFF_FORMAT_CHECKDIFF)
1661                 count++;
1662         if (options->output_format & DIFF_FORMAT_NO_OUTPUT)
1663                 count++;
1664         if (count > 1)
1665                 die("--name-only, --name-status, --check and -s are mutually exclusive");
1666
1667         if (options->find_copies_harder)
1668                 options->detect_rename = DIFF_DETECT_COPY;
1669
1670         if (options->output_format & (DIFF_FORMAT_NAME |
1671                                       DIFF_FORMAT_NAME_STATUS |
1672                                       DIFF_FORMAT_CHECKDIFF |
1673                                       DIFF_FORMAT_NO_OUTPUT))
1674                 options->output_format &= ~(DIFF_FORMAT_RAW |
1675                                             DIFF_FORMAT_DIFFSTAT |
1676                                             DIFF_FORMAT_SUMMARY |
1677                                             DIFF_FORMAT_PATCH);
1678
1679         /*
1680          * These cases always need recursive; we do not drop caller-supplied
1681          * recursive bits for other formats here.
1682          */
1683         if (options->output_format & (DIFF_FORMAT_PATCH |
1684                                       DIFF_FORMAT_DIFFSTAT |
1685                                       DIFF_FORMAT_CHECKDIFF))
1686                 options->recursive = 1;
1687         /*
1688          * Also pickaxe would not work very well if you do not say recursive
1689          */
1690         if (options->pickaxe)
1691                 options->recursive = 1;
1692
1693         if (options->detect_rename && options->rename_limit < 0)
1694                 options->rename_limit = diff_rename_limit_default;
1695         if (options->setup & DIFF_SETUP_USE_CACHE) {
1696                 if (!active_cache)
1697                         /* read-cache does not die even when it fails
1698                          * so it is safe for us to do this here.  Also
1699                          * it does not smudge active_cache or active_nr
1700                          * when it fails, so we do not have to worry about
1701                          * cleaning it up ourselves either.
1702                          */
1703                         read_cache();
1704         }
1705         if (options->setup & DIFF_SETUP_USE_SIZE_CACHE)
1706                 use_size_cache = 1;
1707         if (options->abbrev <= 0 || 40 < options->abbrev)
1708                 options->abbrev = 40; /* full */
1709
1710         return 0;
1711 }
1712
1713 static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
1714 {
1715         char c, *eq;
1716         int len;
1717
1718         if (*arg != '-')
1719                 return 0;
1720         c = *++arg;
1721         if (!c)
1722                 return 0;
1723         if (c == arg_short) {
1724                 c = *++arg;
1725                 if (!c)
1726                         return 1;
1727                 if (val && isdigit(c)) {
1728                         char *end;
1729                         int n = strtoul(arg, &end, 10);
1730                         if (*end)
1731                                 return 0;
1732                         *val = n;
1733                         return 1;
1734                 }
1735                 return 0;
1736         }
1737         if (c != '-')
1738                 return 0;
1739         arg++;
1740         eq = strchr(arg, '=');
1741         if (eq)
1742                 len = eq - arg;
1743         else
1744                 len = strlen(arg);
1745         if (!len || strncmp(arg, arg_long, len))
1746                 return 0;
1747         if (eq) {
1748                 int n;
1749                 char *end;
1750                 if (!isdigit(*++eq))
1751                         return 0;
1752                 n = strtoul(eq, &end, 10);
1753                 if (*end)
1754                         return 0;
1755                 *val = n;
1756         }
1757         return 1;
1758 }
1759
1760 int diff_opt_parse(struct diff_options *options, const char **av, int ac)
1761 {
1762         const char *arg = av[0];
1763         if (!strcmp(arg, "-p") || !strcmp(arg, "-u"))
1764                 options->output_format |= DIFF_FORMAT_PATCH;
1765         else if (opt_arg(arg, 'U', "unified", &options->context))
1766                 options->output_format |= DIFF_FORMAT_PATCH;
1767         else if (!strcmp(arg, "--raw"))
1768                 options->output_format |= DIFF_FORMAT_RAW;
1769         else if (!strcmp(arg, "--patch-with-raw")) {
1770                 options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW;
1771         }
1772         else if (!strcmp(arg, "--stat"))
1773                 options->output_format |= DIFF_FORMAT_DIFFSTAT;
1774         else if (!strcmp(arg, "--check"))
1775                 options->output_format |= DIFF_FORMAT_CHECKDIFF;
1776         else if (!strcmp(arg, "--summary"))
1777                 options->output_format |= DIFF_FORMAT_SUMMARY;
1778         else if (!strcmp(arg, "--patch-with-stat")) {
1779                 options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT;
1780         }
1781         else if (!strcmp(arg, "-z"))
1782                 options->line_termination = 0;
1783         else if (!strncmp(arg, "-l", 2))
1784                 options->rename_limit = strtoul(arg+2, NULL, 10);
1785         else if (!strcmp(arg, "--full-index"))
1786                 options->full_index = 1;
1787         else if (!strcmp(arg, "--binary")) {
1788                 options->output_format |= DIFF_FORMAT_PATCH;
1789                 options->binary = 1;
1790         }
1791         else if (!strcmp(arg, "-a") || !strcmp(arg, "--text")) {
1792                 options->text = 1;
1793         }
1794         else if (!strcmp(arg, "--name-only"))
1795                 options->output_format |= DIFF_FORMAT_NAME;
1796         else if (!strcmp(arg, "--name-status"))
1797                 options->output_format |= DIFF_FORMAT_NAME_STATUS;
1798         else if (!strcmp(arg, "-R"))
1799                 options->reverse_diff = 1;
1800         else if (!strncmp(arg, "-S", 2))
1801                 options->pickaxe = arg + 2;
1802         else if (!strcmp(arg, "-s")) {
1803                 options->output_format |= DIFF_FORMAT_NO_OUTPUT;
1804         }
1805         else if (!strncmp(arg, "-O", 2))
1806                 options->orderfile = arg + 2;
1807         else if (!strncmp(arg, "--diff-filter=", 14))
1808                 options->filter = arg + 14;
1809         else if (!strcmp(arg, "--pickaxe-all"))
1810                 options->pickaxe_opts = DIFF_PICKAXE_ALL;
1811         else if (!strcmp(arg, "--pickaxe-regex"))
1812                 options->pickaxe_opts = DIFF_PICKAXE_REGEX;
1813         else if (!strncmp(arg, "-B", 2)) {
1814                 if ((options->break_opt =
1815                      diff_scoreopt_parse(arg)) == -1)
1816                         return -1;
1817         }
1818         else if (!strncmp(arg, "-M", 2)) {
1819                 if ((options->rename_score =
1820                      diff_scoreopt_parse(arg)) == -1)
1821                         return -1;
1822                 options->detect_rename = DIFF_DETECT_RENAME;
1823         }
1824         else if (!strncmp(arg, "-C", 2)) {
1825                 if ((options->rename_score =
1826                      diff_scoreopt_parse(arg)) == -1)
1827                         return -1;
1828                 options->detect_rename = DIFF_DETECT_COPY;
1829         }
1830         else if (!strcmp(arg, "--find-copies-harder"))
1831                 options->find_copies_harder = 1;
1832         else if (!strcmp(arg, "--abbrev"))
1833                 options->abbrev = DEFAULT_ABBREV;
1834         else if (!strncmp(arg, "--abbrev=", 9)) {
1835                 options->abbrev = strtoul(arg + 9, NULL, 10);
1836                 if (options->abbrev < MINIMUM_ABBREV)
1837                         options->abbrev = MINIMUM_ABBREV;
1838                 else if (40 < options->abbrev)
1839                         options->abbrev = 40;
1840         }
1841         else if (!strcmp(arg, "--color"))
1842                 options->color_diff = 1;
1843         else if (!strcmp(arg, "--no-color"))
1844                 options->color_diff = 0;
1845         else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
1846                 options->xdl_opts |= XDF_IGNORE_WHITESPACE;
1847         else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
1848                 options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
1849         else if (!strcmp(arg, "--color-words"))
1850                 options->color_diff = options->color_diff_words = 1;
1851         else if (!strcmp(arg, "--no-renames"))
1852                 options->detect_rename = 0;
1853         else
1854                 return 0;
1855         return 1;
1856 }
1857
1858 static int parse_num(const char **cp_p)
1859 {
1860         unsigned long num, scale;
1861         int ch, dot;
1862         const char *cp = *cp_p;
1863
1864         num = 0;
1865         scale = 1;
1866         dot = 0;
1867         for(;;) {
1868                 ch = *cp;
1869                 if ( !dot && ch == '.' ) {
1870                         scale = 1;
1871                         dot = 1;
1872                 } else if ( ch == '%' ) {
1873                         scale = dot ? scale*100 : 100;
1874                         cp++;   /* % is always at the end */
1875                         break;
1876                 } else if ( ch >= '0' && ch <= '9' ) {
1877                         if ( scale < 100000 ) {
1878                                 scale *= 10;
1879                                 num = (num*10) + (ch-'0');
1880                         }
1881                 } else {
1882                         break;
1883                 }
1884                 cp++;
1885         }
1886         *cp_p = cp;
1887
1888         /* user says num divided by scale and we say internally that
1889          * is MAX_SCORE * num / scale.
1890          */
1891         return (num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale);
1892 }
1893
1894 int diff_scoreopt_parse(const char *opt)
1895 {
1896         int opt1, opt2, cmd;
1897
1898         if (*opt++ != '-')
1899                 return -1;
1900         cmd = *opt++;
1901         if (cmd != 'M' && cmd != 'C' && cmd != 'B')
1902                 return -1; /* that is not a -M, -C nor -B option */
1903
1904         opt1 = parse_num(&opt);
1905         if (cmd != 'B')
1906                 opt2 = 0;
1907         else {
1908                 if (*opt == 0)
1909                         opt2 = 0;
1910                 else if (*opt != '/')
1911                         return -1; /* we expect -B80/99 or -B80 */
1912                 else {
1913                         opt++;
1914                         opt2 = parse_num(&opt);
1915                 }
1916         }
1917         if (*opt != 0)
1918                 return -1;
1919         return opt1 | (opt2 << 16);
1920 }
1921
1922 struct diff_queue_struct diff_queued_diff;
1923
1924 void diff_q(struct diff_queue_struct *queue, struct diff_filepair *dp)
1925 {
1926         if (queue->alloc <= queue->nr) {
1927                 queue->alloc = alloc_nr(queue->alloc);
1928                 queue->queue = xrealloc(queue->queue,
1929                                         sizeof(dp) * queue->alloc);
1930         }
1931         queue->queue[queue->nr++] = dp;
1932 }
1933
1934 struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
1935                                  struct diff_filespec *one,
1936                                  struct diff_filespec *two)
1937 {
1938         struct diff_filepair *dp = xcalloc(1, sizeof(*dp));
1939         dp->one = one;
1940         dp->two = two;
1941         if (queue)
1942                 diff_q(queue, dp);
1943         return dp;
1944 }
1945
1946 void diff_free_filepair(struct diff_filepair *p)
1947 {
1948         diff_free_filespec_data(p->one);
1949         diff_free_filespec_data(p->two);
1950         free(p->one);
1951         free(p->two);
1952         free(p);
1953 }
1954
1955 /* This is different from find_unique_abbrev() in that
1956  * it stuffs the result with dots for alignment.
1957  */
1958 const char *diff_unique_abbrev(const unsigned char *sha1, int len)
1959 {
1960         int abblen;
1961         const char *abbrev;
1962         if (len == 40)
1963                 return sha1_to_hex(sha1);
1964
1965         abbrev = find_unique_abbrev(sha1, len);
1966         if (!abbrev)
1967                 return sha1_to_hex(sha1);
1968         abblen = strlen(abbrev);
1969         if (abblen < 37) {
1970                 static char hex[41];
1971                 if (len < abblen && abblen <= len + 2)
1972                         sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
1973                 else
1974                         sprintf(hex, "%s...", abbrev);
1975                 return hex;
1976         }
1977         return sha1_to_hex(sha1);
1978 }
1979
1980 static void diff_flush_raw(struct diff_filepair *p,
1981                            struct diff_options *options)
1982 {
1983         int two_paths;
1984         char status[10];
1985         int abbrev = options->abbrev;
1986         const char *path_one, *path_two;
1987         int inter_name_termination = '\t';
1988         int line_termination = options->line_termination;
1989
1990         if (!line_termination)
1991                 inter_name_termination = 0;
1992
1993         path_one = p->one->path;
1994         path_two = p->two->path;
1995         if (line_termination) {
1996                 path_one = quote_one(path_one);
1997                 path_two = quote_one(path_two);
1998         }
1999
2000         if (p->score)
2001                 sprintf(status, "%c%03d", p->status,
2002                         (int)(0.5 + p->score * 100.0/MAX_SCORE));
2003         else {
2004                 status[0] = p->status;
2005                 status[1] = 0;
2006         }
2007         switch (p->status) {
2008         case DIFF_STATUS_COPIED:
2009         case DIFF_STATUS_RENAMED:
2010                 two_paths = 1;
2011                 break;
2012         case DIFF_STATUS_ADDED:
2013         case DIFF_STATUS_DELETED:
2014                 two_paths = 0;
2015                 break;
2016         default:
2017                 two_paths = 0;
2018                 break;
2019         }
2020         if (!(options->output_format & DIFF_FORMAT_NAME_STATUS)) {
2021                 printf(":%06o %06o %s ",
2022                        p->one->mode, p->two->mode,
2023                        diff_unique_abbrev(p->one->sha1, abbrev));
2024                 printf("%s ",
2025                        diff_unique_abbrev(p->two->sha1, abbrev));
2026         }
2027         printf("%s%c%s", status, inter_name_termination, path_one);
2028         if (two_paths)
2029                 printf("%c%s", inter_name_termination, path_two);
2030         putchar(line_termination);
2031         if (path_one != p->one->path)
2032                 free((void*)path_one);
2033         if (path_two != p->two->path)
2034                 free((void*)path_two);
2035 }
2036
2037 static void diff_flush_name(struct diff_filepair *p, int line_termination)
2038 {
2039         char *path = p->two->path;
2040
2041         if (line_termination)
2042                 path = quote_one(p->two->path);
2043         printf("%s%c", path, line_termination);
2044         if (p->two->path != path)
2045                 free(path);
2046 }
2047
2048 int diff_unmodified_pair(struct diff_filepair *p)
2049 {
2050         /* This function is written stricter than necessary to support
2051          * the currently implemented transformers, but the idea is to
2052          * let transformers to produce diff_filepairs any way they want,
2053          * and filter and clean them up here before producing the output.
2054          */
2055         struct diff_filespec *one, *two;
2056
2057         if (DIFF_PAIR_UNMERGED(p))
2058                 return 0; /* unmerged is interesting */
2059
2060         one = p->one;
2061         two = p->two;
2062
2063         /* deletion, addition, mode or type change
2064          * and rename are all interesting.
2065          */
2066         if (DIFF_FILE_VALID(one) != DIFF_FILE_VALID(two) ||
2067             DIFF_PAIR_MODE_CHANGED(p) ||
2068             strcmp(one->path, two->path))
2069                 return 0;
2070
2071         /* both are valid and point at the same path.  that is, we are
2072          * dealing with a change.
2073          */
2074         if (one->sha1_valid && two->sha1_valid &&
2075             !hashcmp(one->sha1, two->sha1))
2076                 return 1; /* no change */
2077         if (!one->sha1_valid && !two->sha1_valid)
2078                 return 1; /* both look at the same file on the filesystem. */
2079         return 0;
2080 }
2081
2082 static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
2083 {
2084         if (diff_unmodified_pair(p))
2085                 return;
2086
2087         if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
2088             (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
2089                 return; /* no tree diffs in patch format */
2090
2091         run_diff(p, o);
2092 }
2093
2094 static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
2095                             struct diffstat_t *diffstat)
2096 {
2097         if (diff_unmodified_pair(p))
2098                 return;
2099
2100         if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
2101             (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
2102                 return; /* no tree diffs in patch format */
2103
2104         run_diffstat(p, o, diffstat);
2105 }
2106
2107 static void diff_flush_checkdiff(struct diff_filepair *p,
2108                 struct diff_options *o)
2109 {
2110         if (diff_unmodified_pair(p))
2111                 return;
2112
2113         if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
2114             (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
2115                 return; /* no tree diffs in patch format */
2116
2117         run_checkdiff(p, o);
2118 }
2119
2120 int diff_queue_is_empty(void)
2121 {
2122         struct diff_queue_struct *q = &diff_queued_diff;
2123         int i;
2124         for (i = 0; i < q->nr; i++)
2125                 if (!diff_unmodified_pair(q->queue[i]))
2126                         return 0;
2127         return 1;
2128 }
2129
2130 #if DIFF_DEBUG
2131 void diff_debug_filespec(struct diff_filespec *s, int x, const char *one)
2132 {
2133         fprintf(stderr, "queue[%d] %s (%s) %s %06o %s\n",
2134                 x, one ? one : "",
2135                 s->path,
2136                 DIFF_FILE_VALID(s) ? "valid" : "invalid",
2137                 s->mode,
2138                 s->sha1_valid ? sha1_to_hex(s->sha1) : "");
2139         fprintf(stderr, "queue[%d] %s size %lu flags %d\n",
2140                 x, one ? one : "",
2141                 s->size, s->xfrm_flags);
2142 }
2143
2144 void diff_debug_filepair(const struct diff_filepair *p, int i)
2145 {
2146         diff_debug_filespec(p->one, i, "one");
2147         diff_debug_filespec(p->two, i, "two");
2148         fprintf(stderr, "score %d, status %c stays %d broken %d\n",
2149                 p->score, p->status ? p->status : '?',
2150                 p->source_stays, p->broken_pair);
2151 }
2152
2153 void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
2154 {
2155         int i;
2156         if (msg)
2157                 fprintf(stderr, "%s\n", msg);
2158         fprintf(stderr, "q->nr = %d\n", q->nr);
2159         for (i = 0; i < q->nr; i++) {
2160                 struct diff_filepair *p = q->queue[i];
2161                 diff_debug_filepair(p, i);
2162         }
2163 }
2164 #endif
2165
2166 static void diff_resolve_rename_copy(void)
2167 {
2168         int i, j;
2169         struct diff_filepair *p, *pp;
2170         struct diff_queue_struct *q = &diff_queued_diff;
2171
2172         diff_debug_queue("resolve-rename-copy", q);
2173
2174         for (i = 0; i < q->nr; i++) {
2175                 p = q->queue[i];
2176                 p->status = 0; /* undecided */
2177                 if (DIFF_PAIR_UNMERGED(p))
2178                         p->status = DIFF_STATUS_UNMERGED;
2179                 else if (!DIFF_FILE_VALID(p->one))
2180                         p->status = DIFF_STATUS_ADDED;
2181                 else if (!DIFF_FILE_VALID(p->two))
2182                         p->status = DIFF_STATUS_DELETED;
2183                 else if (DIFF_PAIR_TYPE_CHANGED(p))
2184                         p->status = DIFF_STATUS_TYPE_CHANGED;
2185
2186                 /* from this point on, we are dealing with a pair
2187                  * whose both sides are valid and of the same type, i.e.
2188                  * either in-place edit or rename/copy edit.
2189                  */
2190                 else if (DIFF_PAIR_RENAME(p)) {
2191                         if (p->source_stays) {
2192                                 p->status = DIFF_STATUS_COPIED;
2193                                 continue;
2194                         }
2195                         /* See if there is some other filepair that
2196                          * copies from the same source as us.  If so
2197                          * we are a copy.  Otherwise we are either a
2198                          * copy if the path stays, or a rename if it
2199                          * does not, but we already handled "stays" case.
2200                          */
2201                         for (j = i + 1; j < q->nr; j++) {
2202                                 pp = q->queue[j];
2203                                 if (strcmp(pp->one->path, p->one->path))
2204                                         continue; /* not us */
2205                                 if (!DIFF_PAIR_RENAME(pp))
2206                                         continue; /* not a rename/copy */
2207                                 /* pp is a rename/copy from the same source */
2208                                 p->status = DIFF_STATUS_COPIED;
2209                                 break;
2210                         }
2211                         if (!p->status)
2212                                 p->status = DIFF_STATUS_RENAMED;
2213                 }
2214                 else if (hashcmp(p->one->sha1, p->two->sha1) ||
2215                          p->one->mode != p->two->mode)
2216                         p->status = DIFF_STATUS_MODIFIED;
2217                 else {
2218                         /* This is a "no-change" entry and should not
2219                          * happen anymore, but prepare for broken callers.
2220                          */
2221                         error("feeding unmodified %s to diffcore",
2222                               p->one->path);
2223                         p->status = DIFF_STATUS_UNKNOWN;
2224                 }
2225         }
2226         diff_debug_queue("resolve-rename-copy done", q);
2227 }
2228
2229 static int check_pair_status(struct diff_filepair *p)
2230 {
2231         switch (p->status) {
2232         case DIFF_STATUS_UNKNOWN:
2233                 return 0;
2234         case 0:
2235                 die("internal error in diff-resolve-rename-copy");
2236         default:
2237                 return 1;
2238         }
2239 }
2240
2241 static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
2242 {
2243         int fmt = opt->output_format;
2244
2245         if (fmt & DIFF_FORMAT_CHECKDIFF)
2246                 diff_flush_checkdiff(p, opt);
2247         else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS))
2248                 diff_flush_raw(p, opt);
2249         else if (fmt & DIFF_FORMAT_NAME)
2250                 diff_flush_name(p, opt->line_termination);
2251 }
2252
2253 static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs)
2254 {
2255         if (fs->mode)
2256                 printf(" %s mode %06o %s\n", newdelete, fs->mode, fs->path);
2257         else
2258                 printf(" %s %s\n", newdelete, fs->path);
2259 }
2260
2261
2262 static void show_mode_change(struct diff_filepair *p, int show_name)
2263 {
2264         if (p->one->mode && p->two->mode && p->one->mode != p->two->mode) {
2265                 if (show_name)
2266                         printf(" mode change %06o => %06o %s\n",
2267                                p->one->mode, p->two->mode, p->two->path);
2268                 else
2269                         printf(" mode change %06o => %06o\n",
2270                                p->one->mode, p->two->mode);
2271         }
2272 }
2273
2274 static void show_rename_copy(const char *renamecopy, struct diff_filepair *p)
2275 {
2276         const char *old, *new;
2277
2278         /* Find common prefix */
2279         old = p->one->path;
2280         new = p->two->path;
2281         while (1) {
2282                 const char *slash_old, *slash_new;
2283                 slash_old = strchr(old, '/');
2284                 slash_new = strchr(new, '/');
2285                 if (!slash_old ||
2286                     !slash_new ||
2287                     slash_old - old != slash_new - new ||
2288                     memcmp(old, new, slash_new - new))
2289                         break;
2290                 old = slash_old + 1;
2291                 new = slash_new + 1;
2292         }
2293         /* p->one->path thru old is the common prefix, and old and new
2294          * through the end of names are renames
2295          */
2296         if (old != p->one->path)
2297                 printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy,
2298                        (int)(old - p->one->path), p->one->path,
2299                        old, new, (int)(0.5 + p->score * 100.0/MAX_SCORE));
2300         else
2301                 printf(" %s %s => %s (%d%%)\n", renamecopy,
2302                        p->one->path, p->two->path,
2303                        (int)(0.5 + p->score * 100.0/MAX_SCORE));
2304         show_mode_change(p, 0);
2305 }
2306
2307 static void diff_summary(struct diff_filepair *p)
2308 {
2309         switch(p->status) {
2310         case DIFF_STATUS_DELETED:
2311                 show_file_mode_name("delete", p->one);
2312                 break;
2313         case DIFF_STATUS_ADDED:
2314                 show_file_mode_name("create", p->two);
2315                 break;
2316         case DIFF_STATUS_COPIED:
2317                 show_rename_copy("copy", p);
2318                 break;
2319         case DIFF_STATUS_RENAMED:
2320                 show_rename_copy("rename", p);
2321                 break;
2322         default:
2323                 if (p->score) {
2324                         printf(" rewrite %s (%d%%)\n", p->two->path,
2325                                 (int)(0.5 + p->score * 100.0/MAX_SCORE));
2326                         show_mode_change(p, 0);
2327                 } else  show_mode_change(p, 1);
2328                 break;
2329         }
2330 }
2331
2332 struct patch_id_t {
2333         struct xdiff_emit_state xm;
2334         SHA_CTX *ctx;
2335         int patchlen;
2336 };
2337
2338 static int remove_space(char *line, int len)
2339 {
2340         int i;
2341         char *dst = line;
2342         unsigned char c;
2343
2344         for (i = 0; i < len; i++)
2345                 if (!isspace((c = line[i])))
2346                         *dst++ = c;
2347
2348         return dst - line;
2349 }
2350
2351 static void patch_id_consume(void *priv, char *line, unsigned long len)
2352 {
2353         struct patch_id_t *data = priv;
2354         int new_len;
2355
2356         /* Ignore line numbers when computing the SHA1 of the patch */
2357         if (!strncmp(line, "@@ -", 4))
2358                 return;
2359
2360         new_len = remove_space(line, len);
2361
2362         SHA1_Update(data->ctx, line, new_len);
2363         data->patchlen += new_len;
2364 }
2365
2366 /* returns 0 upon success, and writes result into sha1 */
2367 static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
2368 {
2369         struct diff_queue_struct *q = &diff_queued_diff;
2370         int i;
2371         SHA_CTX ctx;
2372         struct patch_id_t data;
2373         char buffer[PATH_MAX * 4 + 20];
2374
2375         SHA1_Init(&ctx);
2376         memset(&data, 0, sizeof(struct patch_id_t));
2377         data.ctx = &ctx;
2378         data.xm.consume = patch_id_consume;
2379
2380         for (i = 0; i < q->nr; i++) {
2381                 xpparam_t xpp;
2382                 xdemitconf_t xecfg;
2383                 xdemitcb_t ecb;
2384                 mmfile_t mf1, mf2;
2385                 struct diff_filepair *p = q->queue[i];
2386                 int len1, len2;
2387
2388                 if (p->status == 0)
2389                         return error("internal diff status error");
2390                 if (p->status == DIFF_STATUS_UNKNOWN)
2391                         continue;
2392                 if (diff_unmodified_pair(p))
2393                         continue;
2394                 if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
2395                     (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
2396                         continue;
2397                 if (DIFF_PAIR_UNMERGED(p))
2398                         continue;
2399
2400                 diff_fill_sha1_info(p->one);
2401                 diff_fill_sha1_info(p->two);
2402                 if (fill_mmfile(&mf1, p->one) < 0 ||
2403                                 fill_mmfile(&mf2, p->two) < 0)
2404                         return error("unable to read files to diff");
2405
2406                 /* Maybe hash p->two? into the patch id? */
2407                 if (mmfile_is_binary(&mf2))
2408                         continue;
2409
2410                 len1 = remove_space(p->one->path, strlen(p->one->path));
2411                 len2 = remove_space(p->two->path, strlen(p->two->path));
2412                 if (p->one->mode == 0)
2413                         len1 = snprintf(buffer, sizeof(buffer),
2414                                         "diff--gita/%.*sb/%.*s"
2415                                         "newfilemode%06o"
2416                                         "---/dev/null"
2417                                         "+++b/%.*s",
2418                                         len1, p->one->path,
2419                                         len2, p->two->path,
2420                                         p->two->mode,
2421                                         len2, p->two->path);
2422                 else if (p->two->mode == 0)
2423                         len1 = snprintf(buffer, sizeof(buffer),
2424                                         "diff--gita/%.*sb/%.*s"
2425                                         "deletedfilemode%06o"
2426                                         "---a/%.*s"
2427                                         "+++/dev/null",
2428                                         len1, p->one->path,
2429                                         len2, p->two->path,
2430                                         p->one->mode,
2431                                         len1, p->one->path);
2432                 else
2433                         len1 = snprintf(buffer, sizeof(buffer),
2434                                         "diff--gita/%.*sb/%.*s"
2435                                         "---a/%.*s"
2436                                         "+++b/%.*s",
2437                                         len1, p->one->path,
2438                                         len2, p->two->path,
2439                                         len1, p->one->path,
2440                                         len2, p->two->path);
2441                 SHA1_Update(&ctx, buffer, len1);
2442
2443                 xpp.flags = XDF_NEED_MINIMAL;
2444                 xecfg.ctxlen = 3;
2445                 xecfg.flags = XDL_EMIT_FUNCNAMES;
2446                 ecb.outf = xdiff_outf;
2447                 ecb.priv = &data;
2448                 xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
2449         }
2450
2451         SHA1_Final(sha1, &ctx);
2452         return 0;
2453 }
2454
2455 int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1)
2456 {
2457         struct diff_queue_struct *q = &diff_queued_diff;
2458         int i;
2459         int result = diff_get_patch_id(options, sha1);
2460
2461         for (i = 0; i < q->nr; i++)
2462                 diff_free_filepair(q->queue[i]);
2463
2464         free(q->queue);
2465         q->queue = NULL;
2466         q->nr = q->alloc = 0;
2467
2468         return result;
2469 }
2470
2471 static int is_summary_empty(const struct diff_queue_struct *q)
2472 {
2473         int i;
2474
2475         for (i = 0; i < q->nr; i++) {
2476                 const struct diff_filepair *p = q->queue[i];
2477
2478                 switch (p->status) {
2479                 case DIFF_STATUS_DELETED:
2480                 case DIFF_STATUS_ADDED:
2481                 case DIFF_STATUS_COPIED:
2482                 case DIFF_STATUS_RENAMED:
2483                         return 0;
2484                 default:
2485                         if (p->score)
2486                                 return 0;
2487                         if (p->one->mode && p->two->mode &&
2488                             p->one->mode != p->two->mode)
2489                                 return 0;
2490                         break;
2491                 }
2492         }
2493         return 1;
2494 }
2495
2496 void diff_flush(struct diff_options *options)
2497 {
2498         struct diff_queue_struct *q = &diff_queued_diff;
2499         int i, output_format = options->output_format;
2500         int separator = 0;
2501
2502         /*
2503          * Order: raw, stat, summary, patch
2504          * or:    name/name-status/checkdiff (other bits clear)
2505          */
2506         if (!q->nr)
2507                 goto free_queue;
2508
2509         if (output_format & (DIFF_FORMAT_RAW |
2510                              DIFF_FORMAT_NAME |
2511                              DIFF_FORMAT_NAME_STATUS |
2512                              DIFF_FORMAT_CHECKDIFF)) {
2513                 for (i = 0; i < q->nr; i++) {
2514                         struct diff_filepair *p = q->queue[i];
2515                         if (check_pair_status(p))
2516                                 flush_one_pair(p, options);
2517                 }
2518                 separator++;
2519         }
2520
2521         if (output_format & DIFF_FORMAT_DIFFSTAT) {
2522                 struct diffstat_t diffstat;
2523
2524                 memset(&diffstat, 0, sizeof(struct diffstat_t));
2525                 diffstat.xm.consume = diffstat_consume;
2526                 for (i = 0; i < q->nr; i++) {
2527                         struct diff_filepair *p = q->queue[i];
2528                         if (check_pair_status(p))
2529                                 diff_flush_stat(p, options, &diffstat);
2530                 }
2531                 show_stats(&diffstat);
2532                 separator++;
2533         }
2534
2535         if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) {
2536                 for (i = 0; i < q->nr; i++)
2537                         diff_summary(q->queue[i]);
2538                 separator++;
2539         }
2540
2541         if (output_format & DIFF_FORMAT_PATCH) {
2542                 if (separator) {
2543                         if (options->stat_sep) {
2544                                 /* attach patch instead of inline */
2545                                 fputs(options->stat_sep, stdout);
2546                         } else {
2547                                 putchar(options->line_termination);
2548                         }
2549                 }
2550
2551                 for (i = 0; i < q->nr; i++) {
2552                         struct diff_filepair *p = q->queue[i];
2553                         if (check_pair_status(p))
2554                                 diff_flush_patch(p, options);
2555                 }
2556         }
2557
2558         if (output_format & DIFF_FORMAT_CALLBACK)
2559                 options->format_callback(q, options, options->format_callback_data);
2560
2561         for (i = 0; i < q->nr; i++)
2562                 diff_free_filepair(q->queue[i]);
2563 free_queue:
2564         free(q->queue);
2565         q->queue = NULL;
2566         q->nr = q->alloc = 0;
2567 }
2568
2569 static void diffcore_apply_filter(const char *filter)
2570 {
2571         int i;
2572         struct diff_queue_struct *q = &diff_queued_diff;
2573         struct diff_queue_struct outq;
2574         outq.queue = NULL;
2575         outq.nr = outq.alloc = 0;
2576
2577         if (!filter)
2578                 return;
2579
2580         if (strchr(filter, DIFF_STATUS_FILTER_AON)) {
2581                 int found;
2582                 for (i = found = 0; !found && i < q->nr; i++) {
2583                         struct diff_filepair *p = q->queue[i];
2584                         if (((p->status == DIFF_STATUS_MODIFIED) &&
2585                              ((p->score &&
2586                                strchr(filter, DIFF_STATUS_FILTER_BROKEN)) ||
2587                               (!p->score &&
2588                                strchr(filter, DIFF_STATUS_MODIFIED)))) ||
2589                             ((p->status != DIFF_STATUS_MODIFIED) &&
2590                              strchr(filter, p->status)))
2591                                 found++;
2592                 }
2593                 if (found)
2594                         return;
2595
2596                 /* otherwise we will clear the whole queue
2597                  * by copying the empty outq at the end of this
2598                  * function, but first clear the current entries
2599                  * in the queue.
2600                  */
2601                 for (i = 0; i < q->nr; i++)
2602                         diff_free_filepair(q->queue[i]);
2603         }
2604         else {
2605                 /* Only the matching ones */
2606                 for (i = 0; i < q->nr; i++) {
2607                         struct diff_filepair *p = q->queue[i];
2608
2609                         if (((p->status == DIFF_STATUS_MODIFIED) &&
2610                              ((p->score &&
2611                                strchr(filter, DIFF_STATUS_FILTER_BROKEN)) ||
2612                               (!p->score &&
2613                                strchr(filter, DIFF_STATUS_MODIFIED)))) ||
2614                             ((p->status != DIFF_STATUS_MODIFIED) &&
2615                              strchr(filter, p->status)))
2616                                 diff_q(&outq, p);
2617                         else
2618                                 diff_free_filepair(p);
2619                 }
2620         }
2621         free(q->queue);
2622         *q = outq;
2623 }
2624
2625 void diffcore_std(struct diff_options *options)
2626 {
2627         if (options->break_opt != -1)
2628                 diffcore_break(options->break_opt);
2629         if (options->detect_rename)
2630                 diffcore_rename(options);
2631         if (options->break_opt != -1)
2632                 diffcore_merge_broken();
2633         if (options->pickaxe)
2634                 diffcore_pickaxe(options->pickaxe, options->pickaxe_opts);
2635         if (options->orderfile)
2636                 diffcore_order(options->orderfile);
2637         diff_resolve_rename_copy();
2638         diffcore_apply_filter(options->filter);
2639 }
2640
2641
2642 void diffcore_std_no_resolve(struct diff_options *options)
2643 {
2644         if (options->pickaxe)
2645                 diffcore_pickaxe(options->pickaxe, options->pickaxe_opts);
2646         if (options->orderfile)
2647                 diffcore_order(options->orderfile);
2648         diffcore_apply_filter(options->filter);
2649 }
2650
2651 void diff_addremove(struct diff_options *options,
2652                     int addremove, unsigned mode,
2653                     const unsigned char *sha1,
2654                     const char *base, const char *path)
2655 {
2656         char concatpath[PATH_MAX];
2657         struct diff_filespec *one, *two;
2658
2659         /* This may look odd, but it is a preparation for
2660          * feeding "there are unchanged files which should
2661          * not produce diffs, but when you are doing copy
2662          * detection you would need them, so here they are"
2663          * entries to the diff-core.  They will be prefixed
2664          * with something like '=' or '*' (I haven't decided
2665          * which but should not make any difference).
2666          * Feeding the same new and old to diff_change() 
2667          * also has the same effect.
2668          * Before the final output happens, they are pruned after
2669          * merged into rename/copy pairs as appropriate.
2670          */
2671         if (options->reverse_diff)
2672                 addremove = (addremove == '+' ? '-' :
2673                              addremove == '-' ? '+' : addremove);
2674
2675         if (!path) path = "";
2676         sprintf(concatpath, "%s%s", base, path);
2677         one = alloc_filespec(concatpath);
2678         two = alloc_filespec(concatpath);
2679
2680         if (addremove != '+')
2681                 fill_filespec(one, sha1, mode);
2682         if (addremove != '-')
2683                 fill_filespec(two, sha1, mode);
2684
2685         diff_queue(&diff_queued_diff, one, two);
2686 }
2687
2688 void diff_change(struct diff_options *options,
2689                  unsigned old_mode, unsigned new_mode,
2690                  const unsigned char *old_sha1,
2691                  const unsigned char *new_sha1,
2692                  const char *base, const char *path) 
2693 {
2694         char concatpath[PATH_MAX];
2695         struct diff_filespec *one, *two;
2696
2697         if (options->reverse_diff) {
2698                 unsigned tmp;
2699                 const unsigned char *tmp_c;
2700                 tmp = old_mode; old_mode = new_mode; new_mode = tmp;
2701                 tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
2702         }
2703         if (!path) path = "";
2704         sprintf(concatpath, "%s%s", base, path);
2705         one = alloc_filespec(concatpath);
2706         two = alloc_filespec(concatpath);
2707         fill_filespec(one, old_sha1, old_mode);
2708         fill_filespec(two, new_sha1, new_mode);
2709
2710         diff_queue(&diff_queued_diff, one, two);
2711 }
2712
2713 void diff_unmerge(struct diff_options *options,
2714                   const char *path)
2715 {
2716         struct diff_filespec *one, *two;
2717         one = alloc_filespec(path);
2718         two = alloc_filespec(path);
2719         diff_queue(&diff_queued_diff, one, two);
2720 }