blob: ac63499a27775c66d41effec5198035f1e3da792 [file] [log] [blame]
package org.apache.maven.scm.provider.hg;
/*
* Copyright 2001-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.maven.scm.ScmException;
import org.apache.maven.scm.ScmFileStatus;
import org.apache.maven.scm.log.DefaultLog;
import org.apache.maven.scm.provider.hg.command.HgCommand;
import org.apache.maven.scm.provider.hg.command.HgConsumer;
import org.codehaus.plexus.util.cli.Commandline;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Check hg installation.
*
* @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a>
*/
public class HgConfig
{
//TODO: change BAZAAR to HG, correct versions, and only test for necessary things
//Minimum version for the Hg SCM
private static final float BAZAAR_REQ = 0.7f;
private static final float PYTHON_REQ = 2.4f;
//Hg spesific
private static final String BAZAAR_VERSION_TAG = "hg (hg-ng) ";
private static final String BAZAAR_INSTALL_URL = "'http://hg-vcs.org/Installation'";
//Python spesific
private static final String PYTHON_EXEC = "python";
private static final String PYTHON_VERSION = "-V";
private static final String PYTHON_VERSION_TAG = "Python ";
//Python modules
private static final String PARAMIKO = "\"import paramiko\"";
private static final String CCRYPT = "\"import Crypto\"";
private static final String CELEMENTREE = "\"import cElementTree\"";
//Configuration to check with default values (not installed)
private VersionConsumer hgVersion = new VersionConsumer( null );
private VersionConsumer pythonVersion = new VersionConsumer( null );
private boolean cElementTree = false;
private boolean paramiko = false;
private boolean cCrypt = false;
HgConfig( File workingDir )
{
try
{
pythonVersion = getPythonVersion( workingDir );
paramiko = checkPyModules( workingDir, PARAMIKO ); //does not throw
cCrypt = checkPyModules( workingDir, CCRYPT ); //does not throw
cElementTree = checkPyModules( workingDir, CELEMENTREE ); //does not throw
hgVersion = getHgVersion( workingDir );
}
catch ( ScmException e )
{
//Ignore - Either python and/or hg is not installed.
//This is already recorded thus we do not generate more info.
}
}
private boolean checkPyModules( File workingDir, String cmd )
{
PythonConsumer consumer = new PythonConsumer();
int exitCode;
try
{
Commandline cmdLine = buildPythonCmd( workingDir, new String[] { "-c", cmd } );
exitCode = HgUtils.executeCmd( consumer, cmdLine );
}
catch ( ScmException e )
{
//Ignore - error here is likly to manifest itself when checking python anyway.
exitCode = -1;
}
return exitCode == 0 && consumer.getConsumedAndClear().equals( "" );
}
/**
* @return True if one can run basic hg commands
*/
private boolean isInstalled()
{
return pythonVersion.isVersionOk( PYTHON_REQ ) && hgVersion.isVersionOk( BAZAAR_REQ );
}
/**
* @return True if all modules for hg are installed.
*/
private boolean isComplete()
{
return isInstalled() && cElementTree && paramiko && cCrypt;
}
public static VersionConsumer getHgVersion( File workingDir )
throws ScmException
{
String[] versionCmd = new String[] { HgCommand.VERSION };
VersionConsumer consumer = new VersionConsumer( BAZAAR_VERSION_TAG );
Commandline cmd = HgUtils.buildCmd( workingDir, versionCmd );
// Execute command
HgUtils.executeCmd( consumer, cmd );
// Return result
return consumer;
}
public static VersionConsumer getPythonVersion( File workingDir )
throws ScmException
{
String[] versionCmd = new String[] { PYTHON_VERSION };
VersionConsumer consumer = new VersionConsumer( PYTHON_VERSION_TAG );
Commandline cmd = buildPythonCmd( workingDir, versionCmd );
// Execute command
HgUtils.executeCmd( consumer, cmd );
// Return result
return consumer;
}
private static Commandline buildPythonCmd( File workingDir, String[] cmdAndArgs )
throws ScmException
{
Commandline cmd = new Commandline();
cmd.setExecutable( PYTHON_EXEC );
cmd.setWorkingDirectory( workingDir.getAbsolutePath() );
cmd.addArguments( cmdAndArgs );
if ( !workingDir.exists() )
{
boolean success = workingDir.mkdirs();
if ( !success )
{
String msg = "Working directory did not exist" + " and it couldn't be created: " + workingDir;
throw new ScmException( msg );
}
}
return cmd;
}
/**
* Get version of the executable.
* Version is resolved to the last match of a defined regexp in the command output.
*/
private static class VersionConsumer
extends HgConsumer
{
private static Pattern VERSION_PATTERN = Pattern.compile( "[\\d]+.?[\\d]*" );
private final String version_tag;
private String versionStr = "NA";
private float version = -1;
VersionConsumer( String version_tag )
{
super( new DefaultLog() );
this.version_tag = version_tag;
}
public void doConsume( ScmFileStatus status, String line )
{
if ( line.startsWith( version_tag ) )
{
versionStr = line.substring( version_tag.length() );
}
}
String getVersion()
{
return versionStr;
}
boolean isVersionOk( float min )
{
Matcher matcher = VERSION_PATTERN.matcher( versionStr );
if ( matcher.find() )
{
String subStr = versionStr.substring( matcher.start(), matcher.end() );
try
{
version = Float.valueOf( subStr ).floatValue();
}
catch ( NumberFormatException e )
{
//Print diagnostics and continue (this is not a major error)
getLogger().error( "Regexp for version did not result in a number: " + subStr, e );
}
}
return min <= version;
}
}
private static class PythonConsumer
extends HgConsumer
{
private String consumed = "";
PythonConsumer()
{
super( new DefaultLog() );
}
public void doConsume( ScmFileStatus status, String line )
{
consumed = line;
}
String getConsumedAndClear()
{
String tmp = consumed;
consumed = "";
return tmp;
}
}
private String getInstalledStr()
{
if ( isComplete() )
{
return "valid and complete.";
}
return ( isInstalled() ? "incomplete. " : "invalid. " ) + "Consult " + BAZAAR_INSTALL_URL;
}
public String toString( File workingDir )
{
boolean hgOk = hgVersion.isVersionOk( BAZAAR_REQ );
boolean pyOk = pythonVersion.isVersionOk( PYTHON_REQ );
return "\n Your Hg installation seems to be " + getInstalledStr() + "\n Python version: "
+ pythonVersion.getVersion() + ( pyOk ? " (OK)" : " (May be INVALID)" ) + "\n Hg version: "
+ hgVersion.getVersion() + ( hgOk ? " (OK)" : " (May be INVALID)" ) + "\n Paramiko installed: "
+ paramiko + " (For remote access eg. sftp) " + "\n cCrypt installed: " + cCrypt
+ " (For remote access eg. sftp) " + "\n cElementTree installed: " + cElementTree + " (Not mandatory) "
+ "\n";
}
}