Skip to content

Commit

Permalink
check version of cabal used in cabal exe and buildwrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
JPMoresmau committed Dec 3, 2012
1 parent 190d188 commit 9b0c727
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 138 deletions.
Expand Up @@ -18,4 +18,6 @@ public class CabalMessages {
public static final String DEPENDENCIES_MISSING="the following dependencies are missing";

public static final String ANY="-any";


}
Expand Up @@ -300,6 +300,20 @@ public void handlePreferenceChangesBrowser() {
* and starting scion server factories.
*/
private synchronized void buildWrapperFactorySetup(){
try {
/** we get the dreaded message about mismatch cabal versions if the buildwrapper cabal library is not the same as the cabal library used to build the cabal executable **/
List<String> ls=ProcessRunner.getExecutableAndCabalVersion( buildWrapperExecutablePath.toOSString(),true);
if (ls!=null && ls.size()>1){
String cabalVersion=ls.get( 1 );
if (CabalImplementationManager.getCabalLibraryVersion()!=null && !CabalImplementationManager.getCabalLibraryVersion().toString().equals( cabalVersion )){
String msg=NLS.bind( UITexts.buildWrapperCabalVersionMismatch, new Object[]{CabalImplementationManager.getCabalLibraryVersion().toString(),cabalVersion,CabalImplementationManager.getCabalExecutable()} );
HaskellUIPlugin.log( msg, IStatus.ERROR );
}
}
} catch (IOException ioe){
HaskellUIPlugin.log(UITexts.error_getVersion, ioe);
}

IPreferenceStore preferenceStore = HaskellUIPlugin.getDefault().getPreferenceStore();

boolean verbose = preferenceStore.getBoolean( IPreferenceConstants.VERBOSE_INTERACTION );
Expand Down
Expand Up @@ -166,6 +166,7 @@ public final class UITexts extends NLS {
public static String buildwrapper_preferences_label;
public static String buildwrapperDoesntExist_title;
public static String buildwrapperDoesntExist_message;
public static String buildWrapperCabalVersionMismatch;

public static String hlint_preferences_label;

Expand Down
Expand Up @@ -169,6 +169,8 @@ scionServerDoesntExist_message = The scion-server executable does not exist:\n\n
buildwrapperDoesntExist_title = buildwrapper doesn't exist
buildwrapperDoesntExist_message = The buildwrapper executable does not exist:\n\n{0}\n\nPlease check preferences!

buildWrapperCabalVersionMismatch = The version of the Cabal library used to build the cabal executable, {0}, does not match the version of the Cabal library used to build the buildwrapper executable, {1}. Please rebuild buildwrapper with the cabal executable {2}.

scionBrowserDoesntExist_title = scion-browser doesn't exist
scionBrowserDoesntExist_message = The scion-browser executable does not exist:\n\n{0}\n\nPlease check preferences!

Expand Down
@@ -1,138 +1,180 @@
package net.sf.eclipsefp.haskell.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;

public class ProcessRunner implements IProcessRunner {

// private final IProcessFactory fProcessFactory;

private final static String STDOUT_REDIRECT = "output_redirect";
private final static String STDERR_REDIRECT = "error_redirect";

public ProcessRunner() {
//this( new ProcessFactory() );
}

// public ProcessRunner( final IProcessFactory factory ) {
// fProcessFactory = factory;
// }

public int executeBlocking( final File workingDir, final Writer out,
final Writer err, final String ... args ) throws IOException {

Process proc = doExecute( workingDir,err==null, args );

Thread outRedirect = redirect( new InputStreamReader( proc.getInputStream() ), out, STDOUT_REDIRECT );
Thread errRedirect = null;
if (err!=null){
errRedirect = redirect( new InputStreamReader( proc.getErrorStream() ), err, STDERR_REDIRECT );
}
int code=-1;
try {
code=proc.waitFor(); // wait for process to finish
outRedirect.join(); // wait until out stream content is redirected
if (errRedirect!=null){
errRedirect.join(); // wait until err stream content is redirected
}
} catch (InterruptedException ex) {
// ignore
}
return code;
}

public Process executeNonblocking( final File workingDir, final Writer out,
Writer err, final String ... args ) throws IOException {
Process proc = doExecute( workingDir,err==null, args );
redirect( new InputStreamReader( proc.getInputStream() ), out, STDOUT_REDIRECT );
if (err==null){
err=new StringWriter();
}
redirect( new InputStreamReader( proc.getErrorStream() ), err, STDERR_REDIRECT );

return proc;
}

private Process doExecute( final File workingDir, final boolean redirect,final String ... args )
throws IOException {
//Process proc = fProcessFactory.startProcess( workingDir, args );
ProcessBuilder builder = new ProcessBuilder(args);
builder.directory( workingDir );
builder.redirectErrorStream(redirect);
return builder.start();
}

private static Thread redirect( final Reader in, final Writer out, String name ) {
Thread outRedirect = new StreamRedirect( name, in, out );
outRedirect.start();
return outRedirect;
}

public static Thread[] consume(Process proc){
Thread t1=redirect( new InputStreamReader( proc.getInputStream() ), new StringWriter(), STDOUT_REDIRECT );
Thread t2=redirect( new InputStreamReader( proc.getErrorStream() ), new StringWriter(), STDERR_REDIRECT );
return new Thread[]{t1,t2};
}

public static String getExecutableVersion(String path,boolean wait) throws IOException{
File f=new File(path);
if (f.exists()){
StringWriter sw=new StringWriter();
// get the process
Process p = new ProcessRunner().doExecute( f.getParentFile(), false,f.getAbsolutePath(),"--version" );
// redirect output into string writer
Thread t1= redirect( new InputStreamReader( p.getInputStream() ), sw, STDOUT_REDIRECT );
// ignore error
redirect( new InputStreamReader( p.getErrorStream() ), new StringWriter(), STDERR_REDIRECT );

try {
// we trust the process to be short lived
if (wait){
try {
p.waitFor();
} catch (InterruptedException ie){
//
}
} else {
// we do not trust the process to be short lived
for (int a=0;a<200;a++){ // 200 * 100 -> 20 seconds maxi
try {
p.exitValue();
break;
} catch (IllegalThreadStateException ise){
// still running
}
try {
Thread.sleep(100);
} catch (InterruptedException ie){
//
}
}
}
} finally {
p.destroy();
}
// we wait for the redirect thread to finish reading/writing
try {
t1.join(10*1000); // 10 seconds max waiting for write
} catch (InterruptedException ignore){
// noop
}
// now we should have the proper result
String line=sw.toString().trim();
int ix=line.lastIndexOf(' ');
if (ix>-1 && ix<line.length()){
line=line.substring(ix+1);
if (Character.isDigit(line.charAt(0))){
return line;
}
}

}
return null;
}
}
package net.sf.eclipsefp.haskell.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ProcessRunner implements IProcessRunner {

// private final IProcessFactory fProcessFactory;

private final static String STDOUT_REDIRECT = "output_redirect";
private final static String STDERR_REDIRECT = "error_redirect";

public static final String LIBRARY_VERSION="using version ((\\d|\\.)*) of the Cabal library";

public ProcessRunner() {
//this( new ProcessFactory() );
}

// public ProcessRunner( final IProcessFactory factory ) {
// fProcessFactory = factory;
// }

public int executeBlocking( final File workingDir, final Writer out,
final Writer err, final String ... args ) throws IOException {

Process proc = doExecute( workingDir,err==null, args );

Thread outRedirect = redirect( new InputStreamReader( proc.getInputStream() ), out, STDOUT_REDIRECT );
Thread errRedirect = null;
if (err!=null){
errRedirect = redirect( new InputStreamReader( proc.getErrorStream() ), err, STDERR_REDIRECT );
}
int code=-1;
try {
code=proc.waitFor(); // wait for process to finish
outRedirect.join(); // wait until out stream content is redirected
if (errRedirect!=null){
errRedirect.join(); // wait until err stream content is redirected
}
} catch (InterruptedException ex) {
// ignore
}
return code;
}

public Process executeNonblocking( final File workingDir, final Writer out,
Writer err, final String ... args ) throws IOException {
Process proc = doExecute( workingDir,err==null, args );
redirect( new InputStreamReader( proc.getInputStream() ), out, STDOUT_REDIRECT );
if (err==null){
err=new StringWriter();
}
redirect( new InputStreamReader( proc.getErrorStream() ), err, STDERR_REDIRECT );

return proc;
}

private Process doExecute( final File workingDir, final boolean redirect,final String ... args )
throws IOException {
//Process proc = fProcessFactory.startProcess( workingDir, args );
ProcessBuilder builder = new ProcessBuilder(args);
builder.directory( workingDir );
builder.redirectErrorStream(redirect);
return builder.start();
}

private static Thread redirect( final Reader in, final Writer out, String name ) {
Thread outRedirect = new StreamRedirect( name, in, out );
outRedirect.start();
return outRedirect;
}

public static Thread[] consume(Process proc){
Thread t1=redirect( new InputStreamReader( proc.getInputStream() ), new StringWriter(), STDOUT_REDIRECT );
Thread t2=redirect( new InputStreamReader( proc.getErrorStream() ), new StringWriter(), STDERR_REDIRECT );
return new Thread[]{t1,t2};
}

/**
* get both the version of the executabl
* @param path the path
* @param wait should we wait for the executable or do we NOT trust it to return and shut down (older versions of scion-browser did not return on the --version flag
* @return the version of the executable or null if we could not get it
* @throws IOException
*/
public static String getExecutableVersion(String path,boolean wait) throws IOException{
List<String> ls=getExecutableAndCabalVersion(path, wait);
if (ls!=null && ls.size()>0){
return ls.get(0);
}
return null;
}

/**
* get both the version of the executable and the version of the Cabal library used to build it
* @param path the path
* @param wait should we wait for the executable or do we NOT trust it to return and shut down (older versions of scion-browser did not return on the --version flag
* @return a list, potentially null or empty, containing first the version of the executable, then the version of Cabal
* @throws IOException
*/
public static List<String> getExecutableAndCabalVersion(String path,boolean wait) throws IOException{
File f=new File(path);
if (f.exists()){
StringWriter sw=new StringWriter();
// get the process
Process p = new ProcessRunner().doExecute( f.getParentFile(), false,f.getAbsolutePath(),"--version" );
// redirect output into string writer
Thread t1= redirect( new InputStreamReader( p.getInputStream() ), sw, STDOUT_REDIRECT );
// ignore error
redirect( new InputStreamReader( p.getErrorStream() ), new StringWriter(), STDERR_REDIRECT );

try {
// we trust the process to be short lived
if (wait){
try {
p.waitFor();
} catch (InterruptedException ie){
//
}
} else {
// we do not trust the process to be short lived
for (int a=0;a<200;a++){ // 200 * 100 -> 20 seconds maxi
try {
p.exitValue();
break;
} catch (IllegalThreadStateException ise){
// still running
}
try {
Thread.sleep(100);
} catch (InterruptedException ie){
//
}
}
}
} finally {
p.destroy();
}
// we wait for the redirect thread to finish reading/writing
try {
t1.join(10*1000); // 10 seconds max waiting for write
} catch (InterruptedException ignore){
// noop
}
List<String> ret=new ArrayList<String>();
// now we should have the proper result
BufferedReader br=new BufferedReader(new StringReader(sw.toString().trim()));
String line=br.readLine();
if (line!=null){
int ix=line.lastIndexOf(' ');
if (ix>-1 && ix<line.length()){
line=line.substring(ix+1);
if (Character.isDigit(line.charAt(0))){
ret.add(line);
}
}
}
// we read the second line to see if we have the cabal version
line=br.readLine();
if (line!=null){
Matcher m=Pattern.compile(LIBRARY_VERSION).matcher(line);
if (m.matches()){
ret.add(m.group(1));
}
}
return ret;
}
return null;
}
}

0 comments on commit 9b0c727

Please sign in to comment.