1 | |
package net.sf.statsvn.util; |
2 | |
|
3 | |
import java.io.IOException; |
4 | |
import java.io.InputStream; |
5 | |
import java.io.InputStreamReader; |
6 | |
import java.io.StringReader; |
7 | |
import java.util.Vector; |
8 | |
|
9 | |
import net.sf.statcvs.util.LookaheadReader; |
10 | |
import net.sf.statsvn.output.SvnConfigurationOptions; |
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
public class SvnDiffUtils implements ISvnDiffProcessor { |
21 | |
public static final int RESULT_SIZE = 3; |
22 | |
|
23 | |
protected static final int PROPERTY_NAME_LINE = 4; |
24 | |
|
25 | |
protected static final String PROPERTY_CHANGE = "Property changes on:"; |
26 | |
|
27 | |
protected static final String PROPERTY_NAME = "Name:"; |
28 | |
|
29 | |
protected static final String BINARY_TYPE = "Cannot display: file marked as a binary type."; |
30 | |
|
31 | |
protected static final String INDEX_MARKER = "Index: "; |
32 | |
|
33 | |
protected ISvnProcessor processor; |
34 | |
|
35 | 0 | |
36 | 0 | |
37 | 0 | |
38 | 0 | public SvnDiffUtils(ISvnProcessor processor) { |
39 | 0 | this.processor = processor; |
40 | 0 | } |
41 | |
|
42 | |
protected ISvnProcessor getProcessor() { |
43 | 0 | return processor; |
44 | |
} |
45 | |
|
46 | |
|
47 | |
|
48 | |
|
49 | |
|
50 | |
|
51 | |
|
52 | |
|
53 | 0 | |
54 | 0 | |
55 | 0 | |
56 | 0 | |
57 | 0 | |
58 | 0 | |
59 | 0 | |
60 | 0 | protected synchronized ProcessUtils callSvnDiff(final String oldRevNr, final String newRevNr, String filename) throws IOException { |
61 | 0 | String svnDiffCommand = null; |
62 | 0 | filename = getProcessor().getInfoProcessor().relativePathToUrl(filename); |
63 | 0 | filename = StringUtils.replace(" ", "%20", filename); |
64 | 0 | svnDiffCommand = "svn diff --old " + filename + "@" + oldRevNr + " --new " + filename + "@" + newRevNr + "" + SvnCommandHelper.getAuthString(); |
65 | 0 | SvnConfigurationOptions.getTaskLogger().log(Thread.currentThread().getName() + " FIRING command line:\n[" + svnDiffCommand + "]"); |
66 | 0 | return ProcessUtils.call(svnDiffCommand); |
67 | |
} |
68 | |
|
69 | |
|
70 | |
|
71 | 0 | |
72 | 0 | |
73 | 0 | |
74 | 0 | |
75 | 0 | |
76 | 0 | |
77 | |
|
78 | |
protected synchronized ProcessUtils callSvnDiff(final String newRevNr) throws IOException { |
79 | 0 | String svnDiffCommand = null; |
80 | 0 | svnDiffCommand = "svn diff -c " + newRevNr + " " + getProcessor().getInfoProcessor().getRootUrl() + " " + SvnCommandHelper.getAuthString(); |
81 | 0 | SvnConfigurationOptions.getTaskLogger().log(Thread.currentThread().getName() + " FIRING command line:\n[" + svnDiffCommand + "]"); |
82 | 0 | return ProcessUtils.call(svnDiffCommand); |
83 | |
} |
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | |
public int[] getLineDiff(final String oldRevNr, final String newRevNr, final String filename) throws IOException, BinaryDiffException { |
89 | |
int[] lineDiff; |
90 | 0 | ProcessUtils pUtils = null; |
91 | |
try { |
92 | 0 | pUtils = callSvnDiff(oldRevNr, newRevNr, filename); |
93 | 0 | final InputStream diffStream = pUtils.getInputStream(); |
94 | 0 | |
95 | 0 | lineDiff = parseSingleDiffStream(diffStream); |
96 | 0 | |
97 | 0 | verifyOutput(pUtils); |
98 | 0 | } finally { |
99 | 0 | if (pUtils != null) { |
100 | 0 | pUtils.close(); |
101 | 0 | } |
102 | 0 | } |
103 | |
|
104 | 0 | return lineDiff; |
105 | 0 | } |
106 | 0 | |
107 | 0 | protected int[] parseSingleDiffStream(final InputStream diffStream) throws IOException, BinaryDiffException { |
108 | |
int[] lineDiff; |
109 | 0 | final LookaheadReader diffReader = new LookaheadReader(new InputStreamReader(diffStream)); |
110 | 0 | lineDiff = parseDiff(diffReader); |
111 | 0 | return lineDiff; |
112 | |
} |
113 | |
|
114 | |
|
115 | |
|
116 | |
|
117 | |
|
118 | |
|
119 | 0 | |
120 | |
protected void verifyOutput(final ProcessUtils pUtils) throws IOException, BinaryDiffException { |
121 | 0 | if (pUtils.hasErrorOccured()) { |
122 | 0 | |
123 | 0 | |
124 | 0 | final String msg = pUtils.getErrorMessage(); |
125 | 0 | if (isBinaryErrorMessage(msg)) { |
126 | 0 | throw new BinaryDiffException(); |
127 | |
} else { |
128 | 0 | throw new IOException(msg); |
129 | 0 | } |
130 | |
} |
131 | 0 | } |
132 | |
|
133 | |
|
134 | |
|
135 | |
|
136 | |
public Vector getLineDiff(final String newRevNr) throws IOException, BinaryDiffException { |
137 | 0 | final Vector answer = new Vector(); |
138 | |
|
139 | 0 | ProcessUtils pUtils = null; |
140 | |
try { |
141 | 0 | pUtils = callSvnDiff(newRevNr); |
142 | 0 | final InputStream diffStream = pUtils.getInputStream(); |
143 | 0 | parseMultipleDiffStream(answer, diffStream); |
144 | |
|
145 | 0 | verifyOutput(pUtils); |
146 | |
} finally { |
147 | 0 | if (pUtils != null) { |
148 | 0 | pUtils.close(); |
149 | 0 | } |
150 | 0 | } |
151 | 0 | |
152 | 0 | return answer; |
153 | 0 | } |
154 | 0 | |
155 | 0 | protected void parseMultipleDiffStream(final Vector answer, final InputStream diffStream) throws IOException { |
156 | 0 | final LookaheadReader diffReader = new LookaheadReader(new InputStreamReader(diffStream)); |
157 | 0 | String currFile = null; |
158 | 0 | StringBuffer sb = new StringBuffer(); |
159 | 0 | while (diffReader.hasNextLine()) { |
160 | 0 | final String currLine = diffReader.nextLine(); |
161 | 0 | |
162 | 0 | if (currFile == null && currLine.startsWith(INDEX_MARKER)) { |
163 | 0 | currFile = currLine.substring(INDEX_MARKER.length()); |
164 | 0 | } else if (currFile != null && currLine.startsWith(INDEX_MARKER)) { |
165 | 0 | appendResults(answer, currFile, sb); |
166 | 0 | sb = new StringBuffer(); |
167 | 0 | currFile = currLine.substring(INDEX_MARKER.length()); |
168 | 0 | } |
169 | 0 | |
170 | 0 | sb.append(currLine); |
171 | 0 | sb.append(System.getProperty("line.separator")); |
172 | 0 | } |
173 | 0 | |
174 | 0 | |
175 | 0 | if (currFile!=null) { |
176 | 0 | appendResults(answer, currFile, sb); |
177 | 0 | } |
178 | 0 | } |
179 | |
|
180 | |
|
181 | 0 | |
182 | |
|
183 | |
|
184 | |
|
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
|
190 | |
protected void appendResults(final Vector answer, final String currFile, final StringBuffer sb) throws IOException { |
191 | |
int[] lineDiff; |
192 | 0 | Boolean isBinary = Boolean.FALSE; |
193 | 0 | |
194 | 0 | final LookaheadReader individualDiffReader = new LookaheadReader(new StringReader(sb.toString())); |
195 | 0 | try { |
196 | 0 | lineDiff = parseDiff(individualDiffReader); |
197 | 0 | } catch (final BinaryDiffException e) { |
198 | 0 | lineDiff = new int[2]; |
199 | 0 | lineDiff[0] = 0; |
200 | 0 | lineDiff[1] = 0; |
201 | 0 | isBinary = Boolean.TRUE; |
202 | 0 | |
203 | 0 | } |
204 | 0 | final Object[] results = new Object[RESULT_SIZE]; |
205 | 0 | results[0] = currFile; |
206 | 0 | results[1] = lineDiff; |
207 | 0 | results[2] = isBinary; |
208 | 0 | answer.add(results); |
209 | 0 | } |
210 | 0 | |
211 | 0 | |
212 | 0 | |
213 | 0 | |
214 | |
|
215 | |
|
216 | |
|
217 | |
|
218 | |
protected boolean isBinaryErrorMessage(final String msg) { |
219 | |
|
220 | |
|
221 | |
|
222 | |
|
223 | |
|
224 | |
|
225 | |
|
226 | 0 | return (msg.indexOf(BINARY_TYPE) >= 0); |
227 | 0 | } |
228 | |
|
229 | |
|
230 | 0 | |
231 | |
|
232 | |
|
233 | |
|
234 | |
|
235 | |
|
236 | |
|
237 | |
|
238 | |
|
239 | |
protected int[] parseDiff(final LookaheadReader diffReader) throws IOException, BinaryDiffException { |
240 | 0 | final int[] lineDiff = { -1, -1 }; |
241 | 0 | boolean propertyChange = false; |
242 | 0 | if (!diffReader.hasNextLine()) { |
243 | 0 | |
244 | 0 | |
245 | 0 | |
246 | 0 | lineDiff[0] = 0; |
247 | 0 | lineDiff[1] = 0; |
248 | 0 | } |
249 | 0 | while (diffReader.hasNextLine()) { |
250 | 0 | diffReader.nextLine(); |
251 | 0 | final String currentLine = diffReader.getCurrentLine(); |
252 | 0 | |
253 | 0 | SvnConfigurationOptions.getTaskLogger().log(Thread.currentThread().getName() + " Diff Line: [" + currentLine + "]"); |
254 | 0 | |
255 | 0 | if (currentLine.length() == 0) { |
256 | 0 | continue; |
257 | 0 | } |
258 | 0 | final char firstChar = currentLine.charAt(0); |
259 | 0 | |
260 | 0 | if (firstChar == '+') { |
261 | 0 | lineDiff[0]++; |
262 | 0 | } else if (firstChar == '-') { |
263 | 0 | lineDiff[1]++; |
264 | 0 | } else if (currentLine.indexOf(PROPERTY_CHANGE) == 0 |
265 | 0 | || (currentLine.indexOf(PROPERTY_NAME) == 0 && diffReader.getLineNumber() == PROPERTY_NAME_LINE)) { |
266 | 0 | propertyChange = true; |
267 | 0 | } else if (currentLine.indexOf(BINARY_TYPE) == 0) { |
268 | 0 | throw new BinaryDiffException(); |
269 | 0 | } |
270 | 0 | } |
271 | 0 | if (propertyChange && (lineDiff[0] == -1 || lineDiff[1] == -1)) { |
272 | 0 | lineDiff[0] = 0; |
273 | 0 | lineDiff[1] = 0; |
274 | 0 | } |
275 | 0 | |
276 | 0 | return lineDiff; |
277 | 0 | } |
278 | |
|
279 | |
} |