On May 26, 2009, at 4:49 PM, Daniel wrote:
Ok, I have been trying to confine all the nasty details of that
Jython artifact handling thing.
But I'm stuck in Gradle. Below is an annotated version of what I
have been trying to get working. I tried to confine everything to
one task to not have all the details spread through the build code.
If I have to structure it differently, please tell me. Also, I'm
pretty sure that I have a boatload of things that could be coded
neater, but I lack the knowledge to make it smooth. Also the current
problem is, even if I get past the Ivy cached resolutions, Ivy uses
the sourceforge resolver, and can actually download something (an
error page), which then fails to work, obviously).
I also tried to solve the problem with a custom IvyResolver, but the
resolver code is pretty involved, and I'm not sure where I have to
plug in (on stackoverflow.com: http://stackoverflow.com/questions/908371/apache-ivy-resolving-dependencies-embedded-in-an-installer
)
Thanks in advance for any help, it's deeply appreciated
Here is one possible solution.
configurations {
jythonInstaller
jython
}
def jythonDep
dependencies {
jythonDep = jython("jython:jython:2.5rc2")
jythonInstaller("jython:jython_installer:${jythonDep.version}")
}
def pythonRepoDir = "$projectDir/jython"
repositories {
flatDir(dirs: "$pythonRepoDir")
}
task getJython << {
def resolveReport = configurations.jython.copy().resolveAsReport()
if (!resolveReport.hasError()) throw new StopExecutionException()
repositories {
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
name = "python_sf" // For non standard resolvers the name is
required
addArtifactPattern("http://downloads.sourceforge.net/
[organisation]/[artifact]-[revision].[ext]")
}
}
File installerFile =
configurations.jythonInstaller.resolve().iterator().next()
ant {
delete(dir: pythonRepoDir)
java(jar: installerFile.path, fork: true) {
arg(value: '--silent')
arg(value: '--directory')
arg(value: "$projectDir/jython")
arg(value: '--type')
arg(value: 'standalone')
//arg(value: '--verbose') // no effect when used called
here.
}
move(file: "$projectDir/jython/jython.jar", tofile:
"$pythonRepoDir/jython-${jythonDep.version}.jar")
}
}
task showJythonFile(dependsOn: getJython) << {
println configurations.jython.resolve()
}
gradle showJythonFile should always produce the jython jar.
A couple of remarks:
- After a configuration is resolved it is immutable. Any attempt to
change to its state leads to an exception. What a configuration
(resolved or unresolved) does offer is a copy method, which creates a
new unresolved configuration with the same dependencies.
- The behavior of the Ivy URL resolver to return a html page as jar in
case the jar is not found is odd. Is this a known Ivy issue?
In the above solution we have two configurations. The first is for the
actual jython jar, the second for the installer. We use a copy of the
first configuration to check if the jar can be found. To avoid the URL
resolver bug, we haven't added the sourceforge resolver to the
repositories yet. We also use the resolveAsReport method which returns
an ivy resolve report and does not throw an exception in case of a
resolve error. This native Ivy object has a method hasError. If the
jython jar does not exist locally, we add the sourceforge repository
and download the installer. Then we create the jython jar with in the
directory of the flat dir repository. The flat dir repository does not
use the cache for retrieving the jar (as it is local anyway).
Conclusions:
- This solution is not flawless. If for example this project retrieves
additional dependencies and one of those dependencies are not
available, the sourceforge repository would hide and download a html
page instead as the jar. There are ways to deal with this situation.
But it would be nice if Gradle offered a way do have multiple
repository contexts per project for dependency retrieval. You could do
this already with 0.6 by using the internal API (as a last resort).
- Right now we use the native Ivy resolver classes as our repository
objects. The API does not always offer what we want (e.g. we would
like to ask the flat dir resolver for its root directories). We will
provide our own domain classes for repositories in a future (pre-1.0)
release.
- Instead of the flat dir resolver you could use a default Ivy
FileSystem resolver. In this case the cache would be used for storing
the jar and you could work with temporary directories.
Thanks for the interesting use case.
<snip>
- Hans
--
Hans Dockter
Gradle Project Manager
http://www.gradle.org
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email