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