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