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