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