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