Initial revision of "git", the information manager from hell
[git] / show-diff.c
1 #include "cache.h"
2
3 #define MTIME_CHANGED   0x0001
4 #define CTIME_CHANGED   0x0002
5 #define OWNER_CHANGED   0x0004
6 #define MODE_CHANGED    0x0008
7 #define INODE_CHANGED   0x0010
8 #define DATA_CHANGED    0x0020
9
10 static int match_stat(struct cache_entry *ce, struct stat *st)
11 {
12         unsigned int changed = 0;
13
14         if (ce->mtime.sec  != (unsigned int)st->st_mtim.tv_sec ||
15             ce->mtime.nsec != (unsigned int)st->st_mtim.tv_nsec)
16                 changed |= MTIME_CHANGED;
17         if (ce->ctime.sec  != (unsigned int)st->st_ctim.tv_sec ||
18             ce->ctime.nsec != (unsigned int)st->st_ctim.tv_nsec)
19                 changed |= CTIME_CHANGED;
20         if (ce->st_uid != (unsigned int)st->st_uid ||
21             ce->st_gid != (unsigned int)st->st_gid)
22                 changed |= OWNER_CHANGED;
23         if (ce->st_mode != (unsigned int)st->st_mode)
24                 changed |= MODE_CHANGED;
25         if (ce->st_dev != (unsigned int)st->st_dev ||
26             ce->st_ino != (unsigned int)st->st_ino)
27                 changed |= INODE_CHANGED;
28         if (ce->st_size != (unsigned int)st->st_size)
29                 changed |= DATA_CHANGED;
30         return changed;
31 }
32
33 static void show_differences(struct cache_entry *ce, struct stat *cur,
34         void *old_contents, unsigned long long old_size)
35 {
36         static char cmd[1000];
37         FILE *f;
38
39         snprintf(cmd, sizeof(cmd), "diff -u - %s", ce->name);
40         f = popen(cmd, "w");
41         fwrite(old_contents, old_size, 1, f);
42         pclose(f);
43 }
44
45 int main(int argc, char **argv)
46 {
47         int entries = read_cache();
48         int i;
49
50         if (entries < 0) {
51                 perror("read_cache");
52                 exit(1);
53         }
54         for (i = 0; i < entries; i++) {
55                 struct stat st;
56                 struct cache_entry *ce = active_cache[i];
57                 int n, changed;
58                 unsigned int mode;
59                 unsigned long size;
60                 char type[20];
61                 void *new;
62
63                 if (stat(ce->name, &st) < 0) {
64                         printf("%s: %s\n", ce->name, strerror(errno));
65                         continue;
66                 }
67                 changed = match_stat(ce, &st);
68                 if (!changed) {
69                         printf("%s: ok\n", ce->name);
70                         continue;
71                 }
72                 printf("%.*s:  ", ce->namelen, ce->name);
73                 for (n = 0; n < 20; n++)
74                         printf("%02x", ce->sha1[n]);
75                 printf("\n");
76                 new = read_sha1_file(ce->sha1, type, &size);
77                 show_differences(ce, &st, new, size);
78                 free(new);
79         }
80         return 0;
81 }