Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 63 additions & 45 deletions src/java/org/codehaus/groovy/grails/cli/GrailsScriptRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -250,17 +250,6 @@ public int executeCommand(String scriptName, String args, String env) {
settings.setRootLoader((URLClassLoader) GrailsScriptRunner.class.getClassLoader());
}

// Get the default environment if one hasn't been set.
boolean useDefaultEnv = env == null;
if (useDefaultEnv) {
env = DEFAULT_ENVS.get(scriptName);
env = env != null ? env : Environment.DEVELOPMENT.getName();
}

System.setProperty("base.dir", settings.getBaseDir().getPath());
System.setProperty(Environment.KEY, env);
System.setProperty(Environment.DEFAULT, "true");

if (args != null) {
// Check whether we are running in non-interactive mode
// by looking for a "non-interactive" argument.
Expand Down Expand Up @@ -297,8 +286,8 @@ public int executeCommand(String scriptName, String args, String env) {
}

// Add some extra binding variables that are now available.
settings.setGrailsEnv(env);
settings.setDefaultEnv(useDefaultEnv);
// settings.setGrailsEnv(env);
// settings.setDefaultEnv(useDefaultEnv);

BuildSettingsHolder.setSettings(settings);

Expand All @@ -310,12 +299,30 @@ public int executeCommand(String scriptName, String args, String env) {
return 1;
}

setRunningEnvironment(scriptName, env);
// This never exits unless an exception is thrown or
// the process is interrupted via a signal.
runInteractive();
return 0;
}
return callPluginOrGrailsScript(scriptName);
return callPluginOrGrailsScript(scriptName, env);
}

private void setRunningEnvironment(String scriptName, String env) {
// Get the default environment if one hasn't been set.
boolean useDefaultEnv = env == null || Environment.DEVELOPMENT.getName().equals(env);
if (useDefaultEnv) {
env = DEFAULT_ENVS.get(scriptName);
env = env != null ? env : Environment.DEVELOPMENT.getName();
}

System.setProperty("base.dir", settings.getBaseDir().getPath());
System.setProperty(Environment.KEY, env);
System.setProperty(Environment.DEFAULT, "true");

// Add some extra binding variables that are now available.
settings.setGrailsEnv(env);
settings.setDefaultEnv(useDefaultEnv);
}

