Skip to content

Commit 53d8d5b

Browse files
committed
Allow for GEMs to be resolved using standard GRadle resolution rules (#325)
For specific cases it might be better to use the standard Gradle resolution strategies rather than the bundler-like strategy supplied via GemVersionResolver. To accomplish this a script author may configure specific configurations and modules (or modules+revisions) to be excluded.
1 parent 42d3beb commit 53d8d5b

File tree

5 files changed

+172
-14
lines changed

5 files changed

+172
-14
lines changed

core-plugin/src/integTest/groovy/com/github/jrubygradle/api/core/IvyXmlProxyServerIntegrationSpec.groovy

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,27 @@ class IvyXmlProxyServerIntegrationSpec extends Specification {
167167
findFiles ~/^jruby-openssl-0.10.2-java.gem$/
168168
}
169169

170+
@Issue('https://github.com/jruby-gradle/jruby-gradle-plugin/issues/325')
171+
void 'Resolve a prerelease GEM by excluding from GEM strategy'() {
172+
setup:
173+
withBuildFile '''
174+
gemResolverStrategy {
175+
excludeModule ~/^asciidoctor-pdf$/, ~/.+(alpha|beta).*/
176+
}
177+
178+
dependencies {
179+
something 'rubygems:asciidoctor-pdf-cjk-kai_gen_gothic:0.1.1'
180+
something 'rubygems:asciidoctor-pdf:1.5.0.alpha.8'
181+
}
182+
'''
183+
184+
when:
185+
build()
186+
187+
then:
188+
findFiles (~/^asciidoctor-pdf.*\.gem$/).size() == 3
189+
}
190+
170191
private List<File> findFiles(Pattern pat) {
171192
new File(projectDir, 'build/something').listFiles(new FilenameFilter() {
172193
@Override

core-plugin/src/main/groovy/com/github/jrubygradle/api/core/JRubyCorePlugin.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*/
2424
package com.github.jrubygradle.api.core
2525

26-
import com.github.jrubygradle.api.gems.GemGroups
26+
import com.github.jrubygradle.api.gems.GemResolverStrategy
2727
import com.github.jrubygradle.internal.gems.GemVersionResolver
2828
import groovy.transform.CompileStatic
2929
import org.gradle.api.Plugin
@@ -42,7 +42,7 @@ import org.gradle.api.plugins.ExtensionAware
4242
class JRubyCorePlugin implements Plugin<Project> {
4343
@Override
4444
void apply(Project project) {
45-
GemGroups gemGroups = project.extensions.create(GemGroups.NAME, GemGroups)
45+
GemResolverStrategy gemGroups = project.extensions.create(GemResolverStrategy.NAME, GemResolverStrategy)
4646

4747
((ExtensionAware) project.repositories).extensions.create(
4848
RepositoryHandlerExtension.NAME,

core-plugin/src/main/groovy/com/github/jrubygradle/api/core/RepositoryHandlerExtension.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*/
2424
package com.github.jrubygradle.api.core
2525

26-
import com.github.jrubygradle.api.gems.GemGroups
26+
import com.github.jrubygradle.api.gems.GemResolverStrategy
2727
import com.github.jrubygradle.internal.core.IvyXmlGlobalProxyRegistry
2828
import groovy.transform.CompileDynamic
2929
import groovy.transform.CompileStatic
@@ -111,7 +111,7 @@ class RepositoryHandlerExtension {
111111
String group
112112
) {
113113
IvyXmlProxyServer proxy = ivyProxies.registerProxy(serverUri, group)
114-
project.extensions.getByType(GemGroups).addGemGroup(group)
114+
project.extensions.getByType(GemResolverStrategy).addGemGroup(group)
115115
restrictToGems(createIvyRepo(serverUri, proxy.bindAddress), group)
116116
}
117117

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* Copyright (c) 2014-2019, R. Tyler Croy <[email protected]>,
3+
* Schalk Cronje <[email protected]>, Christian Meier, Lookout, Inc.
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining
6+
* a copy of this software and associated documentation files (the
7+
* "Software"), to deal in the Software without restriction, including
8+
* without limitation the rights to use, copy, modify, merge, publish,
9+
* distribute, sublicense, and/or sell copies of the Software, and to
10+
* permit persons to whom the Software is furnished to do so, subject to
11+
* the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+
*/
24+
package com.github.jrubygradle.api.gems
25+
26+
import com.github.jrubygradle.api.core.RepositoryHandlerExtension
27+
import groovy.transform.CompileStatic
28+
import groovy.transform.EqualsAndHashCode
29+
import org.gradle.api.artifacts.Configuration
30+
import org.gradle.api.artifacts.ModuleVersionSelector
31+
32+
import java.util.regex.Pattern
33+
34+
/** Defines groups which contains GEMs and controls GEM resolving rules.
35+
*
36+
* @author Schalk W. Cronjé
37+
*
38+
* @since 2.0
39+
*/
40+
@CompileStatic
41+
class GemResolverStrategy {
42+
43+
public static final String NAME = 'gemResolverStrategy'
44+
45+
/** Is this group/organisation a GEM group ?
46+
*
47+
* @param groupName Name of group/organisation.
48+
* @return {@code true} is group is a GEM group.
49+
*/
50+
boolean isGemGroup(final String groupName) {
51+
groups.contains(groupName)
52+
}
53+
54+
/** Add a new group for GEMs.
55+
*
56+
* @param groupName Name of group to add.
57+
*/
58+
void addGemGroup(final String groupName) {
59+
groups.add(groupName)
60+
}
61+
62+
/** Exclude a configuration from being resolved using the GEM
63+
* version resolver strategy.
64+
*
65+
* @param configs Configurations to be excluded
66+
*/
67+
void excludeConfigurations(Configuration... configs) {
68+
this.excludedConfigurations.addAll(configs*.name)
69+
}
70+
71+
/** Exclude a configuration from being resolved using the GEM
72+
* version resolver strategy.
73+
*
74+
* @param configs Configurations to be excluded
75+
*/
76+
void excludeConfigurations(String... configs) {
77+
this.excludedConfigurations.addAll(configs)
78+
}
79+
80+
/** Exclude a module from being resolved using the GEM version resolver
81+
* strategy.
82+
*
83+
* @param name Module name. Never {@code null}.
84+
* @param version Version. Can be {@code null}.
85+
*/
86+
void excludeModule(String name, String version = null) {
87+
excludedModules.add(new Matcher(
88+
module: Pattern.compile(Pattern.quote(name)),
89+
version: version ? Pattern.compile(Pattern.quote(version)) : null
90+
))
91+
}
92+
93+
/** Exclude a module from being resolved using the GEM version resolver
94+
* strategy.
95+
*
96+
* @param namePattern Pattern for name. Never {@code null}.
97+
* @param versionPattern Pattern for version. Can be {@code null}
98+
*/
99+
void excludeModule(Pattern namePattern, Pattern versionPattern = null) {
100+
excludedModules.add(new Matcher(module: namePattern, version: versionPattern))
101+
}
102+
103+
/** Whether the GEM version resolving strategy should be applied for a specific module.
104+
*
105+
* In most cases this will alsways be {@code true} unless a specific rule excludes it.
106+
*
107+
* @param mvs Module version selector
108+
* @return Whether the Bundler-like version selector atregty may be applied
109+
*/
110+
boolean useGemVersionResolver(ModuleVersionSelector mvs) {
111+
isGemGroup(mvs.group) && excludedModules.find { it.match(mvs.name, mvs.version) }
112+
}
113+
114+
/** Whether the GEM version resolving strategy should be applied to a specific configuration.
115+
*
116+
* In most cases this will always be {@code true} unless a specific rule excludes it.
117+
*
118+
* @param configurationName Name fo configuration
119+
* @return Whether the Bundler-like version selector strategy may be applied
120+
*/
121+
boolean useGemVersionResolver(String configurationName) {
122+
configurationName in excludedConfigurations
123+
}
124+
125+
@EqualsAndHashCode
126+
private class Matcher {
127+
Pattern module
128+
Pattern version
129+
130+
boolean match(String name, String ver) {
131+
name =~ module && (this.version == null || ver ==~ this.version)
132+
}
133+
}
134+
135+
private final Set<Matcher> excludedModules = [].toSet()
136+
private final Set<String> excludedConfigurations = [].toSet()
137+
private final Set<String> groups = [RepositoryHandlerExtension.DEFAULT_GROUP_NAME].toSet()
138+
}

core-plugin/src/main/groovy/com/github/jrubygradle/internal/gems/GemVersionResolver.groovy

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
*/
2424
package com.github.jrubygradle.internal.gems
2525

26+
import com.github.jrubygradle.api.gems.GemResolverStrategy
2627
import com.github.jrubygradle.api.gems.GemVersion
27-
import com.github.jrubygradle.api.gems.GemGroups
2828
import groovy.transform.CompileDynamic
2929
import groovy.transform.PackageScope
3030
import org.gradle.api.Action
@@ -46,17 +46,17 @@ import static com.github.jrubygradle.api.gems.GemVersion.gemVersionFromGradleIvy
4646
* @since 2.0
4747
*/
4848
class GemVersionResolver {
49-
static void addGemResolver(Configuration cfg, GemGroups gemGroups, GemVersionResolver versionResolver) {
49+
static void addGemResolver(Configuration cfg, GemResolverStrategy gemGroups, GemVersionResolver versionResolver) {
5050
Action<DependencyResolveDetails> gemResolveRule = {
51-
GemGroups gemgrp, GemVersionResolver resolver, DependencyResolveDetails drd ->
52-
if (gemgrp.isGemGroup(drd.requested.group)) {
51+
String configName, GemResolverStrategy gemgrp, GemVersionResolver resolver, DependencyResolveDetails drd ->
52+
if (gemgrp.useGemVersionResolver(configName) && gemgrp.useGemVersionResolver(drd.requested)) {
5353
resolver.resolve(drd)
5454
}
55-
}.curry(gemGroups, versionResolver)
55+
}.curry(cfg.name, gemGroups, versionResolver)
5656
cfg.resolutionStrategy.eachDependency(gemResolveRule)
5757
}
5858

59-
GemVersionResolver(GemGroups gemGroups, Logger logger, Configuration configuration) {
59+
GemVersionResolver(GemResolverStrategy gemGroups, Logger logger, Configuration configuration) {
6060
this.gemGroups = gemGroups
6161
this.logger = logger
6262
this.configuration = configuration
@@ -83,8 +83,7 @@ class GemVersionResolver {
8383
logger.debug("${configuration} resolved ${next}")
8484

8585
details.useVersion(next.toString())
86-
withReason(details,"Selected by GEM Version Resolver")
87-
86+
withReason(details, 'Selected by GEM Version Resolver')
8887
} else {
8988
GemVersion next = gemVersionFromGradleIvyRequirement(details.requested.version)
9089
versions[details.requested.name] = next
@@ -119,7 +118,7 @@ class GemVersionResolver {
119118

120119
@CompileDynamic
121120
void withReason(DependencyResolveDetails drd, String reason) {
122-
if(HAS_BECAUSE_PROPERTY) {
121+
if (HAS_BECAUSE_PROPERTY) {
123122
drd.because(reason)
124123
}
125124
}
@@ -132,5 +131,5 @@ class GemVersionResolver {
132131
private final Map versions = [:]
133132
private final Configuration configuration
134133
private final Logger logger
135-
private final GemGroups gemGroups
134+
private final GemResolverStrategy gemGroups
136135
}

0 commit comments

Comments
 (0)