1 package org.apache.maven.scm.provider.jazz.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.ScmProviderRepository;
27 import org.apache.maven.scm.provider.jazz.command.consumer.AbstractRepositoryConsumer;
28
29 import java.util.ArrayList;
30 import java.util.Calendar;
31 import java.util.Date;
32 import java.util.List;
33 import java.util.Locale;
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36
37
38
39
40
41
42
43
44
45 public class JazzListChangesetConsumer
46 extends AbstractRepositoryConsumer
47 {
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 private static final int STATE_CHANGE_SETS = 0;
121
122 private static final int STATE_CHANGE_SET = 1;
123
124 private static final int STATE_COMPONENT = 2;
125
126 private static final int STATE_MODIFIED = 3;
127
128 private static final int STATE_CHANGES = 4;
129
130
131 private static final String HEADER_CHANGE_SETS = "Change sets:";
132
133 private static final String HEADER_CHANGE_SET = "(";
134
135 private static final String HEADER_COMPONENT = "Component:";
136
137 private static final String HEADER_MODIFIED = "Modified:";
138
139 private static final String HEADER_CHANGES = "Changes:";
140
141 private static final String JAZZ_TIMESTAMP_PATTERN = "MMM d, yyyy h:mm a";
142
143
144 private static final String JAZZ_TIMESTAMP_PATTERN_TIME = "h:mm a";
145
146
147
148
149 private static final Pattern CHANGESET_PATTERN = Pattern.compile( "\\((\\d+)\\) (....) (\\w+) (.*)" );
150
151
152
153
154
155 private static final Pattern CHANGES_PATTERN = Pattern.compile( "(.....) \\((\\d+)\\) (.*)" );
156
157
158 private List<ChangeSet> entries;
159
160 private final String userDateFormat;
161
162
163 private int currentChangeSetIndex = -1;
164
165 private int currentState = STATE_CHANGE_SETS;
166
167
168
169
170
171
172
173
174 public JazzListChangesetConsumer( ScmProviderRepository repo, ScmLogger logger, List<ChangeSet> entries,
175 String userDateFormat )
176 {
177 super( repo, logger );
178 this.entries = entries;
179 this.userDateFormat = userDateFormat;
180 }
181
182
183
184
185
186
187
188 public void consumeLine( String line )
189 {
190 super.consumeLine( line );
191
192
193 if ( line.trim().startsWith( HEADER_CHANGE_SETS ) )
194 {
195 currentState = STATE_CHANGE_SETS;
196 }
197 else
198 {
199 if ( line.trim().startsWith( HEADER_CHANGE_SET ) )
200 {
201 currentState = STATE_CHANGE_SET;
202 }
203 else
204 {
205 if ( line.trim().startsWith( HEADER_COMPONENT ) )
206 {
207 currentState = STATE_COMPONENT;
208 }
209 else
210 {
211 if ( line.trim().startsWith( HEADER_MODIFIED ) )
212 {
213 currentState = STATE_MODIFIED;
214 }
215 else
216 {
217 if ( line.trim().startsWith( HEADER_CHANGES ) )
218 {
219
220
221
222
223
224
225
226 currentState = STATE_CHANGES;
227 }
228 }
229 }
230 }
231 }
232
233 switch ( currentState )
234 {
235 case STATE_CHANGE_SETS:
236
237 break;
238
239 case STATE_CHANGE_SET:
240 processChangeSetLine( line );
241 break;
242
243 case STATE_COMPONENT:
244
245 break;
246
247 case STATE_MODIFIED:
248 processModifiedLine( line );
249 break;
250
251 case STATE_CHANGES:
252 processChangesLine( line );
253 break;
254 }
255
256 }
257
258 private void processChangeSetLine( String line )
259 {
260
261
262
263 Matcher matcher = CHANGESET_PATTERN.matcher( line );
264 if ( matcher.find() )
265 {
266
267
268 currentChangeSetIndex++;
269 ChangeSet currentChangeSet = entries.get( currentChangeSetIndex );
270
271
272 List<ChangeFile> files = new ArrayList<ChangeFile>();
273 currentChangeSet.setFiles( files );
274
275 String changesetAlias = matcher.group( 1 );
276 String changeFlags = matcher.group( 2 );
277 String author = matcher.group( 3 );
278 String comment = matcher.group( 4 );
279
280 if ( getLogger().isDebugEnabled() )
281 {
282 getLogger().debug( " Parsing ChangeSet Line : " + line );
283 getLogger().debug( " changesetAlias : " + changesetAlias );
284 getLogger().debug( " changeFlags : " + changeFlags );
285 getLogger().debug( " author : " + author );
286 getLogger().debug( " comment : " + comment );
287 }
288
289
290 if ( currentChangeSet.getRevision() != null && !currentChangeSet.getRevision().equals( changesetAlias ) )
291 {
292 getLogger().warn( "Warning! The indexes appear to be out of sequence! " +
293 "For currentChangeSetIndex = " + currentChangeSetIndex + ", we got '" +
294 changesetAlias + "' and not '" + currentChangeSet.getRevision()
295 + "' as expected." );
296 }
297
298 comment = stripDelimiters( comment );
299 currentChangeSet.setAuthor( author );
300 currentChangeSet.setComment( comment );
301 }
302 }
303
304 private void processModifiedLine( String line )
305 {
306
307
308
309
310
311
312
313 if ( getLogger().isDebugEnabled() )
314 {
315 getLogger().debug( " Parsing Modified Line : " + line );
316 }
317
318 int colonPos = line.indexOf( ":" );
319 int parenPos = line.indexOf( "(" );
320
321 String date = null;
322
323 if ( colonPos != -1 && parenPos != -1 )
324 {
325 date = line.substring( colonPos + 2, parenPos - 1 );
326 }
327 else
328 {
329 if ( colonPos != -1 && parenPos == -1 )
330 {
331
332 date = line.substring( colonPos + 2 );
333 }
334 }
335
336 if ( date != null )
337 {
338 Date changesetDate = parseDate( date.toString(), userDateFormat, JAZZ_TIMESTAMP_PATTERN );
339
340 if ( changesetDate == null )
341 {
342 changesetDate = parseDate( date.toString(), userDateFormat, JAZZ_TIMESTAMP_PATTERN, Locale.ENGLISH );
343 }
344 if ( changesetDate == null )
345 {
346
347 changesetDate = parseDate( date.toString(), userDateFormat, JAZZ_TIMESTAMP_PATTERN_TIME );
348
349 Calendar today = Calendar.getInstance();
350
351 Calendar changesetCal = Calendar.getInstance();
352
353 changesetCal.setTimeInMillis( changesetDate.getTime() );
354
355 changesetCal.set( today.get( Calendar.YEAR ), today.get( Calendar.MONTH ),
356 today.get( Calendar.DAY_OF_MONTH ) );
357
358 changesetDate = changesetCal.getTime();
359 }
360
361 if ( getLogger().isDebugEnabled() )
362 {
363 getLogger().debug( " date : " + date );
364 getLogger().debug( " changesetDate : " + changesetDate );
365 }
366
367 ChangeSet currentChangeSet = entries.get( currentChangeSetIndex );
368 currentChangeSet.setDate( changesetDate );
369 }
370 }
371
372 private void processChangesLine( String line )
373 {
374
375
376
377
378
379 Matcher matcher = CHANGES_PATTERN.matcher( line );
380 if ( matcher.find() )
381 {
382 ChangeSet currentChangeSet = entries.get( currentChangeSetIndex );
383
384 String changeFlags = matcher.group( 1 );
385 String fileAlias = matcher.group( 2 );
386 String file = matcher.group( 3 );
387
388 if ( getLogger().isDebugEnabled() )
389 {
390 getLogger().debug( " Parsing Changes Line : " + line );
391 getLogger().debug(
392 " changeFlags : " + changeFlags + " Translated to : " + parseFileChangeState( changeFlags ) );
393 getLogger().debug( " filetAlias : " + fileAlias );
394 getLogger().debug( " file : " + file );
395 }
396
397 ChangeFile changeFile = new ChangeFile( file );
398 ScmFileStatus status = parseFileChangeState( changeFlags );
399 changeFile.setAction( status );
400 currentChangeSet.getFiles().add( changeFile );
401 }
402 }
403
404
405
406
407
408
409
410 protected String stripDelimiters( String text )
411 {
412 if ( text == null )
413 {
414 return null;
415 }
416 String workingText = text;
417 if ( workingText.startsWith( "\"" ) || workingText.startsWith( "<" ) )
418 {
419 workingText = workingText.substring( 1 );
420 }
421 if ( workingText.endsWith( "\"" ) || workingText.endsWith( ">" ) )
422 {
423 workingText = workingText.substring( 0, workingText.length() - 1 );
424 }
425
426 return workingText;
427 }
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442 private ScmFileStatus parseChangeSetChangeState( String state )
443 {
444 if ( state.length() != 4 )
445 {
446 throw new IllegalArgumentException( "Change State string must be 4 chars long!" );
447 }
448
449
450 return ScmFileStatus.UNKNOWN;
451 }
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471 private ScmFileStatus parseFileChangeState( String state )
472 {
473 if ( state.length() != 5 )
474 {
475 throw new IllegalArgumentException( "Change State string must be 5 chars long!" );
476 }
477
478
479
480
481
482 ScmFileStatus status = ScmFileStatus.UNKNOWN;
483
484
485 if ( state.charAt( 0 ) == '!' )
486 {
487 status = ScmFileStatus.CONFLICT;
488 }
489
490 if ( state.charAt( 1 ) == '#' )
491 {
492 status = ScmFileStatus.CONFLICT;
493 }
494
495
496
497
498 if ( state.charAt( 2 ) == 'a' )
499 {
500 status = ScmFileStatus.ADDED;
501 }
502 else
503 {
504 if ( state.charAt( 2 ) == 'd' )
505 {
506 status = ScmFileStatus.DELETED;
507 }
508 else
509 {
510 if ( state.charAt( 2 ) == 'm' )
511 {
512 status = ScmFileStatus.RENAMED;
513 }
514
515
516 if ( state.charAt( 3 ) == 'c' )
517 {
518 status = ScmFileStatus.MODIFIED;
519 }
520
521
522 if ( state.charAt( 4 ) == 'p' )
523 {
524 status =
525 ScmFileStatus.MODIFIED;
526 }
527 }
528 }
529
530 return status;
531 }
532 }