1 package org.apache.maven.scm.provider.svn.svnexe.command;
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.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.PrintStream;
26 import java.util.List;
27
28 import org.apache.maven.scm.log.ScmLogger;
29 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
30 import org.apache.maven.scm.provider.svn.util.SvnUtil;
31 import org.codehaus.plexus.util.Os;
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 import org.codehaus.plexus.util.cli.StreamConsumer;
37
38
39
40
41
42
43
44
45 public final class SvnCommandLineUtils
46 {
47 private SvnCommandLineUtils()
48 {
49 }
50
51 public static void addTarget( Commandline cl, List<File> files )
52 throws IOException
53 {
54 if ( files == null || files.isEmpty() )
55 {
56 return;
57 }
58
59 StringBuilder sb = new StringBuilder();
60 String ls = System.getProperty( "line.separator" );
61 for ( File f : files )
62 {
63 sb.append( f.getPath().replace( '\\', '/' ) );
64 sb.append( ls );
65 }
66
67 File targets = File.createTempFile( "maven-scm-", "-targets" );
68 PrintStream out = new PrintStream( new FileOutputStream( targets ) );
69 out.print( sb.toString() );
70 out.flush();
71 out.close();
72
73 cl.createArg().setValue( "--targets" );
74 cl.createArg().setValue( targets.getAbsolutePath() );
75
76 targets.deleteOnExit();
77 }
78
79 public static Commandline getBaseSvnCommandLine( File workingDirectory, SvnScmProviderRepository repository )
80 {
81 Commandline cl = new Commandline();
82
83 cl.setExecutable( "svn" );
84 try
85 {
86 cl.addSystemEnvironment();
87 cl.addEnvironment( "LC_MESSAGES", "C" );
88 }
89 catch ( Exception e )
90 {
91
92 }
93
94 if ( workingDirectory != null )
95 {
96 cl.setWorkingDirectory( workingDirectory.getAbsolutePath() );
97 }
98
99 if ( !StringUtils.isEmpty( System.getProperty( "maven.scm.svn.config_directory" ) ) )
100 {
101 cl.createArg().setValue( "--config-dir" );
102 cl.createArg().setValue( System.getProperty( "maven.scm.svn.config_directory" ) );
103 }
104 else if ( !StringUtils.isEmpty( SvnUtil.getSettings().getConfigDirectory() ) )
105 {
106 cl.createArg().setValue( "--config-dir" );
107 cl.createArg().setValue( SvnUtil.getSettings().getConfigDirectory() );
108 }
109
110 boolean hasAuthInfo = false;
111 if ( repository != null && !StringUtils.isEmpty( repository.getUser() ) )
112 {
113 hasAuthInfo = true;
114 cl.createArg().setValue( "--username" );
115 cl.createArg().setValue( repository.getUser() );
116 }
117
118 if ( repository != null && !StringUtils.isEmpty( repository.getPassword() ) )
119 {
120 hasAuthInfo = true;
121 cl.createArg().setValue( "--password" );
122 cl.createArg().setValue( repository.getPassword() );
123 }
124
125
126 if ( hasAuthInfo && !SvnUtil.getSettings().isUseAuthCache() )
127 {
128 cl.createArg().setValue( "--no-auth-cache" );
129 }
130
131 if ( SvnUtil.getSettings().isUseNonInteractive() )
132 {
133 cl.createArg().setValue( "--non-interactive" );
134 }
135
136 if ( SvnUtil.getSettings().isTrustServerCert() )
137 {
138 cl.createArg().setValue( "--trust-server-cert" );
139 }
140
141 return cl;
142 }
143
144 public static int execute( Commandline cl, StreamConsumer consumer, CommandLineUtils.StringStreamConsumer stderr,
145 ScmLogger logger )
146 throws CommandLineException
147 {
148
149 cl.addEnvironment( "LC_MESSAGES", "en" );
150
151 int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
152
153 exitCode = checkIfCleanUpIsNeeded( exitCode, cl, consumer, stderr, logger );
154
155 return exitCode;
156 }
157
158 public static int execute( Commandline cl, CommandLineUtils.StringStreamConsumer stdout,
159 CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
160 throws CommandLineException
161 {
162 int exitCode = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
163
164 exitCode = checkIfCleanUpIsNeeded( exitCode, cl, stdout, stderr, logger );
165
166 return exitCode;
167 }
168
169 private static int checkIfCleanUpIsNeeded( int exitCode, Commandline cl, StreamConsumer consumer,
170 CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
171 throws CommandLineException
172 {
173 if ( exitCode != 0 && stderr.getOutput() != null && stderr.getOutput().indexOf( "'svn cleanup'" ) > 0
174 && stderr.getOutput().indexOf( "'svn help cleanup'" ) > 0 )
175 {
176 if ( logger.isInfoEnabled() )
177 {
178 logger.info( "Svn command failed due to some locks in working copy. We try to run a 'svn cleanup'." );
179 }
180
181 if ( executeCleanUp( cl.getWorkingDirectory(), consumer, stderr, logger ) == 0 )
182 {
183 exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
184 }
185 }
186 return exitCode;
187 }
188
189 public static int executeCleanUp( File workinDirectory, StreamConsumer stdout, StreamConsumer stderr )
190 throws CommandLineException
191 {
192 return executeCleanUp( workinDirectory, stdout, stderr, null );
193 }
194
195 public static int executeCleanUp( File workinDirectory, StreamConsumer stdout, StreamConsumer stderr,
196 ScmLogger logger )
197 throws CommandLineException
198 {
199 Commandline cl = new Commandline();
200
201 cl.setExecutable( "svn" );
202
203 cl.setWorkingDirectory( workinDirectory.getAbsolutePath() );
204
205 if ( logger != null )
206 {
207 if ( logger.isInfoEnabled() )
208 {
209 logger.info( "Executing: " + SvnCommandLineUtils.cryptPassword( cl ) );
210
211 if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
212 {
213 logger.info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
214 }
215 }
216 }
217
218 return CommandLineUtils.executeCommandLine( cl, stdout, stderr );
219 }
220
221 public static String cryptPassword( Commandline cl )
222 {
223 String clString = cl.toString();
224
225 final String passwordOpt = "--password";
226 String quoteChar;
227 String escapedQuoteChar;
228 String cryptedPassword;
229
230 int pos = clString.indexOf( passwordOpt );
231
232 if ( pos > 0 )
233 {
234 if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
235 {
236 quoteChar = "\"";
237 escapedQuoteChar = "\"\"";
238 cryptedPassword = "*****";
239 }
240 else
241 {
242 quoteChar = "'";
243 escapedQuoteChar = "'\"'\"'";
244 cryptedPassword = "'*****'";
245 }
246
247
248 pos += passwordOpt.length();
249
250
251 if ( clString.substring( pos, pos + 1 ).equals( quoteChar ) )
252 {
253 pos++;
254 }
255
256
257 pos++;
258
259 String beforePassword = clString.substring( 0, pos );
260 String afterPassword = clString.substring( pos );
261
262 if ( afterPassword.startsWith( quoteChar ) )
263 {
264 pos = 1;
265 while ( afterPassword.indexOf( escapedQuoteChar, pos ) != -1 )
266 {
267 pos = afterPassword.indexOf( escapedQuoteChar, pos ) + escapedQuoteChar.length();
268 }
269 afterPassword = afterPassword.substring ( afterPassword.indexOf( quoteChar, pos )
270 + quoteChar.length() );
271 }
272 else
273 {
274
275 afterPassword = afterPassword.substring( afterPassword.indexOf( ' ' ) );
276 }
277
278 clString = beforePassword + cryptedPassword + afterPassword;
279
280 }
281
282 return clString;
283 }
284 }