1 package org.apache.maven.scm.provider.starteam.command.diff;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.maven.scm.ScmFile;
29 import org.apache.maven.scm.ScmFileStatus;
30 import org.apache.maven.scm.log.ScmLogger;
31 import org.codehaus.plexus.util.cli.StreamConsumer;
32
33
34
35
36
37 public class StarteamDiffConsumer
38 implements StreamConsumer
39 {
40 private static final String WORKING_DIR_TOKEN = "(working dir: ";
41
42 private static final String PATCH_SEPARATOR_TOKEN = "--------------";
43
44 private static final String REVISION_TOKEN = " Revision: ";
45
46 private static final String ONDISK_TOKEN = " (on disk)";
47
48 private static final String ADDED_LINE_TOKEN = "+";
49
50 private static final String REMOVED_LINE_TOKEN = "-";
51
52 private static final String UNCHANGED_LINE_TOKEN = " ";
53
54 private ScmLogger logger;
55
56 @SuppressWarnings( "unused" )
57 private String currentDir = "";
58
59 private boolean diffBlockProcessingStarted = false;
60
61 private boolean revisionBlockStarted = false;
62
63 private String currentFile;
64
65 private StringBuilder currentDifference;
66
67 private List<ScmFile> changedFiles = new ArrayList<ScmFile>();
68
69 private Map<String, CharSequence> differences = new HashMap<String, CharSequence>();
70
71 private StringBuilder patch = new StringBuilder();
72
73
74
75
76
77 public StarteamDiffConsumer( ScmLogger logger, File workingDirectory )
78 {
79 this.logger = logger;
80 }
81
82
83
84
85
86
87 public void consumeLine( String line )
88 {
89 int pos = 0;
90
91 if ( logger.isDebugEnabled() )
92 {
93 logger.debug( line );
94 }
95
96 patch.append( line ).append( "\n" );
97
98 if ( line.trim().length() == 0 )
99 {
100 return;
101 }
102
103 if ( ( pos = line.indexOf( WORKING_DIR_TOKEN ) ) != -1 )
104 {
105 processGetDir( line, pos );
106
107 return;
108 }
109
110 if ( line.startsWith( PATCH_SEPARATOR_TOKEN ) )
111 {
112 diffBlockProcessingStarted = !diffBlockProcessingStarted;
113
114 if ( diffBlockProcessingStarted )
115 {
116 if ( revisionBlockStarted )
117 {
118 throw new IllegalStateException( "Missing second Revision line or local copy line " );
119 }
120 }
121
122 return;
123 }
124
125 if ( ( pos = line.indexOf( REVISION_TOKEN ) ) != -1 )
126 {
127 if ( revisionBlockStarted )
128 {
129 revisionBlockStarted = false;
130 }
131 else
132 {
133 extractCurrentFile( line, pos );
134
135 revisionBlockStarted = true;
136 }
137
138 return;
139 }
140
141 if ( ( pos = line.indexOf( ONDISK_TOKEN ) ) != -1 )
142 {
143 if ( revisionBlockStarted )
144 {
145 revisionBlockStarted = false;
146 }
147 else
148 {
149 throw new IllegalStateException( "Working copy line found at the wrong state " );
150 }
151
152 return;
153 }
154
155 if ( !diffBlockProcessingStarted )
156 {
157 if ( logger.isWarnEnabled() )
158 {
159 logger.warn( "Unparseable line: '" + line + "'" );
160 }
161
162 return;
163 }
164
165 if ( line.startsWith( ADDED_LINE_TOKEN ) || line.startsWith( REMOVED_LINE_TOKEN )
166 || line.startsWith( UNCHANGED_LINE_TOKEN ) )
167 {
168
169 currentDifference.append( line ).append( "\n" );
170 }
171 else
172 {
173 if ( logger.isWarnEnabled() )
174 {
175 logger.warn( "Unparseable line: '" + line + "'" );
176 }
177 }
178 }
179
180
181
182
183
184
185 private void processGetDir( String line, int pos )
186 {
187 String dirPath = line.substring( pos + WORKING_DIR_TOKEN.length(), line.length() - 1 ).replace( '\\', '/' );
188
189 this.currentDir = dirPath;
190 }
191
192 private void extractCurrentFile( String line, int pos )
193 {
194 currentFile = line.substring( 0, pos );
195
196 changedFiles.add( new ScmFile( currentFile, ScmFileStatus.MODIFIED ) );
197
198 currentDifference = new StringBuilder();
199
200 differences.put( currentFile, currentDifference );
201 }
202
203 public List<ScmFile> getChangedFiles()
204 {
205 return changedFiles;
206 }
207
208 public Map<String, CharSequence> getDifferences()
209 {
210 return differences;
211 }
212
213 public String getPatch()
214 {
215 return patch.toString();
216 }
217
218 }