Code

[PATCH] Optionally tell show-diff to show only named files
[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"
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;
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 }
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;
28         old = read_sha1_file(ce->sha1, type, &size);
29         if (size > 0) {
30                 int startline = 1;
31                 int c = 0;
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 }
58 static const char *show_diff_usage = "show-diff [-s] [-q] [paths...]";
60 static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt)
61 {
62         int i;
63         int namelen = ce_namelen(ce);
64         for (i = 0; i < cnt; i++) {
65                 int speclen = strlen(spec[i]);
66                 if (! strncmp(spec[i], ce->name, speclen) &&
67                     speclen <= namelen &&
68                     (ce->name[speclen] == 0 ||
69                      ce->name[speclen] == '/'))
70                         return 1;
71         }
72         return 0;
73 }
75 int main(int argc, char **argv)
76 {
77         int silent = 0;
78         int silent_on_nonexisting_files = 0;
79         int entries = read_cache();
80         int i;
82         while (1 < argc && argv[1][0] == '-') {
83                 if (!strcmp(argv[1], "-s"))
84                         silent_on_nonexisting_files = silent = 1;
85                 else if (!strcmp(argv[1], "-q"))
86                         silent_on_nonexisting_files = 1;
87                 else
88                         usage(show_diff_usage);
89                 argv++; argc--;
90         }
92         /* At this point, if argc == 1, then we are doing everything.
93          * Otherwise argv[1] .. argv[argc-1] have the explicit paths.
94          */
95         if (entries < 0) {
96                 perror("read_cache");
97                 exit(1);
98         }
99         for (i = 0; i < entries; i++) {
100                 struct stat st;
101                 struct cache_entry *ce = active_cache[i];
102                 int n, changed;
103                 unsigned long size;
104                 char type[20];
105                 void *new;
107                 if (1 <argc &&
108                     ! matches_pathspec(ce, argv+1, argc-1))
109                         continue;
111                 if (stat(ce->name, &st) < 0) {
112                         if (errno == ENOENT && silent_on_nonexisting_files)
113                                 continue;
114                         printf("%s: %s\n", ce->name, strerror(errno));
115                         if (errno == ENOENT)
116                                 show_diff_empty(ce);
117                         continue;
118                 }
119                 changed = cache_match_stat(ce, &st);
120                 if (!changed)
121                         continue;
122                 printf("%s:  ", ce->name);
123                 for (n = 0; n < 20; n++)
124                         printf("%02x", ce->sha1[n]);
125                 printf("\n");
126                 fflush(stdout);
127                 if (silent)
128                         continue;
130                 new = read_sha1_file(ce->sha1, type, &size);
131                 show_differences(ce->name, new, size);
132                 free(new);
133         }
134         return 0;