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


Reply via email to