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