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 */
8
9static const char *pickaxe = NULL;
10static int line_termination = '\n';
11static int inter_name_termination = '\t';
12
13static const char *diff_helper_usage =
14 "git-diff-helper [-z] [-S<string>] paths...";
15
16int main(int ac, const char **av) {
17 struct strbuf sb;
18
19 strbuf_init(&sb);
20
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;
26 }
27 else
28 usage(diff_helper_usage);
29 ac--; av++;
30 }
31 /* the remaining parameters are paths patterns */
32
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];
40
41 int ch;
42 char *cp, *ep;
43
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++;
55 }
56 if (*cp++ != ' ')
57 break;
58 while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
59 new_mode = (new_mode << 3) | (ch - '0');
60 cp++;
61 }
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;
87 }
88 }
89
90 if (*cp++ != inter_name_termination)
91 break;
92
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);
99 }
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;
109 }
110
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);
121 }
122 else
123 strcpy(new_path, cp);
124 }
125 diff_helper_input(old_mode, new_mode,
126 old_sha1, new_sha1,
127 old_path, status, score,
128 new_path);
129 continue;
130 }
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);
137 }
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;
144}