1 package org.apache.maven.scm.provider.perforce.command.checkout;
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.ScmException;
23 import org.apache.maven.scm.ScmFileSet;
24 import org.apache.maven.scm.ScmVersion;
25 import org.apache.maven.scm.command.checkout.AbstractCheckOutCommand;
26 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
27 import org.apache.maven.scm.provider.ScmProviderRepository;
28 import org.apache.maven.scm.provider.perforce.PerforceScmProvider;
29 import org.apache.maven.scm.provider.perforce.command.PerforceCommand;
30 import org.apache.maven.scm.provider.perforce.repository.PerforceScmProviderRepository;
31 import org.apache.regexp.RE;
32 import org.codehaus.plexus.util.IOUtil;
33 import org.codehaus.plexus.util.StringUtils;
34 import org.codehaus.plexus.util.cli.CommandLineException;
35 import org.codehaus.plexus.util.cli.CommandLineUtils;
36 import org.codehaus.plexus.util.cli.Commandline;
37
38 import java.io.BufferedReader;
39 import java.io.ByteArrayInputStream;
40 import java.io.File;
41 import java.io.IOException;
42 import java.io.InputStreamReader;
43
44
45
46
47
48 public class PerforceCheckOutCommand
49 extends AbstractCheckOutCommand
50 implements PerforceCommand
51 {
52 private String actualLocation;
53
54
55
56
57
58
59
60
61
62
63
64
65
66 protected CheckOutScmResult executeCheckOutCommand( ScmProviderRepository repo, ScmFileSet files,
67 ScmVersion version, boolean recursive )
68 throws ScmException
69 {
70 PerforceScmProviderRepository prepo = (PerforceScmProviderRepository) repo;
71 File workingDirectory = new File( files.getBasedir().getAbsolutePath() );
72
73 actualLocation = PerforceScmProvider.getRepoPath( getLogger(), prepo, files.getBasedir() );
74
75 String specname = PerforceScmProvider.getClientspecName( getLogger(), prepo, workingDirectory );
76 PerforceCheckOutConsumer consumer = new PerforceCheckOutConsumer( specname, actualLocation );
77 if ( getLogger().isInfoEnabled() )
78 {
79 getLogger().info( "Checkout working directory: " + workingDirectory );
80 }
81 Commandline cl = null;
82
83
84 try
85 {
86
87
88 cl = PerforceScmProvider.createP4Command( prepo, workingDirectory );
89 cl.createArg().setValue( "client" );
90 cl.createArg().setValue( "-i" );
91 if ( getLogger().isInfoEnabled() )
92 {
93 getLogger().info( "Executing: " + PerforceScmProvider.clean( cl.toString() ) );
94 }
95
96 String client =
97 PerforceScmProvider.createClientspec( getLogger(), prepo, workingDirectory, actualLocation );
98
99 if ( getLogger().isDebugEnabled() )
100 {
101 getLogger().debug( "Updating clientspec:\n" + client );
102 }
103
104 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
105 int exitCode =
106 CommandLineUtils.executeCommandLine( cl, new ByteArrayInputStream( client.getBytes() ), consumer, err );
107
108 if ( exitCode != 0 )
109 {
110 String cmdLine = CommandLineUtils.toString( cl.getCommandline() );
111
112 StringBuilder msg = new StringBuilder( "Exit code: " + exitCode + " - " + err.getOutput() );
113 msg.append( '\n' );
114 msg.append( "Command line was:" + cmdLine );
115
116 throw new CommandLineException( msg.toString() );
117 }
118 }
119 catch ( CommandLineException e )
120 {
121 if ( getLogger().isErrorEnabled() )
122 {
123 getLogger().error( "CommandLineException " + e.getMessage(), e );
124 }
125 }
126
127 boolean clientspecExists = consumer.isSuccess();
128
129
130 try
131 {
132 if ( clientspecExists )
133 {
134 try
135 {
136 getLastChangelist( prepo, workingDirectory, specname );
137 cl = createCommandLine( prepo, workingDirectory, version, specname );
138 if ( getLogger().isDebugEnabled() )
139 {
140 getLogger().debug( "Executing: " + PerforceScmProvider.clean( cl.toString() ) );
141 }
142 Process proc = cl.execute();
143 BufferedReader br = new BufferedReader( new InputStreamReader( proc.getInputStream() ) );
144 String line;
145 while ( ( line = br.readLine() ) != null )
146 {
147 if ( getLogger().isDebugEnabled() )
148 {
149 getLogger().debug( "Consuming: " + line );
150 }
151 consumer.consumeLine( line );
152 }
153 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
154 int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, err );
155
156 if ( exitCode != 0 )
157 {
158 String cmdLine = CommandLineUtils.toString( cl.getCommandline() );
159
160 StringBuilder msg = new StringBuilder( "Exit code: " + exitCode + " - " + err.getOutput() );
161 msg.append( '\n' );
162 msg.append( "Command line was:" + cmdLine );
163
164 throw new CommandLineException( msg.toString() );
165 }
166 if ( getLogger().isDebugEnabled() )
167 {
168 getLogger().debug( "Perforce sync complete." );
169 }
170 }
171 catch ( CommandLineException e )
172 {
173 if ( getLogger().isErrorEnabled() )
174 {
175 getLogger().error( "CommandLineException " + e.getMessage(), e );
176 }
177 }
178 catch ( IOException e )
179 {
180 if ( getLogger().isErrorEnabled() )
181 {
182 getLogger().error( "IOException " + e.getMessage(), e );
183 }
184 }
185 }
186
187 if ( consumer.isSuccess() )
188 {
189 return new CheckOutScmResult( cl.toString(), consumer.getCheckedout() );
190 }
191 else
192 {
193 return new CheckOutScmResult( cl.toString(), "Unable to sync. Are you logged in?",
194 consumer.getOutput(), consumer.isSuccess() );
195 }
196 }
197 finally
198 {
199
200
201 if ( clientspecExists && !prepo.isPersistCheckout() )
202 {
203
204 InputStreamReader isReader = null;
205 InputStreamReader isReaderErr = null;
206 try
207 {
208 cl = PerforceScmProvider.createP4Command( prepo, workingDirectory );
209 cl.createArg().setValue( "client" );
210 cl.createArg().setValue( "-d" );
211 cl.createArg().setValue( specname );
212 if ( getLogger().isInfoEnabled() )
213 {
214 getLogger().info( "Executing: " + PerforceScmProvider.clean( cl.toString() ) );
215 }
216 Process proc = cl.execute();
217 isReader = new InputStreamReader( proc.getInputStream() );
218 BufferedReader br = new BufferedReader( isReader );
219 String line;
220 while ( ( line = br.readLine() ) != null )
221 {
222 if ( getLogger().isDebugEnabled() )
223 {
224 getLogger().debug( "Consuming: " + line );
225 }
226 consumer.consumeLine( line );
227 }
228 br.close();
229
230 isReaderErr = new InputStreamReader( proc.getErrorStream() );
231 BufferedReader brErr = new BufferedReader( isReaderErr );
232 while ( ( line = brErr.readLine() ) != null )
233 {
234 if ( getLogger().isDebugEnabled() )
235 {
236 getLogger().debug( "Consuming stderr: " + line );
237 }
238 consumer.consumeLine( line );
239 }
240 brErr.close();
241 }
242 catch ( CommandLineException e )
243 {
244 if ( getLogger().isErrorEnabled() )
245 {
246 getLogger().error( "CommandLineException " + e.getMessage(), e );
247 }
248 }
249 catch ( IOException e )
250 {
251 if ( getLogger().isErrorEnabled() )
252 {
253 getLogger().error( "IOException " + e.getMessage(), e );
254 }
255 }
256 finally
257 {
258 IOUtil.close( isReader );
259 IOUtil.close( isReaderErr );
260 }
261 }
262 else if ( clientspecExists )
263 {
264
265 System.setProperty( PerforceScmProvider.DEFAULT_CLIENTSPEC_PROPERTY, specname );
266 }
267 }
268 }
269
270 public static Commandline createCommandLine( PerforceScmProviderRepository repo, File workingDirectory,
271 ScmVersion version, String specname )
272 {
273 Commandline command = PerforceScmProvider.createP4Command( repo, workingDirectory );
274
275 command.createArg().setValue( "-c" + specname );
276 command.createArg().setValue( "sync" );
277
278
279
280
281
282
283
284
285 String[] files = workingDirectory.list();
286 if ( files == null || files.length == 0 )
287 {
288
289 command.createArg().setValue( "-f" );
290 }
291
292
293
294
295
296 if ( version != null && StringUtils.isNotEmpty( version.getName() ) )
297 {
298 command.createArg().setValue( "@" + version.getName() );
299 }
300 return command;
301 }
302
303 private int getLastChangelist( PerforceScmProviderRepository repo, File workingDirectory, String specname )
304 {
305 int lastChangelist = 0;
306 try
307 {
308 Commandline command = PerforceScmProvider.createP4Command( repo, workingDirectory );
309
310 command.createArg().setValue( "-c" + specname );
311 command.createArg().setValue( "changes" );
312 command.createArg().setValue( "-m1" );
313 command.createArg().setValue( "-ssubmitted" );
314 command.createArg().setValue( "//" + specname + "/..." );
315 getLogger().debug( "Executing: " + PerforceScmProvider.clean( command.toString() ) );
316 Process proc = command.execute();
317 BufferedReader br = new BufferedReader( new InputStreamReader( proc.getInputStream() ) );
318 String line;
319
320 String lastChangelistStr = "";
321 while ( ( line = br.readLine() ) != null )
322 {
323 getLogger().debug( "Consuming: " + line );
324 RE changeRegexp = new RE( "Change (\\d+)" );
325 if ( changeRegexp.match( line ) )
326 {
327 lastChangelistStr = changeRegexp.getParen( 1 );
328 }
329 }
330 br.close();
331
332
333 try
334 {
335 lastChangelist = Integer.parseInt( lastChangelistStr );
336 }
337 catch ( NumberFormatException nfe )
338 {
339 getLogger().debug( "Could not parse changelist from line " + line );
340 }
341 }
342 catch ( IOException e )
343 {
344 getLogger().error( e );
345 }
346 catch ( CommandLineException e )
347 {
348 getLogger().error( e );
349 }
350
351 return lastChangelist;
352 }
353 }