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.hg;
20
21 import java.io.File;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.maven.scm.ScmException;
28 import org.apache.maven.scm.ScmFileSet;
29 import org.apache.maven.scm.ScmFileStatus;
30 import org.apache.maven.scm.ScmResult;
31 import org.apache.maven.scm.provider.hg.command.HgCommandConstants;
32 import org.apache.maven.scm.provider.hg.command.HgConsumer;
33 import org.apache.maven.scm.provider.hg.command.inventory.HgChangeSet;
34 import org.apache.maven.scm.provider.hg.command.inventory.HgOutgoingConsumer;
35 import org.codehaus.plexus.util.cli.CommandLineException;
36 import org.codehaus.plexus.util.cli.CommandLineUtils;
37 import org.codehaus.plexus.util.cli.Commandline;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41
42
43
44
45
46 public final class HgUtils {
47 private static final Logger LOGGER = LoggerFactory.getLogger(HgUtils.class);
48
49 public static final String DEFAULT = "default";
50
51 private HgUtils() {
52
53 }
54
55
56
57
58 private static final Map<String, List<Integer>> EXIT_CODE_MAP = new HashMap<>();
59
60
61
62
63 private static final List<Integer> DEFAULT_EXIT_CODES = new ArrayList<>();
64
65
66 static {
67 DEFAULT_EXIT_CODES.add(Integer.valueOf(0));
68
69
70 List<Integer> diffExitCodes = new ArrayList<>(3);
71 diffExitCodes.add(Integer.valueOf(0));
72 diffExitCodes.add(Integer.valueOf(1));
73 diffExitCodes.add(Integer.valueOf(2));
74 EXIT_CODE_MAP.put(HgCommandConstants.DIFF_CMD, diffExitCodes);
75
76 List<Integer> outgoingExitCodes = new ArrayList<>(2);
77 outgoingExitCodes.add(Integer.valueOf(0));
78 outgoingExitCodes.add(Integer.valueOf(1));
79 EXIT_CODE_MAP.put(HgCommandConstants.OUTGOING_CMD, outgoingExitCodes);
80 }
81
82 public static ScmResult execute(HgConsumer consumer, File workingDir, String[] cmdAndArgs) throws ScmException {
83 try {
84
85 Commandline cmd = buildCmd(workingDir, cmdAndArgs);
86 if (LOGGER.isInfoEnabled()) {
87 LOGGER.info("EXECUTING: " + maskPassword(cmd));
88 }
89
90
91 int exitCode = executeCmd(consumer, cmd);
92
93
94 List<Integer> exitCodes = DEFAULT_EXIT_CODES;
95 if (EXIT_CODE_MAP.containsKey(cmdAndArgs[0])) {
96 exitCodes = EXIT_CODE_MAP.get(cmdAndArgs[0]);
97 }
98 boolean success = exitCodes.contains(Integer.valueOf(exitCode));
99
100
101 String providerMsg = "Execution of hg command succeded";
102 if (!success) {
103 HgConfig config = new HgConfig(workingDir);
104 providerMsg = "\nEXECUTION FAILED" + "\n Execution of cmd : " + cmdAndArgs[0]
105 + " failed with exit code: "
106 + exitCode + "." + "\n Working directory was: " + "\n " + workingDir.getAbsolutePath()
107 + config.toString(workingDir) + "\n";
108 if (LOGGER.isErrorEnabled()) {
109 LOGGER.error(providerMsg);
110 }
111 }
112
113 return new ScmResult(cmd.toString(), providerMsg, consumer.getStdErr(), success);
114 } catch (ScmException se) {
115 String msg = "EXECUTION FAILED" + "\n Execution failed before invoking the Hg command. Last exception:"
116 + "\n " + se.getMessage();
117
118
119 if (se.getCause() != null) {
120 msg += "\n Nested exception:" + "\n " + se.getCause().getMessage();
121 }
122
123
124 if (LOGGER.isErrorEnabled()) {
125 LOGGER.error(msg);
126 }
127 throw se;
128 }
129 }
130
131 static Commandline buildCmd(File workingDir, String[] cmdAndArgs) throws ScmException {
132 Commandline cmd = new Commandline();
133 cmd.setExecutable(HgCommandConstants.EXEC);
134 cmd.addArguments(cmdAndArgs);
135 if (workingDir != null) {
136 cmd.setWorkingDirectory(workingDir.getAbsolutePath());
137
138 if (!workingDir.exists()) {
139 boolean success = workingDir.mkdirs();
140 if (!success) {
141 String msg = "Working directory did not exist" + " and it couldn't be created: " + workingDir;
142 throw new ScmException(msg);
143 }
144 }
145 }
146 return cmd;
147 }
148
149 static int executeCmd(HgConsumer consumer, Commandline cmd) throws ScmException {
150 final int exitCode;
151 try {
152 exitCode = CommandLineUtils.executeCommandLine(cmd, consumer, consumer);
153 } catch (CommandLineException ex) {
154 throw new ScmException("Command could not be executed: " + cmd, ex);
155 }
156 return exitCode;
157 }
158
159 public static ScmResult execute(File workingDir, String[] cmdAndArgs) throws ScmException {
160 return execute(new HgConsumer(), workingDir, cmdAndArgs);
161 }
162
163 public static String[] expandCommandLine(String[] cmdAndArgs, ScmFileSet additionalFiles) {
164 List<File> filesList = additionalFiles.getFileList();
165 String[] cmd = new String[filesList.size() + cmdAndArgs.length];
166
167
168 System.arraycopy(cmdAndArgs, 0, cmd, 0, cmdAndArgs.length);
169
170
171 int i = 0;
172 for (File scmFile : filesList) {
173 String file = scmFile.getPath().replace('\\', File.separatorChar);
174 cmd[i + cmdAndArgs.length] = file;
175 i++;
176 }
177
178 return cmd;
179 }
180
181 public static int getCurrentRevisionNumber(File workingDir) throws ScmException {
182
183 String[] revCmd = new String[] {HgCommandConstants.REVNO_CMD};
184 HgRevNoConsumer consumer = new HgRevNoConsumer();
185 HgUtils.execute(consumer, workingDir, revCmd);
186
187 return consumer.getCurrentRevisionNumber();
188 }
189
190 public static String getCurrentBranchName(File workingDir) throws ScmException {
191 String[] branchnameCmd = new String[] {HgCommandConstants.BRANCH_NAME_CMD};
192 HgBranchnameConsumer consumer = new HgBranchnameConsumer();
193 HgUtils.execute(consumer, workingDir, branchnameCmd);
194 return consumer.getBranchName();
195 }
196
197
198
199
200
201
202 private static class HgRevNoConsumer extends HgConsumer {
203
204 private int revNo;
205
206 public void doConsume(ScmFileStatus status, String line) {
207 try {
208 revNo = Integer.valueOf(line).intValue();
209 } catch (NumberFormatException e) {
210
211 }
212 }
213
214 int getCurrentRevisionNumber() {
215 return revNo;
216 }
217 }
218
219
220
221
222 private static class HgBranchnameConsumer extends HgConsumer {
223
224 private String branchName;
225
226 public void doConsume(ScmFileStatus status, String trimmedLine) {
227 branchName = String.valueOf(trimmedLine);
228 }
229
230 String getBranchName() {
231 return branchName;
232 }
233
234
235
236
237 public void consumeLine(String line) {
238 if (logger.isDebugEnabled()) {
239 logger.debug(line);
240 }
241 String trimmedLine = line.trim();
242
243 doConsume(null, trimmedLine);
244 }
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 public static boolean differentOutgoingBranchFound(File workingDir, String workingbranchName) throws ScmException {
261 String[] outCmd = new String[] {HgCommandConstants.OUTGOING_CMD};
262 HgOutgoingConsumer outConsumer = new HgOutgoingConsumer();
263 ScmResult outResult = HgUtils.execute(outConsumer, workingDir, outCmd);
264 List<HgChangeSet> changes = outConsumer.getChanges();
265 if (outResult.isSuccess()) {
266 for (HgChangeSet set : changes) {
267 if (!getBranchName(workingbranchName).equals(getBranchName(set.getBranch()))) {
268 LOGGER.warn("A different branch than " + getBranchName(workingbranchName)
269 + " was found in outgoing changes, branch name was " + getBranchName(set.getBranch())
270 + ". Only local branch named " + getBranchName(workingbranchName) + " will be pushed.");
271 return true;
272 }
273 }
274 }
275 return false;
276 }
277
278 private static String getBranchName(String branch) {
279 return branch == null ? DEFAULT : branch;
280 }
281
282 public static String maskPassword(Commandline cl) {
283 String clString = cl.toString();
284
285 int pos = clString.indexOf('@');
286
287 if (pos > 0) {
288 clString = clString.replaceAll(":\\w+@", ":*****@");
289 }
290
291 return clString;
292 }
293 }