001 package org.apache.maven.scm.provider.svn.svnexe.command;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.io.File;
023 import java.io.FileOutputStream;
024 import java.io.IOException;
025 import java.io.PrintStream;
026 import java.util.List;
027
028 import org.apache.maven.scm.log.ScmLogger;
029 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
030 import org.apache.maven.scm.provider.svn.util.SvnUtil;
031 import org.codehaus.plexus.util.Os;
032 import org.codehaus.plexus.util.StringUtils;
033 import org.codehaus.plexus.util.cli.CommandLineException;
034 import org.codehaus.plexus.util.cli.CommandLineUtils;
035 import org.codehaus.plexus.util.cli.Commandline;
036 import org.codehaus.plexus.util.cli.StreamConsumer;
037
038 /**
039 * Command line construction utility.
040 *
041 * @author Brett Porter
042 * @author Olivier Lamy
043 *
044 */
045 public final class SvnCommandLineUtils
046 {
047 private SvnCommandLineUtils()
048 {
049 }
050
051 public static void addTarget( Commandline cl, List<File> files )
052 throws IOException
053 {
054 if ( files == null || files.isEmpty() )
055 {
056 return;
057 }
058
059 StringBuilder sb = new StringBuilder();
060 String ls = System.getProperty( "line.separator" );
061 for ( File f : files )
062 {
063 sb.append( f.getPath().replace( '\\', '/' ) );
064 sb.append( ls );
065 }
066
067 File targets = File.createTempFile( "maven-scm-", "-targets" );
068 PrintStream out = new PrintStream( new FileOutputStream( targets ) );
069 out.print( sb.toString() );
070 out.flush();
071 out.close();
072
073 cl.createArg().setValue( "--targets" );
074 cl.createArg().setValue( targets.getAbsolutePath() );
075
076 targets.deleteOnExit();
077 }
078
079 public static Commandline getBaseSvnCommandLine( File workingDirectory, SvnScmProviderRepository repository )
080 {
081 Commandline cl = new Commandline();
082
083 cl.setExecutable( "svn" );
084 try
085 {
086 cl.addSystemEnvironment();
087 cl.addEnvironment( "LC_MESSAGES", "C" );
088 }
089 catch ( Exception e )
090 {
091 //Do nothing
092 }
093
094 if ( workingDirectory != null )
095 {
096 cl.setWorkingDirectory( workingDirectory.getAbsolutePath() );
097 }
098
099 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 // [by Lenik] don't overwrite existing auth cache by default.
126 if ( hasAuthInfo && !SvnUtil.getSettings().isUseAuthCache() )
127 {
128 cl.createArg().setValue( "--no-auth-cache" );
129 }
130
131 if ( SvnUtil.getSettings().isUseNonInteractive() ) {
132 cl.createArg().setValue( "--non-interactive" );
133 }
134
135 if (SvnUtil.getSettings().isTrustServerCert()) {
136 cl.createArg().setValue( "--trust-server-cert" );
137 }
138
139 return cl;
140 }
141
142 public static int execute( Commandline cl, StreamConsumer consumer, CommandLineUtils.StringStreamConsumer stderr,
143 ScmLogger logger )
144 throws CommandLineException
145 {
146 // SCM-482: force English resource bundle
147 cl.addEnvironment( "LC_MESSAGES", "en" );
148
149 int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
150
151 exitCode = checkIfCleanUpIsNeeded( exitCode, cl, consumer, stderr, logger );
152
153 return exitCode;
154 }
155
156 public static int execute( Commandline cl, CommandLineUtils.StringStreamConsumer stdout,
157 CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
158 throws CommandLineException
159 {
160 int exitCode = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
161
162 exitCode = checkIfCleanUpIsNeeded( exitCode, cl, stdout, stderr, logger );
163
164 return exitCode;
165 }
166
167 private static int checkIfCleanUpIsNeeded( int exitCode, Commandline cl, StreamConsumer consumer,
168 CommandLineUtils.StringStreamConsumer stderr, ScmLogger logger )
169 throws CommandLineException
170 {
171 if ( exitCode != 0 && stderr.getOutput() != null && stderr.getOutput().indexOf( "'svn cleanup'" ) > 0
172 && stderr.getOutput().indexOf( "'svn help cleanup'" ) > 0 )
173 {
174 if ( logger.isInfoEnabled() )
175 {
176 logger.info( "Svn command failed due to some locks in working copy. We try to run a 'svn cleanup'." );
177 }
178
179 if ( executeCleanUp( cl.getWorkingDirectory(), consumer, stderr, logger ) == 0 )
180 {
181 exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr );
182 }
183 }
184 return exitCode;
185 }
186
187 public static int executeCleanUp( File workinDirectory, StreamConsumer stdout, StreamConsumer stderr )
188 throws CommandLineException
189 {
190 return executeCleanUp( workinDirectory, stdout, stderr, null );
191 }
192
193 public static int executeCleanUp( File workinDirectory, StreamConsumer stdout, StreamConsumer stderr,
194 ScmLogger logger )
195 throws CommandLineException
196 {
197 Commandline cl = new Commandline();
198
199 cl.setExecutable( "svn" );
200
201 cl.setWorkingDirectory( workinDirectory.getAbsolutePath() );
202
203 if ( logger != null )
204 {
205 if ( logger.isInfoEnabled() )
206 {
207 logger.info( "Executing: " + SvnCommandLineUtils.cryptPassword( cl ) );
208 logger.info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
209 }
210 }
211
212 return CommandLineUtils.executeCommandLine( cl, stdout, stderr );
213 }
214
215 public static String cryptPassword( Commandline cl )
216 {
217 String clString = cl.toString();
218
219 int pos = clString.indexOf( "--password" );
220
221 if ( pos > 0 )
222 {
223 String beforePassword = clString.substring( 0, pos + "--password ".length() );
224 String afterPassword = clString.substring( pos + "--password ".length() );
225 afterPassword = afterPassword.substring( afterPassword.indexOf( ' ' ) );
226 if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
227 {
228 clString = beforePassword + "*****" + afterPassword;
229 }
230 else
231 {
232 clString = beforePassword + "'*****'" + afterPassword;
233 }
234 }
235
236 return clString;
237 }
238 }