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