Make "diff-tree" have similar behaviour as "ls-tree" wrt line termination.
[git.git] / show-diff.c
1 /*
2  * GIT - The information manager from hell
3  *
4  * Copyright (C) Linus Torvalds, 2005
5  */
6 #include "cache.h"
7
8 static void show_differences(char *name,
9         void *old_contents, unsigned long long old_size)
10 {
11         static char cmd[1000];
12         FILE *f;
13
14         snprintf(cmd, sizeof(cmd), "diff -L %s -u -N  - %s", name, name);
15         f = popen(cmd, "w");
16         if (old_size)
17                 fwrite(old_contents, old_size, 1, f);
18         pclose(f);
19 }
20
21 static void show_diff_empty(struct cache_entry *ce)
22 {
23         char *old;
24         unsigned long int size;
25         int lines=0;
26         unsigned char type[20], *p, *end;
27
28         old = read_sha1_file(ce->sha1, type, &size);
29         if (size > 0) {
30                 int startline = 1;
31                 int c = 0;
32
33                 printf("--- %s\n", ce->name);
34                 printf("+++ /dev/null\n");
35                 p = old;
36                 end = old + size;
37                 while (p < end)
38                         if (*p++ == '\n')
39                                 lines ++;
40                 printf("@@ -1,%d +0,0 @@\n", lines);
41                 p = old;
42                 while (p < end) {
43                         c = *p++;
44                         if (startline) {
45                                 putchar('-');
46                                 startline = 0;
47                         }
48                         putchar(c);
49                         if (c == '\n')
50                                 startline = 1;
51                 }
52                 if (c!='\n')
53                         printf("\n");
54                 fflush(stdout);
55         }
56 }
57
58 int main(int argc, char **argv)
59 {
60         int silent = 0;
61         int silent_on_nonexisting_files = 0;
62         int entries = read_cache();
63         int i;
64
65         for (i = 1; i < argc; i++) {
66                 if (!strcmp(argv[i], "-s")) {
67                         silent_on_nonexisting_files = silent = 1;
68                         continue;
69                 }
70                 if (!strcmp(argv[i], "-q")) {
71                         silent_on_nonexisting_files = 1;
72                         continue;
73                 }
74                 usage("show-diff [-s] [-q]");
75         }
76
77         if (entries < 0) {
78                 perror("read_cache");
79                 exit(1);
80         }
81         for (i = 0; i < entries; i++) {
82                 struct stat st;
83                 struct cache_entry *ce = active_cache[i];
84                 int n, changed;
85                 unsigned long size;
86                 char type[20];
87                 void *new;
88
89                 if (stat(ce->name, &st) < 0) {
90                         if (errno == ENOENT && silent_on_nonexisting_files)
91                                 continue;
92                         printf("%s: %s\n", ce->name, strerror(errno));
93                         if (errno == ENOENT)
94                                 show_diff_empty(ce);
95                         continue;
96                 }
97                 changed = cache_match_stat(ce, &st);
98                 if (!changed)
99                         continue;
100                 printf("%.*s:  ", ce_namelen(ce), ce->name);
101                 for (n = 0; n < 20; n++)
102                         printf("%02x", ce->sha1[n]);
103                 printf("\n");
104                 fflush(stdout);
105                 if (silent)
106                         continue;
107
108                 new = read_sha1_file(ce->sha1, type, &size);
109                 show_differences(ce->name, new, size);
110                 free(new);
111         }
112         return 0;
113 }