[PATCH] Reworked external diff interface.
[git/git.git] / show-diff.c
CommitLineData
8bc9a0c7
LT
1/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
e83c5163 6#include "cache.h"
c0fb976a 7
d2522a65 8static const char *show_diff_usage = "show-diff [-q] [-s] [-z] [paths...]";
b8f80925 9
0a7668e9
LT
10static int recursive = 0;
11static int line_termination = '\n';
12static int silent = 0;
13static int silent_on_nonexisting_files = 0;
14
b8f80925
JH
15static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt)
16{
17 int i;
18 int namelen = ce_namelen(ce);
19 for (i = 0; i < cnt; i++) {
20 int speclen = strlen(spec[i]);
21 if (! strncmp(spec[i], ce->name, speclen) &&
22 speclen <= namelen &&
23 (ce->name[speclen] == 0 ||
24 ce->name[speclen] == '/'))
25 return 1;
26 }
27 return 0;
28}
29
0a7668e9
LT
30static void show_file(const char *prefix, struct cache_entry *ce)
31{
32 printf("%s%o\t%s\t%s\t%s%c", prefix, ntohl(ce->ce_mode), "blob",
33 sha1_to_hex(ce->sha1), ce->name, line_termination);
34}
35
e83c5163
LT
36int main(int argc, char **argv)
37{
0a7668e9 38 static const char null_sha1_hex[] = "0000000000000000000000000000000000000000";
e83c5163
LT
39 int entries = read_cache();
40 int i;
41
b8f80925 42 while (1 < argc && argv[1][0] == '-') {
0a7668e9 43 if (!strcmp(argv[1], "-s"))
ca2a0798 44 silent_on_nonexisting_files = silent = 1;
b8f80925 45 else if (!strcmp(argv[1], "-q"))
ca2a0798 46 silent_on_nonexisting_files = 1;
d2522a65 47 else if (!strcmp(argv[1], "-z"))
0a7668e9
LT
48 line_termination = 0;
49 else if (!strcmp(argv[1], "-r"))
50 recursive = 1; /* No-op */
b8f80925
JH
51 else
52 usage(show_diff_usage);
53 argv++; argc--;
e2e5e98a
PB
54 }
55
b8f80925
JH
56 /* At this point, if argc == 1, then we are doing everything.
57 * Otherwise argv[1] .. argv[argc-1] have the explicit paths.
58 */
e83c5163
LT
59 if (entries < 0) {
60 perror("read_cache");
61 exit(1);
62 }
be3cfa85 63
e83c5163
LT
64 for (i = 0; i < entries; i++) {
65 struct stat st;
0a7668e9 66 unsigned int oldmode, mode;
e83c5163 67 struct cache_entry *ce = active_cache[i];
d94c6128 68 int changed;
e83c5163 69
d2522a65 70 if (1 < argc &&
b8f80925
JH
71 ! matches_pathspec(ce, argv+1, argc-1))
72 continue;
73
9fec8b26 74 if (ce_stage(ce)) {
b8a55ce7 75 printf("U %s%c", ce->name, line_termination);
0a7668e9 76
9fec8b26
JH
77 while (i < entries &&
78 !strcmp(ce->name, active_cache[i]->name))
79 i++;
80 i--; /* compensate for loop control increments */
81 continue;
82 }
83
e83c5163 84 if (stat(ce->name, &st) < 0) {
0a7668e9
LT
85 if (errno != ENOENT) {
86 perror(ce->name);
ca2a0798 87 continue;
0a7668e9
LT
88 }
89 if (silent_on_nonexisting_files)
90 continue;
91 show_file("-", ce);
e83c5163
LT
92 continue;
93 }
734aab75 94 changed = cache_match_stat(ce, &st);
5e76011c 95 if (!changed)
e83c5163 96 continue;
e2e5e98a 97
0a7668e9
LT
98 oldmode = ntohl(ce->ce_mode);
99 mode = S_IFREG | ce_permissions(st.st_mode);
100
101 printf("*%o->%o\t%s\t%s->%s\t%s%c",
102 oldmode, mode, "blob",
103 sha1_to_hex(ce->sha1), null_sha1_hex,
104 ce->name, line_termination);
e83c5163
LT
105 }
106 return 0;
107}