diff --git a/base-plugin/src/integTest/groovy/com/github/jrubygradle/JRubyPrepareGemsIntegrationSpec.groovy b/base-plugin/src/integTest/groovy/com/github/jrubygradle/JRubyPrepareGemsIntegrationSpec.groovy index 00618560..87218748 100644 --- a/base-plugin/src/integTest/groovy/com/github/jrubygradle/JRubyPrepareGemsIntegrationSpec.groovy +++ b/base-plugin/src/integTest/groovy/com/github/jrubygradle/JRubyPrepareGemsIntegrationSpec.groovy @@ -30,8 +30,9 @@ import spock.lang.Issue /** * @author Schalk W. Cronjé. + * @author Guillaume Grossetie */ -@IgnoreIf({System.getProperty('TESTS_ARE_OFFLINE')}) +@IgnoreIf({ IntegrationSpecification.OFFLINE }) class JRubyPrepareGemsIntegrationSpec extends IntegrationSpecification { static final String DEFAULT_TASK_NAME = 'jrubyPrepare' @@ -54,7 +55,6 @@ class JRubyPrepareGemsIntegrationSpec extends IntegrationSpecification { new File(projectDir, "gems/slim-${slimVersion}").exists() } - @IgnoreIf({ IntegrationSpecification.OFFLINE }) void "Check if rack version gets resolved"() { setup: withPreamble """repositories.ruby.gems() @@ -76,7 +76,6 @@ class JRubyPrepareGemsIntegrationSpec extends IntegrationSpecification { new File(projectDir, "gems/rack-1.6.12").exists() } - @IgnoreIf({ IntegrationSpecification.OFFLINE }) void "Check if selenium-webdriver version gets resolved"() { setup: withPreamble """repositories.ruby.gems() @@ -97,7 +96,6 @@ class JRubyPrepareGemsIntegrationSpec extends IntegrationSpecification { new File(projectDir, "gems/selenium-webdriver-3.142.6").exists() } - @IgnoreIf({ IntegrationSpecification.OFFLINE }) void "Check that GEM dependencies are locked"() { setup: File lockFile = new File(projectDir, 'gradle/dependency-locks/gems.lockfile') @@ -139,7 +137,6 @@ rubygems:tilt:2.0.9 new File(projectDir, "gems/rack-1.6.10").exists() } - @IgnoreIf({ IntegrationSpecification.OFFLINE }) void "Check if prerelease gem gets resolved"() { setup: withDefaultRepositories() @@ -156,7 +153,6 @@ rubygems:tilt:2.0.9 } @Issue('https://github.com/jruby-gradle/jruby-gradle-plugin/issues/341') - @IgnoreIf({ IntegrationSpecification.OFFLINE }) void "Make an install-time gem dependency available"() { setup: withRubyGemsRepository() diff --git a/base-plugin/src/main/groovy/com/github/jrubygradle/JRubyExec.groovy b/base-plugin/src/main/groovy/com/github/jrubygradle/JRubyExec.groovy index a213c38b..c47c39b9 100644 --- a/base-plugin/src/main/groovy/com/github/jrubygradle/JRubyExec.groovy +++ b/base-plugin/src/main/groovy/com/github/jrubygradle/JRubyExec.groovy @@ -26,6 +26,7 @@ package com.github.jrubygradle import com.github.jrubygradle.api.core.JRubyAwareTask import com.github.jrubygradle.api.core.JRubyExecSpec import com.github.jrubygradle.internal.JRubyExecUtils +import groovy.transform.CompileStatic import org.gradle.api.Task import org.gradle.api.artifacts.Configuration import org.gradle.api.provider.Provider @@ -48,6 +49,7 @@ import static org.ysb33r.grolifant.api.StringUtils.stringize * @author Christian Meier * */ +@CompileStatic class JRubyExec extends JavaExec implements JRubyAwareTask, JRubyExecSpec { public static final String MAIN_CLASS = 'org.jruby.Main' @@ -65,13 +67,13 @@ class JRubyExec extends JavaExec implements JRubyAwareTask, JRubyExecSpec { super.setMain MAIN_CLASS this.jruby = extensions.create(JRubyPluginExtension.NAME, JRubyPluginExtension, this) - inputs.property 'jrubyver', { + inputs.property 'jrubyver', { JRubyPluginExtension jruby -> jruby.jrubyVersion - } + }.curry(this.jruby) - inputs.property 'gemConfiguration', { + inputs.property 'gemConfiguration', { JRubyPluginExtension jruby -> jruby.gemConfiguration - } + }.curry(this.jruby) if (GradleVersion.current() >= GradleVersion.version('4.10')) { dependsOn(project.provider({ JRubyPluginExtension jpe -> @@ -85,7 +87,7 @@ class JRubyExec extends JavaExec implements JRubyAwareTask, JRubyExecSpec { } /** Script to execute. - * @return The path to the script (or nul if not set) + * @return The path to the script (or {@code null} if not set) */ @Optional @Input @@ -184,12 +186,12 @@ class JRubyExec extends JavaExec implements JRubyAwareTask, JRubyExecSpec { /** If it is required that a JRubyExec task needs to be executed with a different version of JRuby that the * globally configured one, it can be done by setting it here. * - * @deprecated Use{@code jruby.getProposedJRubyVersion( )} instead. + * @deprecated Use {@code jruby.getJrubyVersion( )} instead. * */ @Deprecated String getJrubyVersion() { - deprecated('Use jruby.getProposedJRubyVersion() rather getProposedJRubyVersion()') + deprecated('Use jruby.getJrubyVersion() rather getJrubyVersion()') jruby.jrubyVersion } diff --git a/base-plugin/src/main/groovy/com/github/jrubygradle/JRubyPluginExtension.groovy b/base-plugin/src/main/groovy/com/github/jrubygradle/JRubyPluginExtension.groovy index e5104843..7d4605ec 100644 --- a/base-plugin/src/main/groovy/com/github/jrubygradle/JRubyPluginExtension.groovy +++ b/base-plugin/src/main/groovy/com/github/jrubygradle/JRubyPluginExtension.groovy @@ -111,7 +111,7 @@ class JRubyPluginExtension extends AbstractCombinedProjectTaskExtension { */ @Deprecated String getDefaultVersion() { - deprecated('Use getProposedJRubyVersion() rather than getDefaultVersion()') + deprecated('Use getJrubyVersion() rather than getDefaultVersion()') getJrubyVersion() } diff --git a/base-plugin/src/test/groovy/com/github/jrubygradle/JRubyExecTaskSpec.groovy b/base-plugin/src/test/groovy/com/github/jrubygradle/JRubyExecTaskSpec.groovy index ea761972..720adb96 100644 --- a/base-plugin/src/test/groovy/com/github/jrubygradle/JRubyExecTaskSpec.groovy +++ b/base-plugin/src/test/groovy/com/github/jrubygradle/JRubyExecTaskSpec.groovy @@ -72,12 +72,12 @@ class JRubyExecTaskSpec extends Specification { when: project.configure(execTask) { jruby.gemConfiguration configurationName - jruby.getProposedJRubyVersion newVersion + jruby.jrubyVersion newVersion } project.evaluate() then: - execTask.jruby.jrubyVersion != project.jruby.getProposedJRubyVersion + execTask.jruby.jrubyVersion != project.jruby.jrubyVersion and: "jrubyConfigurationName must point to this new configuration" execTask.jruby.getGemConfiguration().name == configurationName diff --git a/core-plugin/src/integTest/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerIntegrationSpec.groovy b/core-plugin/src/integTest/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerIntegrationSpec.groovy index e606ceae..00a4c66c 100644 --- a/core-plugin/src/integTest/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerIntegrationSpec.groovy +++ b/core-plugin/src/integTest/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerIntegrationSpec.groovy @@ -30,6 +30,7 @@ import org.junit.rules.TemporaryFolder import spock.lang.IgnoreIf import spock.lang.Issue import spock.lang.Specification +import spock.lang.Unroll import java.util.regex.Pattern @@ -185,7 +186,7 @@ class IvyXmlProxyServerIntegrationSpec extends Specification { build() then: - findFiles (~/^asciidoctor-pdf.*\.gem$/).size() == 3 + findFiles(~/^asciidoctor-pdf.*\.gem$/).size() == 3 } @Issue('https://github.com/jruby-gradle/jruby-gradle-plugin/issues/380') @@ -243,14 +244,16 @@ class IvyXmlProxyServerIntegrationSpec extends Specification { .build() } - private void withBuildFile(String content) { + private void withBuildFile(String content, boolean prerelease = false) { buildFile.text = """ plugins { id 'com.github.jruby-gradle.core' } repositories { - ruby.gems() + ruby.gems { + prerelease = ${prerelease} + } } configurations { diff --git a/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/GemRepositoryConfiguration.groovy b/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/GemRepositoryConfiguration.groovy new file mode 100644 index 00000000..548662bd --- /dev/null +++ b/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/GemRepositoryConfiguration.groovy @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014-2019, R. Tyler Croy , + * Schalk Cronje , Christian Meier, Lookout, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.github.jrubygradle.api.core + +import groovy.transform.CompileStatic + +/** Additional options for configuring a remote GEM repository + * + * @author Schalk W. Cronjé + * + * @since 2.0 + */ +@CompileStatic +class GemRepositoryConfiguration { + + /** Set whether pre-release GEMs should be considered. + * + */ + boolean prerelease = false +} diff --git a/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RepositoryHandlerExtension.groovy b/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RepositoryHandlerExtension.groovy index dfb4ff00..a24e48d9 100644 --- a/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RepositoryHandlerExtension.groovy +++ b/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RepositoryHandlerExtension.groovy @@ -31,8 +31,8 @@ import org.gradle.api.Action import org.gradle.api.Project import org.gradle.api.artifacts.repositories.ArtifactRepository import org.gradle.api.artifacts.repositories.IvyArtifactRepository -import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.util.GradleVersion +import org.ysb33r.grolifant.api.ClosureUtils /** Extension which can be added to {@code project.repositories}. * @@ -60,7 +60,31 @@ class RepositoryHandlerExtension { * @return Artifact repository. */ ArtifactRepository gems() { - bindRepositoryToProxyServer('https://rubygems.org'.toURI(), DEFAULT_GROUP_NAME) + bindRepositoryToProxyServer( + RUBYGEMS_URI, + DEFAULT_GROUP_NAME, + new GemRepositoryConfiguration() + ) + } + + /** Create an artifact repository which will use {@link https://rubygems.org} and + * associate group {@code rubygems} with it. + * + * @param cfg GEM repository configuration + * @return Artifact repository. + */ + ArtifactRepository gems(@DelegatesTo(GemRepositoryConfiguration) Closure cfg) { + bindRepositoryToProxyServer(RUBYGEMS_URI, DEFAULT_GROUP_NAME, cfg) + } + + /** Create an artifact repository which will use {@link https://rubygems.org} and + * associate group {@code rubygems} with it. + * + * @param cfg GEM repository configuration + * @return Artifact repository. + */ + ArtifactRepository gems(Action cfg) { + bindRepositoryToProxyServer(RUBYGEMS_URI, DEFAULT_GROUP_NAME, cfg) } /** Create an artifact repository which will use specified URI and @@ -72,7 +96,33 @@ class RepositoryHandlerExtension { * @return Artifact repository. */ ArtifactRepository gems(Object uri) { - bindRepositoryToProxyServer(project.uri(uri), DEFAULT_GROUP_NAME) + bindRepositoryToProxyServer(project.uri(uri), DEFAULT_GROUP_NAME, new GemRepositoryConfiguration()) + } + + /** Create an artifact repository which will use specified URI and + * associate group {@code rubygems} with it. + * + * @param uri URI of remote repository that serves up Rubygems. Any object convertible + * with {@code project.uri} can be provided. + * @param cfg GEM repository configuration + * + * @return Artifact repository. + */ + ArtifactRepository gems(Object uri, @DelegatesTo(GemRepositoryConfiguration) Closure cfg) { + bindRepositoryToProxyServer(project.uri(uri), DEFAULT_GROUP_NAME, cfg) + } + + /** Create an artifact repository which will use specified URI and + * associate group {@code rubygems} with it. + * + * @param uri URI of remote repository that serves up Rubygems. Any object convertible + * with {@code project.uri} can be provided. + * @param cfg GEM repository configuration + * + * @return Artifact repository. + */ + ArtifactRepository gems(Object uri, Action cfg) { + bindRepositoryToProxyServer(project.uri(uri), DEFAULT_GROUP_NAME, cfg) } /** Create an artifact repository which will use specified URI and @@ -84,37 +134,65 @@ class RepositoryHandlerExtension { * @return Artifact repository. */ ArtifactRepository gems(String group, Object uri) { - bindRepositoryToProxyServer(project.uri(uri), group) + bindRepositoryToProxyServer(project.uri(uri), group, new GemRepositoryConfiguration()) } - /** Adds the legacy Torquebox Maven proxy to {@code rubygems.org}. + /** Create an artifact repository which will use specified URI and + * associate a specified group with it. * - * Please note that this proxy is effectively unmaintained an no longer supported - * by the original creators. + * @param group Group to associate this server with. + * @param uri URI of remote repository that serves up Rubygems. Any object convertible + * with {@code project.uri} can be provided. + * @param cfg GEM repository configuration + * @return Artifact repository. + */ + ArtifactRepository gems(String group, Object uri, @DelegatesTo(GemRepositoryConfiguration) Closure cfg) { + bindRepositoryToProxyServer(project.uri(uri), group, cfg) + } + + /** Create an artifact repository which will use specified URI and + * associate a specified group with it. * - * @return Maven artifact repository + * @param group Group to associate this server with. + * @param uri URI of remote repository that serves up Rubygems. Any object convertible + * with {@code project.uri} can be provided. + * @param cfg GEM repository configuration + * @return Artifact repository. */ - MavenArtifactRepository torquebox() { - Action mvnConfigurator = new Action() { - void execute(MavenArtifactRepository mvn) { - mvn.url = 'http://rubygems-proxy.torquebox.org/releases'.toURI() - } - } - (MavenArtifactRepository) restrictToGems( - this.project.repositories.maven(mvnConfigurator), - DEFAULT_GROUP_NAME - ) + ArtifactRepository gems(String group, Object uri, Action cfg) { + bindRepositoryToProxyServer(project.uri(uri), group, cfg) } private ArtifactRepository bindRepositoryToProxyServer( URI serverUri, - String group + String group, + GemRepositoryConfiguration cfg ) { - IvyXmlProxyServer proxy = ivyProxies.registerProxy(serverUri, group) + IvyXmlProxyServer proxy = ivyProxies.registerProxy(serverUri, group, cfg) project.extensions.getByType(GemResolverStrategy).addGemGroup(group) restrictToGems(createIvyRepo(serverUri, proxy.bindAddress), group) } + private ArtifactRepository bindRepositoryToProxyServer( + URI serverUri, + String group, + @DelegatesTo(GemRepositoryConfiguration) Closure cfg + ) { + GemRepositoryConfiguration grc = new GemRepositoryConfiguration() + ClosureUtils.configureItem(grc, cfg) + bindRepositoryToProxyServer(serverUri, group, grc) + } + + private ArtifactRepository bindRepositoryToProxyServer( + URI serverUri, + String group, + Action cfg + ) { + GemRepositoryConfiguration grc = new GemRepositoryConfiguration() + cfg.execute(grc) + bindRepositoryToProxyServer(serverUri, group, grc) + } + @CompileDynamic private IvyArtifactRepository createIvyRepo(URI server, URI bindAddress) { this.project.repositories.ivy { @@ -141,4 +219,5 @@ class RepositoryHandlerExtension { private final IvyXmlGlobalProxyRegistry ivyProxies private static final boolean HAS_CONTENT_FEATURE = GradleVersion.current() >= GradleVersion.version('5.1') private static final boolean HAS_SECURE_PROTOCOL_FEATURE = GradleVersion.current() >= GradleVersion.version('6.0') + private static final URI RUBYGEMS_URI = 'https://rubygems.org'.toURI() } diff --git a/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RubyGemQueryRestApi.java b/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RubyGemQueryRestApi.java index 0ba83bd9..73cf0046 100644 --- a/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RubyGemQueryRestApi.java +++ b/core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RubyGemQueryRestApi.java @@ -33,9 +33,10 @@ * * @since 2.0. * - * @see https://guides.rubygems.org/rubygems-org-api + * @see {@link https://guides.rubygems.org/rubygems-org-api} */ public interface RubyGemQueryRestApi { + /** * Return all published versions for a specific GEM * @@ -45,6 +46,16 @@ public interface RubyGemQueryRestApi { */ List allVersions(String gemName) throws ApiException; + /** + * Return all published versions for a specific GEM + * + * @param gemName Name of GEM. + * @param includePrelease Whether pre-release versions should be included. + * @return List of versions. Can be empty if the GEM does not have any versions. Never {@code null}. + * @throws {@link ApiException} if a networking or parser error occurs. + */ + List allVersions(String gemName, boolean includePrelease) throws ApiException; + /** * Return latest published version of GEM. * @@ -54,6 +65,16 @@ public interface RubyGemQueryRestApi { */ String latestVersion(String gemName) throws ApiException; + /** + * Return latest published version of GEM. + * + * @param gemName Name of GEM. + * @param allowPrerelease Whether a prereleased version can be considered a latest version. + * @return Version of GEM + * @throws {@link ApiException} if GEM does not exist. + */ + String latestVersion(String gemName, boolean allowPrerelease) throws ApiException; + /** Returns the basic metadata for a GEM. * * @param gemName Name of GEM. diff --git a/core-plugin/src/main/groovy/com/github/jrubygradle/api/gems/GemVersion.groovy b/core-plugin/src/main/groovy/com/github/jrubygradle/api/gems/GemVersion.groovy index 286476f9..15ee9329 100644 --- a/core-plugin/src/main/groovy/com/github/jrubygradle/api/gems/GemVersion.groovy +++ b/core-plugin/src/main/groovy/com/github/jrubygradle/api/gems/GemVersion.groovy @@ -62,6 +62,7 @@ import static com.github.jrubygradle.api.gems.GemVersion.Boundary.OPEN_ENDED * * @author Christian Meier * @author Schalk W. Cronjé + * @author Guillaume Grossetie * * @since 2.0 (Moved here from base plugin where it existed since 0.4.0) */ diff --git a/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/AbstractIvyXmlProxyServer.groovy b/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/AbstractIvyXmlProxyServer.groovy index d25746c7..94d9496b 100644 --- a/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/AbstractIvyXmlProxyServer.groovy +++ b/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/AbstractIvyXmlProxyServer.groovy @@ -24,6 +24,7 @@ package com.github.jrubygradle.internal.core import com.github.jrubygradle.api.core.ApiException +import com.github.jrubygradle.api.core.GemRepositoryConfiguration import com.github.jrubygradle.api.core.IvyXmlProxyServer import com.github.jrubygradle.api.core.RubyGemQueryRestApi import com.github.jrubygradle.api.gems.GemInfo @@ -94,12 +95,19 @@ abstract class AbstractIvyXmlProxyServer implements IvyXmlProxyServer { * @param cache Root directory for local Ivy XML cache. * @param serverUri URI of remote Rubygems proxy. * @param group Group that will be associated with the Rubygems proxy. + * @param grc Additional configuration regarding remote GEM server */ - protected AbstractIvyXmlProxyServer(File cache, URI serverUri, String group) { + protected AbstractIvyXmlProxyServer( + File cache, + URI serverUri, + String group, + GemRepositoryConfiguration grc + ) { localCachePath = cache gemToIvy = new GemToIvy(serverUri) api = new DefaultRubyGemRestApi(serverUri) this.group = group + this.configuration = grc } @Synchronized @@ -170,7 +178,7 @@ abstract class AbstractIvyXmlProxyServer implements IvyXmlProxyServer { protected String getDirectoryListing(String grp, String name) throws NotFound { if (inGroups(grp)) { debug "Request to find all versions for ${grp}:${name}" - List versions = api.allVersions(name) + List versions = api.allVersions(name, configuration.prerelease) debug "Got versions ${versions.join(', ')}" revisionsAsHtmlDirectoryListing(versions) } else { @@ -185,7 +193,7 @@ abstract class AbstractIvyXmlProxyServer implements IvyXmlProxyServer { private String getGemQueryRevisionFromIvy(String gemName, String revisionPattern) { GemVersion version = gemVersionFromGradleIvyRequirement(revisionPattern) - version.highOpenEnded ? api.latestVersion(gemName) : version.high + version.highOpenEnded ? api.latestVersion(gemName, configuration.prerelease) : version.high } private void debug(String text) { @@ -203,4 +211,5 @@ abstract class AbstractIvyXmlProxyServer implements IvyXmlProxyServer { private final GemToIvy gemToIvy private final RubyGemQueryRestApi api private final String group + private final GemRepositoryConfiguration configuration } diff --git a/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/DefaultRubyGemRestApi.groovy b/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/DefaultRubyGemRestApi.groovy index f1af2eb1..e0ac5817 100644 --- a/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/DefaultRubyGemRestApi.groovy +++ b/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/DefaultRubyGemRestApi.groovy @@ -23,6 +23,7 @@ */ package com.github.jrubygradle.internal.core +import com.github.jrubygradle.api.core.ApiException import com.github.jrubygradle.api.gems.GemInfo import com.github.jrubygradle.api.gems.JarDependency import com.github.jrubygradle.internal.gems.DefaultGemDependency @@ -33,6 +34,7 @@ import groovy.transform.CompileStatic import groovyx.net.http.HttpBuilder import groovyx.net.http.HttpException import okhttp3.OkHttpClient +import org.gradle.util.GradleVersion import static com.github.jrubygradle.internal.gems.GemToIvy.JAVA_PLATFORM import static groovyx.net.http.ContentTypes.JSON @@ -51,7 +53,7 @@ class DefaultRubyGemRestApi implements com.github.jrubygradle.api.core.RubyGemQu /** Creates a client from a URI * - * @param serverUri URI as a String. ONly the scheme plus host + * @param serverUri URI as a String. Only the scheme plus host * parts should be provided. */ DefaultRubyGemRestApi(final String serverUri) { @@ -74,12 +76,25 @@ class DefaultRubyGemRestApi implements com.github.jrubygradle.api.core.RubyGemQu * @throw {@link com.github.jrubygradle.api.core.ApiException} if a networking error occurred. */ @Override - @SuppressWarnings('CatchThrowable') List allVersions(String gemName) { + allVersions(gemName, false) + } + + /** + * Return all published versions for a specific GEM + * + * @param gemName Name of GEM. + * @param includePrelease Whether pre-release versions should be included. + * @return List of versions. Can be empty if the GEM does not have any versions. Never {@code null}. + * @throws {@link ApiException} if a networking or parser error occurs. + */ + @Override + @SuppressWarnings('CatchThrowable') + List allVersions(String gemName, boolean includePrelease) { try { - extractVersions(getData(V1, "versions/${gemName}")) + extractVersions(getData(V1, "versions/${gemName}"), includePrelease) } catch (Throwable e) { - throw new com.github.jrubygradle.api.core.ApiException("Count not retrieve list of versions for ${gemName}", e) + throw new ApiException("Count not retrieve list of versions for ${gemName}", e) } } @@ -90,16 +105,33 @@ class DefaultRubyGemRestApi implements com.github.jrubygradle.api.core.RubyGemQu * @throw {@link com.github.jrubygradle.api.core.ApiException} if a networking error occurred or the GEM does not exist. */ @Override - @SuppressWarnings('CatchThrowable') String latestVersion(String gemName) { + latestVersion(gemName, false) + } + + /** + * Return latest published version of GEM. + * + * @param gemName Name of GEM. + * @param allowPrerelease Whether a prereleased version can be considered a latest version. + * @return Version of GEM + * @throws {@link ApiException} if GEM does not exist. + */ + @Override + @SuppressWarnings('CatchThrowable') + String latestVersion(String gemName, boolean allowPrerelease) { String version try { - version = extractVersion(getData(V1, "versions/${gemName}/latest")) + if (allowPrerelease) { + version = allVersions(gemName, allowPrerelease).collect { GradleVersion.version(it) }.max().toString() + } else { + version = extractVersion(getData(V1, "versions/${gemName}/latest")) + } } catch (Throwable e) { - throw new com.github.jrubygradle.api.core.ApiException("Failed to retrieve latest version of ${gemName}", e) + throw new ApiException("Failed to retrieve latest version of ${gemName}", e) } if (version == 'unknown') { - throw new com.github.jrubygradle.api.core.ApiException("Cound not retrieve latest version of ${gemName}. Maybe it does not exist") + throw new ApiException("Cound not retrieve latest version of ${gemName}. Maybe it does not exist") } version } @@ -117,9 +149,9 @@ class DefaultRubyGemRestApi implements com.github.jrubygradle.api.core.RubyGemQu try { extractMetadata(getData(V2, "rubygems/${gemName}/versions/${gemVersion}")) } catch (HttpException e) { - throw new com.github.jrubygradle.api.core.ApiException(":${gemName}:${gemVersion} not found", e) + throw new ApiException(":${gemName}:${gemVersion} not found", e) } catch (Throwable e) { - throw new com.github.jrubygradle.api.core.ApiException("Could not obtain information for :${gemName}:${gemVersion}.", e) + throw new ApiException("Could not obtain information for :${gemName}:${gemVersion}.", e) } } @@ -148,8 +180,12 @@ class DefaultRubyGemRestApi implements com.github.jrubygradle.api.core.RubyGemQu } @CompileDynamic - private List extractVersions(Object jsonParser) { - jsonParser*.number + private List extractVersions(Object jsonParser, boolean includePrerelease) { + if (includePrerelease) { + jsonParser*.number + } else { + jsonParser.findAll { !it.prerelease }*.number + } } @CompileDynamic diff --git a/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/IvyXmlGlobalProxyRegistry.groovy b/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/IvyXmlGlobalProxyRegistry.groovy index 40e05b49..8077d48f 100644 --- a/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/IvyXmlGlobalProxyRegistry.groovy +++ b/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/IvyXmlGlobalProxyRegistry.groovy @@ -23,6 +23,7 @@ */ package com.github.jrubygradle.internal.core +import com.github.jrubygradle.api.core.GemRepositoryConfiguration import groovy.transform.CompileStatic import org.gradle.api.Project @@ -54,8 +55,17 @@ class IvyXmlGlobalProxyRegistry { * @param group Group name for GEMs that will be fected from the remote. * @return Access to a proxy sever. If the server does not exist it will be created. */ - com.github.jrubygradle.api.core.IvyXmlProxyServer registerProxy(URI remoteURI, String group) { - com.github.jrubygradle.api.core.IvyXmlProxyServer proxy = getOrCreateServer(remoteURI, group, new File(rootCacheDir, uriHash(remoteURI))) + com.github.jrubygradle.api.core.IvyXmlProxyServer registerProxy( + URI remoteURI, + String group, + GemRepositoryConfiguration grc + ) { + com.github.jrubygradle.api.core.IvyXmlProxyServer proxy = getOrCreateServer( + remoteURI, + group, + new File(rootCacheDir, uriHash(remoteURI)), + grc + ) proxy.refreshDependencies = refresh proxy } @@ -68,10 +78,11 @@ class IvyXmlGlobalProxyRegistry { static private com.github.jrubygradle.api.core.IvyXmlProxyServer getOrCreateServer( URI uri, String group, - File cacheDir + File cacheDir, + GemRepositoryConfiguration grc ) { SERVER_MAP.computeIfAbsent(uri, { - com.github.jrubygradle.api.core.IvyXmlProxyServer server = createProxyServer(uri, group, cacheDir) + com.github.jrubygradle.api.core.IvyXmlProxyServer server = createProxyServer(uri, group, cacheDir, grc) server.run() server }) @@ -80,9 +91,10 @@ class IvyXmlGlobalProxyRegistry { static private com.github.jrubygradle.api.core.IvyXmlProxyServer createProxyServer( URI uri, String group, - File cacheDir + File cacheDir, + GemRepositoryConfiguration grc ) { - new IvyXmlRatpackProxyServer(cacheDir, uri, group) + new IvyXmlRatpackProxyServer(cacheDir, uri, group, grc) } static private final ConcurrentMap SERVER_MAP = new ConcurrentHashMap<>() diff --git a/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/IvyXmlRatpackProxyServer.java b/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/IvyXmlRatpackProxyServer.java index c4204dbf..150b312f 100644 --- a/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/IvyXmlRatpackProxyServer.java +++ b/core-plugin/src/main/groovy/com/github/jrubygradle/internal/core/IvyXmlRatpackProxyServer.java @@ -23,6 +23,7 @@ */ package com.github.jrubygradle.internal.core; +import com.github.jrubygradle.api.core.GemRepositoryConfiguration; import ratpack.server.RatpackServer; import java.io.File; @@ -46,9 +47,15 @@ public class IvyXmlRatpackProxyServer extends AbstractIvyXmlProxyServer { * @param cache Root directory for local Ivy XML cache. * @param serverUri URI of remote Rubygems proxy. * @param group Group that will be associated with the Rubygems proxy. + * @param grc Additional configuration regarding remote GEM server */ - public IvyXmlRatpackProxyServer(File cache, URI serverUri, String group) { - super(cache, serverUri, group); + public IvyXmlRatpackProxyServer( + File cache, + URI serverUri, + String group, + GemRepositoryConfiguration grc + ) { + super(cache, serverUri, group, grc); } /** diff --git a/core-plugin/src/test/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerSpec.groovy b/core-plugin/src/test/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerSpec.groovy index 449ffc1b..9ab04fd8 100644 --- a/core-plugin/src/test/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerSpec.groovy +++ b/core-plugin/src/test/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerSpec.groovy @@ -42,7 +42,12 @@ class IvyXmlProxyServerSpec extends Specification { TemporaryFolder projectRoot void setup() { - server = new IvyXmlRatpackProxyServer(projectRoot.root, 'https://rubygems.org'.toURI(), 'rubygems') + server = new IvyXmlRatpackProxyServer( + projectRoot.root, + 'https://rubygems.org'.toURI(), + 'rubygems', + new GemRepositoryConfiguration() + ) server.run() httpBuilder = OkHttpBuilder.configure { request.uri = server.bindAddress diff --git a/gradle.properties b/gradle.properties index 29bf97a0..f0bbf264 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=2.0.0-alpha.6 +version=2.0.0-alpha.7 group=com.github.jruby-gradle copyrightYear=2014-2019