Griffon' command line system is built on Gant - a simple Groovy wrapper around Apache Ant.However, Griffon takes it a bit further through the use of convention and the griffon
command. When you type:
Griffon does a search in the following directories for Gant scripts to execute:
USER_HOME/.griffon/scripts
PROJECT_HOME/scripts
PROJECT_HOME/plugins/*/scripts
GRIFFON_HOME/scripts
Griffon will also convert command names that are in lower case form such as run-app into camel case. So typingResults in a search for the following files:
USER_HOME/.griffon/scripts/RunApp.groovy
PROJECT_HOME/scripts/RunApp.groovy
PLUGINS_HOME/*/scripts/RunApp.groovy
GRIFFON_HOME/scripts/RunApp.groovy
If multiple matches are found Griffon will give you a choice of which one to execute. When Griffon executes a Gant script, it invokes the "default" target defined in that script. If there is no default, Griffon will quit with an error.To get a list and some help about the available commands type:Which outputs usage instructions and the list of commands Griffon is aware of:
Usage (optionals marked with *):
griffon [environment]* [target] [arguments]*Examples:
griffon dev run-app
griffon create-app booksAvailable Targets (type griffon help 'target-name' for more info):
griffon clean
griffon compile
griffon package
...
The command interpreter is able to expand abbreviations following a camel case convention.Examples:
griffon tA // expands to test-app
griffon cAd // expands to create-addon
griffon cIT // expands to create-integration-test
Refer to the Command Line reference in left menu of the reference guide for more information about individual commands
You can create your own Gant scripts by running the create-script command from the root of your project. For example the following command:griffon create-script compile-sources
Will create a script called scripts/CompileSources.groovy
. A Gant script itself is similar to a regular Groovy script except that it supports the concept of "targets" and dependencies between them:target(default:"The default target is the one that gets executed by Griffon") {
depends(clean, compile)
}
target(clean:"Clean out things") {
ant.delete(dir:"output")
}
target(compile:"Compile some sources") {
ant.mkdir(dir:"mkdir")
ant.javac(srcdir:"src/main", destdir:"output")
}
As demonstrated in the script above, there is an implicit ant
variable that allows access to the Apache Ant API.You can also "depend" on other targets using the depends
method demonstrated in the default
target above.The default target
In the example above, we specified a target with the explicit name "default". This is one way of defining the default target for a script. An alternative approach is to use the setDefaultTarget()
method:target("clean-compile": "Performs a clean compilation on the app's source files.") {
depends(clean, compile)
}
target(clean:"Clean out things") {
ant.delete(dir:"output")
}
target(compile:"Compile some sources") {
ant.mkdir(dir:"mkdir")
ant.javac(srcdir:"src/java", destdir:"output")
}setDefaultTarget("clean-compile")
This allows you to call the default target directly from other scripts if you wish. Also, although we have put the call to setDefaultTarget()
at the end of the script in this example, it can go anywhere as long as it comes after the target it refers to ("clean-compile" in this case).Which approach is better? To be honest, you can use whichever you prefer - there don't seem to be any major advantages in either case. One thing we would say is that if you want to allow other scripts to call your "default" target, you should move it into a shared script that doesn't have a default target at all. We'll talk some more about this in the next section.
Griffon ships with a lot of command line functionality out of the box that you may find useful in your own scripts (See the command line reference in the reference guide for info on all the commands). Of particular use are the compile and package scripts.Pulling in targets from other scripts
Gant allows you to pull in all targets (except "default") from another Gant script. You can then depend upon or invoke those targets as if they had been defined in the current script. The mechanism for doing this is the includeTargets
property. Simply "append" a file or class to it using the left-shift operator:
includeTargets << new File("/path/to/my/script.groovy")
includeTargets << gant.tools.Ivy
Don't worry too much about the syntax using a class, it's quite specialized. If you're interested, look into the Gant documentation.Core Griffon targets
As you saw in the example at the beginning of this section, you use neither the File- nor the class-based syntax for includeTargets
when including core Griffon targets. Instead, you should use the special griffonScript()
method that is provided by the Griffon command launcher (note that this is not available in normal Gant scripts, just Griffon ones).The syntax for the griffonScript()
method is pretty straightforward: simply pass it the name of the Griffon script you want to include, without any path information. Here is a list of Griffon scripts that you may want to re-use:
Script | Description |
---|
_GriffonSettings | You really should include this! Fortunately, it is included automatically by all other Griffon scripts bar one (_GriffonProxy), so you usually don't have to include it explicitly. |
_GriffonEvents | If you want to fire events, you need to include this. Adds an event(String eventName, List args) method. Again, included by almost all other Griffon scripts. |
_GriffonClasspath | Sets up compilation, test, and runtime classpaths. If you want to use or play with them, include this script. Again, included by almost all other Griffon scripts. |
_GriffonProxy | If you want to access the internet, include this script so that you don't run into problems with proxies. |
_GriffonArgParsing | Provides a parseArguments target that does what it says on the tin: parses the arguments provided by the user when they run your script. Adds them to the argsMap property. |
_GriffonTest | Contains all the shared test code. Useful if you want to add any extra tests. |
RunApp | Provides all you need to run the application in standalone mode. |
RunApplet | Provides all you need to run the application in applet mode. |
RunWebstart | Provides all you need to run the application in webstart mode. |
There are many more scripts provided by Griffon, so it is worth digging into the scripts themselves to find out what kind of targets are available. Anything that starts with an "_" is designed for re-use.Script architecture
You maybe wondering what those underscores are doing in the names of the Griffon scripts. That is Griffon' way of determining that a script is internal , or in other words that it has not corresponding "command". So you can't run "griffon _griffon-settings" for example. That is also why they don't have a default target.Internal scripts are all about code sharing and re-use. In fact, we recommend you take a similar approach in your own scripts: put all your targets into an internal script that can be easily shared, and provide simple command scripts that parse any command line arguments and delegate to the targets in the internal script. Say you have a script that runs some functional tests - you can split it like this:
./scripts/FunctionalTests.groovy:includeTargets << new File("${basedir}/scripts/_FunctionalTests.groovy")target(default: "Runs the functional tests for this project.") {
depends(runFunctionalTests)
}./scripts/_FunctionalTests.groovy:includeTargets << griffonScript("_GriffonTest")target(runFunctionalTests: "Run functional tests.") {
depends(...)
…
}
Here are a few general guidelines on writing scripts:
- Split scripts into a "command" script and an internal one.
- Put the bulk of the implementation in the internal script.
- Put argument parsing into the "command" script.
- To pass arguments to a target, create some script variables and initialize them before calling the target.
- Avoid name clashes by using closures assigned to script variables instead of targets. You can then pass arguments direct to the closures.
Griffon provides the ability to hook into scripting events. These are events triggered during execution of Griffon target and plugin scripts.The mechanism is deliberately simple and loosely specified. The list of possible events is not fixed in any way, so it is possible to hook into events triggered by plugin scripts, for which there is no equivalent event in the core target scripts.Defining event handlers
Event handlers are defined in scripts called _Events.groovy
. Griffon searches for these scripts in the following locations:
USER_HOME/.griffon/scripts
- user-specific event handlers
PROJECT_HOME/scripts
- application-specific event handlers
PLUGINS_HOME/*/scripts
- plugin-specific event handlers
Whenever an event is fired, all the registered handlers for that event are executed. Note that the registration of handlers is performed automatically by Griffon, so you just need to declare them in the relevant _Events.groovy
file.Event handlers are blocks defined in _Events.groovy
, with a name beginning with "event". The following example can be put in your /scripts directory to demonstrate the feature:eventCreatedArtefact = { type, name ->
println "Created $type $name"
}eventStatusUpdate = { msg ->
println msg
}eventStatusFinal = { msg ->
println msg
}
You can see here the three handlers eventCreatedArtefact
, eventStatusUpdate
, eventStatusFinal
. Griffon provides some standard events, which are documented in the command line reference guide. For example the compile command fires the following events:
CompileStart
- Called when compilation starts, passing the kind of compile - source or tests
CompileEnd
- Called when compilation is finished, passing the kind of compile - source or tests
Triggering events
To trigger an event simply call the event() closure:event("StatusFinal", ["Super duper plugin action complete!"])
Common Events
Below is a table of some of the common events that can be leveraged:Event | Parameters | Description |
---|
StatusUpdate | message | Passed a string indicating current script status/progress |
StatusError | message | Passed a string indicating an error message from the current script |
StatusFinal | message | Passed a string indicating the final script status message, i.e. when completing a target, even if the target does not exit the scripting environment |
CreatedArtefact | artefactType,artefactName | Called when a create-xxxx script has completed and created an artifact |
CreatedFile | fileName | Called whenever a project source filed is created, not including files constantly managed by Griffon |
Exiting | returnCode | Called when the scripting environment is about to exit cleanly |
PluginInstalled | pluginName | Called after a plugin has been installed |
CompileStart | kind | Called when compilation starts, passing the kind of compile - source or tests |
CompileEnd | kind | Called when compilation is finished, passing the kind of compile - source or tests |
DocStart | kind | Called when documentation generation is about to start - javadoc or groovydoc |
DocEnd | kind | Called when documentation generation has ended - javadoc or groovydoc |
Griffon is most definitely an opinionated framework and it prefers convention to configuration, but this doesn't mean you can't configure it. In this section, we look at how you can influence and modify the standard Griffon build.The defaults
In order to customize a build, you first need to know what you can customize. The core of the Griffon build configuration is the griffon.util.BuildSettings
class, which contains quite a bit of useful information. It controls where classes are compiled to, what dependencies the application has, and other such settings.Here is a selection of the configuration options and their default values:
Property | Config option | Default value |
---|
griffonWorkDir | griffon.work.dir | $USER_HOME/.griffon/<griffonVersion> |
projectWorkDir | griffon.project.work.dir | <griffonWorkDir>/projects/<baseDirName> |
classesDir | griffon.project.class.dir | <projectWorkDir>/classes |
testClassesDir | griffon.project.test.class.dir | <projectWorkDir>/test-classes |
testReportsDir | griffon.project.test.reports.dir | <projectWorkDir>/test/reports |
resourcesDir | griffon.project.resource.dir | <projectWorkDir>/resources |
projectPluginsDir | griffon.plugins.dir | <projectWorkDir>/plugins |
The BuildSettings
class has some other properties too, but they should be treated as read-only:
Property | Description |
---|
baseDir | The location of the project. |
userHome | The user's home directory. |
griffonHome | The location of the Griffon installation in use (may be null). |
griffonVersion | The version of Griffon being used by the project. |
griffonEnv | The current Griffon environment. |
compileDependencies | A list of compile-time project dependencies as File instances. |
testDependencies | A list of test-time project dependencies as File instances. |
runtimeDependencies | A list of runtime-time project dependencies as File instances. |
Of course, these properties aren't much good if you can't get hold of them. Fortunately that's easy to do: an instance of BuildSettings
is available to your scripts via the griffonSettings
script variable. You can also access it from your code by using the griffon.util.BuildSettingsHolder
class, but this isn't recommended.Overriding the defaults
All of the properties in the first table can be overridden by a system property or a configuration option - simply use the "config option" name. For example, to change the project working directory, you could either run this command:
griffon -Dgriffon.project.work.dir=work compile
or add this option to your griffon-app/conf/BuildConfig.groovy
file:
griffon.project.work.dir = "work"
Note that the default values take account of the property values they depend on, so setting the project working directory like this would also relocate the compiled classes, test classes, resources, and plugins.What happens if you use both a system property and a configuration option? Then the system property wins because it takes precedence over the BuildConfig.groovy
file, which in turn takes precedence over the default values.Available build settings
Name | Description |
---|
griffon.compiler.dependencies | Legacy approach to adding extra dependencies to the compiler classpath. Set it to a closure containing "fileset()" entries. |
griffon.testing.patterns | A list of Ant path patterns that allow you to control which files are included in the tests. The patterns should not include the test case suffix, which is set by the next property. |
griffon.testing.nameSuffix | By default, tests are assumed to have a suffix of "Tests". You can change it to anything you like but setting this option. For example, another common suffix is "Test". |
If all the other projects in your team or company are built using a standard build tool such as Ant or Maven, you become the black sheep of the family when you use the Griffon command line to build your application. Fortunately, you can easily integrate the Griffon build system into the main build tools in use today (well, the ones in use in Java projects at least).Ant Integration
When you invoke the integrate-with command with the -ant option enabledgriffon integrate-with --ant
Griffon creates an Apache Ant build.xml
file for you containing the following targets:
clean
- Cleans the Griffon application
debug-app
- Runs the application in debug mode
test
- Runs the unit tests
run-app
- Equivalent to "griffon run-app"
run-applet
- Equivalent to "griffon run-applet"
run-webstart
- Equivalent to "griffon run-webstart"
dist
- Packages the application for production
Each of these can be run by Ant, for example:The build file is all geared up to use Apache Ivy for dependency management, which means that it will automatically download all the requisite Griffon JAR files and other dependencies on demand. You don't even have to install Griffon locally to use it! That makes it particularly useful for continuous integration systems such as CruiseControl or JenkinsIt uses the Griffon Ant task to hook into the existing Griffon build system. The task allows you to run any Griffon script that's available, not just the ones used by the generated build file. To use the task, you must first declare it:
<taskdef name="griffonTask"
classname="griffon.ant.GriffonTask"
classpathref="griffon.classpath"/>
This raises the question: what should be in "griffon.classpath"? The task itself is in the "griffon-cli" JAR artifact, so that needs to be on the classpath at least. You should also include the "groovy-all" JAR. With the task defined, you just need to use it! The following table shows you what attributes are available:
Attribute | Description | Required |
---|
home | The location of the Griffon installation directory to use for the build. | Yes, unless classpath is specified. |
classpathref | Classpath to load Griffon from. Must include the "griffon-bootstrap" artifact and should include "griffon-scripts". | Yes, unless home is set or you use a classpath element. |
script | The name of the Griffon script to run, e.g. "TestApp". | Yes. |
args | The arguments to pass to the script, e.g. "-unit -xml". | No. Defaults to "". |
environment | The Griffon environment to run the script in. | No. Defaults to the script default. |
includeRuntimeClasspath | Advanced setting: adds the application's runtime classpath to the build classpath if true. | No. Defaults to true. |
The task also supports the following nested elements, all of which are standard Ant path structures:
classpath
- The build classpath (used to load Gant and the Griffon scripts).
compileClasspath
- Classpath used to compile the application's classes.
runtimeClasspath
- Classpath used to run the application and package the WAR. Typically includes everything in @compileClasspath.
testClasspath
- Classpath used to compile and run the tests. Typically includes everything in runtimeClasspath
.
How you populate these paths is up to you. If you are using the home
attribute and put your own dependencies in the lib
directory, then you don't even need to use any of them. For an example of their use, take a look at the generated Ant build file for new apps.Maven Integration
TBDGradle Integration
When you invoke the integrate-with command with the -gradle option enabledgriffon integrate-with --gradle
Griffon creates a Gradle build.gradle
file for you. From here you can call the standard Gradle commands such as clean
, assemble
and build
to build your application. You can also use griffon
as a command prefix to execute any of the regular Griffon command targets such asThis neat feature lets you execute Griffon commands without having a previously installing Griffon in your environment. This is a perfect fit for running tests in a continuous integration environment like Jenkins as there are no other requirements than a matching JDK.When an application or plugin are created you'll get also the hooks for calling the wrapper, even configuring it in case you need it to point to a different Griffon release. These files are
griffonw
griffonw.bat
wrapper/griffon-wrapper.jar
wrapper/griffon-wrapper.properties
The first 2 files define platform dependent launch scripts. The third file contains the required classes to bootstrap the wrapper itself. The last file defines the configuration that the wrapper requires to work properly.The wrapper works in the same way as the Griffon command, this means you can feed it every single command target and parameter the Griffon command accepts, like the following onesCompiles and runs the application in standalone mode../griffonw list-plugin-updates -install
Displays a list of available updates for all plugins installed and proceeds to update them if the confirmation is successful.
The following command line options only have meaning while building the project. They have no effect when running the application once it has been packaged.It's worth noting that all of the following options can also be specified in either griffon-app/conf/BuildConfig.groovy
(local to project) or $USER_HOME/.griffon/settings.groovy
(global to all projects), with the caveat that values specified at the command prompt will have precedence over those specified in the config file.
Scripts have the choice of printing to the console whenever they need to communicate something to the developer. They would normally use a standard println
sentence. Sometimes it's useful to know what a script is doing with further detail but it makes no sense to see that information every single time. A conditional output is required.All scripts inherit a debug()
closure that will print its argument to stdout if an only if the following flag is enabled: griffon.cli.verbose
. As an example, the following script has two print outsincludeTargets << griffonScript("Init")
target(main: "The description of the script goes here!") {
println 'Hello world!'
debug 'Hello World (debug)'
}
setDefaultTarget(main)
Running the script without the flag will print out 'Hello World!' all the time but never the second one$ griffon hello
Welcome to Griffon 0.9.5-rc2 - http://griffon.codehaus.org/
Licensed under Apache Standard License 2.0
Griffon home is set to: /usr/local/griffon
…
Environment set to development
Hello world!
The second message will only appear if you specify the verbose flag$ griffon -Dgriffon.cli.verbose=true hello
Welcome to Griffon 0.9.5-rc2 - http://griffon.codehaus.org/
Licensed under Apache Standard License 2.0
Griffon home is set to: /usr/local/griffon
…
Environment set to development
Hello world!
[11/11/10 4:43:04 PM] Hello World (debug)
Since Griffon 0.9.1 all artifacts now share a common interface (GriffonArtifact). They may implement additional interfaces that define their role in a better way. For example controllers implement GriffonController whereas models implement GriffonModel. Despite this, you are not forced to implement these interfaces yourself, the Griffon compiler can do the work for you. It will even inject the appropriate behavior to classes that extend from base types other than Object
. All this is done by leveraging the powerful AST Transformations framework introduced in Groovy 1.6.If this feature ever gets in the way then you can disable it with the following command flaggriffon -Dgriffon.disable.ast.injection=true compile
Be sure to clean the project before using this flag, otherwise some classes may still have the AST additions weaved into their bytecode.
Another feature introduced in Griffon 0.9.1 is the ability to define default imports for artifacts and scripts.If this feature proves to be a disadvantage then disable it with the following command flaggriffon -Dgriffon.disable.default.imports=true compile
Griffon 0.9.1 added a log property to all artifacts, and enabled logging on addons. Groovy 1.8 adds a new set of AST transformations, @Log being one of them. It's job is to transform an unguarded logging statement into a guarded one. Starting with 0.9.2, Griffon can do the same without the need of annotating artifacts or addons with @Log.If this feature proves to be a disadvantage then disable it with the following command flaggriffon -Dgriffon.disable.logging.injection=true compile
Griffon 0.9.2 adds the option for all controller actions to be executed off the UI thread automatically. This feature breaks backward compatibility with previous releases.In order to regain the previous behavior you can disable this feature by specifying the following command flaggriffon -Dgriffon.disable.threading.injection=true compile
Sometimes a command may require the user to specify a missing value. When the build is run in interactive mode (the default mode) then it's just a matter of typing the value in the console. However, if the build is run in non-interactive mode then it's very likely it will fail.For this reason, the Griffon build accepts the definition of a default answer if the griffon.noninteractive.default.answer
key is specified, like thisgriffon -Dgriffon.noninteractive.default.answer=y release-plugin
Be warned that this setting applies to every single input asked by a command.Failures may occur during plugin installation. It may be the case that a plugin could not be found in the configured repositories, or a JAR dependency failed to be resolved. When this happens the build will try its best cope with the error, usually by continuing installing remainder plugin dependencies (if any).This behavior can be altered by specifying a value for griffon.install.failure
. Accepted values are:Value | Description |
---|
abort | Aborts the installation sequence, even if there are other plugins left to be installed. It will also delete all installed plugins in the current session. |
continue | Continues with the next plugin in the list. this is the default behavior. |
retry | Retries failed plugins a second time. A second failure skips the plugin from being installed but does not affect any other plugins that have been successfully installed or are yet to be installed. |
For example, to return the build to its previous behavior (abort on failures) you'll type the following in your command promptgriffon -Dgriffon.install.failure='abort' compile
The Griffon build assumes griffon-legacy
to be the default Artifact Repository to be searched when querying for artifacts (either to list them, get some info or install them). This setting can be altered by specifying a value for griffon.artifact.repository.default.search
. The value must be a valid repository name available in the configuration files.For example, a local repository identified by the name 'my-local-repo
' can be set as the default search repository like sogriffon -Dgriffon.artifact.repository.default.search='my-local-repo' install-plugin cool-plugin
When a plugin or archetype is downloaded from an artifact repository the Griffon build will place a copy of it in the griffon-local
repository. This speeds up searches and further plugin installations. If you would like to specify a different local repository to be used as a cache then define a value for the griffon.artifact.repository.default.install
key.Assuming that 'my-local-repo
' is configured in the project's settings then the following command will download the miglayout plugin and place a copy in that specific repository.griffon -Dgriffon.artifact.repository.default.install='my-local-repo' install-plugin miglayout
Section 4.7.9 describes that copies of plugins and archetypes will be placed in a local repository whenever they are downloaded from other repositories. You can disable this feature altogether by specifying a value for griffon.disable.local.repository.sync
as true, like the following example showsgriffon -Dgriffon.disable.local.repository.sync=true install-archetype scala
Starting with Griffon 0.9.5 there's a new command line tool at your disposal: the Griffon Shell or griffonsh
for short. This is an interactive shell that can be kept running in the background, this way you don't pay the penalty of starting a new JVM every time you invoke a command. Other benefits are the bypass of dependency resolution if dependencies have not changed from the last command invocation. Here's a sample usage session:$ griffonsh
Welcome to Griffon 0.9.5-rc2 - http://griffon.codehaus.org/
Licensed under Apache Standard License 2.0
Griffon home is set to: /usr/local/griffonType 'exit' or ^D to terminate this interactive shell
griffon> compile
Resolving dependencies…
Dependencies resolved in 903ms.
Environment set to development
Resolving plugin dependencies …
Plugin dependencies resolved in 1502 ms.
[mkdir] Created dir: /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/cli
[mkdir] Created dir: /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/main
[mkdir] Created dir: /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/test
[mkdir] Created dir: /Users/joe/.griffon/0.9.5-rc2/projects/sample/test-classes
[mkdir] Created dir: /Users/joe/.griffon/0.9.5-rc2/projects/sample/test-resources
[mkdir] Created dir: /Users/joe/.griffon/0.9.5-rc2/projects/sample/resources
[griffonc] Compiling 8 source files to /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/main
[griffonc] Compiling 4 source files to /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/main
griffon> run-app
Resolving dependencies…
Dependencies resolved in 1ms.
[mkdir] Created dir: /Users/joe/.griffon/0.9.5-rc2/projects/sample/resources/griffon-app/i18n
[mkdir] Created dir: /Users/joe/.griffon/0.9.5-rc2/projects/sample/resources/griffon-app/resources
[copy] Copying 1 file to /Users/joe/.griffon/0.9.5-rc2/projects/sample/resources/griffon-app/i18n
[copy] Copying 8 files to /Users/joe/.griffon/0.9.5-rc2/projects/sample/resources/griffon-app/resources
[copy] Copying 1 file to /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/main
[copy] Copying 11 files to /Users/joe/.griffon/0.9.5-rc2/projects/sample/resources
[copy] Copied 8 empty directories to 8 empty directories under /Users/joe/.griffon/0.9.5-rc2/projects/sample/resources
[copy] Copying 1 file to /projects/sample/staging
[copy] Copying 1 file to /projects/sample/staging
[copy] Copying 1 file to /projects/sample/staging
[copy] Copying 1 file to /projects/sample/staging
[copy] Copying 1 file to /projects/sample/staging
[copy] Copying 1 file to /projects/sample/staging
[copy] Copying 1 file to /projects/sample/staging
[copy] Copying 1 file to /projects/sample/staging
Launching application …
2012-02-07 17:27:11,007 [main] INFO griffon.swing.SwingApplication - Initializing all startup groups: [sample]
2012-02-07 17:27:16,555 [AWT-EventQueue-0] INFO griffon.swing.SwingApplication - Shutdown is in process
[delete] Deleting directory /projects/sample/staging/macosx64
[delete] Deleting directory /projects/sample/staging/macosx
griffon> clean
Resolving dependencies…
Dependencies resolved in 1ms.
[delete] Deleting directory /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/cli
[delete] Deleting directory /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/main
[delete] Deleting directory /Users/joe/.griffon/0.9.5-rc2/projects/sample/classes/test
[delete] Deleting directory /Users/joe/.griffon/0.9.5-rc2/projects/sample/test-classes
[delete] Deleting directory /Users/joe/.griffon/0.9.5-rc2/projects/sample/test-resources
[delete] Deleting directory /Users/joe/.griffon/0.9.5-rc2/projects/sample/resources
[delete] Deleting directory /projects/sample/staging
griffon>
This command environment accepts all commands available to the griffon
command (except those that let you create a new project) plus a few more that are unique to the griffon shell. Please refer to the help command for more information on those extra commands.