]> rtime.felk.cvut.cz Git - git.git/blob - diff.c
diff: add --word-diff option that generalizes --color-words
[git.git] / diff.c
1 /*
2  * Copyright (C) 2005 Junio C Hamano
3  */
4 #include "cache.h"
5 #include "quote.h"
6 #include "diff.h"
7 #include "diffcore.h"
8 #include "delta.h"
9 #include "xdiff-interface.h"
10 #include "color.h"
11 #include "attr.h"
12 #include "run-command.h"
13 #include "utf8.h"
14 #include "userdiff.h"
15 #include "sigchain.h"
16 #include "submodule.h"
17
18 #ifdef NO_FAST_WORKING_DIRECTORY
19 #define FAST_WORKING_DIRECTORY 0
20 #else
21 #define FAST_WORKING_DIRECTORY 1
22 #endif
23
24 static int diff_detect_rename_default;
25 static int diff_rename_limit_default = 200;
26 static int diff_suppress_blank_empty;
27 int diff_use_color_default = -1;
28 static const char *diff_word_regex_cfg;
29 static const char *external_diff_cmd_cfg;
30 int diff_auto_refresh_index = 1;
31 static int diff_mnemonic_prefix;
32
33 static char diff_colors[][COLOR_MAXLEN] = {
34         GIT_COLOR_RESET,
35         GIT_COLOR_NORMAL,       /* PLAIN */
36         GIT_COLOR_BOLD,         /* METAINFO */
37         GIT_COLOR_CYAN,         /* FRAGINFO */
38         GIT_COLOR_RED,          /* OLD */
39         GIT_COLOR_GREEN,        /* NEW */
40         GIT_COLOR_YELLOW,       /* COMMIT */
41         GIT_COLOR_BG_RED,       /* WHITESPACE */
42         GIT_COLOR_NORMAL,       /* FUNCINFO */
43 };
44
45 static void diff_filespec_load_driver(struct diff_filespec *one);
46 static char *run_textconv(const char *, struct diff_filespec *, size_t *);
47
48 static int parse_diff_color_slot(const char *var, int ofs)
49 {
50         if (!strcasecmp(var+ofs, "plain"))
51                 return DIFF_PLAIN;
52         if (!strcasecmp(var+ofs, "meta"))
53                 return DIFF_METAINFO;
54         if (!strcasecmp(var+ofs, "frag"))
55                 return DIFF_FRAGINFO;
56         if (!strcasecmp(var+ofs, "old"))
57                 return DIFF_FILE_OLD;
58         if (!strcasecmp(var+ofs, "new"))
59                 return DIFF_FILE_NEW;
60         if (!strcasecmp(var+ofs, "commit"))
61                 return DIFF_COMMIT;
62         if (!strcasecmp(var+ofs, "whitespace"))
63                 return DIFF_WHITESPACE;
64         if (!strcasecmp(var+ofs, "func"))
65                 return DIFF_FUNCINFO;
66         return -1;
67 }
68
69 static int git_config_rename(const char *var, const char *value)
70 {
71         if (!value)
72                 return DIFF_DETECT_RENAME;
73         if (!strcasecmp(value, "copies") || !strcasecmp(value, "copy"))
74                 return  DIFF_DETECT_COPY;
75         return git_config_bool(var,value) ? DIFF_DETECT_RENAME : 0;
76 }
77
78 /*
79  * These are to give UI layer defaults.
80  * The core-level commands such as git-diff-files should
81  * never be affected by the setting of diff.renames
82  * the user happens to have in the configuration file.
83  */
84 int git_diff_ui_config(const char *var, const char *value, void *cb)
85 {
86         if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
87                 diff_use_color_default = git_config_colorbool(var, value, -1);
88                 return 0;
89         }
90         if (!strcmp(var, "diff.renames")) {
91                 diff_detect_rename_default = git_config_rename(var, value);
92                 return 0;
93         }
94         if (!strcmp(var, "diff.autorefreshindex")) {
95                 diff_auto_refresh_index = git_config_bool(var, value);
96                 return 0;
97         }
98         if (!strcmp(var, "diff.mnemonicprefix")) {
99                 diff_mnemonic_prefix = git_config_bool(var, value);
100                 return 0;
101         }
102         if (!strcmp(var, "diff.external"))
103                 return git_config_string(&external_diff_cmd_cfg, var, value);
104         if (!strcmp(var, "diff.wordregex"))
105                 return git_config_string(&diff_word_regex_cfg, var, value);
106
107         return git_diff_basic_config(var, value, cb);
108 }
109
110 int git_diff_basic_config(const char *var, const char *value, void *cb)
111 {
112         if (!strcmp(var, "diff.renamelimit")) {
113                 diff_rename_limit_default = git_config_int(var, value);
114                 return 0;
115         }
116
117         switch (userdiff_config(var, value)) {
118                 case 0: break;
119                 case -1: return -1;
120                 default: return 0;
121         }
122
123         if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
124                 int slot = parse_diff_color_slot(var, 11);
125                 if (slot < 0)
126                         return 0;
127                 if (!value)
128                         return config_error_nonbool(var);
129                 color_parse(value, var, diff_colors[slot]);
130                 return 0;
131         }
132
133         /* like GNU diff's --suppress-blank-empty option  */
134         if (!strcmp(var, "diff.suppressblankempty") ||
135                         /* for backwards compatibility */
136                         !strcmp(var, "diff.suppress-blank-empty")) {
137                 diff_suppress_blank_empty = git_config_bool(var, value);
138                 return 0;
139         }
140
141         return git_color_default_config(var, value, cb);
142 }
143
144 static char *quote_two(const char *one, const char *two)
145 {
146         int need_one = quote_c_style(one, NULL, NULL, 1);
147         int need_two = quote_c_style(two, NULL, NULL, 1);
148         struct strbuf res = STRBUF_INIT;
149
150         if (need_one + need_two) {
151                 strbuf_addch(&res, '"');
152                 quote_c_style(one, &res, NULL, 1);
153                 quote_c_style(two, &res, NULL, 1);
154                 strbuf_addch(&res, '"');
155         } else {
156                 strbuf_addstr(&res, one);
157                 strbuf_addstr(&res, two);
158         }
159         return strbuf_detach(&res, NULL);
160 }
161
162 static const char *external_diff(void)
163 {
164         static const char *external_diff_cmd = NULL;
165         static int done_preparing = 0;
166
167         if (done_preparing)
168                 return external_diff_cmd;
169         external_diff_cmd = getenv("GIT_EXTERNAL_DIFF");
170         if (!external_diff_cmd)
171                 external_diff_cmd = external_diff_cmd_cfg;
172         done_preparing = 1;
173         return external_diff_cmd;
174 }
175
176 static struct diff_tempfile {
177         const char *name; /* filename external diff should read from */
178         char hex[41];
179         char mode[10];
180         char tmp_path[PATH_MAX];
181 } diff_temp[2];
182
183 typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
184
185 struct emit_callback {
186         int color_diff;
187         unsigned ws_rule;
188         int blank_at_eof_in_preimage;
189         int blank_at_eof_in_postimage;
190         int lno_in_preimage;
191         int lno_in_postimage;
192         sane_truncate_fn truncate;
193         const char **label_path;
194         struct diff_words_data *diff_words;
195         int *found_changesp;
196         FILE *file;
197         struct strbuf *header;
198 };
199
200 static int count_lines(const char *data, int size)
201 {
202         int count, ch, completely_empty = 1, nl_just_seen = 0;
203         count = 0;
204         while (0 < size--) {
205                 ch = *data++;
206                 if (ch == '\n') {
207                         count++;
208                         nl_just_seen = 1;
209                         completely_empty = 0;
210                 }
211                 else {
212                         nl_just_seen = 0;
213                         completely_empty = 0;
214                 }
215         }
216         if (completely_empty)
217                 return 0;
218         if (!nl_just_seen)
219                 count++; /* no trailing newline */
220         return count;
221 }
222
223 static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
224 {
225         if (!DIFF_FILE_VALID(one)) {
226                 mf->ptr = (char *)""; /* does not matter */
227                 mf->size = 0;
228                 return 0;
229         }
230         else if (diff_populate_filespec(one, 0))
231                 return -1;
232
233         mf->ptr = one->data;
234         mf->size = one->size;
235         return 0;
236 }
237
238 static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)
239 {
240         char *ptr = mf->ptr;
241         long size = mf->size;
242         int cnt = 0;
243
244         if (!size)
245                 return cnt;
246         ptr += size - 1; /* pointing at the very end */
247         if (*ptr != '\n')
248                 ; /* incomplete line */
249         else
250                 ptr--; /* skip the last LF */
251         while (mf->ptr < ptr) {
252                 char *prev_eol;
253                 for (prev_eol = ptr; mf->ptr <= prev_eol; prev_eol--)
254                         if (*prev_eol == '\n')
255                                 break;
256                 if (!ws_blank_line(prev_eol + 1, ptr - prev_eol, ws_rule))
257                         break;
258                 cnt++;
259                 ptr = prev_eol - 1;
260         }
261         return cnt;
262 }
263
264 static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2,
265                                struct emit_callback *ecbdata)
266 {
267         int l1, l2, at;
268         unsigned ws_rule = ecbdata->ws_rule;
269         l1 = count_trailing_blank(mf1, ws_rule);
270         l2 = count_trailing_blank(mf2, ws_rule);
271         if (l2 <= l1) {
272                 ecbdata->blank_at_eof_in_preimage = 0;
273                 ecbdata->blank_at_eof_in_postimage = 0;
274                 return;
275         }
276         at = count_lines(mf1->ptr, mf1->size);
277         ecbdata->blank_at_eof_in_preimage = (at - l1) + 1;
278
279         at = count_lines(mf2->ptr, mf2->size);
280         ecbdata->blank_at_eof_in_postimage = (at - l2) + 1;
281 }
282
283 static void emit_line_0(FILE *file, const char *set, const char *reset,
284                         int first, const char *line, int len)
285 {
286         int has_trailing_newline, has_trailing_carriage_return;
287         int nofirst;
288
289         if (len == 0) {
290                 has_trailing_newline = (first == '\n');
291                 has_trailing_carriage_return = (!has_trailing_newline &&
292                                                 (first == '\r'));
293                 nofirst = has_trailing_newline || has_trailing_carriage_return;
294         } else {
295                 has_trailing_newline = (len > 0 && line[len-1] == '\n');
296                 if (has_trailing_newline)
297                         len--;
298                 has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
299                 if (has_trailing_carriage_return)
300                         len--;
301                 nofirst = 0;
302         }
303
304         if (len || !nofirst) {
305                 fputs(set, file);
306                 if (!nofirst)
307                         fputc(first, file);
308                 fwrite(line, len, 1, file);
309                 fputs(reset, file);
310         }
311         if (has_trailing_carriage_return)
312                 fputc('\r', file);
313         if (has_trailing_newline)
314                 fputc('\n', file);
315 }
316
317 static void emit_line(FILE *file, const char *set, const char *reset,
318                       const char *line, int len)
319 {
320         emit_line_0(file, set, reset, line[0], line+1, len-1);
321 }
322
323 static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line, int len)
324 {
325         if (!((ecbdata->ws_rule & WS_BLANK_AT_EOF) &&
326               ecbdata->blank_at_eof_in_preimage &&
327               ecbdata->blank_at_eof_in_postimage &&
328               ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage &&
329               ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage))
330                 return 0;
331         return ws_blank_line(line, len, ecbdata->ws_rule);
332 }
333
334 static void emit_add_line(const char *reset,
335                           struct emit_callback *ecbdata,
336                           const char *line, int len)
337 {
338         const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
339         const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
340
341         if (!*ws)
342                 emit_line_0(ecbdata->file, set, reset, '+', line, len);
343         else if (new_blank_line_at_eof(ecbdata, line, len))
344                 /* Blank line at EOF - paint '+' as well */
345                 emit_line_0(ecbdata->file, ws, reset, '+', line, len);
346         else {
347                 /* Emit just the prefix, then the rest. */
348                 emit_line_0(ecbdata->file, set, reset, '+', "", 0);
349                 ws_check_emit(line, len, ecbdata->ws_rule,
350                               ecbdata->file, set, reset, ws);
351         }
352 }
353
354 static void emit_hunk_header(struct emit_callback *ecbdata,
355                              const char *line, int len)
356 {
357         const char *plain = diff_get_color(ecbdata->color_diff, DIFF_PLAIN);
358         const char *frag = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO);
359         const char *func = diff_get_color(ecbdata->color_diff, DIFF_FUNCINFO);
360         const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
361         static const char atat[2] = { '@', '@' };
362         const char *cp, *ep;
363
364         /*
365          * As a hunk header must begin with "@@ -<old>, +<new> @@",
366          * it always is at least 10 bytes long.
367          */
368         if (len < 10 ||
369             memcmp(line, atat, 2) ||
370             !(ep = memmem(line + 2, len - 2, atat, 2))) {
371                 emit_line(ecbdata->file, plain, reset, line, len);
372                 return;
373         }
374         ep += 2; /* skip over @@ */
375
376         /* The hunk header in fraginfo color */
377         emit_line(ecbdata->file, frag, reset, line, ep - line);
378
379         /* blank before the func header */
380         for (cp = ep; ep - line < len; ep++)
381                 if (*ep != ' ' && *ep != '\t')
382                         break;
383         if (ep != cp)
384                 emit_line(ecbdata->file, plain, reset, cp, ep - cp);
385
386         if (ep < line + len)
387                 emit_line(ecbdata->file, func, reset, ep, line + len - ep);
388 }
389
390 static struct diff_tempfile *claim_diff_tempfile(void) {
391         int i;
392         for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
393                 if (!diff_temp[i].name)
394                         return diff_temp + i;
395         die("BUG: diff is failing to clean up its tempfiles");
396 }
397
398 static int remove_tempfile_installed;
399
400 static void remove_tempfile(void)
401 {
402         int i;
403         for (i = 0; i < ARRAY_SIZE(diff_temp); i++) {
404                 if (diff_temp[i].name == diff_temp[i].tmp_path)
405                         unlink_or_warn(diff_temp[i].name);
406                 diff_temp[i].name = NULL;
407         }
408 }
409
410 static void remove_tempfile_on_signal(int signo)
411 {
412         remove_tempfile();
413         sigchain_pop(signo);
414         raise(signo);
415 }
416
417 static void print_line_count(FILE *file, int count)
418 {
419         switch (count) {
420         case 0:
421                 fprintf(file, "0,0");
422                 break;
423         case 1:
424                 fprintf(file, "1");
425                 break;
426         default:
427                 fprintf(file, "1,%d", count);
428                 break;
429         }
430 }
431
432 static void emit_rewrite_lines(struct emit_callback *ecb,
433                                int prefix, const char *data, int size)
434 {
435         const char *endp = NULL;
436         static const char *nneof = " No newline at end of file\n";
437         const char *old = diff_get_color(ecb->color_diff, DIFF_FILE_OLD);
438         const char *reset = diff_get_color(ecb->color_diff, DIFF_RESET);
439
440         while (0 < size) {
441                 int len;
442
443                 endp = memchr(data, '\n', size);
444                 len = endp ? (endp - data + 1) : size;
445                 if (prefix != '+') {
446                         ecb->lno_in_preimage++;
447                         emit_line_0(ecb->file, old, reset, '-',
448                                     data, len);
449                 } else {
450                         ecb->lno_in_postimage++;
451                         emit_add_line(reset, ecb, data, len);
452                 }
453                 size -= len;
454                 data += len;
455         }
456         if (!endp) {
457                 const char *plain = diff_get_color(ecb->color_diff,
458                                                    DIFF_PLAIN);
459                 emit_line_0(ecb->file, plain, reset, '\\',
460                             nneof, strlen(nneof));
461         }
462 }
463
464 static void emit_rewrite_diff(const char *name_a,
465                               const char *name_b,
466                               struct diff_filespec *one,
467                               struct diff_filespec *two,
468                               const char *textconv_one,
469                               const char *textconv_two,
470                               struct diff_options *o)
471 {
472         int lc_a, lc_b;
473         int color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
474         const char *name_a_tab, *name_b_tab;
475         const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
476         const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
477         const char *reset = diff_get_color(color_diff, DIFF_RESET);
478         static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
479         const char *a_prefix, *b_prefix;
480         const char *data_one, *data_two;
481         size_t size_one, size_two;
482         struct emit_callback ecbdata;
483
484         if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) {
485                 a_prefix = o->b_prefix;
486                 b_prefix = o->a_prefix;
487         } else {
488                 a_prefix = o->a_prefix;
489                 b_prefix = o->b_prefix;
490         }
491
492         name_a += (*name_a == '/');
493         name_b += (*name_b == '/');
494         name_a_tab = strchr(name_a, ' ') ? "\t" : "";
495         name_b_tab = strchr(name_b, ' ') ? "\t" : "";
496
497         strbuf_reset(&a_name);
498         strbuf_reset(&b_name);
499         quote_two_c_style(&a_name, a_prefix, name_a, 0);
500         quote_two_c_style(&b_name, b_prefix, name_b, 0);
501
502         diff_populate_filespec(one, 0);
503         diff_populate_filespec(two, 0);
504         if (textconv_one) {
505                 data_one = run_textconv(textconv_one, one, &size_one);
506                 if (!data_one)
507                         die("unable to read files to diff");
508         }
509         else {
510                 data_one = one->data;
511                 size_one = one->size;
512         }
513         if (textconv_two) {
514                 data_two = run_textconv(textconv_two, two, &size_two);
515                 if (!data_two)
516                         die("unable to read files to diff");
517         }
518         else {
519                 data_two = two->data;
520                 size_two = two->size;
521         }
522
523         memset(&ecbdata, 0, sizeof(ecbdata));
524         ecbdata.color_diff = color_diff;
525         ecbdata.found_changesp = &o->found_changes;
526         ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
527         ecbdata.file = o->file;
528         if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
529                 mmfile_t mf1, mf2;
530                 mf1.ptr = (char *)data_one;
531                 mf2.ptr = (char *)data_two;
532                 mf1.size = size_one;
533                 mf2.size = size_two;
534                 check_blank_at_eof(&mf1, &mf2, &ecbdata);
535         }
536         ecbdata.lno_in_preimage = 1;
537         ecbdata.lno_in_postimage = 1;
538
539         lc_a = count_lines(data_one, size_one);
540         lc_b = count_lines(data_two, size_two);
541         fprintf(o->file,
542                 "%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -",
543                 metainfo, a_name.buf, name_a_tab, reset,
544                 metainfo, b_name.buf, name_b_tab, reset, fraginfo);
545         print_line_count(o->file, lc_a);
546         fprintf(o->file, " +");
547         print_line_count(o->file, lc_b);
548         fprintf(o->file, " @@%s\n", reset);
549         if (lc_a)
550                 emit_rewrite_lines(&ecbdata, '-', data_one, size_one);
551         if (lc_b)
552                 emit_rewrite_lines(&ecbdata, '+', data_two, size_two);
553 }
554
555 struct diff_words_buffer {
556         mmfile_t text;
557         long alloc;
558         struct diff_words_orig {
559                 const char *begin, *end;
560         } *orig;
561         int orig_nr, orig_alloc;
562 };
563
564 static void diff_words_append(char *line, unsigned long len,
565                 struct diff_words_buffer *buffer)
566 {
567         ALLOC_GROW(buffer->text.ptr, buffer->text.size + len, buffer->alloc);
568         line++;
569         len--;
570         memcpy(buffer->text.ptr + buffer->text.size, line, len);
571         buffer->text.size += len;
572         buffer->text.ptr[buffer->text.size] = '\0';
573 }
574
575 struct diff_words_style_elem
576 {
577         const char *prefix;
578         const char *suffix;
579         const char *color; /* NULL; filled in by the setup code if
580                             * color is enabled */
581 };
582
583 struct diff_words_style
584 {
585         enum diff_words_type type;
586         struct diff_words_style_elem new, old, ctx;
587         const char *newline;
588 };
589
590 struct diff_words_style diff_words_styles[] = {
591         { DIFF_WORDS_PORCELAIN, {"+", "\n"}, {"-", "\n"}, {" ", "\n"}, "~\n" },
592         { DIFF_WORDS_PLAIN, {"{+", "+}"}, {"[-", "-]"}, {"", ""}, "\n" },
593         { DIFF_WORDS_COLOR, {"", ""}, {"", ""}, {"", ""}, "\n" }
594 };
595
596 struct diff_words_data {
597         struct diff_words_buffer minus, plus;
598         const char *current_plus;
599         FILE *file;
600         regex_t *word_regex;
601         enum diff_words_type type;
602         struct diff_words_style *style;
603 };
604
605 static int fn_out_diff_words_write_helper(FILE *fp,
606                                           struct diff_words_style_elem *st_el,
607                                           const char *newline,
608                                           size_t count, const char *buf)
609 {
610         while (count) {
611                 char *p = memchr(buf, '\n', count);
612                 if (p != buf) {
613                         if (st_el->color && fputs(st_el->color, fp) < 0)
614                                 return -1;
615                         if (fputs(st_el->prefix, fp) < 0 ||
616                             fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
617                             fputs(st_el->suffix, fp) < 0)
618                                 return -1;
619                         if (st_el->color && *st_el->color
620                             && fputs(GIT_COLOR_RESET, fp) < 0)
621                                 return -1;
622                 }
623                 if (!p)
624                         return 0;
625                 if (fputs(newline, fp) < 0)
626                         return -1;
627                 count -= p + 1 - buf;
628                 buf = p + 1;
629         }
630         return 0;
631 }
632
633 static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
634 {
635         struct diff_words_data *diff_words = priv;
636         struct diff_words_style *style = diff_words->style;
637         int minus_first, minus_len, plus_first, plus_len;
638         const char *minus_begin, *minus_end, *plus_begin, *plus_end;
639
640         if (line[0] != '@' || parse_hunk_header(line, len,
641                         &minus_first, &minus_len, &plus_first, &plus_len))
642                 return;
643
644         /* POSIX requires that first be decremented by one if len == 0... */
645         if (minus_len) {
646                 minus_begin = diff_words->minus.orig[minus_first].begin;
647                 minus_end =
648                         diff_words->minus.orig[minus_first + minus_len - 1].end;
649         } else
650                 minus_begin = minus_end =
651                         diff_words->minus.orig[minus_first].end;
652
653         if (plus_len) {
654                 plus_begin = diff_words->plus.orig[plus_first].begin;
655                 plus_end = diff_words->plus.orig[plus_first + plus_len - 1].end;
656         } else
657                 plus_begin = plus_end = diff_words->plus.orig[plus_first].end;
658
659         if (diff_words->current_plus != plus_begin)
660                 fn_out_diff_words_write_helper(diff_words->file,
661                                 &style->ctx, style->newline,
662                                 plus_begin - diff_words->current_plus,
663                                 diff_words->current_plus);
664         if (minus_begin != minus_end)
665                 fn_out_diff_words_write_helper(diff_words->file,
666                                 &style->old, style->newline,
667                                 minus_end - minus_begin, minus_begin);
668         if (plus_begin != plus_end)
669                 fn_out_diff_words_write_helper(diff_words->file,
670                                 &style->new, style->newline,
671                                 plus_end - plus_begin, plus_begin);
672
673         diff_words->current_plus = plus_end;
674 }
675
676 /* This function starts looking at *begin, and returns 0 iff a word was found. */
677 static int find_word_boundaries(mmfile_t *buffer, regex_t *word_regex,
678                 int *begin, int *end)
679 {
680         if (word_regex && *begin < buffer->size) {
681                 regmatch_t match[1];
682                 if (!regexec(word_regex, buffer->ptr + *begin, 1, match, 0)) {
683                         char *p = memchr(buffer->ptr + *begin + match[0].rm_so,
684                                         '\n', match[0].rm_eo - match[0].rm_so);
685                         *end = p ? p - buffer->ptr : match[0].rm_eo + *begin;
686                         *begin += match[0].rm_so;
687                         return *begin >= *end;
688                 }
689                 return -1;
690         }
691
692         /* find the next word */
693         while (*begin < buffer->size && isspace(buffer->ptr[*begin]))
694                 (*begin)++;
695         if (*begin >= buffer->size)
696                 return -1;
697
698         /* find the end of the word */
699         *end = *begin + 1;
700         while (*end < buffer->size && !isspace(buffer->ptr[*end]))
701                 (*end)++;
702
703         return 0;
704 }
705
706 /*
707  * This function splits the words in buffer->text, stores the list with
708  * newline separator into out, and saves the offsets of the original words
709  * in buffer->orig.
710  */
711 static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out,
712                 regex_t *word_regex)
713 {
714         int i, j;
715         long alloc = 0;
716
717         out->size = 0;
718         out->ptr = NULL;
719
720         /* fake an empty "0th" word */
721         ALLOC_GROW(buffer->orig, 1, buffer->orig_alloc);
722         buffer->orig[0].begin = buffer->orig[0].end = buffer->text.ptr;
723         buffer->orig_nr = 1;
724
725         for (i = 0; i < buffer->text.size; i++) {
726                 if (find_word_boundaries(&buffer->text, word_regex, &i, &j))
727                         return;
728
729                 /* store original boundaries */
730                 ALLOC_GROW(buffer->orig, buffer->orig_nr + 1,
731                                 buffer->orig_alloc);
732                 buffer->orig[buffer->orig_nr].begin = buffer->text.ptr + i;
733                 buffer->orig[buffer->orig_nr].end = buffer->text.ptr + j;
734                 buffer->orig_nr++;
735
736                 /* store one word */
737                 ALLOC_GROW(out->ptr, out->size + j - i + 1, alloc);
738                 memcpy(out->ptr + out->size, buffer->text.ptr + i, j - i);
739                 out->ptr[out->size + j - i] = '\n';
740                 out->size += j - i + 1;
741
742                 i = j - 1;
743         }
744 }
745
746 /* this executes the word diff on the accumulated buffers */
747 static void diff_words_show(struct diff_words_data *diff_words)
748 {
749         xpparam_t xpp;
750         xdemitconf_t xecfg;
751         xdemitcb_t ecb;
752         mmfile_t minus, plus;
753         struct diff_words_style *style = diff_words->style;
754
755         /* special case: only removal */
756         if (!diff_words->plus.text.size) {
757                 fn_out_diff_words_write_helper(diff_words->file,
758                         &style->old, style->newline,
759                         diff_words->minus.text.size, diff_words->minus.text.ptr);
760                 diff_words->minus.text.size = 0;
761                 return;
762         }
763
764         diff_words->current_plus = diff_words->plus.text.ptr;
765
766         memset(&xpp, 0, sizeof(xpp));
767         memset(&xecfg, 0, sizeof(xecfg));
768         diff_words_fill(&diff_words->minus, &minus, diff_words->word_regex);
769         diff_words_fill(&diff_words->plus, &plus, diff_words->word_regex);
770         xpp.flags = XDF_NEED_MINIMAL;
771         /* as only the hunk header will be parsed, we need a 0-context */
772         xecfg.ctxlen = 0;
773         xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
774                       &xpp, &xecfg, &ecb);
775         free(minus.ptr);
776         free(plus.ptr);
777         if (diff_words->current_plus != diff_words->plus.text.ptr +
778                         diff_words->plus.text.size)
779                 fn_out_diff_words_write_helper(diff_words->file,
780                         &style->ctx, style->newline,
781                         diff_words->plus.text.ptr + diff_words->plus.text.size
782                         - diff_words->current_plus, diff_words->current_plus);
783         diff_words->minus.text.size = diff_words->plus.text.size = 0;
784 }
785
786 /* In "color-words" mode, show word-diff of words accumulated in the buffer */
787 static void diff_words_flush(struct emit_callback *ecbdata)
788 {
789         if (ecbdata->diff_words->minus.text.size ||
790             ecbdata->diff_words->plus.text.size)
791                 diff_words_show(ecbdata->diff_words);
792 }
793
794 static void free_diff_words_data(struct emit_callback *ecbdata)
795 {
796         if (ecbdata->diff_words) {
797                 diff_words_flush(ecbdata);
798                 free (ecbdata->diff_words->minus.text.ptr);
799                 free (ecbdata->diff_words->minus.orig);
800                 free (ecbdata->diff_words->plus.text.ptr);
801                 free (ecbdata->diff_words->plus.orig);
802                 free(ecbdata->diff_words->word_regex);
803                 free(ecbdata->diff_words);
804                 ecbdata->diff_words = NULL;
805         }
806 }
807
808 const char *diff_get_color(int diff_use_color, enum color_diff ix)
809 {
810         if (diff_use_color)
811                 return diff_colors[ix];
812         return "";
813 }
814
815 static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
816 {
817         const char *cp;
818         unsigned long allot;
819         size_t l = len;
820
821         if (ecb->truncate)
822                 return ecb->truncate(line, len);
823         cp = line;
824         allot = l;
825         while (0 < l) {
826                 (void) utf8_width(&cp, &l);
827                 if (!cp)
828                         break; /* truncated in the middle? */
829         }
830         return allot - l;
831 }
832
833 static void find_lno(const char *line, struct emit_callback *ecbdata)
834 {
835         const char *p;
836         ecbdata->lno_in_preimage = 0;
837         ecbdata->lno_in_postimage = 0;
838         p = strchr(line, '-');
839         if (!p)
840                 return; /* cannot happen */
841         ecbdata->lno_in_preimage = strtol(p + 1, NULL, 10);
842         p = strchr(p, '+');
843         if (!p)
844                 return; /* cannot happen */
845         ecbdata->lno_in_postimage = strtol(p + 1, NULL, 10);
846 }
847
848 static void fn_out_consume(void *priv, char *line, unsigned long len)
849 {
850         struct emit_callback *ecbdata = priv;
851         const char *meta = diff_get_color(ecbdata->color_diff, DIFF_METAINFO);
852         const char *plain = diff_get_color(ecbdata->color_diff, DIFF_PLAIN);
853         const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
854
855         if (ecbdata->header) {
856                 fprintf(ecbdata->file, "%s", ecbdata->header->buf);
857                 strbuf_reset(ecbdata->header);
858                 ecbdata->header = NULL;
859         }
860         *(ecbdata->found_changesp) = 1;
861
862         if (ecbdata->label_path[0]) {
863                 const char *name_a_tab, *name_b_tab;
864
865                 name_a_tab = strchr(ecbdata->label_path[0], ' ') ? "\t" : "";
866                 name_b_tab = strchr(ecbdata->label_path[1], ' ') ? "\t" : "";
867
868                 fprintf(ecbdata->file, "%s--- %s%s%s\n",
869                         meta, ecbdata->label_path[0], reset, name_a_tab);
870                 fprintf(ecbdata->file, "%s+++ %s%s%s\n",
871                         meta, ecbdata->label_path[1], reset, name_b_tab);
872                 ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
873         }
874
875         if (diff_suppress_blank_empty
876             && len == 2 && line[0] == ' ' && line[1] == '\n') {
877                 line[0] = '\n';
878                 len = 1;
879         }
880
881         if (line[0] == '@') {
882                 if (ecbdata->diff_words)
883                         diff_words_flush(ecbdata);
884                 len = sane_truncate_line(ecbdata, line, len);
885                 find_lno(line, ecbdata);
886                 emit_hunk_header(ecbdata, line, len);
887                 if (line[len-1] != '\n')
888                         putc('\n', ecbdata->file);
889                 return;
890         }
891
892         if (len < 1) {
893                 emit_line(ecbdata->file, reset, reset, line, len);
894                 if (ecbdata->diff_words
895                     && ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN)
896                         fputs("~\n", ecbdata->file);
897                 return;
898         }
899
900         if (ecbdata->diff_words) {
901                 if (line[0] == '-') {
902                         diff_words_append(line, len,
903                                           &ecbdata->diff_words->minus);
904                         return;
905                 } else if (line[0] == '+') {
906                         diff_words_append(line, len,
907                                           &ecbdata->diff_words->plus);
908                         return;
909                 }
910                 diff_words_flush(ecbdata);
911                 if (ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN) {
912                         emit_line(ecbdata->file, plain, reset, line, len);
913                         fputs("~\n", ecbdata->file);
914                 } else {
915                         /* don't print the prefix character */
916                         emit_line(ecbdata->file, plain, reset, line+1, len-1);
917                 }
918                 return;
919         }
920
921         if (line[0] != '+') {
922                 const char *color =
923                         diff_get_color(ecbdata->color_diff,
924                                        line[0] == '-' ? DIFF_FILE_OLD : DIFF_PLAIN);
925                 ecbdata->lno_in_preimage++;
926                 if (line[0] == ' ')
927                         ecbdata->lno_in_postimage++;
928                 emit_line(ecbdata->file, color, reset, line, len);
929         } else {
930                 ecbdata->lno_in_postimage++;
931                 emit_add_line(reset, ecbdata, line + 1, len - 1);
932         }
933 }
934
935 static char *pprint_rename(const char *a, const char *b)
936 {
937         const char *old = a;
938         const char *new = b;
939         struct strbuf name = STRBUF_INIT;
940         int pfx_length, sfx_length;
941         int len_a = strlen(a);
942         int len_b = strlen(b);
943         int a_midlen, b_midlen;
944         int qlen_a = quote_c_style(a, NULL, NULL, 0);
945         int qlen_b = quote_c_style(b, NULL, NULL, 0);
946
947         if (qlen_a || qlen_b) {
948                 quote_c_style(a, &name, NULL, 0);
949                 strbuf_addstr(&name, " => ");
950                 quote_c_style(b, &name, NULL, 0);
951                 return strbuf_detach(&name, NULL);
952         }
953
954         /* Find common prefix */
955         pfx_length = 0;
956         while (*old && *new && *old == *new) {
957                 if (*old == '/')
958                         pfx_length = old - a + 1;
959                 old++;
960                 new++;
961         }
962
963         /* Find common suffix */
964         old = a + len_a;
965         new = b + len_b;
966         sfx_length = 0;
967         while (a <= old && b <= new && *old == *new) {
968                 if (*old == '/')
969                         sfx_length = len_a - (old - a);
970                 old--;
971                 new--;
972         }
973
974         /*
975          * pfx{mid-a => mid-b}sfx
976          * {pfx-a => pfx-b}sfx
977          * pfx{sfx-a => sfx-b}
978          * name-a => name-b
979          */
980         a_midlen = len_a - pfx_length - sfx_length;
981         b_midlen = len_b - pfx_length - sfx_length;
982         if (a_midlen < 0)
983                 a_midlen = 0;
984         if (b_midlen < 0)
985                 b_midlen = 0;
986
987         strbuf_grow(&name, pfx_length + a_midlen + b_midlen + sfx_length + 7);
988         if (pfx_length + sfx_length) {
989                 strbuf_add(&name, a, pfx_length);
990                 strbuf_addch(&name, '{');
991         }
992         strbuf_add(&name, a + pfx_length, a_midlen);
993         strbuf_addstr(&name, " => ");
994         strbuf_add(&name, b + pfx_length, b_midlen);
995         if (pfx_length + sfx_length) {
996                 strbuf_addch(&name, '}');
997                 strbuf_add(&name, a + len_a - sfx_length, sfx_length);
998         }
999         return strbuf_detach(&name, NULL);
1000 }
1001
1002 struct diffstat_t {
1003         int nr;
1004         int alloc;
1005         struct diffstat_file {
1006                 char *from_name;
1007                 char *name;
1008                 char *print_name;
1009                 unsigned is_unmerged:1;
1010                 unsigned is_binary:1;
1011                 unsigned is_renamed:1;
1012                 unsigned int added, deleted;
1013         } **files;
1014 };
1015
1016 static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,
1017                                           const char *name_a,
1018                                           const char *name_b)
1019 {
1020         struct diffstat_file *x;
1021         x = xcalloc(sizeof (*x), 1);
1022         if (diffstat->nr == diffstat->alloc) {
1023                 diffstat->alloc = alloc_nr(diffstat->alloc);
1024                 diffstat->files = xrealloc(diffstat->files,
1025                                 diffstat->alloc * sizeof(x));
1026         }
1027         diffstat->files[diffstat->nr++] = x;
1028         if (name_b) {
1029                 x->from_name = xstrdup(name_a);
1030                 x->name = xstrdup(name_b);
1031                 x->is_renamed = 1;
1032         }
1033         else {
1034                 x->from_name = NULL;
1035                 x->name = xstrdup(name_a);
1036         }
1037         return x;
1038 }
1039
1040 static void diffstat_consume(void *priv, char *line, unsigned long len)
1041 {
1042         struct diffstat_t *diffstat = priv;
1043         struct diffstat_file *x = diffstat->files[diffstat->nr - 1];
1044
1045         if (line[0] == '+')
1046                 x->added++;
1047         else if (line[0] == '-')
1048                 x->deleted++;
1049 }
1050
1051 const char mime_boundary_leader[] = "------------";
1052
1053 static int scale_linear(int it, int width, int max_change)
1054 {
1055         /*
1056          * make sure that at least one '-' is printed if there were deletions,
1057          * and likewise for '+'.
1058          */
1059         if (max_change < 2)
1060                 return it;
1061         return ((it - 1) * (width - 1) + max_change - 1) / (max_change - 1);
1062 }
1063
1064 static void show_name(FILE *file,
1065                       const char *prefix, const char *name, int len)
1066 {
1067         fprintf(file, " %s%-*s |", prefix, len, name);
1068 }
1069
1070 static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset)
1071 {
1072         if (cnt <= 0)
1073                 return;
1074         fprintf(file, "%s", set);
1075         while (cnt--)
1076                 putc(ch, file);
1077         fprintf(file, "%s", reset);
1078 }
1079
1080 static void fill_print_name(struct diffstat_file *file)
1081 {
1082         char *pname;
1083
1084         if (file->print_name)
1085                 return;
1086
1087         if (!file->is_renamed) {
1088                 struct strbuf buf = STRBUF_INIT;
1089                 if (quote_c_style(file->name, &buf, NULL, 0)) {
1090                         pname = strbuf_detach(&buf, NULL);
1091                 } else {
1092                         pname = file->name;
1093                         strbuf_release(&buf);
1094                 }
1095         } else {
1096                 pname = pprint_rename(file->from_name, file->name);
1097         }
1098         file->print_name = pname;
1099 }
1100
1101 static void show_stats(struct diffstat_t *data, struct diff_options *options)
1102 {
1103         int i, len, add, del, adds = 0, dels = 0;
1104         int max_change = 0, max_len = 0;
1105         int total_files = data->nr;
1106         int width, name_width;
1107         const char *reset, *set, *add_c, *del_c;
1108
1109         if (data->nr == 0)
1110                 return;
1111
1112         width = options->stat_width ? options->stat_width : 80;
1113         name_width = options->stat_name_width ? options->stat_name_width : 50;
1114
1115         /* Sanity: give at least 5 columns to the graph,
1116          * but leave at least 10 columns for the name.
1117          */
1118         if (width < 25)
1119                 width = 25;
1120         if (name_width < 10)
1121                 name_width = 10;
1122         else if (width < name_width + 15)
1123                 name_width = width - 15;
1124
1125         /* Find the longest filename and max number of changes */
1126         reset = diff_get_color_opt(options, DIFF_RESET);
1127         set   = diff_get_color_opt(options, DIFF_PLAIN);
1128         add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
1129         del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
1130
1131         for (i = 0; i < data->nr; i++) {
1132                 struct diffstat_file *file = data->files[i];
1133                 int change = file->added + file->deleted;
1134                 fill_print_name(file);
1135                 len = strlen(file->print_name);
1136                 if (max_len < len)
1137                         max_len = len;
1138
1139                 if (file->is_binary || file->is_unmerged)
1140                         continue;
1141                 if (max_change < change)
1142                         max_change = change;
1143         }
1144
1145         /* Compute the width of the graph part;
1146          * 10 is for one blank at the beginning of the line plus
1147          * " | count " between the name and the graph.
1148          *
1149          * From here on, name_width is the width of the name area,
1150          * and width is the width of the graph area.
1151          */
1152         name_width = (name_width < max_len) ? name_width : max_len;
1153         if (width < (name_width + 10) + max_change)
1154                 width = width - (name_width + 10);
1155         else
1156                 width = max_change;
1157
1158         for (i = 0; i < data->nr; i++) {
1159                 const char *prefix = "";
1160                 char *name = data->files[i]->print_name;
1161                 int added = data->files[i]->added;
1162                 int deleted = data->files[i]->deleted;
1163                 int name_len;
1164
1165                 /*
1166                  * "scale" the filename
1167                  */
1168                 len = name_width;
1169                 name_len = strlen(name);
1170                 if (name_width < name_len) {
1171                         char *slash;
1172                         prefix = "...";
1173                         len -= 3;
1174                         name += name_len - len;
1175                         slash = strchr(name, '/');
1176                         if (slash)
1177                                 name = slash;
1178                 }
1179
1180                 if (data->files[i]->is_binary) {
1181                         show_name(options->file, prefix, name, len);
1182                         fprintf(options->file, "  Bin ");
1183                         fprintf(options->file, "%s%d%s", del_c, deleted, reset);
1184                         fprintf(options->file, " -> ");
1185                         fprintf(options->file, "%s%d%s", add_c, added, reset);
1186                         fprintf(options->file, " bytes");
1187                         fprintf(options->file, "\n");
1188                         continue;
1189                 }
1190                 else if (data->files[i]->is_unmerged) {
1191                         show_name(options->file, prefix, name, len);
1192                         fprintf(options->file, "  Unmerged\n");
1193                         continue;
1194                 }
1195                 else if (!data->files[i]->is_renamed &&
1196                          (added + deleted == 0)) {
1197                         total_files--;
1198                         continue;
1199                 }
1200
1201                 /*
1202                  * scale the add/delete
1203                  */
1204                 add = added;
1205                 del = deleted;
1206                 adds += add;
1207                 dels += del;
1208
1209                 if (width <= max_change) {
1210                         add = scale_linear(add, width, max_change);
1211                         del = scale_linear(del, width, max_change);
1212                 }
1213                 show_name(options->file, prefix, name, len);
1214                 fprintf(options->file, "%5d%s", added + deleted,
1215                                 added + deleted ? " " : "");
1216                 show_graph(options->file, '+', add, add_c, reset);
1217                 show_graph(options->file, '-', del, del_c, reset);
1218                 fprintf(options->file, "\n");
1219         }
1220         fprintf(options->file,
1221                " %d files changed, %d insertions(+), %d deletions(-)\n",
1222                total_files, adds, dels);
1223 }
1224
1225 static void show_shortstats(struct diffstat_t *data, struct diff_options *options)
1226 {
1227         int i, adds = 0, dels = 0, total_files = data->nr;
1228
1229         if (data->nr == 0)
1230                 return;
1231
1232         for (i = 0; i < data->nr; i++) {
1233                 if (!data->files[i]->is_binary &&
1234                     !data->files[i]->is_unmerged) {
1235                         int added = data->files[i]->added;
1236                         int deleted= data->files[i]->deleted;
1237                         if (!data->files[i]->is_renamed &&
1238                             (added + deleted == 0)) {
1239                                 total_files--;
1240                         } else {
1241                                 adds += added;
1242                                 dels += deleted;
1243                         }
1244                 }
1245         }
1246         fprintf(options->file, " %d files changed, %d insertions(+), %d deletions(-)\n",
1247                total_files, adds, dels);
1248 }
1249
1250 static void show_numstat(struct diffstat_t *data, struct diff_options *options)
1251 {
1252         int i;
1253
1254         if (data->nr == 0)
1255                 return;
1256
1257         for (i = 0; i < data->nr; i++) {
1258                 struct diffstat_file *file = data->files[i];
1259
1260                 if (file->is_binary)
1261                         fprintf(options->file, "-\t-\t");
1262                 else
1263                         fprintf(options->file,
1264                                 "%d\t%d\t", file->added, file->deleted);
1265                 if (options->line_termination) {
1266                         fill_print_name(file);
1267                         if (!file->is_renamed)
1268                                 write_name_quoted(file->name, options->file,
1269                                                   options->line_termination);
1270                         else {
1271                                 fputs(file->print_name, options->file);
1272                                 putc(options->line_termination, options->file);
1273                         }
1274                 } else {
1275                         if (file->is_renamed) {
1276                                 putc('\0', options->file);
1277                                 write_name_quoted(file->from_name, options->file, '\0');
1278                         }
1279                         write_name_quoted(file->name, options->file, '\0');
1280                 }
1281         }
1282 }
1283
1284 struct dirstat_file {
1285         const char *name;
1286         unsigned long changed;
1287 };
1288
1289 struct dirstat_dir {
1290         struct dirstat_file *files;
1291         int alloc, nr, percent, cumulative;
1292 };
1293
1294 static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long changed, const char *base, int baselen)
1295 {
1296         unsigned long this_dir = 0;
1297         unsigned int sources = 0;
1298
1299         while (dir->nr) {
1300                 struct dirstat_file *f = dir->files;
1301                 int namelen = strlen(f->name);
1302                 unsigned long this;
1303                 char *slash;
1304
1305                 if (namelen < baselen)
1306                         break;
1307                 if (memcmp(f->name, base, baselen))
1308                         break;
1309                 slash = strchr(f->name + baselen, '/');
1310                 if (slash) {
1311                         int newbaselen = slash + 1 - f->name;
1312                         this = gather_dirstat(file, dir, changed, f->name, newbaselen);
1313                         sources++;
1314                 } else {
1315                         this = f->changed;
1316                         dir->files++;
1317                         dir->nr--;
1318                         sources += 2;
1319                 }
1320                 this_dir += this;
1321         }
1322
1323         /*
1324          * We don't report dirstat's for
1325          *  - the top level
1326          *  - or cases where everything came from a single directory
1327          *    under this directory (sources == 1).
1328          */
1329         if (baselen && sources != 1) {
1330                 int permille = this_dir * 1000 / changed;
1331                 if (permille) {
1332                         int percent = permille / 10;
1333                         if (percent >= dir->percent) {
1334                                 fprintf(file, "%4d.%01d%% %.*s\n", percent, permille % 10, baselen, base);
1335                                 if (!dir->cumulative)
1336                                         return 0;
1337                         }
1338                 }
1339         }
1340         return this_dir;
1341 }
1342
1343 static int dirstat_compare(const void *_a, const void *_b)
1344 {
1345         const struct dirstat_file *a = _a;
1346         const struct dirstat_file *b = _b;
1347         return strcmp(a->name, b->name);
1348 }
1349
1350 static void show_dirstat(struct diff_options *options)
1351 {
1352         int i;
1353         unsigned long changed;
1354         struct dirstat_dir dir;
1355         struct diff_queue_struct *q = &diff_queued_diff;
1356
1357         dir.files = NULL;
1358         dir.alloc = 0;
1359         dir.nr = 0;
1360         dir.percent = options->dirstat_percent;
1361         dir.cumulative = DIFF_OPT_TST(options, DIRSTAT_CUMULATIVE);
1362
1363         changed = 0;
1364         for (i = 0; i < q->nr; i++) {
1365                 struct diff_filepair *p = q->queue[i];
1366                 const char *name;
1367                 unsigned long copied, added, damage;
1368
1369                 name = p->one->path ? p->one->path : p->two->path;
1370
1371                 if (DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {
1372                         diff_populate_filespec(p->one, 0);
1373                         diff_populate_filespec(p->two, 0);
1374                         diffcore_count_changes(p->one, p->two, NULL, NULL, 0,
1375                                                &copied, &added);
1376                         diff_free_filespec_data(p->one);
1377                         diff_free_filespec_data(p->two);
1378                 } else if (DIFF_FILE_VALID(p->one)) {
1379                         diff_populate_filespec(p->one, 1);
1380                         copied = added = 0;
1381                         diff_free_filespec_data(p->one);
1382                 } else if (DIFF_FILE_VALID(p->two)) {
1383                         diff_populate_filespec(p->two, 1);
1384                         copied = 0;
1385                         added = p->two->size;
1386                         diff_free_filespec_data(p->two);
1387                 } else
1388                         continue;
1389
1390                 /*
1391                  * Original minus copied is the removed material,
1392                  * added is the new material.  They are both damages
1393                  * made to the preimage. In --dirstat-by-file mode, count
1394                  * damaged files, not damaged lines. This is done by
1395                  * counting only a single damaged line per file.
1396                  */
1397                 damage = (p->one->size - copied) + added;
1398                 if (DIFF_OPT_TST(options, DIRSTAT_BY_FILE) && damage > 0)
1399                         damage = 1;
1400
1401                 ALLOC_GROW(dir.files, dir.nr + 1, dir.alloc);
1402                 dir.files[dir.nr].name = name;
1403                 dir.files[dir.nr].changed = damage;
1404                 changed += damage;
1405                 dir.nr++;
1406         }
1407
1408         /* This can happen even with many files, if everything was renames */
1409         if (!changed)
1410                 return;
1411
1412         /* Show all directories with more than x% of the changes */
1413         qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare);
1414         gather_dirstat(options->file, &dir, changed, "", 0);
1415 }
1416
1417 static void free_diffstat_info(struct diffstat_t *diffstat)
1418 {
1419         int i;
1420         for (i = 0; i < diffstat->nr; i++) {
1421                 struct diffstat_file *f = diffstat->files[i];
1422                 if (f->name != f->print_name)
1423                         free(f->print_name);
1424                 free(f->name);
1425                 free(f->from_name);
1426                 free(f);
1427         }
1428         free(diffstat->files);
1429 }
1430
1431 struct checkdiff_t {
1432         const char *filename;
1433         int lineno;
1434         struct diff_options *o;
1435         unsigned ws_rule;
1436         unsigned status;
1437 };
1438
1439 static int is_conflict_marker(const char *line, unsigned long len)
1440 {
1441         char firstchar;
1442         int cnt;
1443
1444         if (len < 8)
1445                 return 0;
1446         firstchar = line[0];
1447         switch (firstchar) {
1448         case '=': case '>': case '<':
1449                 break;
1450         default:
1451                 return 0;
1452         }
1453         for (cnt = 1; cnt < 7; cnt++)
1454                 if (line[cnt] != firstchar)
1455                         return 0;
1456         /* line[0] thru line[6] are same as firstchar */
1457         if (firstchar == '=') {
1458                 /* divider between ours and theirs? */
1459                 if (len != 8 || line[7] != '\n')
1460                         return 0;
1461         } else if (len < 8 || !isspace(line[7])) {
1462                 /* not divider before ours nor after theirs */
1463                 return 0;
1464         }
1465         return 1;
1466 }
1467
1468 static void checkdiff_consume(void *priv, char *line, unsigned long len)
1469 {
1470         struct checkdiff_t *data = priv;
1471         int color_diff = DIFF_OPT_TST(data->o, COLOR_DIFF);
1472         const char *ws = diff_get_color(color_diff, DIFF_WHITESPACE);
1473         const char *reset = diff_get_color(color_diff, DIFF_RESET);
1474         const char *set = diff_get_color(color_diff, DIFF_FILE_NEW);
1475         char *err;
1476
1477         if (line[0] == '+') {
1478                 unsigned bad;
1479                 data->lineno++;
1480                 if (is_conflict_marker(line + 1, len - 1)) {
1481                         data->status |= 1;
1482                         fprintf(data->o->file,
1483                                 "%s:%d: leftover conflict marker\n",
1484                                 data->filename, data->lineno);
1485                 }
1486                 bad = ws_check(line + 1, len - 1, data->ws_rule);
1487                 if (!bad)
1488                         return;
1489                 data->status |= bad;
1490                 err = whitespace_error_string(bad);
1491                 fprintf(data->o->file, "%s:%d: %s.\n",
1492                         data->filename, data->lineno, err);
1493                 free(err);
1494                 emit_line(data->o->file, set, reset, line, 1);
1495                 ws_check_emit(line + 1, len - 1, data->ws_rule,
1496                               data->o->file, set, reset, ws);
1497         } else if (line[0] == ' ') {
1498                 data->lineno++;
1499         } else if (line[0] == '@') {
1500                 char *plus = strchr(line, '+');
1501                 if (plus)
1502                         data->lineno = strtol(plus, NULL, 10) - 1;
1503                 else
1504                         die("invalid diff");
1505         }
1506 }
1507
1508 static unsigned char *deflate_it(char *data,
1509                                  unsigned long size,
1510                                  unsigned long *result_size)
1511 {
1512         int bound;
1513         unsigned char *deflated;
1514         z_stream stream;
1515
1516         memset(&stream, 0, sizeof(stream));
1517         deflateInit(&stream, zlib_compression_level);
1518         bound = deflateBound(&stream, size);
1519         deflated = xmalloc(bound);
1520         stream.next_out = deflated;
1521         stream.avail_out = bound;
1522
1523         stream.next_in = (unsigned char *)data;
1524         stream.avail_in = size;
1525         while (deflate(&stream, Z_FINISH) == Z_OK)
1526                 ; /* nothing */
1527         deflateEnd(&stream);
1528         *result_size = stream.total_out;
1529         return deflated;
1530 }
1531
1532 static void emit_binary_diff_body(FILE *file, mmfile_t *one, mmfile_t *two)
1533 {
1534         void *cp;
1535         void *delta;
1536         void *deflated;
1537         void *data;
1538         unsigned long orig_size;
1539         unsigned long delta_size;
1540         unsigned long deflate_size;
1541         unsigned long data_size;
1542
1543         /* We could do deflated delta, or we could do just deflated two,
1544          * whichever is smaller.
1545          */
1546         delta = NULL;
1547         deflated = deflate_it(two->ptr, two->size, &deflate_size);
1548         if (one->size && two->size) {
1549                 delta = diff_delta(one->ptr, one->size,
1550                                    two->ptr, two->size,
1551                                    &delta_size, deflate_size);
1552                 if (delta) {
1553                         void *to_free = delta;
1554                         orig_size = delta_size;
1555                         delta = deflate_it(delta, delta_size, &delta_size);
1556                         free(to_free);
1557                 }
1558         }
1559
1560         if (delta && delta_size < deflate_size) {
1561                 fprintf(file, "delta %lu\n", orig_size);
1562                 free(deflated);
1563                 data = delta;
1564                 data_size = delta_size;
1565         }
1566         else {
1567                 fprintf(file, "literal %lu\n", two->size);
1568                 free(delta);
1569                 data = deflated;
1570                 data_size = deflate_size;
1571         }
1572
1573         /* emit data encoded in base85 */
1574         cp = data;
1575         while (data_size) {
1576                 int bytes = (52 < data_size) ? 52 : data_size;
1577                 char line[70];
1578                 data_size -= bytes;
1579                 if (bytes <= 26)
1580                         line[0] = bytes + 'A' - 1;
1581                 else
1582                         line[0] = bytes - 26 + 'a' - 1;
1583                 encode_85(line + 1, cp, bytes);
1584                 cp = (char *) cp + bytes;
1585                 fputs(line, file);
1586                 fputc('\n', file);
1587         }
1588         fprintf(file, "\n");
1589         free(data);
1590 }
1591
1592 static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two)
1593 {
1594         fprintf(file, "GIT binary patch\n");
1595         emit_binary_diff_body(file, one, two);
1596         emit_binary_diff_body(file, two, one);
1597 }
1598
1599 static void diff_filespec_load_driver(struct diff_filespec *one)
1600 {
1601         if (!one->driver)
1602                 one->driver = userdiff_find_by_path(one->path);
1603         if (!one->driver)
1604                 one->driver = userdiff_find_by_name("default");
1605 }
1606
1607 int diff_filespec_is_binary(struct diff_filespec *one)
1608 {
1609         if (one->is_binary == -1) {
1610                 diff_filespec_load_driver(one);
1611                 if (one->driver->binary != -1)
1612                         one->is_binary = one->driver->binary;
1613                 else {
1614                         if (!one->data && DIFF_FILE_VALID(one))
1615                                 diff_populate_filespec(one, 0);
1616                         if (one->data)
1617                                 one->is_binary = buffer_is_binary(one->data,
1618                                                 one->size);
1619                         if (one->is_binary == -1)
1620                                 one->is_binary = 0;
1621                 }
1622         }
1623         return one->is_binary;
1624 }
1625
1626 static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespec *one)
1627 {
1628         diff_filespec_load_driver(one);
1629         return one->driver->funcname.pattern ? &one->driver->funcname : NULL;
1630 }
1631
1632 static const char *userdiff_word_regex(struct diff_filespec *one)
1633 {
1634         diff_filespec_load_driver(one);
1635         return one->driver->word_regex;
1636 }
1637
1638 void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b)
1639 {
1640         if (!options->a_prefix)
1641                 options->a_prefix = a;
1642         if (!options->b_prefix)
1643                 options->b_prefix = b;
1644 }
1645
1646 static const char *get_textconv(struct diff_filespec *one)
1647 {
1648         if (!DIFF_FILE_VALID(one))
1649                 return NULL;
1650         if (!S_ISREG(one->mode))
1651                 return NULL;
1652         diff_filespec_load_driver(one);
1653         return one->driver->textconv;
1654 }
1655
1656 static void builtin_diff(const char *name_a,
1657                          const char *name_b,
1658                          struct diff_filespec *one,
1659                          struct diff_filespec *two,
1660                          const char *xfrm_msg,
1661                          struct diff_options *o,
1662                          int complete_rewrite)
1663 {
1664         mmfile_t mf1, mf2;
1665         const char *lbl[2];
1666         char *a_one, *b_two;
1667         const char *set = diff_get_color_opt(o, DIFF_METAINFO);
1668         const char *reset = diff_get_color_opt(o, DIFF_RESET);
1669         const char *a_prefix, *b_prefix;
1670         const char *textconv_one = NULL, *textconv_two = NULL;
1671         struct strbuf header = STRBUF_INIT;
1672
1673         if (DIFF_OPT_TST(o, SUBMODULE_LOG) &&
1674                         (!one->mode || S_ISGITLINK(one->mode)) &&
1675                         (!two->mode || S_ISGITLINK(two->mode))) {
1676                 const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
1677                 const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
1678                 show_submodule_summary(o->file, one ? one->path : two->path,
1679                                 one->sha1, two->sha1, two->dirty_submodule,
1680                                 del, add, reset);
1681                 return;
1682         }
1683
1684         if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
1685                 textconv_one = get_textconv(one);
1686                 textconv_two = get_textconv(two);
1687         }
1688
1689         diff_set_mnemonic_prefix(o, "a/", "b/");
1690         if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
1691                 a_prefix = o->b_prefix;
1692                 b_prefix = o->a_prefix;
1693         } else {
1694                 a_prefix = o->a_prefix;
1695                 b_prefix = o->b_prefix;
1696         }
1697
1698         /* Never use a non-valid filename anywhere if at all possible */
1699         name_a = DIFF_FILE_VALID(one) ? name_a : name_b;
1700         name_b = DIFF_FILE_VALID(two) ? name_b : name_a;
1701
1702         a_one = quote_two(a_prefix, name_a + (*name_a == '/'));
1703         b_two = quote_two(b_prefix, name_b + (*name_b == '/'));
1704         lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
1705         lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
1706         strbuf_addf(&header, "%sdiff --git %s %s%s\n", set, a_one, b_two, reset);
1707         if (lbl[0][0] == '/') {
1708                 /* /dev/null */
1709                 strbuf_addf(&header, "%snew file mode %06o%s\n", set, two->mode, reset);
1710                 if (xfrm_msg && xfrm_msg[0])
1711                         strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
1712         }
1713         else if (lbl[1][0] == '/') {
1714                 strbuf_addf(&header, "%sdeleted file mode %06o%s\n", set, one->mode, reset);
1715                 if (xfrm_msg && xfrm_msg[0])
1716                         strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
1717         }
1718         else {
1719                 if (one->mode != two->mode) {
1720                         strbuf_addf(&header, "%sold mode %06o%s\n", set, one->mode, reset);
1721                         strbuf_addf(&header, "%snew mode %06o%s\n", set, two->mode, reset);
1722                 }
1723                 if (xfrm_msg && xfrm_msg[0])
1724                         strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
1725
1726                 /*
1727                  * we do not run diff between different kind
1728                  * of objects.
1729                  */
1730                 if ((one->mode ^ two->mode) & S_IFMT)
1731                         goto free_ab_and_return;
1732                 if (complete_rewrite &&
1733                     (textconv_one || !diff_filespec_is_binary(one)) &&
1734                     (textconv_two || !diff_filespec_is_binary(two))) {
1735                         fprintf(o->file, "%s", header.buf);
1736                         strbuf_reset(&header);
1737                         emit_rewrite_diff(name_a, name_b, one, two,
1738                                                 textconv_one, textconv_two, o);
1739                         o->found_changes = 1;
1740                         goto free_ab_and_return;
1741                 }
1742         }
1743
1744         if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
1745                 die("unable to read files to diff");
1746
1747         if (!DIFF_OPT_TST(o, TEXT) &&
1748             ( (diff_filespec_is_binary(one) && !textconv_one) ||
1749               (diff_filespec_is_binary(two) && !textconv_two) )) {
1750                 /* Quite common confusing case */
1751                 if (mf1.size == mf2.size &&
1752                     !memcmp(mf1.ptr, mf2.ptr, mf1.size))
1753                         goto free_ab_and_return;
1754                 fprintf(o->file, "%s", header.buf);
1755                 strbuf_reset(&header);
1756                 if (DIFF_OPT_TST(o, BINARY))
1757                         emit_binary_diff(o->file, &mf1, &mf2);
1758                 else
1759                         fprintf(o->file, "Binary files %s and %s differ\n",
1760                                 lbl[0], lbl[1]);
1761                 o->found_changes = 1;
1762         }
1763         else {
1764                 /* Crazy xdl interfaces.. */
1765                 const char *diffopts = getenv("GIT_DIFF_OPTS");
1766                 xpparam_t xpp;
1767                 xdemitconf_t xecfg;
1768                 xdemitcb_t ecb;
1769                 struct emit_callback ecbdata;
1770                 const struct userdiff_funcname *pe;
1771
1772                 if (!DIFF_XDL_TST(o, WHITESPACE_FLAGS)) {
1773                         fprintf(o->file, "%s", header.buf);
1774                         strbuf_reset(&header);
1775                 }
1776
1777                 if (textconv_one) {
1778                         size_t size;
1779                         mf1.ptr = run_textconv(textconv_one, one, &size);
1780                         if (!mf1.ptr)
1781                                 die("unable to read files to diff");
1782                         mf1.size = size;
1783                 }
1784                 if (textconv_two) {
1785                         size_t size;
1786                         mf2.ptr = run_textconv(textconv_two, two, &size);
1787                         if (!mf2.ptr)
1788                                 die("unable to read files to diff");
1789                         mf2.size = size;
1790                 }
1791
1792                 pe = diff_funcname_pattern(one);
1793                 if (!pe)
1794                         pe = diff_funcname_pattern(two);
1795
1796                 memset(&xpp, 0, sizeof(xpp));
1797                 memset(&xecfg, 0, sizeof(xecfg));
1798                 memset(&ecbdata, 0, sizeof(ecbdata));
1799                 ecbdata.label_path = lbl;
1800                 ecbdata.color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
1801                 ecbdata.found_changesp = &o->found_changes;
1802                 ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
1803                 if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
1804                         check_blank_at_eof(&mf1, &mf2, &ecbdata);
1805                 ecbdata.file = o->file;
1806                 ecbdata.header = header.len ? &header : NULL;
1807                 xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
1808                 xecfg.ctxlen = o->context;
1809                 xecfg.interhunkctxlen = o->interhunkcontext;
1810                 xecfg.flags = XDL_EMIT_FUNCNAMES;
1811                 if (pe)
1812                         xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
1813                 if (!diffopts)
1814                         ;
1815                 else if (!prefixcmp(diffopts, "--unified="))
1816                         xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
1817                 else if (!prefixcmp(diffopts, "-u"))
1818                         xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
1819                 if (o->word_diff) {
1820                         int i;
1821
1822                         ecbdata.diff_words =
1823                                 xcalloc(1, sizeof(struct diff_words_data));
1824                         ecbdata.diff_words->file = o->file;
1825                         ecbdata.diff_words->type = o->word_diff;
1826                         if (!o->word_regex)
1827                                 o->word_regex = userdiff_word_regex(one);
1828                         if (!o->word_regex)
1829                                 o->word_regex = userdiff_word_regex(two);
1830                         if (!o->word_regex)
1831                                 o->word_regex = diff_word_regex_cfg;
1832                         if (o->word_regex) {
1833                                 ecbdata.diff_words->word_regex = (regex_t *)
1834                                         xmalloc(sizeof(regex_t));
1835                                 if (regcomp(ecbdata.diff_words->word_regex,
1836                                                 o->word_regex,
1837                                                 REG_EXTENDED | REG_NEWLINE))
1838                                         die ("Invalid regular expression: %s",
1839                                                         o->word_regex);
1840                         }
1841                         for (i = 0; i < ARRAY_SIZE(diff_words_styles); i++) {
1842                                 if (o->word_diff == diff_words_styles[i].type) {
1843                                         ecbdata.diff_words->style =
1844                                                 &diff_words_styles[i];
1845                                         break;
1846                                 }
1847                         }
1848                         if (DIFF_OPT_TST(o, COLOR_DIFF)) {
1849                                 struct diff_words_style *st = ecbdata.diff_words->style;
1850                                 st->old.color = diff_get_color_opt(o, DIFF_FILE_OLD);
1851                                 st->new.color = diff_get_color_opt(o, DIFF_FILE_NEW);
1852                                 st->ctx.color = diff_get_color_opt(o, DIFF_PLAIN);
1853                         }
1854                 }
1855                 xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
1856                               &xpp, &xecfg, &ecb);
1857                 if (o->word_diff)
1858                         free_diff_words_data(&ecbdata);
1859                 if (textconv_one)
1860                         free(mf1.ptr);
1861                 if (textconv_two)
1862                         free(mf2.ptr);
1863                 xdiff_clear_find_func(&xecfg);
1864         }
1865
1866  free_ab_and_return:
1867         strbuf_release(&header);
1868         diff_free_filespec_data(one);
1869         diff_free_filespec_data(two);
1870         free(a_one);
1871         free(b_two);
1872         return;
1873 }
1874
1875 static void builtin_diffstat(const char *name_a, const char *name_b,
1876                              struct diff_filespec *one,
1877                              struct diff_filespec *two,
1878                              struct diffstat_t *diffstat,
1879                              struct diff_options *o,
1880                              int complete_rewrite)
1881 {
1882         mmfile_t mf1, mf2;
1883         struct diffstat_file *data;
1884
1885         data = diffstat_add(diffstat, name_a, name_b);
1886
1887         if (!one || !two) {
1888                 data->is_unmerged = 1;
1889                 return;
1890         }
1891         if (complete_rewrite) {
1892                 diff_populate_filespec(one, 0);
1893                 diff_populate_filespec(two, 0);
1894                 data->deleted = count_lines(one->data, one->size);
1895                 data->added = count_lines(two->data, two->size);
1896                 goto free_and_return;
1897         }
1898         if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
1899                 die("unable to read files to diff");
1900
1901         if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
1902                 data->is_binary = 1;
1903                 data->added = mf2.size;
1904                 data->deleted = mf1.size;
1905         } else {
1906                 /* Crazy xdl interfaces.. */
1907                 xpparam_t xpp;
1908                 xdemitconf_t xecfg;
1909                 xdemitcb_t ecb;
1910
1911                 memset(&xpp, 0, sizeof(xpp));
1912                 memset(&xecfg, 0, sizeof(xecfg));
1913                 xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
1914                 xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
1915                               &xpp, &xecfg, &ecb);
1916         }
1917
1918  free_and_return:
1919         diff_free_filespec_data(one);
1920         diff_free_filespec_data(two);
1921 }
1922
1923 static void builtin_checkdiff(const char *name_a, const char *name_b,
1924                               const char *attr_path,
1925                               struct diff_filespec *one,
1926                               struct diff_filespec *two,
1927                               struct diff_options *o)
1928 {
1929         mmfile_t mf1, mf2;
1930         struct checkdiff_t data;
1931
1932         if (!two)
1933                 return;
1934
1935         memset(&data, 0, sizeof(data));
1936         data.filename = name_b ? name_b : name_a;
1937         data.lineno = 0;
1938         data.o = o;
1939         data.ws_rule = whitespace_rule(attr_path);
1940
1941         if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
1942                 die("unable to read files to diff");
1943
1944         /*
1945          * All the other codepaths check both sides, but not checking
1946          * the "old" side here is deliberate.  We are checking the newly
1947          * introduced changes, and as long as the "new" side is text, we
1948          * can and should check what it introduces.
1949          */
1950         if (diff_filespec_is_binary(two))
1951                 goto free_and_return;
1952         else {
1953                 /* Crazy xdl interfaces.. */
1954                 xpparam_t xpp;
1955                 xdemitconf_t xecfg;
1956                 xdemitcb_t ecb;
1957
1958                 memset(&xpp, 0, sizeof(xpp));
1959                 memset(&xecfg, 0, sizeof(xecfg));
1960                 xecfg.ctxlen = 1; /* at least one context line */
1961                 xpp.flags = XDF_NEED_MINIMAL;
1962                 xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
1963                               &xpp, &xecfg, &ecb);
1964
1965                 if (data.ws_rule & WS_BLANK_AT_EOF) {
1966                         struct emit_callback ecbdata;
1967                         int blank_at_eof;
1968
1969                         ecbdata.ws_rule = data.ws_rule;
1970                         check_blank_at_eof(&mf1, &mf2, &ecbdata);
1971                         blank_at_eof = ecbdata.blank_at_eof_in_preimage;
1972
1973                         if (blank_at_eof) {
1974                                 static char *err;
1975                                 if (!err)
1976                                         err = whitespace_error_string(WS_BLANK_AT_EOF);
1977                                 fprintf(o->file, "%s:%d: %s.\n",
1978                                         data.filename, blank_at_eof, err);
1979                                 data.status = 1; /* report errors */
1980                         }
1981                 }
1982         }
1983  free_and_return:
1984         diff_free_filespec_data(one);
1985         diff_free_filespec_data(two);
1986         if (data.status)
1987                 DIFF_OPT_SET(o, CHECK_FAILED);
1988 }
1989
1990 struct diff_filespec *alloc_filespec(const char *path)
1991 {
1992         int namelen = strlen(path);
1993         struct diff_filespec *spec = xmalloc(sizeof(*spec) + namelen + 1);
1994
1995         memset(spec, 0, sizeof(*spec));
1996         spec->path = (char *)(spec + 1);
1997         memcpy(spec->path, path, namelen+1);
1998         spec->count = 1;
1999         spec->is_binary = -1;
2000         return spec;
2001 }
2002
2003 void free_filespec(struct diff_filespec *spec)
2004 {
2005         if (!--spec->count) {
2006                 diff_free_filespec_data(spec);
2007                 free(spec);
2008         }
2009 }
2010
2011 void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
2012                    unsigned short mode)
2013 {
2014         if (mode) {
2015                 spec->mode = canon_mode(mode);
2016                 hashcpy(spec->sha1, sha1);
2017                 spec->sha1_valid = !is_null_sha1(sha1);
2018         }
2019 }
2020
2021 /*
2022  * Given a name and sha1 pair, if the index tells us the file in
2023  * the work tree has that object contents, return true, so that
2024  * prepare_temp_file() does not have to inflate and extract.
2025  */
2026 static int reuse_worktree_file(const char *name, const unsigned char *sha1, int want_file)
2027 {
2028         struct cache_entry *ce;
2029         struct stat st;
2030         int pos, len;
2031
2032         /*
2033          * We do not read the cache ourselves here, because the
2034          * benchmark with my previous version that always reads cache
2035          * shows that it makes things worse for diff-tree comparing
2036          * two linux-2.6 kernel trees in an already checked out work
2037          * tree.  This is because most diff-tree comparisons deal with
2038          * only a small number of files, while reading the cache is
2039          * expensive for a large project, and its cost outweighs the
2040          * savings we get by not inflating the object to a temporary
2041          * file.  Practically, this code only helps when we are used
2042          * by diff-cache --cached, which does read the cache before
2043          * calling us.
2044          */
2045         if (!active_cache)
2046                 return 0;
2047
2048         /* We want to avoid the working directory if our caller
2049          * doesn't need the data in a normal file, this system
2050          * is rather slow with its stat/open/mmap/close syscalls,
2051          * and the object is contained in a pack file.  The pack
2052          * is probably already open and will be faster to obtain
2053          * the data through than the working directory.  Loose
2054          * objects however would tend to be slower as they need
2055          * to be individually opened and inflated.
2056          */
2057         if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1))
2058                 return 0;
2059
2060         len = strlen(name);
2061         pos = cache_name_pos(name, len);
2062         if (pos < 0)
2063                 return 0;
2064         ce = active_cache[pos];
2065
2066         /*
2067          * This is not the sha1 we are looking for, or
2068          * unreusable because it is not a regular file.
2069          */
2070         if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode))
2071                 return 0;
2072
2073         /*
2074          * If ce is marked as "assume unchanged", there is no
2075          * guarantee that work tree matches what we are looking for.
2076          */
2077         if ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce))
2078                 return 0;
2079
2080         /*
2081          * If ce matches the file in the work tree, we can reuse it.
2082          */
2083         if (ce_uptodate(ce) ||
2084             (!lstat(name, &st) && !ce_match_stat(ce, &st, 0)))
2085                 return 1;
2086
2087         return 0;
2088 }
2089
2090 static int populate_from_stdin(struct diff_filespec *s)
2091 {
2092         struct strbuf buf = STRBUF_INIT;
2093         size_t size = 0;
2094
2095         if (strbuf_read(&buf, 0, 0) < 0)
2096                 return error("error while reading from stdin %s",
2097                                      strerror(errno));
2098
2099         s->should_munmap = 0;
2100         s->data = strbuf_detach(&buf, &size);
2101         s->size = size;
2102         s->should_free = 1;
2103         return 0;
2104 }
2105
2106 static int diff_populate_gitlink(struct diff_filespec *s, int size_only)
2107 {
2108         int len;
2109         char *data = xmalloc(100), *dirty = "";
2110
2111         /* Are we looking at the work tree? */
2112         if (s->dirty_submodule)
2113                 dirty = "-dirty";
2114
2115         len = snprintf(data, 100,
2116                        "Subproject commit %s%s\n", sha1_to_hex(s->sha1), dirty);
2117         s->data = data;
2118         s->size = len;
2119         s->should_free = 1;
2120         if (size_only) {
2121                 s->data = NULL;
2122                 free(data);
2123         }
2124         return 0;
2125 }
2126
2127 /*
2128  * While doing rename detection and pickaxe operation, we may need to
2129  * grab the data for the blob (or file) for our own in-core comparison.
2130  * diff_filespec has data and size fields for this purpose.
2131  */
2132 int diff_populate_filespec(struct diff_filespec *s, int size_only)
2133 {
2134         int err = 0;
2135         if (!DIFF_FILE_VALID(s))
2136                 die("internal error: asking to populate invalid file.");
2137         if (S_ISDIR(s->mode))
2138                 return -1;
2139
2140         if (s->data)
2141                 return 0;
2142
2143         if (size_only && 0 < s->size)
2144                 return 0;
2145
2146         if (S_ISGITLINK(s->mode))
2147                 return diff_populate_gitlink(s, size_only);
2148
2149         if (!s->sha1_valid ||
2150             reuse_worktree_file(s->path, s->sha1, 0)) {
2151                 struct strbuf buf = STRBUF_INIT;
2152                 struct stat st;
2153                 int fd;
2154
2155                 if (!strcmp(s->path, "-"))
2156                         return populate_from_stdin(s);
2157
2158                 if (lstat(s->path, &st) < 0) {
2159                         if (errno == ENOENT) {
2160                         err_empty:
2161                                 err = -1;
2162                         empty:
2163                                 s->data = (char *)"";
2164                                 s->size = 0;
2165                                 return err;
2166                         }
2167                 }
2168                 s->size = xsize_t(st.st_size);
2169                 if (!s->size)
2170                         goto empty;
2171                 if (S_ISLNK(st.st_mode)) {
2172                         struct strbuf sb = STRBUF_INIT;
2173
2174                         if (strbuf_readlink(&sb, s->path, s->size))
2175                                 goto err_empty;
2176                         s->size = sb.len;
2177                         s->data = strbuf_detach(&sb, NULL);
2178                         s->should_free = 1;
2179                         return 0;
2180                 }
2181                 if (size_only)
2182                         return 0;
2183                 fd = open(s->path, O_RDONLY);
2184                 if (fd < 0)
2185                         goto err_empty;
2186                 s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
2187                 close(fd);
2188                 s->should_munmap = 1;
2189
2190                 /*
2191                  * Convert from working tree format to canonical git format
2192                  */
2193                 if (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf)) {
2194                         size_t size = 0;
2195                         munmap(s->data, s->size);
2196                         s->should_munmap = 0;
2197                         s->data = strbuf_detach(&buf, &size);
2198                         s->size = size;
2199                         s->should_free = 1;
2200                 }
2201         }
2202         else {
2203                 enum object_type type;
2204                 if (size_only)
2205                         type = sha1_object_info(s->sha1, &s->size);
2206                 else {
2207                         s->data = read_sha1_file(s->sha1, &type, &s->size);
2208                         s->should_free = 1;
2209                 }
2210         }
2211         return 0;
2212 }
2213
2214 void diff_free_filespec_blob(struct diff_filespec *s)
2215 {
2216         if (s->should_free)
2217                 free(s->data);
2218         else if (s->should_munmap)
2219                 munmap(s->data, s->size);
2220
2221         if (s->should_free || s->should_munmap) {
2222                 s->should_free = s->should_munmap = 0;
2223                 s->data = NULL;
2224         }
2225 }
2226
2227 void diff_free_filespec_data(struct diff_filespec *s)
2228 {
2229         diff_free_filespec_blob(s);
2230         free(s->cnt_data);
2231         s->cnt_data = NULL;
2232 }
2233
2234 static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
2235                            void *blob,
2236                            unsigned long size,
2237                            const unsigned char *sha1,
2238                            int mode)
2239 {
2240         int fd;
2241         struct strbuf buf = STRBUF_INIT;
2242         struct strbuf template = STRBUF_INIT;
2243         char *path_dup = xstrdup(path);
2244         const char *base = basename(path_dup);
2245
2246         /* Generate "XXXXXX_basename.ext" */
2247         strbuf_addstr(&template, "XXXXXX_");
2248         strbuf_addstr(&template, base);
2249
2250         fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf,
2251                         strlen(base) + 1);
2252         if (fd < 0)
2253                 die_errno("unable to create temp-file");
2254         if (convert_to_working_tree(path,
2255                         (const char *)blob, (size_t)size, &buf)) {
2256                 blob = buf.buf;
2257                 size = buf.len;
2258         }
2259         if (write_in_full(fd, blob, size) != size)
2260                 die_errno("unable to write temp-file");
2261         close(fd);
2262         temp->name = temp->tmp_path;
2263         strcpy(temp->hex, sha1_to_hex(sha1));
2264         temp->hex[40] = 0;
2265         sprintf(temp->mode, "%06o", mode);
2266         strbuf_release(&buf);
2267         strbuf_release(&template);
2268         free(path_dup);
2269 }
2270
2271 static struct diff_tempfile *prepare_temp_file(const char *name,
2272                 struct diff_filespec *one)
2273 {
2274         struct diff_tempfile *temp = claim_diff_tempfile();
2275
2276         if (!DIFF_FILE_VALID(one)) {
2277         not_a_valid_file:
2278                 /* A '-' entry produces this for file-2, and
2279                  * a '+' entry produces this for file-1.
2280                  */
2281                 temp->name = "/dev/null";
2282                 strcpy(temp->hex, ".");
2283                 strcpy(temp->mode, ".");
2284                 return temp;
2285         }
2286
2287         if (!remove_tempfile_installed) {
2288                 atexit(remove_tempfile);
2289                 sigchain_push_common(remove_tempfile_on_signal);
2290                 remove_tempfile_installed = 1;
2291         }
2292
2293         if (!one->sha1_valid ||
2294             reuse_worktree_file(name, one->sha1, 1)) {
2295                 struct stat st;
2296                 if (lstat(name, &st) < 0) {
2297                         if (errno == ENOENT)
2298                                 goto not_a_valid_file;
2299                         die_errno("stat(%s)", name);
2300                 }
2301                 if (S_ISLNK(st.st_mode)) {
2302                         struct strbuf sb = STRBUF_INIT;
2303                         if (strbuf_readlink(&sb, name, st.st_size) < 0)
2304                                 die_errno("readlink(%s)", name);
2305                         prep_temp_blob(name, temp, sb.buf, sb.len,
2306                                        (one->sha1_valid ?
2307                                         one->sha1 : null_sha1),
2308                                        (one->sha1_valid ?
2309                                         one->mode : S_IFLNK));
2310                         strbuf_release(&sb);
2311                 }
2312                 else {
2313                         /* we can borrow from the file in the work tree */
2314                         temp->name = name;
2315                         if (!one->sha1_valid)
2316                                 strcpy(temp->hex, sha1_to_hex(null_sha1));
2317                         else
2318                                 strcpy(temp->hex, sha1_to_hex(one->sha1));
2319                         /* Even though we may sometimes borrow the
2320                          * contents from the work tree, we always want
2321                          * one->mode.  mode is trustworthy even when
2322                          * !(one->sha1_valid), as long as
2323                          * DIFF_FILE_VALID(one).
2324                          */
2325                         sprintf(temp->mode, "%06o", one->mode);
2326                 }
2327                 return temp;
2328         }
2329         else {
2330                 if (diff_populate_filespec(one, 0))
2331                         die("cannot read data blob for %s", one->path);
2332                 prep_temp_blob(name, temp, one->data, one->size,
2333                                one->sha1, one->mode);
2334         }
2335         return temp;
2336 }
2337
2338 /* An external diff command takes:
2339  *
2340  * diff-cmd name infile1 infile1-sha1 infile1-mode \
2341  *               infile2 infile2-sha1 infile2-mode [ rename-to ]
2342  *
2343  */
2344 static void run_external_diff(const char *pgm,
2345                               const char *name,
2346                               const char *other,
2347                               struct diff_filespec *one,
2348                               struct diff_filespec *two,
2349                               const char *xfrm_msg,
2350                               int complete_rewrite)
2351 {
2352         const char *spawn_arg[10];
2353         int retval;
2354         const char **arg = &spawn_arg[0];
2355
2356         if (one && two) {
2357                 struct diff_tempfile *temp_one, *temp_two;
2358                 const char *othername = (other ? other : name);
2359                 temp_one = prepare_temp_file(name, one);
2360                 temp_two = prepare_temp_file(othername, two);
2361                 *arg++ = pgm;
2362                 *arg++ = name;
2363                 *arg++ = temp_one->name;
2364                 *arg++ = temp_one->hex;
2365                 *arg++ = temp_one->mode;
2366                 *arg++ = temp_two->name;
2367                 *arg++ = temp_two->hex;
2368                 *arg++ = temp_two->mode;
2369                 if (other) {
2370                         *arg++ = other;
2371                         *arg++ = xfrm_msg;
2372                 }
2373         } else {
2374                 *arg++ = pgm;
2375                 *arg++ = name;
2376         }
2377         *arg = NULL;
2378         fflush(NULL);
2379         retval = run_command_v_opt(spawn_arg, RUN_USING_SHELL);
2380         remove_tempfile();
2381         if (retval) {
2382                 fprintf(stderr, "external diff died, stopping at %s.\n", name);
2383                 exit(1);
2384         }
2385 }
2386
2387 static int similarity_index(struct diff_filepair *p)
2388 {
2389         return p->score * 100 / MAX_SCORE;
2390 }
2391
2392 static void fill_metainfo(struct strbuf *msg,
2393                           const char *name,
2394                           const char *other,
2395                           struct diff_filespec *one,
2396                           struct diff_filespec *two,
2397                           struct diff_options *o,
2398                           struct diff_filepair *p)
2399 {
2400         strbuf_init(msg, PATH_MAX * 2 + 300);
2401         switch (p->status) {
2402         case DIFF_STATUS_COPIED:
2403                 strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
2404                 strbuf_addstr(msg, "\ncopy from ");
2405                 quote_c_style(name, msg, NULL, 0);
2406                 strbuf_addstr(msg, "\ncopy to ");
2407                 quote_c_style(other, msg, NULL, 0);
2408                 strbuf_addch(msg, '\n');
2409                 break;
2410         case DIFF_STATUS_RENAMED:
2411                 strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
2412                 strbuf_addstr(msg, "\nrename from ");
2413                 quote_c_style(name, msg, NULL, 0);
2414                 strbuf_addstr(msg, "\nrename to ");
2415                 quote_c_style(other, msg, NULL, 0);
2416                 strbuf_addch(msg, '\n');
2417                 break;
2418         case DIFF_STATUS_MODIFIED:
2419                 if (p->score) {
2420                         strbuf_addf(msg, "dissimilarity index %d%%\n",
2421                                     similarity_index(p));
2422                         break;
2423                 }
2424                 /* fallthru */
2425         default:
2426                 /* nothing */
2427                 ;
2428         }
2429         if (one && two && hashcmp(one->sha1, two->sha1)) {
2430                 int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
2431
2432                 if (DIFF_OPT_TST(o, BINARY)) {
2433                         mmfile_t mf;
2434                         if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) ||
2435                             (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
2436                                 abbrev = 40;
2437                 }
2438                 strbuf_addf(msg, "index %.*s..%.*s",
2439                             abbrev, sha1_to_hex(one->sha1),
2440                             abbrev, sha1_to_hex(two->sha1));
2441                 if (one->mode == two->mode)
2442                         strbuf_addf(msg, " %06o", one->mode);
2443                 strbuf_addch(msg, '\n');
2444         }
2445         if (msg->len)
2446                 strbuf_setlen(msg, msg->len - 1);
2447 }
2448
2449 static void run_diff_cmd(const char *pgm,
2450                          const char *name,
2451                          const char *other,
2452                          const char *attr_path,
2453                          struct diff_filespec *one,
2454                          struct diff_filespec *two,
2455                          struct strbuf *msg,
2456                          struct diff_options *o,
2457                          struct diff_filepair *p)
2458 {
2459         const char *xfrm_msg = NULL;
2460         int complete_rewrite = (p->status == DIFF_STATUS_MODIFIED) && p->score;
2461
2462         if (msg) {
2463                 fill_metainfo(msg, name, other, one, two, o, p);
2464                 xfrm_msg = msg->len ? msg->buf : NULL;
2465         }
2466
2467         if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
2468                 pgm = NULL;
2469         else {
2470                 struct userdiff_driver *drv = userdiff_find_by_path(attr_path);
2471                 if (drv && drv->external)
2472                         pgm = drv->external;
2473         }
2474
2475         if (pgm) {
2476                 run_external_diff(pgm, name, other, one, two, xfrm_msg,
2477                                   complete_rewrite);
2478                 return;
2479         }
2480         if (one && two)
2481                 builtin_diff(name, other ? other : name,
2482                              one, two, xfrm_msg, o, complete_rewrite);
2483         else
2484                 fprintf(o->file, "* Unmerged path %s\n", name);
2485 }
2486
2487 static void diff_fill_sha1_info(struct diff_filespec *one)
2488 {
2489         if (DIFF_FILE_VALID(one)) {
2490                 if (!one->sha1_valid) {
2491                         struct stat st;
2492                         if (!strcmp(one->path, "-")) {
2493                                 hashcpy(one->sha1, null_sha1);
2494                                 return;
2495                         }
2496                         if (lstat(one->path, &st) < 0)
2497                                 die_errno("stat '%s'", one->path);
2498                         if (index_path(one->sha1, one->path, &st, 0))
2499                                 die("cannot hash %s", one->path);
2500                 }
2501         }
2502         else
2503                 hashclr(one->sha1);
2504 }
2505
2506 static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
2507 {
2508         /* Strip the prefix but do not molest /dev/null and absolute paths */
2509         if (*namep && **namep != '/')
2510                 *namep += prefix_length;
2511         if (*otherp && **otherp != '/')
2512                 *otherp += prefix_length;
2513 }
2514
2515 static void run_diff(struct diff_filepair *p, struct diff_options *o)
2516 {
2517         const char *pgm = external_diff();
2518         struct strbuf msg;
2519         struct diff_filespec *one = p->one;
2520         struct diff_filespec *two = p->two;
2521         const char *name;
2522         const char *other;
2523         const char *attr_path;
2524
2525         name  = p->one->path;
2526         other = (strcmp(name, p->two->path) ? p->two->path : NULL);
2527         attr_path = name;
2528         if (o->prefix_length)
2529                 strip_prefix(o->prefix_length, &name, &other);
2530
2531         if (DIFF_PAIR_UNMERGED(p)) {
2532                 run_diff_cmd(pgm, name, NULL, attr_path,
2533                              NULL, NULL, NULL, o, p);
2534                 return;
2535         }
2536
2537         diff_fill_sha1_info(one);
2538         diff_fill_sha1_info(two);
2539
2540         if (!pgm &&
2541             DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
2542             (S_IFMT & one->mode) != (S_IFMT & two->mode)) {
2543                 /*
2544                  * a filepair that changes between file and symlink
2545                  * needs to be split into deletion and creation.
2546                  */
2547                 struct diff_filespec *null = alloc_filespec(two->path);
2548                 run_diff_cmd(NULL, name, other, attr_path,
2549                              one, null, &msg, o, p);
2550                 free(null);
2551                 strbuf_release(&msg);
2552
2553                 null = alloc_filespec(one->path);
2554                 run_diff_cmd(NULL, name, other, attr_path,
2555                              null, two, &msg, o, p);
2556                 free(null);
2557         }
2558         else
2559                 run_diff_cmd(pgm, name, other, attr_path,
2560                              one, two, &msg, o, p);
2561
2562         strbuf_release(&msg);
2563 }
2564
2565 static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
2566                          struct diffstat_t *diffstat)
2567 {
2568         const char *name;
2569         const char *other;
2570         int complete_rewrite = 0;
2571
2572         if (DIFF_PAIR_UNMERGED(p)) {
2573                 /* unmerged */
2574                 builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, 0);
2575                 return;
2576         }
2577
2578         name = p->one->path;
2579         other = (strcmp(name, p->two->path) ? p->two->path : NULL);
2580
2581         if (o->prefix_length)
2582                 strip_prefix(o->prefix_length, &name, &other);
2583
2584         diff_fill_sha1_info(p->one);
2585         diff_fill_sha1_info(p->two);
2586
2587         if (p->status == DIFF_STATUS_MODIFIED && p->score)
2588                 complete_rewrite = 1;
2589         builtin_diffstat(name, other, p->one, p->two, diffstat, o, complete_rewrite);
2590 }
2591
2592 static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
2593 {
2594         const char *name;
2595         const char *other;
2596         const char *attr_path;
2597
2598         if (DIFF_PAIR_UNMERGED(p)) {
2599                 /* unmerged */
2600                 return;
2601         }
2602
2603         name = p->one->path;
2604         other = (strcmp(name, p->two->path) ? p->two->path : NULL);
2605         attr_path = other ? other : name;
2606
2607         if (o->prefix_length)
2608                 strip_prefix(o->prefix_length, &name, &other);
2609
2610         diff_fill_sha1_info(p->one);
2611         diff_fill_sha1_info(p->two);
2612
2613         builtin_checkdiff(name, other, attr_path, p->one, p->two, o);
2614 }
2615
2616 void diff_setup(struct diff_options *options)
2617 {
2618         memset(options, 0, sizeof(*options));
2619
2620         options->file = stdout;
2621
2622         options->line_termination = '\n';
2623         options->break_opt = -1;
2624         options->rename_limit = -1;
2625         options->dirstat_percent = 3;
2626         options->context = 3;
2627
2628         options->change = diff_change;
2629         options->add_remove = diff_addremove;
2630         if (diff_use_color_default > 0)
2631                 DIFF_OPT_SET(options, COLOR_DIFF);
2632         options->detect_rename = diff_detect_rename_default;
2633
2634         if (!diff_mnemonic_prefix) {
2635                 options->a_prefix = "a/";
2636                 options->b_prefix = "b/";
2637         }
2638 }
2639
2640 int diff_setup_done(struct diff_options *options)
2641 {
2642         int count = 0;
2643
2644         if (options->output_format & DIFF_FORMAT_NAME)
2645                 count++;
2646         if (options->output_format & DIFF_FORMAT_NAME_STATUS)
2647                 count++;
2648         if (options->output_format & DIFF_FORMAT_CHECKDIFF)
2649                 count++;
2650         if (options->output_format & DIFF_FORMAT_NO_OUTPUT)
2651                 count++;
2652         if (count > 1)
2653                 die("--name-only, --name-status, --check and -s are mutually exclusive");
2654
2655         /*
2656          * Most of the time we can say "there are changes"
2657          * only by checking if there are changed paths, but
2658          * --ignore-whitespace* options force us to look
2659          * inside contents.
2660          */
2661
2662         if (DIFF_XDL_TST(options, IGNORE_WHITESPACE) ||
2663             DIFF_XDL_TST(options, IGNORE_WHITESPACE_CHANGE) ||
2664             DIFF_XDL_TST(options, IGNORE_WHITESPACE_AT_EOL))
2665                 DIFF_OPT_SET(options, DIFF_FROM_CONTENTS);
2666         else
2667                 DIFF_OPT_CLR(options, DIFF_FROM_CONTENTS);
2668
2669         if (DIFF_OPT_TST(options, FIND_COPIES_HARDER))
2670                 options->detect_rename = DIFF_DETECT_COPY;
2671
2672         if (!DIFF_OPT_TST(options, RELATIVE_NAME))
2673                 options->prefix = NULL;
2674         if (options->prefix)
2675                 options->prefix_length = strlen(options->prefix);
2676         else
2677                 options->prefix_length = 0;
2678
2679         if (options->output_format & (DIFF_FORMAT_NAME |
2680                                       DIFF_FORMAT_NAME_STATUS |
2681                                       DIFF_FORMAT_CHECKDIFF |
2682                                       DIFF_FORMAT_NO_OUTPUT))
2683                 options->output_format &= ~(DIFF_FORMAT_RAW |
2684                                             DIFF_FORMAT_NUMSTAT |
2685                                             DIFF_FORMAT_DIFFSTAT |
2686                                             DIFF_FORMAT_SHORTSTAT |
2687                                             DIFF_FORMAT_DIRSTAT |
2688                                             DIFF_FORMAT_SUMMARY |
2689                                             DIFF_FORMAT_PATCH);
2690
2691         /*
2692          * These cases always need recursive; we do not drop caller-supplied
2693          * recursive bits for other formats here.
2694          */
2695         if (options->output_format & (DIFF_FORMAT_PATCH |
2696                                       DIFF_FORMAT_NUMSTAT |
2697                                       DIFF_FORMAT_DIFFSTAT |
2698                                       DIFF_FORMAT_SHORTSTAT |
2699                                       DIFF_FORMAT_DIRSTAT |
2700                                       DIFF_FORMAT_SUMMARY |
2701                                       DIFF_FORMAT_CHECKDIFF))
2702                 DIFF_OPT_SET(options, RECURSIVE);
2703         /*
2704          * Also pickaxe would not work very well if you do not say recursive
2705          */
2706         if (options->pickaxe)
2707                 DIFF_OPT_SET(options, RECURSIVE);
2708         /*
2709          * When patches are generated, submodules diffed against the work tree
2710          * must be checked for dirtiness too so it can be shown in the output
2711          */
2712         if (options->output_format & DIFF_FORMAT_PATCH)
2713                 DIFF_OPT_SET(options, DIRTY_SUBMODULES);
2714
2715         if (options->detect_rename && options->rename_limit < 0)
2716                 options->rename_limit = diff_rename_limit_default;
2717         if (options->setup & DIFF_SETUP_USE_CACHE) {
2718                 if (!active_cache)
2719                         /* read-cache does not die even when it fails
2720                          * so it is safe for us to do this here.  Also
2721                          * it does not smudge active_cache or active_nr
2722                          * when it fails, so we do not have to worry about
2723                          * cleaning it up ourselves either.
2724                          */
2725                         read_cache();
2726         }
2727         if (options->abbrev <= 0 || 40 < options->abbrev)
2728                 options->abbrev = 40; /* full */
2729
2730         /*
2731          * It does not make sense to show the first hit we happened
2732          * to have found.  It does not make sense not to return with
2733          * exit code in such a case either.
2734          */
2735         if (DIFF_OPT_TST(options, QUICK)) {
2736                 options->output_format = DIFF_FORMAT_NO_OUTPUT;
2737                 DIFF_OPT_SET(options, EXIT_WITH_STATUS);
2738         }
2739
2740         return 0;
2741 }
2742
2743 static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
2744 {
2745         char c, *eq;
2746         int len;
2747
2748         if (*arg != '-')
2749                 return 0;
2750         c = *++arg;
2751         if (!c)
2752                 return 0;
2753         if (c == arg_short) {
2754                 c = *++arg;
2755                 if (!c)
2756                         return 1;
2757                 if (val && isdigit(c)) {
2758                         char *end;
2759                         int n = strtoul(arg, &end, 10);
2760                         if (*end)
2761                                 return 0;
2762                         *val = n;
2763                         return 1;
2764                 }
2765                 return 0;
2766         }
2767         if (c != '-')
2768                 return 0;
2769         arg++;
2770         eq = strchr(arg, '=');
2771         if (eq)
2772                 len = eq - arg;
2773         else
2774                 len = strlen(arg);
2775         if (!len || strncmp(arg, arg_long, len))
2776                 return 0;
2777         if (eq) {
2778                 int n;
2779                 char *end;
2780                 if (!isdigit(*++eq))
2781                         return 0;
2782                 n = strtoul(eq, &end, 10);
2783                 if (*end)
2784                         return 0;
2785                 *val = n;
2786         }
2787         return 1;
2788 }
2789
2790 static int diff_scoreopt_parse(const char *opt);
2791
2792 int diff_opt_parse(struct diff_options *options, const char **av, int ac)
2793 {
2794         const char *arg = av[0];
2795
2796         /* Output format options */
2797         if (!strcmp(arg, "-p") || !strcmp(arg, "-u"))
2798                 options->output_format |= DIFF_FORMAT_PATCH;
2799         else if (opt_arg(arg, 'U', "unified", &options->context))
2800                 options->output_format |= DIFF_FORMAT_PATCH;
2801         else if (!strcmp(arg, "--raw"))
2802                 options->output_format |= DIFF_FORMAT_RAW;
2803         else if (!strcmp(arg, "--patch-with-raw"))
2804                 options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW;
2805         else if (!strcmp(arg, "--numstat"))
2806                 options->output_format |= DIFF_FORMAT_NUMSTAT;
2807         else if (!strcmp(arg, "--shortstat"))
2808                 options->output_format |= DIFF_FORMAT_SHORTSTAT;
2809         else if (opt_arg(arg, 'X', "dirstat", &options->dirstat_percent))
2810                 options->output_format |= DIFF_FORMAT_DIRSTAT;
2811         else if (!strcmp(arg, "--cumulative")) {
2812                 options->output_format |= DIFF_FORMAT_DIRSTAT;
2813                 DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE);
2814         } else if (opt_arg(arg, 0, "dirstat-by-file",
2815                            &options->dirstat_percent)) {
2816                 options->output_format |= DIFF_FORMAT_DIRSTAT;
2817                 DIFF_OPT_SET(options, DIRSTAT_BY_FILE);
2818         }
2819         else if (!strcmp(arg, "--check"))
2820                 options->output_format |= DIFF_FORMAT_CHECKDIFF;
2821         else if (!strcmp(arg, "--summary"))
2822                 options->output_format |= DIFF_FORMAT_SUMMARY;
2823         else if (!strcmp(arg, "--patch-with-stat"))
2824                 options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT;
2825         else if (!strcmp(arg, "--name-only"))
2826                 options->output_format |= DIFF_FORMAT_NAME;
2827         else if (!strcmp(arg, "--name-status"))
2828                 options->output_format |= DIFF_FORMAT_NAME_STATUS;
2829         else if (!strcmp(arg, "-s"))
2830                 options->output_format |= DIFF_FORMAT_NO_OUTPUT;
2831         else if (!prefixcmp(arg, "--stat")) {
2832                 char *end;
2833                 int width = options->stat_width;
2834                 int name_width = options->stat_name_width;
2835                 arg += 6;
2836                 end = (char *)arg;
2837
2838                 switch (*arg) {
2839                 case '-':
2840                         if (!prefixcmp(arg, "-width="))
2841                                 width = strtoul(arg + 7, &end, 10);
2842                         else if (!prefixcmp(arg, "-name-width="))
2843                                 name_width = strtoul(arg + 12, &end, 10);
2844                         break;
2845                 case '=':
2846                         width = strtoul(arg+1, &end, 10);
2847                         if (*end == ',')
2848                                 name_width = strtoul(end+1, &end, 10);
2849                 }
2850
2851                 /* Important! This checks all the error cases! */
2852                 if (*end)
2853                         return 0;
2854                 options->output_format |= DIFF_FORMAT_DIFFSTAT;
2855                 options->stat_name_width = name_width;
2856                 options->stat_width = width;
2857         }
2858
2859         /* renames options */
2860         else if (!prefixcmp(arg, "-B")) {
2861                 if ((options->break_opt = diff_scoreopt_parse(arg)) == -1)
2862                         return -1;
2863         }
2864         else if (!prefixcmp(arg, "-M")) {
2865                 if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
2866                         return -1;
2867                 options->detect_rename = DIFF_DETECT_RENAME;
2868         }
2869         else if (!prefixcmp(arg, "-C")) {
2870                 if (options->detect_rename == DIFF_DETECT_COPY)
2871                         DIFF_OPT_SET(options, FIND_COPIES_HARDER);
2872                 if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
2873                         return -1;
2874                 options->detect_rename = DIFF_DETECT_COPY;
2875         }
2876         else if (!strcmp(arg, "--no-renames"))
2877                 options->detect_rename = 0;
2878         else if (!strcmp(arg, "--relative"))
2879                 DIFF_OPT_SET(options, RELATIVE_NAME);
2880         else if (!prefixcmp(arg, "--relative=")) {
2881                 DIFF_OPT_SET(options, RELATIVE_NAME);
2882                 options->prefix = arg + 11;
2883         }
2884
2885         /* xdiff options */
2886         else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
2887                 DIFF_XDL_SET(options, IGNORE_WHITESPACE);
2888         else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
2889                 DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);
2890         else if (!strcmp(arg, "--ignore-space-at-eol"))
2891                 DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
2892         else if (!strcmp(arg, "--patience"))
2893                 DIFF_XDL_SET(options, PATIENCE_DIFF);
2894
2895         /* flags options */
2896         else if (!strcmp(arg, "--binary")) {
2897                 options->output_format |= DIFF_FORMAT_PATCH;
2898                 DIFF_OPT_SET(options, BINARY);
2899         }
2900         else if (!strcmp(arg, "--full-index"))
2901                 DIFF_OPT_SET(options, FULL_INDEX);
2902         else if (!strcmp(arg, "-a") || !strcmp(arg, "--text"))
2903                 DIFF_OPT_SET(options, TEXT);
2904         else if (!strcmp(arg, "-R"))
2905                 DIFF_OPT_SET(options, REVERSE_DIFF);
2906         else if (!strcmp(arg, "--find-copies-harder"))
2907                 DIFF_OPT_SET(options, FIND_COPIES_HARDER);
2908         else if (!strcmp(arg, "--follow"))
2909                 DIFF_OPT_SET(options, FOLLOW_RENAMES);
2910         else if (!strcmp(arg, "--color"))
2911                 DIFF_OPT_SET(options, COLOR_DIFF);
2912         else if (!prefixcmp(arg, "--color=")) {
2913                 int value = git_config_colorbool(NULL, arg+8, -1);
2914                 if (value == 0)
2915                         DIFF_OPT_CLR(options, COLOR_DIFF);
2916                 else if (value > 0)
2917                         DIFF_OPT_SET(options, COLOR_DIFF);
2918                 else
2919                         return error("option `color' expects \"always\", \"auto\", or \"never\"");
2920         }
2921         else if (!strcmp(arg, "--no-color"))
2922                 DIFF_OPT_CLR(options, COLOR_DIFF);
2923         else if (!strcmp(arg, "--color-words")) {
2924                 DIFF_OPT_SET(options, COLOR_DIFF);
2925                 options->word_diff = DIFF_WORDS_COLOR;
2926         }
2927         else if (!prefixcmp(arg, "--color-words=")) {
2928                 DIFF_OPT_SET(options, COLOR_DIFF);
2929                 options->word_diff = DIFF_WORDS_COLOR;
2930                 options->word_regex = arg + 14;
2931         }
2932         else if (!strcmp(arg, "--word-diff")) {
2933                 if (options->word_diff == DIFF_WORDS_NONE)
2934                         options->word_diff = DIFF_WORDS_PLAIN;
2935         }
2936         else if (!prefixcmp(arg, "--word-diff=")) {
2937                 const char *type = arg + 12;
2938                 if (!strcmp(type, "plain"))
2939                         options->word_diff = DIFF_WORDS_PLAIN;
2940                 else if (!strcmp(type, "color")) {
2941                         DIFF_OPT_SET(options, COLOR_DIFF);
2942                         options->word_diff = DIFF_WORDS_COLOR;
2943                 }
2944                 else if (!strcmp(type, "porcelain"))
2945                         options->word_diff = DIFF_WORDS_PORCELAIN;
2946                 else if (!strcmp(type, "none"))
2947                         options->word_diff = DIFF_WORDS_NONE;
2948                 else
2949                         die("bad --word-diff argument: %s", type);
2950         }
2951         else if (!prefixcmp(arg, "--word-diff-regex=")) {
2952                 if (options->word_diff == DIFF_WORDS_NONE)
2953                         options->word_diff = DIFF_WORDS_PLAIN;
2954                 options->word_regex = arg + 18;
2955         }
2956         else if (!strcmp(arg, "--exit-code"))
2957                 DIFF_OPT_SET(options, EXIT_WITH_STATUS);
2958         else if (!strcmp(arg, "--quiet"))
2959                 DIFF_OPT_SET(options, QUICK);
2960         else if (!strcmp(arg, "--ext-diff"))
2961                 DIFF_OPT_SET(options, ALLOW_EXTERNAL);
2962         else if (!strcmp(arg, "--no-ext-diff"))
2963                 DIFF_OPT_CLR(options, ALLOW_EXTERNAL);
2964         else if (!strcmp(arg, "--textconv"))
2965                 DIFF_OPT_SET(options, ALLOW_TEXTCONV);
2966         else if (!strcmp(arg, "--no-textconv"))
2967                 DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
2968         else if (!strcmp(arg, "--ignore-submodules"))
2969                 DIFF_OPT_SET(options, IGNORE_SUBMODULES);
2970         else if (!strcmp(arg, "--submodule"))
2971                 DIFF_OPT_SET(options, SUBMODULE_LOG);
2972         else if (!prefixcmp(arg, "--submodule=")) {
2973                 if (!strcmp(arg + 12, "log"))
2974                         DIFF_OPT_SET(options, SUBMODULE_LOG);
2975         }
2976
2977         /* misc options */
2978         else if (!strcmp(arg, "-z"))
2979                 options->line_termination = 0;
2980         else if (!prefixcmp(arg, "-l"))
2981                 options->rename_limit = strtoul(arg+2, NULL, 10);
2982         else if (!prefixcmp(arg, "-S"))
2983                 options->pickaxe = arg + 2;
2984         else if (!strcmp(arg, "--pickaxe-all"))
2985                 options->pickaxe_opts = DIFF_PICKAXE_ALL;
2986         else if (!strcmp(arg, "--pickaxe-regex"))
2987                 options->pickaxe_opts = DIFF_PICKAXE_REGEX;
2988         else if (!prefixcmp(arg, "-O"))
2989                 options->orderfile = arg + 2;
2990         else if (!prefixcmp(arg, "--diff-filter="))
2991                 options->filter = arg + 14;
2992         else if (!strcmp(arg, "--abbrev"))
2993                 options->abbrev = DEFAULT_ABBREV;
2994         else if (!prefixcmp(arg, "--abbrev=")) {
2995                 options->abbrev = strtoul(arg + 9, NULL, 10);
2996                 if (options->abbrev < MINIMUM_ABBREV)
2997                         options->abbrev = MINIMUM_ABBREV;
2998                 else if (40 < options->abbrev)
2999                         options->abbrev = 40;
3000         }
3001         else if (!prefixcmp(arg, "--src-prefix="))
3002                 options->a_prefix = arg + 13;
3003         else if (!prefixcmp(arg, "--dst-prefix="))
3004                 options->b_prefix = arg + 13;
3005         else if (!strcmp(arg, "--no-prefix"))
3006                 options->a_prefix = options->b_prefix = "";
3007         else if (opt_arg(arg, '\0', "inter-hunk-context",
3008                          &options->interhunkcontext))
3009                 ;
3010         else if (!prefixcmp(arg, "--output=")) {
3011                 options->file = fopen(arg + strlen("--output="), "w");
3012                 if (!options->file)
3013                         die_errno("Could not open '%s'", arg + strlen("--output="));
3014                 options->close_file = 1;
3015         } else
3016                 return 0;
3017         return 1;
3018 }
3019
3020 static int parse_num(const char **cp_p)
3021 {
3022         unsigned long num, scale;
3023         int ch, dot;
3024         const char *cp = *cp_p;
3025
3026         num = 0;
3027         scale = 1;
3028         dot = 0;
3029         for (;;) {
3030                 ch = *cp;
3031                 if ( !dot && ch == '.' ) {
3032                         scale = 1;
3033                         dot = 1;
3034                 } else if ( ch == '%' ) {
3035                         scale = dot ? scale*100 : 100;
3036                         cp++;   /* % is always at the end */
3037                         break;
3038                 } else if ( ch >= '0' && ch <= '9' ) {
3039                         if ( scale < 100000 ) {
3040                                 scale *= 10;
3041                                 num = (num*10) + (ch-'0');
3042                         }
3043                 } else {
3044                         break;
3045                 }
3046                 cp++;
3047         }
3048         *cp_p = cp;
3049
3050         /* user says num divided by scale and we say internally that
3051          * is MAX_SCORE * num / scale.
3052          */
3053         return (int)((num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale));
3054 }
3055
3056 static int diff_scoreopt_parse(const char *opt)
3057 {
3058         int opt1, opt2, cmd;
3059
3060         if (*opt++ != '-')
3061                 return -1;
3062         cmd = *opt++;
3063         if (cmd != 'M' && cmd != 'C' && cmd != 'B')
3064                 return -1; /* that is not a -M, -C nor -B option */
3065
3066         opt1 = parse_num(&opt);
3067         if (cmd != 'B')
3068                 opt2 = 0;
3069         else {
3070                 if (*opt == 0)
3071                         opt2 = 0;
3072                 else if (*opt != '/')
3073                         return -1; /* we expect -B80/99 or -B80 */
3074                 else {
3075                         opt++;
3076                         opt2 = parse_num(&opt);
3077                 }
3078         }
3079         if (*opt != 0)
3080                 return -1;
3081         return opt1 | (opt2 << 16);
3082 }
3083
3084 struct diff_queue_struct diff_queued_diff;
3085
3086 void diff_q(struct diff_queue_struct *queue, struct diff_filepair *dp)
3087 {
3088         if (queue->alloc <= queue->nr) {
3089                 queue->alloc = alloc_nr(queue->alloc);
3090                 queue->queue = xrealloc(queue->queue,
3091                                         sizeof(dp) * queue->alloc);
3092         }
3093         queue->queue[queue->nr++] = dp;
3094 }
3095
3096 struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
3097                                  struct diff_filespec *one,
3098                                  struct diff_filespec *two)
3099 {
3100         struct diff_filepair *dp = xcalloc(1, sizeof(*dp));
3101         dp->one = one;
3102         dp->two = two;
3103         if (queue)
3104                 diff_q(queue, dp);
3105         return dp;
3106 }
3107
3108 void diff_free_filepair(struct diff_filepair *p)
3109 {
3110         free_filespec(p->one);
3111         free_filespec(p->two);
3112         free(p);
3113 }
3114
3115 /* This is different from find_unique_abbrev() in that
3116  * it stuffs the result with dots for alignment.
3117  */
3118 const char *diff_unique_abbrev(const unsigned char *sha1, int len)
3119 {
3120         int abblen;
3121         const char *abbrev;
3122         if (len == 40)
3123                 return sha1_to_hex(sha1);
3124
3125         abbrev = find_unique_abbrev(sha1, len);
3126         abblen = strlen(abbrev);
3127         if (abblen < 37) {
3128                 static char hex[41];
3129                 if (len < abblen && abblen <= len + 2)
3130                         sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
3131                 else
3132                         sprintf(hex, "%s...", abbrev);
3133                 return hex;
3134         }
3135         return sha1_to_hex(sha1);
3136 }
3137
3138 static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt)
3139 {
3140         int line_termination = opt->line_termination;
3141         int inter_name_termination = line_termination ? '\t' : '\0';
3142
3143         if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) {
3144                 fprintf(opt->file, ":%06o %06o %s ", p->one->mode, p->two->mode,
3145                         diff_unique_abbrev(p->one->sha1, opt->abbrev));
3146                 fprintf(opt->file, "%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev));
3147         }
3148         if (p->score) {
3149                 fprintf(opt->file, "%c%03d%c", p->status, similarity_index(p),
3150                         inter_name_termination);
3151         } else {
3152                 fprintf(opt->file, "%c%c", p->status, inter_name_termination);
3153         }
3154
3155         if (p->status == DIFF_STATUS_COPIED ||
3156             p->status == DIFF_STATUS_RENAMED) {
3157                 const char *name_a, *name_b;
3158                 name_a = p->one->path;
3159                 name_b = p->two->path;
3160                 strip_prefix(opt->prefix_length, &name_a, &name_b);
3161                 write_name_quoted(name_a, opt->file, inter_name_termination);
3162                 write_name_quoted(name_b, opt->file, line_termination);
3163         } else {
3164                 const char *name_a, *name_b;
3165                 name_a = p->one->mode ? p->one->path : p->two->path;
3166                 name_b = NULL;
3167                 strip_prefix(opt->prefix_length, &name_a, &name_b);
3168                 write_name_quoted(name_a, opt->file, line_termination);
3169         }
3170 }
3171
3172 int diff_unmodified_pair(struct diff_filepair *p)
3173 {
3174         /* This function is written stricter than necessary to support
3175          * the currently implemented transformers, but the idea is to
3176          * let transformers to produce diff_filepairs any way they want,
3177          * and filter and clean them up here before producing the output.
3178          */
3179         struct diff_filespec *one = p->one, *two = p->two;
3180
3181         if (DIFF_PAIR_UNMERGED(p))
3182                 return 0; /* unmerged is interesting */
3183
3184         /* deletion, addition, mode or type change
3185          * and rename are all interesting.
3186          */
3187         if (DIFF_FILE_VALID(one) != DIFF_FILE_VALID(two) ||
3188             DIFF_PAIR_MODE_CHANGED(p) ||
3189             strcmp(one->path, two->path))
3190                 return 0;
3191
3192         /* both are valid and point at the same path.  that is, we are
3193          * dealing with a change.
3194          */
3195         if (one->sha1_valid && two->sha1_valid &&
3196             !hashcmp(one->sha1, two->sha1) &&
3197             !one->dirty_submodule && !two->dirty_submodule)
3198                 return 1; /* no change */
3199         if (!one->sha1_valid && !two->sha1_valid)
3200                 return 1; /* both look at the same file on the filesystem. */
3201         return 0;
3202 }
3203
3204 static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
3205 {
3206         if (diff_unmodified_pair(p))
3207                 return;
3208
3209         if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
3210             (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
3211                 return; /* no tree diffs in patch format */
3212
3213         run_diff(p, o);
3214 }
3215
3216 static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
3217                             struct diffstat_t *diffstat)
3218 {
3219         if (diff_unmodified_pair(p))
3220                 return;
3221
3222         if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
3223             (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
3224                 return; /* no tree diffs in patch format */
3225
3226         run_diffstat(p, o, diffstat);
3227 }
3228
3229 static void diff_flush_checkdiff(struct diff_filepair *p,
3230                 struct diff_options *o)
3231 {
3232         if (diff_unmodified_pair(p))
3233                 return;
3234
3235         if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
3236             (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
3237                 return; /* no tree diffs in patch format */
3238
3239         run_checkdiff(p, o);
3240 }
3241
3242 int diff_queue_is_empty(void)
3243 {
3244         struct diff_queue_struct *q = &diff_queued_diff;
3245         int i;
3246         for (i = 0; i < q->nr; i++)
3247                 if (!diff_unmodified_pair(q->queue[i]))
3248                         return 0;
3249         return 1;
3250 }
3251
3252 #if DIFF_DEBUG
3253 void diff_debug_filespec(struct diff_filespec *s, int x, const char *one)
3254 {
3255         fprintf(stderr, "queue[%d] %s (%s) %s %06o %s\n",
3256                 x, one ? one : "",
3257                 s->path,
3258                 DIFF_FILE_VALID(s) ? "valid" : "invalid",
3259                 s->mode,
3260                 s->sha1_valid ? sha1_to_hex(s->sha1) : "");
3261         fprintf(stderr, "queue[%d] %s size %lu flags %d\n",
3262                 x, one ? one : "",
3263                 s->size, s->xfrm_flags);
3264 }
3265
3266 void diff_debug_filepair(const struct diff_filepair *p, int i)
3267 {
3268         diff_debug_filespec(p->one, i, "one");
3269         diff_debug_filespec(p->two, i, "two");
3270         fprintf(stderr, "score %d, status %c rename_used %d broken %d\n",
3271                 p->score, p->status ? p->status : '?',
3272                 p->one->rename_used, p->broken_pair);
3273 }
3274
3275 void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
3276 {
3277         int i;
3278         if (msg)
3279                 fprintf(stderr, "%s\n", msg);
3280         fprintf(stderr, "q->nr = %d\n", q->nr);
3281         for (i = 0; i < q->nr; i++) {
3282                 struct diff_filepair *p = q->queue[i];
3283                 diff_debug_filepair(p, i);
3284         }
3285 }
3286 #endif
3287
3288 static void diff_resolve_rename_copy(void)
3289 {
3290         int i;
3291         struct diff_filepair *p;
3292         struct diff_queue_struct *q = &diff_queued_diff;
3293
3294         diff_debug_queue("resolve-rename-copy", q);
3295
3296         for (i = 0; i < q->nr; i++) {
3297                 p = q->queue[i];
3298                 p->status = 0; /* undecided */
3299                 if (DIFF_PAIR_UNMERGED(p))
3300                         p->status = DIFF_STATUS_UNMERGED;
3301                 else if (!DIFF_FILE_VALID(p->one))
3302                         p->status = DIFF_STATUS_ADDED;
3303                 else if (!DIFF_FILE_VALID(p->two))
3304                         p->status = DIFF_STATUS_DELETED;
3305                 else if (DIFF_PAIR_TYPE_CHANGED(p))
3306                         p->status = DIFF_STATUS_TYPE_CHANGED;
3307
3308                 /* from this point on, we are dealing with a pair
3309                  * whose both sides are valid and of the same type, i.e.
3310                  * either in-place edit or rename/copy edit.
3311                  */
3312                 else if (DIFF_PAIR_RENAME(p)) {
3313                         /*
3314                          * A rename might have re-connected a broken
3315                          * pair up, causing the pathnames to be the
3316                          * same again. If so, that's not a rename at
3317                          * all, just a modification..
3318                          *
3319                          * Otherwise, see if this source was used for
3320                          * multiple renames, in which case we decrement
3321                          * the count, and call it a copy.
3322                          */
3323                         if (!strcmp(p->one->path, p->two->path))
3324                                 p->status = DIFF_STATUS_MODIFIED;
3325                         else if (--p->one->rename_used > 0)
3326                                 p->status = DIFF_STATUS_COPIED;
3327                         else
3328                                 p->status = DIFF_STATUS_RENAMED;
3329                 }
3330                 else if (hashcmp(p->one->sha1, p->two->sha1) ||
3331                          p->one->mode != p->two->mode ||
3332                          p->one->dirty_submodule ||
3333                          p->two->dirty_submodule ||
3334                          is_null_sha1(p->one->sha1))
3335                         p->status = DIFF_STATUS_MODIFIED;
3336                 else {
3337                         /* This is a "no-change" entry and should not
3338                          * happen anymore, but prepare for broken callers.
3339                          */
3340                         error("feeding unmodified %s to diffcore",
3341                               p->one->path);
3342                         p->status = DIFF_STATUS_UNKNOWN;
3343                 }
3344         }
3345         diff_debug_queue("resolve-rename-copy done", q);
3346 }
3347
3348 static int check_pair_status(struct diff_filepair *p)
3349 {
3350         switch (p->status) {
3351         case DIFF_STATUS_UNKNOWN:
3352                 return 0;
3353         case 0:
3354                 die("internal error in diff-resolve-rename-copy");
3355         default:
3356                 return 1;
3357         }
3358 }
3359
3360 static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
3361 {
3362         int fmt = opt->output_format;
3363
3364         if (fmt & DIFF_FORMAT_CHECKDIFF)
3365                 diff_flush_checkdiff(p, opt);
3366         else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS))
3367                 diff_flush_raw(p, opt);
3368         else if (fmt & DIFF_FORMAT_NAME) {
3369                 const char *name_a, *name_b;
3370                 name_a = p->two->path;
3371                 name_b = NULL;
3372                 strip_prefix(opt->prefix_length, &name_a, &name_b);
3373                 write_name_quoted(name_a, opt->file, opt->line_termination);
3374         }
3375 }
3376
3377 static void show_file_mode_name(FILE *file, const char *newdelete, struct diff_filespec *fs)
3378 {
3379         if (fs->mode)
3380                 fprintf(file, " %s mode %06o ", newdelete, fs->mode);
3381         else
3382                 fprintf(file, " %s ", newdelete);
3383         write_name_quoted(fs->path, file, '\n');
3384 }
3385
3386
3387 static void show_mode_change(FILE *file, struct diff_filepair *p, int show_name)
3388 {
3389         if (p->one->mode && p->two->mode && p->one->mode != p->two->mode) {
3390                 fprintf(file, " mode change %06o => %06o%c", p->one->mode, p->two->mode,
3391                         show_name ? ' ' : '\n');
3392                 if (show_name) {
3393                         write_name_quoted(p->two->path, file, '\n');
3394                 }
3395         }
3396 }
3397
3398 static void show_rename_copy(FILE *file, const char *renamecopy, struct diff_filepair *p)
3399 {
3400         char *names = pprint_rename(p->one->path, p->two->path);
3401
3402         fprintf(file, " %s %s (%d%%)\n", renamecopy, names, similarity_index(p));
3403         free(names);
3404         show_mode_change(file, p, 0);
3405 }
3406
3407 static void diff_summary(FILE *file, struct diff_filepair *p)
3408 {
3409         switch(p->status) {
3410         case DIFF_STATUS_DELETED:
3411                 show_file_mode_name(file, "delete", p->one);
3412                 break;
3413         case DIFF_STATUS_ADDED:
3414                 show_file_mode_name(file, "create", p->two);
3415                 break;
3416         case DIFF_STATUS_COPIED:
3417                 show_rename_copy(file, "copy", p);
3418                 break;
3419         case DIFF_STATUS_RENAMED:
3420                 show_rename_copy(file, "rename", p);
3421                 break;
3422         default:
3423                 if (p->score) {
3424                         fputs(" rewrite ", file);
3425                         write_name_quoted(p->two->path, file, ' ');
3426                         fprintf(file, "(%d%%)\n", similarity_index(p));
3427                 }
3428                 show_mode_change(file, p, !p->score);
3429                 break;
3430         }
3431 }
3432
3433 struct patch_id_t {
3434         git_SHA_CTX *ctx;
3435         int patchlen;
3436 };
3437
3438 static int remove_space(char *line, int len)
3439 {
3440         int i;
3441         char *dst = line;
3442         unsigned char c;
3443
3444         for (i = 0; i < len; i++)
3445                 if (!isspace((c = line[i])))
3446                         *dst++ = c;
3447
3448         return dst - line;
3449 }
3450
3451 static void patch_id_consume(void *priv, char *line, unsigned long len)
3452 {
3453         struct patch_id_t *data = priv;
3454         int new_len;
3455
3456         /* Ignore line numbers when computing the SHA1 of the patch */
3457         if (!prefixcmp(line, "@@ -"))
3458                 return;
3459
3460         new_len = remove_space(line, len);
3461
3462         git_SHA1_Update(data->ctx, line, new_len);
3463         data->patchlen += new_len;
3464 }
3465
3466 /* returns 0 upon success, and writes result into sha1 */
3467 static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
3468 {
3469         struct diff_queue_struct *q = &diff_queued_diff;
3470         int i;
3471         git_SHA_CTX ctx;
3472         struct patch_id_t data;
3473         char buffer[PATH_MAX * 4 + 20];
3474
3475         git_SHA1_Init(&ctx);
3476         memset(&data, 0, sizeof(struct patch_id_t));
3477         data.ctx = &ctx;
3478
3479         for (i = 0; i < q->nr; i++) {
3480                 xpparam_t xpp;
3481                 xdemitconf_t xecfg;
3482                 xdemitcb_t ecb;
3483                 mmfile_t mf1, mf2;
3484                 struct diff_filepair *p = q->queue[i];
3485                 int len1, len2;
3486
3487                 memset(&xpp, 0, sizeof(xpp));
3488                 memset(&xecfg, 0, sizeof(xecfg));
3489                 if (p->status == 0)
3490                         return error("internal diff status error");
3491                 if (p->status == DIFF_STATUS_UNKNOWN)
3492                         continue;
3493                 if (diff_unmodified_pair(p))
3494                         continue;
3495                 if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
3496                     (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
3497                         continue;
3498                 if (DIFF_PAIR_UNMERGED(p))
3499                         continue;
3500
3501                 diff_fill_sha1_info(p->one);
3502                 diff_fill_sha1_info(p->two);
3503                 if (fill_mmfile(&mf1, p->one) < 0 ||
3504                                 fill_mmfile(&mf2, p->two) < 0)
3505                         return error("unable to read files to diff");
3506
3507                 len1 = remove_space(p->one->path, strlen(p->one->path));
3508                 len2 = remove_space(p->two->path, strlen(p->two->path));
3509                 if (p->one->mode == 0)
3510                         len1 = snprintf(buffer, sizeof(buffer),
3511                                         "diff--gita/%.*sb/%.*s"
3512                                         "newfilemode%06o"
3513                                         "---/dev/null"
3514                                         "+++b/%.*s",
3515                                         len1, p->one->path,
3516                                         len2, p->two->path,
3517                                         p->two->mode,
3518                                         len2, p->two->path);
3519                 else if (p->two->mode == 0)
3520                         len1 = snprintf(buffer, sizeof(buffer),
3521                                         "diff--gita/%.*sb/%.*s"
3522                                         "deletedfilemode%06o"
3523                                         "---a/%.*s"
3524                                         "+++/dev/null",
3525                                         len1, p->one->path,
3526                                         len2, p->two->path,
3527                                         p->one->mode,
3528                                         len1, p->one->path);
3529                 else
3530                         len1 = snprintf(buffer, sizeof(buffer),
3531                                         "diff--gita/%.*sb/%.*s"
3532                                         "---a/%.*s"
3533                                         "+++b/%.*s",
3534                                         len1, p->one->path,
3535                                         len2, p->two->path,
3536                                         len1, p->one->path,
3537                                         len2, p->two->path);
3538                 git_SHA1_Update(&ctx, buffer, len1);
3539
3540                 xpp.flags = XDF_NEED_MINIMAL;
3541                 xecfg.ctxlen = 3;
3542                 xecfg.flags = XDL_EMIT_FUNCNAMES;
3543                 xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
3544                               &xpp, &xecfg, &ecb);
3545         }
3546
3547         git_SHA1_Final(sha1, &ctx);
3548         return 0;
3549 }
3550
3551 int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1)
3552 {
3553         struct diff_queue_struct *q = &diff_queued_diff;
3554         int i;
3555         int result = diff_get_patch_id(options, sha1);
3556
3557         for (i = 0; i < q->nr; i++)
3558                 diff_free_filepair(q->queue[i]);
3559
3560         free(q->queue);
3561         q->queue = NULL;
3562         q->nr = q->alloc = 0;
3563
3564         return result;
3565 }
3566
3567 static int is_summary_empty(const struct diff_queue_struct *q)
3568 {
3569         int i;
3570
3571         for (i = 0; i < q->nr; i++) {
3572                 const struct diff_filepair *p = q->queue[i];
3573
3574                 switch (p->status) {
3575                 case DIFF_STATUS_DELETED:
3576                 case DIFF_STATUS_ADDED:
3577                 case DIFF_STATUS_COPIED:
3578                 case DIFF_STATUS_RENAMED:
3579                         return 0;
3580                 default:
3581                         if (p->score)
3582                                 return 0;
3583                         if (p->one->mode && p->two->mode &&
3584                             p->one->mode != p->two->mode)
3585                                 return 0;
3586                         break;
3587                 }
3588         }
3589         return 1;
3590 }
3591
3592 void diff_flush(struct diff_options *options)
3593 {
3594         struct diff_queue_struct *q = &diff_queued_diff;
3595         int i, output_format = options->output_format;
3596         int separator = 0;
3597
3598         /*
3599          * Order: raw, stat, summary, patch
3600          * or:    name/name-status/checkdiff (other bits clear)
3601          */
3602         if (!q->nr)
3603                 goto free_queue;
3604
3605         if (output_format & (DIFF_FORMAT_RAW |
3606                              DIFF_FORMAT_NAME |
3607                              DIFF_FORMAT_NAME_STATUS |
3608                              DIFF_FORMAT_CHECKDIFF)) {
3609                 for (i = 0; i < q->nr; i++) {
3610                         struct diff_filepair *p = q->queue[i];
3611                         if (check_pair_status(p))
3612                                 flush_one_pair(p, options);
3613                 }
3614                 separator++;
3615         }
3616
3617         if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT)) {
3618                 struct diffstat_t diffstat;
3619
3620                 memset(&diffstat, 0, sizeof(struct diffstat_t));
3621                 for (i = 0; i < q->nr; i++) {
3622                         struct diff_filepair *p = q->queue[i];
3623                         if (check_pair_status(p))
3624                                 diff_flush_stat(p, options, &diffstat);
3625                 }
3626                 if (output_format & DIFF_FORMAT_NUMSTAT)
3627                         show_numstat(&diffstat, options);
3628                 if (output_format & DIFF_FORMAT_DIFFSTAT)
3629                         show_stats(&diffstat, options);
3630                 if (output_format & DIFF_FORMAT_SHORTSTAT)
3631                         show_shortstats(&diffstat, options);
3632                 free_diffstat_info(&diffstat);
3633                 separator++;
3634         }
3635         if (output_format & DIFF_FORMAT_DIRSTAT)
3636                 show_dirstat(options);
3637
3638         if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) {
3639                 for (i = 0; i < q->nr; i++)
3640                         diff_summary(options->file, q->queue[i]);
3641                 separator++;
3642         }
3643
3644         if (output_format & DIFF_FORMAT_NO_OUTPUT &&
3645             DIFF_OPT_TST(options, EXIT_WITH_STATUS) &&
3646             DIFF_OPT_TST(options, DIFF_FROM_CONTENTS)) {
3647                 /*
3648                  * run diff_flush_patch for the exit status. setting
3649                  * options->file to /dev/null should be safe, becaue we
3650                  * aren't supposed to produce any output anyway.
3651                  */
3652                 if (options->close_file)
3653                         fclose(options->file);
3654                 options->file = fopen("/dev/null", "w");
3655                 if (!options->file)
3656                         die_errno("Could not open /dev/null");
3657                 options->close_file = 1;
3658                 for (i = 0; i < q->nr; i++) {
3659                         struct diff_filepair *p = q->queue[i];
3660                         if (check_pair_status(p))
3661                                 diff_flush_patch(p, options);
3662                         if (options->found_changes)
3663                                 break;
3664                 }
3665         }
3666
3667         if (output_format & DIFF_FORMAT_PATCH) {
3668                 if (separator) {
3669                         putc(options->line_termination, options->file);
3670                         if (options->stat_sep) {
3671                                 /* attach patch instead of inline */
3672                                 fputs(options->stat_sep, options->file);
3673                         }
3674                 }
3675
3676                 for (i = 0; i < q->nr; i++) {
3677                         struct diff_filepair *p = q->queue[i];
3678                         if (check_pair_status(p))
3679                                 diff_flush_patch(p, options);
3680                 }
3681         }
3682
3683         if (output_format & DIFF_FORMAT_CALLBACK)
3684                 options->format_callback(q, options, options->format_callback_data);
3685
3686         for (i = 0; i < q->nr; i++)
3687                 diff_free_filepair(q->queue[i]);
3688 free_queue:
3689         free(q->queue);
3690         q->queue = NULL;
3691         q->nr = q->alloc = 0;
3692         if (options->close_file)
3693                 fclose(options->file);
3694
3695         /*
3696          * Report the content-level differences with HAS_CHANGES;
3697          * diff_addremove/diff_change does not set the bit when
3698          * DIFF_FROM_CONTENTS is in effect (e.g. with -w).
3699          */
3700         if (DIFF_OPT_TST(options, DIFF_FROM_CONTENTS)) {
3701                 if (options->found_changes)
3702                         DIFF_OPT_SET(options, HAS_CHANGES);
3703                 else
3704                         DIFF_OPT_CLR(options, HAS_CHANGES);
3705         }
3706 }
3707
3708 static void diffcore_apply_filter(const char *filter)
3709 {
3710         int i;
3711         struct diff_queue_struct *q = &diff_queued_diff;
3712         struct diff_queue_struct outq;
3713         outq.queue = NULL;
3714         outq.nr = outq.alloc = 0;
3715
3716         if (!filter)
3717                 return;
3718
3719         if (strchr(filter, DIFF_STATUS_FILTER_AON)) {
3720                 int found;
3721                 for (i = found = 0; !found && i < q->nr; i++) {
3722                         struct diff_filepair *p = q->queue[i];
3723                         if (((p->status == DIFF_STATUS_MODIFIED) &&
3724                              ((p->score &&
3725                                strchr(filter, DIFF_STATUS_FILTER_BROKEN)) ||
3726                               (!p->score &&
3727                                strchr(filter, DIFF_STATUS_MODIFIED)))) ||
3728                             ((p->status != DIFF_STATUS_MODIFIED) &&
3729                              strchr(filter, p->status)))
3730                                 found++;
3731                 }
3732                 if (found)
3733                         return;
3734
3735                 /* otherwise we will clear the whole queue
3736                  * by copying the empty outq at the end of this
3737                  * function, but first clear the current entries
3738                  * in the queue.
3739                  */
3740                 for (i = 0; i < q->nr; i++)
3741                         diff_free_filepair(q->queue[i]);
3742         }
3743         else {
3744                 /* Only the matching ones */
3745                 for (i = 0; i < q->nr; i++) {
3746                         struct diff_filepair *p = q->queue[i];
3747
3748                         if (((p->status == DIFF_STATUS_MODIFIED) &&
3749                              ((p->score &&
3750                                strchr(filter, DIFF_STATUS_FILTER_BROKEN)) ||
3751                               (!p->score &&
3752                                strchr(filter, DIFF_STATUS_MODIFIED)))) ||
3753                             ((p->status != DIFF_STATUS_MODIFIED) &&
3754                              strchr(filter, p->status)))
3755                                 diff_q(&outq, p);
3756                         else
3757                                 diff_free_filepair(p);
3758                 }
3759         }
3760         free(q->queue);
3761         *q = outq;
3762 }
3763
3764 /* Check whether two filespecs with the same mode and size are identical */
3765 static int diff_filespec_is_identical(struct diff_filespec *one,
3766                                       struct diff_filespec *two)
3767 {
3768         if (S_ISGITLINK(one->mode))
3769                 return 0;
3770         if (diff_populate_filespec(one, 0))
3771                 return 0;
3772         if (diff_populate_filespec(two, 0))
3773                 return 0;
3774         return !memcmp(one->data, two->data, one->size);
3775 }
3776
3777 static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
3778 {
3779         int i;
3780         struct diff_queue_struct *q = &diff_queued_diff;
3781         struct diff_queue_struct outq;
3782         outq.queue = NULL;
3783         outq.nr = outq.alloc = 0;
3784
3785         for (i = 0; i < q->nr; i++) {
3786                 struct diff_filepair *p = q->queue[i];
3787
3788                 /*
3789                  * 1. Entries that come from stat info dirtiness
3790                  *    always have both sides (iow, not create/delete),
3791                  *    one side of the object name is unknown, with
3792                  *    the same mode and size.  Keep the ones that
3793                  *    do not match these criteria.  They have real
3794                  *    differences.
3795                  *
3796                  * 2. At this point, the file is known to be modified,
3797                  *    with the same mode and size, and the object
3798                  *    name of one side is unknown.  Need to inspect
3799                  *    the identical contents.
3800                  */
3801                 if (!DIFF_FILE_VALID(p->one) || /* (1) */
3802                     !DIFF_FILE_VALID(p->two) ||
3803                     (p->one->sha1_valid && p->two->sha1_valid) ||
3804                     (p->one->mode != p->two->mode) ||
3805                     diff_populate_filespec(p->one, 1) ||
3806                     diff_populate_filespec(p->two, 1) ||
3807                     (p->one->size != p->two->size) ||
3808                     !diff_filespec_is_identical(p->one, p->two)) /* (2) */
3809                         diff_q(&outq, p);
3810                 else {
3811                         /*
3812                          * The caller can subtract 1 from skip_stat_unmatch
3813                          * to determine how many paths were dirty only
3814                          * due to stat info mismatch.
3815                          */
3816                         if (!DIFF_OPT_TST(diffopt, NO_INDEX))
3817                                 diffopt->skip_stat_unmatch++;
3818                         diff_free_filepair(p);
3819                 }
3820         }
3821         free(q->queue);
3822         *q = outq;
3823 }
3824
3825 static int diffnamecmp(const void *a_, const void *b_)
3826 {
3827         const struct diff_filepair *a = *((const struct diff_filepair **)a_);
3828         const struct diff_filepair *b = *((const struct diff_filepair **)b_);
3829         const char *name_a, *name_b;
3830
3831         name_a = a->one ? a->one->path : a->two->path;
3832         name_b = b->one ? b->one->path : b->two->path;
3833         return strcmp(name_a, name_b);
3834 }
3835
3836 void diffcore_fix_diff_index(struct diff_options *options)
3837 {
3838         struct diff_queue_struct *q = &diff_queued_diff;
3839         qsort(q->queue, q->nr, sizeof(q->queue[0]), diffnamecmp);
3840 }
3841
3842 void diffcore_std(struct diff_options *options)
3843 {
3844         if (options->skip_stat_unmatch)
3845                 diffcore_skip_stat_unmatch(options);
3846         if (options->break_opt != -1)
3847                 diffcore_break(options->break_opt);
3848         if (options->detect_rename)
3849                 diffcore_rename(options);
3850         if (options->break_opt != -1)
3851                 diffcore_merge_broken();
3852         if (options->pickaxe)
3853                 diffcore_pickaxe(options->pickaxe, options->pickaxe_opts);
3854         if (options->orderfile)
3855                 diffcore_order(options->orderfile);
3856         diff_resolve_rename_copy();
3857         diffcore_apply_filter(options->filter);
3858
3859         if (diff_queued_diff.nr && !DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
3860                 DIFF_OPT_SET(options, HAS_CHANGES);
3861         else
3862                 DIFF_OPT_CLR(options, HAS_CHANGES);
3863 }
3864
3865 int diff_result_code(struct diff_options *opt, int status)
3866 {
3867         int result = 0;
3868         if (!DIFF_OPT_TST(opt, EXIT_WITH_STATUS) &&
3869             !(opt->output_format & DIFF_FORMAT_CHECKDIFF))
3870                 return status;
3871         if (DIFF_OPT_TST(opt, EXIT_WITH_STATUS) &&
3872             DIFF_OPT_TST(opt, HAS_CHANGES))
3873                 result |= 01;
3874         if ((opt->output_format & DIFF_FORMAT_CHECKDIFF) &&
3875             DIFF_OPT_TST(opt, CHECK_FAILED))
3876                 result |= 02;
3877         return result;
3878 }
3879
3880 void diff_addremove(struct diff_options *options,
3881                     int addremove, unsigned mode,
3882                     const unsigned char *sha1,
3883                     const char *concatpath, unsigned dirty_submodule)
3884 {
3885         struct diff_filespec *one, *two;
3886
3887         if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode))
3888                 return;
3889
3890         /* This may look odd, but it is a preparation for
3891          * feeding "there are unchanged files which should
3892          * not produce diffs, but when you are doing copy
3893          * detection you would need them, so here they are"
3894          * entries to the diff-core.  They will be prefixed
3895          * with something like '=' or '*' (I haven't decided
3896          * which but should not make any difference).
3897          * Feeding the same new and old to diff_change()
3898          * also has the same effect.
3899          * Before the final output happens, they are pruned after
3900          * merged into rename/copy pairs as appropriate.
3901          */
3902         if (DIFF_OPT_TST(options, REVERSE_DIFF))
3903                 addremove = (addremove == '+' ? '-' :
3904                              addremove == '-' ? '+' : addremove);
3905
3906         if (options->prefix &&
3907             strncmp(concatpath, options->prefix, options->prefix_length))
3908                 return;
3909
3910         one = alloc_filespec(concatpath);
3911         two = alloc_filespec(concatpath);
3912
3913         if (addremove != '+')
3914                 fill_filespec(one, sha1, mode);
3915         if (addremove != '-') {
3916                 fill_filespec(two, sha1, mode);
3917                 two->dirty_submodule = dirty_submodule;
3918         }
3919
3920         diff_queue(&diff_queued_diff, one, two);
3921         if (!DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
3922                 DIFF_OPT_SET(options, HAS_CHANGES);
3923 }
3924
3925 void diff_change(struct diff_options *options,
3926                  unsigned old_mode, unsigned new_mode,
3927                  const unsigned char *old_sha1,
3928                  const unsigned char *new_sha1,
3929                  const char *concatpath,
3930                  unsigned old_dirty_submodule, unsigned new_dirty_submodule)
3931 {
3932         struct diff_filespec *one, *two;
3933
3934         if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode)
3935                         && S_ISGITLINK(new_mode))
3936                 return;
3937
3938         if (DIFF_OPT_TST(options, REVERSE_DIFF)) {
3939                 unsigned tmp;
3940                 const unsigned char *tmp_c;
3941                 tmp = old_mode; old_mode = new_mode; new_mode = tmp;
3942                 tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
3943                 tmp = old_dirty_submodule; old_dirty_submodule = new_dirty_submodule;
3944                         new_dirty_submodule = tmp;
3945         }
3946
3947         if (options->prefix &&
3948             strncmp(concatpath, options->prefix, options->prefix_length))
3949                 return;
3950
3951         one = alloc_filespec(concatpath);
3952         two = alloc_filespec(concatpath);
3953         fill_filespec(one, old_sha1, old_mode);
3954         fill_filespec(two, new_sha1, new_mode);
3955         one->dirty_submodule = old_dirty_submodule;
3956         two->dirty_submodule = new_dirty_submodule;
3957
3958         diff_queue(&diff_queued_diff, one, two);
3959         if (!DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
3960                 DIFF_OPT_SET(options, HAS_CHANGES);
3961 }
3962
3963 void diff_unmerge(struct diff_options *options,
3964                   const char *path,
3965                   unsigned mode, const unsigned char *sha1)
3966 {
3967         struct diff_filespec *one, *two;
3968
3969         if (options->prefix &&
3970             strncmp(path, options->prefix, options->prefix_length))
3971                 return;
3972
3973         one = alloc_filespec(path);
3974         two = alloc_filespec(path);
3975         fill_filespec(one, sha1, mode);
3976         diff_queue(&diff_queued_diff, one, two)->is_unmerged = 1;
3977 }
3978
3979 static char *run_textconv(const char *pgm, struct diff_filespec *spec,
3980                 size_t *outsize)
3981 {
3982         struct diff_tempfile *temp;
3983         const char *argv[3];
3984         const char **arg = argv;
3985         struct child_process child;
3986         struct strbuf buf = STRBUF_INIT;
3987         int err = 0;
3988
3989         temp = prepare_temp_file(spec->path, spec);
3990         *arg++ = pgm;
3991         *arg++ = temp->name;
3992         *arg = NULL;
3993
3994         memset(&child, 0, sizeof(child));
3995         child.use_shell = 1;
3996         child.argv = argv;
3997         child.out = -1;
3998         if (start_command(&child)) {
3999                 remove_tempfile();
4000                 return NULL;
4001         }
4002
4003         if (strbuf_read(&buf, child.out, 0) < 0)
4004                 err = error("error reading from textconv command '%s'", pgm);
4005         close(child.out);
4006
4007         if (finish_command(&child) || err) {
4008                 strbuf_release(&buf);
4009                 remove_tempfile();
4010                 return NULL;
4011         }
4012         remove_tempfile();
4013
4014         return strbuf_detach(&buf, outsize);
4015 }