blob: 4efcbe4d2efccbe92ca2dbd84e1b2c8857880043 [file] [log] [blame]
package org.apache.maven.scm.provider.bazaar;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.bazaar.command.BazaarConstants;
import org.apache.maven.scm.provider.bazaar.command.BazaarConsumer;
import org.codehaus.plexus.util.cli.Commandline;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Check bazaar installation.
*
* @author <a href="mailto:torbjorn@smorgrav.org">Torbj�rn Eikli Sm�rgrav</a>
* @version $Id$
*/
public class BazaarConfig
{
//Minimum version for the Bazaar SCM
private static final float BAZAAR_REQ = 0.7f;
private static final float PYTHON_REQ = 2.4f;
//Bazaar spesific
private static final String BAZAAR_VERSION_TAG = "bzr (bazaar-ng) ";
private static final String BAZAAR_INSTALL_URL = "'http://bazaar-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 bazaarVersion = new VersionConsumer( null );
private VersionConsumer pythonVersion = new VersionConsumer( null );
private boolean cElementTree = false;
private boolean paramiko = false;
private boolean cCrypt = false;
BazaarConfig( 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
bazaarVersion = getBazaarVersion( workingDir );
}
catch ( ScmException e )
{
//Ignore - Either python and/or bazaar 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 = BazaarUtils.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 bazaar commands
*/
private boolean isInstalled()
{
return pythonVersion.isVersionOk( PYTHON_REQ ) && bazaarVersion.isVersionOk( BAZAAR_REQ );
}
/**
* @return True if all modules for bazaar are installed.
*/
private boolean isComplete()
{
return isInstalled() && cElementTree && paramiko && cCrypt;
}
public static VersionConsumer getBazaarVersion( File workingDir )
throws ScmException
{
String[] versionCmd = new String[]{BazaarConstants.VERSION};
VersionConsumer consumer = new VersionConsumer( BAZAAR_VERSION_TAG );
Commandline cmd = BazaarUtils.buildCmd( workingDir, versionCmd );
// Execute command
BazaarUtils.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
BazaarUtils.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 BazaarConsumer
{
private static final Pattern VERSION_PATTERN = Pattern.compile( "[\\d]+.?[\\d]*" );
private final String versionTag;
private String versionStr = "NA";
private float version = -1;
VersionConsumer( String aVersionTag )
{
super( new DefaultLog() );
this.versionTag = aVersionTag;
}
public void doConsume( ScmFileStatus status, String line )
{
if ( line.startsWith( versionTag ) )
{
versionStr = line.substring( versionTag.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 BazaarConsumer
{
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 bzrOk = bazaarVersion.isVersionOk( BAZAAR_REQ );
boolean pyOk = pythonVersion.isVersionOk( PYTHON_REQ );
return "\n Your Bazaar installation seems to be " + getInstalledStr() + "\n Python version: "
+ pythonVersion.getVersion() + ( pyOk ? " (OK)" : " (May be INVALID)" ) + "\n Bazaar version: "
+ bazaarVersion.getVersion() + ( bzrOk ? " (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";
}
}