[PATCH] Update git-tag-script to create the .git/refs/tags if it does not already...
[git.git] / diff-helper.c
1 /*
2  * Copyright (C) 2005 Junio C Hamano
3  */
4 #include "cache.h"
5 #include "strbuf.h"
6 #include "diff.h"
7
8 static const char *pickaxe = NULL;
9 static int pickaxe_opts = 0;
10 static const char *orderfile = NULL;
11 static const char *diff_filter = NULL;
12 static int line_termination = '\n';
13 static int inter_name_termination = '\t';
14
15 static void flush_them(int ac, const char **av)
16 {
17         diffcore_std_no_resolve(av + 1,
18                                 pickaxe, pickaxe_opts,
19                                 orderfile, diff_filter);
20         diff_flush(DIFF_FORMAT_PATCH, '\n');
21 }
22
23 static const char *diff_helper_usage =
24 "git-diff-helper [-z] [-O<orderfile>] [-S<string>] [--pickaxe-all] [<path>...]";
25
26 int main(int ac, const char **av) {
27         struct strbuf sb;
28         const char *garbage_flush_format;
29
30         strbuf_init(&sb);
31
32         while (1 < ac && av[1][0] == '-') {
33                 if (av[1][1] == 'z')
34                         line_termination = inter_name_termination = 0;
35                 else if (av[1][1] == 'S') {
36                         pickaxe = av[1] + 2;
37                 }
38                 else if (!strcmp(av[1], "--pickaxe-all"))
39                         pickaxe_opts = DIFF_PICKAXE_ALL;
40                 else if (!strncmp(av[1], "--diff-filter=", 14))
41                         diff_filter = av[1] + 14;
42                 else if (!strncmp(av[1], "-O", 2))
43                         orderfile = av[1] + 2;
44                 else
45                         usage(diff_helper_usage);
46                 ac--; av++;
47         }
48         garbage_flush_format = (line_termination == 0) ? "%s" : "%s\n";
49
50         /* the remaining parameters are paths patterns */
51
52         diff_setup(0);
53         while (1) {
54                 unsigned old_mode, new_mode;
55                 unsigned char old_sha1[20], new_sha1[20];
56                 char old_path[PATH_MAX];
57                 int status, score, two_paths;
58                 char new_path[PATH_MAX];
59
60                 int ch;
61                 char *cp, *ep;
62
63                 read_line(&sb, stdin, line_termination);
64                 if (sb.eof)
65                         break;
66                 switch (sb.buf[0]) {
67                 case ':':
68                         /* parse the first part up to the status */
69                         cp = sb.buf + 1;
70                         old_mode = new_mode = 0;
71                         while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
72                                 old_mode = (old_mode << 3) | (ch - '0');
73                                 cp++;
74                         }
75                         if (*cp++ != ' ')
76                                 break;
77                         while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
78                                 new_mode = (new_mode << 3) | (ch - '0');
79                                 cp++;
80                         }
81                         if (*cp++ != ' ')
82                                 break;
83                         if (get_sha1_hex(cp, old_sha1))
84                                 break;
85                         cp += 40;
86                         if (*cp++ != ' ')
87                                 break;
88                         if (get_sha1_hex(cp, new_sha1))
89                                 break;
90                         cp += 40;
91                         if (*cp++ != ' ')
92                                 break;
93                         status = *cp++;
94                         if (!strchr("MCRNDU", status))
95                                 break;
96                         two_paths = score = 0;
97                         if (status == 'R' || status == 'C')
98                                 two_paths = 1;
99
100                         /* pick up score if exists */
101                         if (sscanf(cp, "%d", &score) != 1)
102                                 score = 0;
103                         cp = strchr(cp,
104                                     inter_name_termination);
105                         if (!cp)
106                                 break;
107                         if (*cp++ != inter_name_termination)
108                                 break;
109
110                         /* first pathname */
111                         if (!line_termination) {
112                                 read_line(&sb, stdin, line_termination);
113                                 if (sb.eof)
114                                         break;
115                                 strcpy(old_path, sb.buf);
116                         }
117                         else if (!two_paths)
118                                 strcpy(old_path, cp);
119                         else {
120                                 ep = strchr(cp, inter_name_termination);
121                                 if (!ep)
122                                         break;
123                                 strncpy(old_path, cp, ep-cp);
124                                 old_path[ep-cp] = 0;
125                                 cp = ep + 1;
126                         }
127
128                         /* second pathname */
129                         if (!two_paths)
130                                 strcpy(new_path, old_path);
131                         else {
132                                 if (!line_termination) {
133                                         read_line(&sb, stdin,
134                                                   line_termination);
135                                         if (sb.eof)
136                                                 break;
137                                         strcpy(new_path, sb.buf);
138                                 }
139                                 else
140                                         strcpy(new_path, cp);
141                         }
142                         diff_helper_input(old_mode, new_mode,
143                                           old_sha1, new_sha1,
144                                           old_path, status, score,
145                                           new_path);
146                         continue;
147                 }
148                 flush_them(ac, av);
149                 printf(garbage_flush_format, sb.buf);
150         }
151         flush_them(ac, av);
152         return 0;
153 }