/**
Expand All @@ -329,6 +336,7 @@ private void runInteractive() {
System.setProperty("grails.interactive.mode", "true");

ScriptAndArgs script = new ScriptAndArgs();
String env = null;
while (true) {
// Clear unhelpful system properties.
System.clearProperty("grails.env.set");
Expand All @@ -349,20 +357,7 @@ private void runInteractive() {
System.setProperty("grails.cli.args", "");
}

// Make sure we run the command with the correct environment.
if (script.env != null) {
settings.setGrailsEnv(script.env);
settings.setDefaultEnv(false);
}
else {
// This is a bit of an anachronism, but some of the
// default environments are hard-coded in this class.
String defaultEnv = DEFAULT_ENVS.get(script.name);
if (defaultEnv == null) defaultEnv = Environment.DEVELOPMENT.getName();

settings.setGrailsEnv(defaultEnv);
settings.setDefaultEnv(true);
}
env = script.env != null ? script.env : Environment.DEVELOPMENT.getName();
}

if (script.name == null) {
Expand All @@ -375,7 +370,7 @@ else if (script.name.equalsIgnoreCase("exit") || script.name.equalsIgnoreCase("q

long now = System.currentTimeMillis();
try {
callPluginOrGrailsScript(script.name);
callPluginOrGrailsScript(script.name, env);
}
catch (ScriptNotFoundException ex) {
out.println("No script found for " + script.name);
Expand All @@ -399,7 +394,7 @@ else if (script.name.equalsIgnoreCase("exit") || script.name.equalsIgnoreCase("q
private final List<File> scriptsAllowedOutsideOfProject = new ArrayList<File>();

@SuppressWarnings({ "unchecked", "rawtypes" })
private int callPluginOrGrailsScript(String scriptName) {
private int callPluginOrGrailsScript(String scriptName, String env) {
// The directory where scripts are cached.
File scriptCacheDir = new File(settings.getProjectWorkDir(), "scriptCache");

Expand Down Expand Up @@ -466,15 +461,22 @@ private int callPluginOrGrailsScript(String scriptName) {
}

// Now find what scripts match the one requested by the user.
boolean exactMatchFound = false;
potentialScripts = new ArrayList<File>();
for (File scriptPath : allScripts) {
String scriptFileName = scriptPath.getName().substring(0,scriptPath.getName().length()-7); // trim .groovy extension
if (scriptFileName.endsWith("_")) {
scriptsAllowedOutsideOfProject.add(scriptPath);
scriptFileName = scriptFileName.substring(0, scriptFileName.length()-1);
}

if (scriptFileName.equals(scriptName)) potentialScripts.add(scriptPath);

if (scriptFileName.equals(scriptName)) {
potentialScripts.add(scriptPath);
exactMatchFound = true;
continue;
}

if (!exactMatchFound && ScriptNameResolver.resolvesTo(scriptName, scriptFileName)) potentialScripts.add(scriptPath);
}

if (!potentialScripts.isEmpty()) {
Expand All @@ -485,15 +487,12 @@ private int callPluginOrGrailsScript(String scriptName) {
}
}

// Prep the binding with important variables.
initBinding(binding);
final Closure doNothingClosure = new Closure(this) {
private static final long serialVersionUID = 1L;
@Override public Object call(Object arguments) { return null; }
@Override public Object call() { return null; }
@Override public Object call(Object[] args) { return null; }
};
binding.setVariable("scriptName", scriptName);

// First try to load the script from its file. If there is no
// file, then attempt to load it as a pre-compiled script. If
Expand All @@ -513,9 +512,13 @@ private int callPluginOrGrailsScript(String scriptName) {
return -1;
}
out.println("Running script " + scriptFile.getAbsolutePath());
// We can now safely set the default environment
String scriptFileName = getScriptNameFromFile(scriptFile);
setRunningEnvironment(scriptFileName, env);
binding.setVariable("scriptName", scriptFileName);

// Setup the script to call.
Gant gant = new Gant(binding, classLoader);
Gant gant = new Gant(initBinding(binding), classLoader);
gant.setUseCache(true);
gant.setCacheDirectory(scriptCacheDir);
gant.loadScript(scriptFile);
Expand All @@ -542,13 +545,17 @@ private int callPluginOrGrailsScript(String scriptName) {
if (enteredValue == null) return 1;

int number = Integer.parseInt(enteredValue);

out.println("Running script "+ potentialScripts.get(number - 1).getAbsolutePath());
File scriptFile = (File) potentialScripts.get(number - 1);
out.println("Running script "+ scriptFile.getAbsolutePath());
// We can now safely set the default environment
String scriptFileName = getScriptNameFromFile(scriptFile);
setRunningEnvironment(scriptFileName, env);
binding.setVariable("scriptName", scriptFileName);

// Set up the script to call.
Gant gant = new Gant(binding, classLoader);
Gant gant = new Gant(initBinding(binding), classLoader);

gant.loadScript(potentialScripts.get(number - 1));
gant.loadScript(scriptFile);

// Invoke the default target.
return executeWithGantInstance(gant, doNothingClosure);
Expand All @@ -557,24 +564,25 @@ private int callPluginOrGrailsScript(String scriptName) {
out.println("Running pre-compiled script");

// Get Gant to load the class by name using our class loader.
Gant gant = new Gant(binding, classLoader);
Gant gant = new Gant(initBinding(binding), classLoader);

try {
loadScriptClass(gant, scriptName);
}
catch (ScriptNotFoundException e) {
if(isInteractive) {
String fixedName = fixScriptName(scriptName, allScripts);
if (fixedName == null) {
scriptName = fixScriptName(scriptName, allScripts);
if (scriptName == null) {
throw e;
}

loadScriptClass(gant, fixedName);
loadScriptClass(gant, scriptName);
} else {
throw e;
}
}

setRunningEnvironment(scriptName, env);
return executeWithGantInstance(gant, doNothingClosure);
}

Expand Down Expand Up @@ -664,6 +672,14 @@ private boolean isExternalScript(File scriptFile) {
return scriptsAllowedOutsideOfProject.contains(scriptFile);
}

private String getScriptNameFromFile(File scriptPath) {
String scriptFileName = scriptPath.getName().substring(0,scriptPath.getName().length()-7); // trim .groovy extension
if(scriptFileName.endsWith("_")) {
scriptFileName = scriptFileName.substring(0, scriptFileName.length()-1);
}
return scriptFileName;
}

/**
* Prep the binding. We add the location of GRAILS_HOME under
* the variable name "grailsHome". We also add a closure that
Expand All @@ -678,7 +694,7 @@ private boolean isExternalScript(File scriptFile) {
* will load the "Init" script from $GRAILS_HOME/scripts if it
* exists there; otherwise it will load the Init class.
*/
private void initBinding(Binding binding) {
private GantBinding initBinding(GantBinding binding) {
Closure c = settings.getGrailsScriptClosure();
c.setDelegate(binding);
binding.setVariable("grailsScript", c);
Expand Down Expand Up @@ -758,6 +774,8 @@ private void initBinding(Binding binding) {
catch (Exception e) {
// No plugins found.
}

return binding;
}

/**
Expand Down
39 changes: 39 additions & 0 deletions src/java/org/codehaus/groovy/grails/cli/ScriptNameResolver.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2010 the original author or authors.
*
* 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.
*/

package org.codehaus.groovy.grails.cli

/**
* @author Andres Almiray
* @author Dierk Koenig
*/
class ScriptNameResolver {
/**
* Matches a camelCase scriptName to a potential scriptFileName in canonical form.<p>
* The following scriptNames match FooBar: FB, FoB, FBa
*/
static boolean resolvesTo(String scriptName, String scriptFileName) {
def scriptFileNameTokens = scriptFileName.findAll(/[A-Z][a-z]+/)
def scriptNameTokens = scriptName.findAll(/[A-Z][a-z]*/)

if(scriptFileNameTokens.size() != scriptNameTokens.size()) return false
for(int i = 0; i < scriptNameTokens.size(); i++) {
String str = scriptNameTokens[i]
if(!scriptFileNameTokens[i].startsWith(str)) return false
}
true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.codehaus.groovy.grails.cli

class ScriptNameResolverTests extends GroovyTestCase {
void testFoo(){
assert ScriptNameResolver.resolvesTo('F', 'Foo')
assert ScriptNameResolver.resolvesTo('FB', 'FooBar')
assert ScriptNameResolver.resolvesTo('FoB', 'FooBar')
assert ScriptNameResolver.resolvesTo('FBa', 'FooBar')
assert ScriptNameResolver.resolvesTo('FoBa', 'FooBar')
assert ScriptNameResolver.resolvesTo('FooBar', 'FooBar')
assert !ScriptNameResolver.resolvesTo('FB', 'FooBarZoo')
assert !ScriptNameResolver.resolvesTo('FBaz', 'FooBar')
assert !ScriptNameResolver.resolvesTo('FBr', 'FooBar')
assert !ScriptNameResolver.resolvesTo('F', 'FooBar')
assert !ScriptNameResolver.resolvesTo('Fo', 'FooBar')
assert !ScriptNameResolver.resolvesTo('Foo', 'FooBar')
}
}