git-apply: add "--check" option to check that the diff makes sense
[git/mjg.git] / diff-helper.c
blob2dd6bdac33a470d3ff4f6fe63149ba33f167a4a3
1 /*
2 * Copyright (C) 2005 Junio C Hamano
3 */
4 #include "cache.h"
5 #include "strbuf.h"
6 #include "diff.h"
7 #include "diffcore.h" /* just for MAX_SCORE */
9 static const char *pickaxe = NULL;
10 static int line_termination = '\n';
11 static int inter_name_termination = '\t';
13 static const char *diff_helper_usage =
14 "git-diff-helper [-z] [-S<string>] paths...";
16 int main(int ac, const char **av) {
17 struct strbuf sb;
19 strbuf_init(&sb);
21 while (1 < ac && av[1][0] == '-') {
22 if (av[1][1] == 'z')
23 line_termination = inter_name_termination = 0;
24 else if (av[1][1] == 'S') {
25 pickaxe = av[1] + 2;
27 else
28 usage(diff_helper_usage);
29 ac--; av++;
31 /* the remaining parameters are paths patterns */
33 diff_setup(0);
34 while (1) {
35 unsigned old_mode, new_mode;
36 unsigned char old_sha1[20], new_sha1[20];
37 char old_path[PATH_MAX];
38 int status, score, two_paths;
39 char new_path[PATH_MAX];
41 int ch;
42 char *cp, *ep;
44 read_line(&sb, stdin, line_termination);
45 if (sb.eof)
46 break;
47 switch (sb.buf[0]) {
48 case ':':
49 /* parse the first part up to the status */
50 cp = sb.buf + 1;
51 old_mode = new_mode = 0;
52 while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
53 old_mode = (old_mode << 3) | (ch - '0');
54 cp++;
56 if (*cp++ != ' ')
57 break;
58 while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
59 new_mode = (new_mode << 3) | (ch - '0');
60 cp++;
62 if (*cp++ != ' ')
63 break;
64 if (get_sha1_hex(cp, old_sha1))
65 break;
66 cp += 40;
67 if (*cp++ != ' ')
68 break;
69 if (get_sha1_hex(cp, new_sha1))
70 break;
71 cp += 40;
72 if (*cp++ != ' ')
73 break;
74 status = *cp++;
75 if (!strchr("MCRNDU", status))
76 break;
77 two_paths = score = 0;
78 if (status == 'R' || status == 'C') {
79 two_paths = 1;
80 sscanf(cp, "%d", &score);
81 score = score * MAX_SCORE / 100;
82 if (line_termination) {
83 cp = strchr(cp,
84 inter_name_termination);
85 if (!cp)
86 break;
90 if (*cp++ != inter_name_termination)
91 break;
93 /* first pathname */
94 if (!line_termination) {
95 read_line(&sb, stdin, line_termination);
96 if (sb.eof)
97 break;
98 strcpy(old_path, sb.buf);
100 else if (!two_paths)
101 strcpy(old_path, cp);
102 else {
103 ep = strchr(cp, inter_name_termination);
104 if (!ep)
105 break;
106 strncpy(old_path, cp, ep-cp);
107 old_path[ep-cp] = 0;
108 cp = ep + 1;
111 /* second pathname */
112 if (!two_paths)
113 strcpy(new_path, old_path);
114 else {
115 if (!line_termination) {
116 read_line(&sb, stdin,
117 line_termination);
118 if (sb.eof)
119 break;
120 strcpy(new_path, sb.buf);
122 else
123 strcpy(new_path, cp);
125 diff_helper_input(old_mode, new_mode,
126 old_sha1, new_sha1,
127 old_path, status, score,
128 new_path);
129 continue;
131 if (pickaxe)
132 diffcore_pickaxe(pickaxe);
133 if (1 < ac)
134 diffcore_pathspec(av + 1);
135 diff_flush(DIFF_FORMAT_PATCH, 0);
136 printf("%s\n", sb.buf);
138 if (pickaxe)
139 diffcore_pickaxe(pickaxe);
140 if (1 < ac)
141 diffcore_pathspec(av + 1);
142 diff_flush(DIFF_FORMAT_PATCH, 0);
143 return 0;