1 package org.apache.maven.scm.provider.svn.svnexe.command.changelog;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.scm.ChangeFile;
23 import org.apache.maven.scm.ChangeSet;
24 import org.apache.maven.scm.ScmFileStatus;
25 import org.apache.maven.scm.log.ScmLogger;
26 import org.apache.maven.scm.provider.svn.SvnChangeSet;
27 import org.apache.maven.scm.util.AbstractConsumer;
28
29 import java.util.ArrayList;
30 import java.util.Date;
31 import java.util.List;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34
35
36
37
38
39 public class SvnChangeLogConsumer
40 extends AbstractConsumer
41 {
42
43
44
45 private static final String SVN_TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss zzzzzzzzz";
46
47
48
49
50 private static final int GET_HEADER = 1;
51
52
53
54
55 private static final int GET_FILE = 2;
56
57
58
59
60 private static final int GET_COMMENT = 3;
61
62
63
64
65 private static final Pattern FILE_PATTERN = Pattern.compile( "^\\s\\s\\s([A-Z])\\s(.+)$" );
66
67
68
69
70
71 private static final Pattern ORIG_FILE_PATTERN = Pattern.compile( "\\([A-Za-z]+ (.+):(\\d+)\\)" );
72
73
74
75
76 private static final String FILE_END_TOKEN = "";
77
78
79
80
81 private static final String COMMENT_END_TOKEN =
82 "------------------------------------" + "------------------------------------";
83
84
85
86
87 private int status = GET_HEADER;
88
89
90
91
92 private List<ChangeSet> entries = new ArrayList<ChangeSet>();
93
94
95
96
97 private SvnChangeSet currentChange;
98
99
100
101
102 private String currentRevision;
103
104
105
106
107 private StringBuilder currentComment;
108
109
110
111
112 private static final Pattern HEADER_REG_EXP = Pattern.compile( "^(.+) \\| (.+) \\| (.+) \\|.*$" );
113
114 private static final int REVISION_GROUP = 1;
115
116 private static final int AUTHOR_GROUP = 2;
117
118 private static final int DATE_GROUP = 3;
119
120 private static final Pattern REVISION_REG_EXP1 = Pattern.compile( "rev (\\d+):" );
121
122 private static final Pattern REVISION_REG_EXP2 = Pattern.compile( "r(\\d+)" );
123
124 private static final Pattern DATE_REG_EXP = Pattern.compile( "(\\d+-\\d+-\\d+ " +
125 "\\d+:\\d+:\\d+) " +
126 "([\\-+])(\\d\\d)(\\d\\d)" );
127
128 private final String userDateFormat;
129
130
131
132
133 public SvnChangeLogConsumer( ScmLogger logger, String userDateFormat )
134 {
135 super( logger );
136
137 this.userDateFormat = userDateFormat;
138 }
139
140 public List<ChangeSet> getModifications()
141 {
142 return entries;
143 }
144
145
146
147
148
149
150
151
152 public void consumeLine( String line )
153 {
154 if ( getLogger().isDebugEnabled() )
155 {
156 getLogger().debug( line );
157 }
158 switch ( status )
159 {
160 case GET_HEADER:
161 processGetHeader( line );
162 break;
163 case GET_FILE:
164 processGetFile( line );
165 break;
166 case GET_COMMENT:
167 processGetComment( line );
168 break;
169 default:
170 throw new IllegalStateException( "Unknown state: " + status );
171 }
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 private void processGetHeader( String line )
188 {
189 Matcher matcher = HEADER_REG_EXP.matcher( line );
190 if ( !matcher.matches() )
191 {
192
193 return;
194 }
195
196 currentRevision = getRevision( matcher.group( REVISION_GROUP ) );
197
198 currentChange = new SvnChangeSet();
199
200 currentChange.setAuthor( matcher.group( AUTHOR_GROUP ) );
201
202 currentChange.setDate( getDate( matcher.group( DATE_GROUP ) ) );
203
204 currentChange.setRevision( currentRevision );
205
206 status = GET_FILE;
207 }
208
209
210
211
212
213
214
215 private String getRevision( final String revisionOutput )
216 {
217 Matcher matcher;
218 if ( ( matcher = REVISION_REG_EXP1.matcher( revisionOutput ) ).matches() )
219 {
220 return matcher.group( 1 );
221 }
222 else if ( ( matcher = REVISION_REG_EXP2.matcher( revisionOutput ) ).matches() )
223 {
224 return matcher.group( 1 );
225 }
226 else
227 {
228 throw new IllegalOutputException( revisionOutput );
229 }
230 }
231
232
233
234
235
236
237
238
239
240 private void processGetFile( String line )
241 {
242 Matcher matcher = FILE_PATTERN.matcher( line );
243 if ( matcher.matches() )
244 {
245 final String fileinfo = matcher.group( 2 );
246 String name = fileinfo;
247 String originalName = null;
248 String originalRev = null;
249 final int n = fileinfo.indexOf( " (" );
250 if ( n > 1 && fileinfo.endsWith( ")" ) )
251 {
252 final String origFileInfo = fileinfo.substring( n );
253 Matcher matcher2 = ORIG_FILE_PATTERN.matcher( origFileInfo );
254 if ( matcher2.find() )
255 {
256
257 name = fileinfo.substring( 0, n );
258 originalName = matcher2.group( 1 );
259 originalRev = matcher2.group( 2 );
260 }
261 }
262 final String actionStr = matcher.group( 1 );
263 final ScmFileStatus action;
264 if ( "A".equals( actionStr ) )
265 {
266
267 action = originalRev == null ? ScmFileStatus.ADDED : ScmFileStatus.COPIED;
268 }
269 else if ( "D".equals( actionStr ) )
270 {
271 action = ScmFileStatus.DELETED;
272 }
273 else if ( "M".equals( actionStr ) )
274 {
275 action = ScmFileStatus.MODIFIED;
276 }
277 else if ( "R".equals( actionStr ) )
278 {
279 action = ScmFileStatus.UPDATED;
280 }
281 else
282 {
283 action = ScmFileStatus.UNKNOWN;
284 }
285 System.out.println( actionStr + " : " + name );
286 final ChangeFile changeFile = new ChangeFile( name, currentRevision );
287 changeFile.setAction( action );
288 changeFile.setOriginalName( originalName );
289 changeFile.setOriginalRevision( originalRev );
290 currentChange.addFile( changeFile );
291
292 status = GET_FILE;
293 }
294 else if ( line.equals( FILE_END_TOKEN ) )
295 {
296
297
298 currentComment = new StringBuilder();
299
300 status = GET_COMMENT;
301 }
302 }
303
304
305
306
307
308
309
310 private void processGetComment( String line )
311 {
312 if ( line.equals( COMMENT_END_TOKEN ) )
313 {
314 currentChange.setComment( currentComment.toString() );
315
316 entries.add( currentChange );
317
318 status = GET_HEADER;
319 }
320 else
321 {
322 currentComment.append( line ).append( '\n' );
323 }
324 }
325
326
327
328
329
330
331
332
333 private Date getDate( final String dateOutput )
334 {
335 Matcher matcher = DATE_REG_EXP.matcher( dateOutput );
336 if ( !matcher.find() )
337 {
338 throw new IllegalOutputException( dateOutput );
339 }
340
341 final StringBuilder date = new StringBuilder();
342 date.append( matcher.group( 1 ) );
343 date.append( " GMT" );
344 date.append( matcher.group( 2 ) );
345 date.append( matcher.group( 3 ) );
346 date.append( ':' );
347 date.append( matcher.group( 4 ) );
348
349 return parseDate( date.toString(), userDateFormat, SVN_TIMESTAMP_PATTERN );
350 }
351 }