diff --git a/src/main/groovy/nebula/plugin/release/NetflixOssStrategies.groovy b/src/main/groovy/nebula/plugin/release/NetflixOssStrategies.groovy index 164b25e..2f841d0 100644 --- a/src/main/groovy/nebula/plugin/release/NetflixOssStrategies.groovy +++ b/src/main/groovy/nebula/plugin/release/NetflixOssStrategies.groovy @@ -131,12 +131,12 @@ class NetflixOssStrategies { return { state -> def nebulaReleaseExtension = project.extensions.findByType(ReleaseExtension) boolean needsBranchMetadata = true - nebulaReleaseExtension.releaseBranchPatterns.each { + nebulaReleaseExtension.releaseBranchPatterns.get().each { if (state.currentBranch.name =~ it) { needsBranchMetadata = false } } - String shortenedBranch = (state.currentBranch.name =~ nebulaReleaseExtension.shortenedBranchPattern)[0][1] + String shortenedBranch = (state.currentBranch.name =~ nebulaReleaseExtension.shortenedBranchPattern.get())[0][1] shortenedBranch = shortenedBranch.replaceAll(/[_\/-]/, '.') def metadata = needsBranchMetadata ? "${shortenedBranch}.${state.currentHead.abbreviatedId}" : state.currentHead.abbreviatedId state.copyWith(inferredBuildMetadata: metadata) diff --git a/src/main/groovy/nebula/plugin/release/ReleaseCheck.groovy b/src/main/groovy/nebula/plugin/release/ReleaseCheck.groovy index ef54ed3..d07ffa3 100644 --- a/src/main/groovy/nebula/plugin/release/ReleaseCheck.groovy +++ b/src/main/groovy/nebula/plugin/release/ReleaseCheck.groovy @@ -17,43 +17,51 @@ package nebula.plugin.release import org.gradle.api.DefaultTask import org.gradle.api.GradleException +import org.gradle.api.provider.Property import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Nested import org.gradle.api.tasks.TaskAction import org.gradle.work.DisableCachingByDefault @DisableCachingByDefault -class ReleaseCheck extends DefaultTask { +abstract class ReleaseCheck extends DefaultTask { @Input - String branchName - @Input - ReleaseExtension patterns + abstract Property getBranchName() + + @Nested + abstract Property getPatterns() + @Input - boolean isSnapshotRelease + abstract Property getIsSnapshotRelease() @TaskAction void check() { - if (patterns.allowReleaseFromDetached) { + ReleaseExtension patternsValue = patterns.get() + String branch = branchName.get() + boolean isSnapshot = isSnapshotRelease.get() + + if (patternsValue.allowReleaseFromDetached.get()) { return } - boolean includeMatch = patterns.releaseBranchPatterns.isEmpty() + boolean includeMatch = patternsValue.releaseBranchPatterns.get().isEmpty() - patterns.releaseBranchPatterns.each { String pattern -> - if (getBranchName() ==~ pattern) includeMatch = true + patternsValue.releaseBranchPatterns.get().each { String pattern -> + if (branch ==~ pattern) includeMatch = true } boolean excludeMatch = false - patterns.excludeBranchPatterns.each { String pattern -> - if (getBranchName() ==~ pattern) excludeMatch = true + patternsValue.excludeBranchPatterns.get().each { String pattern -> + if (branch ==~ pattern) excludeMatch = true } - if (!includeMatch && !isSnapshotRelease) { - String message = "Branch ${getBranchName()} does not match one of the included patterns: ${patterns.releaseBranchPatterns}" + if (!includeMatch && !isSnapshot) { + String message = "Branch ${branch} does not match one of the included patterns: ${patternsValue.releaseBranchPatterns.get()}" logger.error(message) throw new GradleException(message) } if (excludeMatch) { - String message = "Branch ${getBranchName()} matched an excluded pattern: ${patterns.excludeBranchPatterns}" + String message = "Branch ${branch} matched an excluded pattern: ${patternsValue.excludeBranchPatterns.get()}" logger.error(message) throw new GradleException(message) } diff --git a/src/main/groovy/nebula/plugin/release/ReleaseExtension.groovy b/src/main/groovy/nebula/plugin/release/ReleaseExtension.groovy index 6dc7d95..6e0b41f 100644 --- a/src/main/groovy/nebula/plugin/release/ReleaseExtension.groovy +++ b/src/main/groovy/nebula/plugin/release/ReleaseExtension.groovy @@ -15,20 +15,42 @@ */ package nebula.plugin.release -class ReleaseExtension { - Set releaseBranchPatterns = [/master/, /HEAD/, /main/, /(release(-|\/))?\d+(\.\d+)?\.x/, /v?\d+\.\d+\.\d+/] as Set - Set excludeBranchPatterns = [] as Set +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.provider.SetProperty +import org.gradle.api.tasks.Input + +import javax.inject.Inject + +abstract class ReleaseExtension { + @Input + abstract SetProperty getReleaseBranchPatterns() + + @Input + abstract SetProperty getExcludeBranchPatterns() /** * This should be a regex pattern with one(1) capture group. By default shortens the typical * {bugfix|feature|hotfix|release}/branch-name to branch-name. The prefix is optional and a * dash may be used instead of the forward slash. */ - String shortenedBranchPattern = /(?:(?:bugfix|feature|hotfix|release)(?:-|\/))?(.+)/ + @Input + abstract Property getShortenedBranchPattern() - Boolean allowReleaseFromDetached = false + @Input + abstract Property getAllowReleaseFromDetached() - Boolean checkRemoteBranchOnRelease = false + @Input + abstract Property getCheckRemoteBranchOnRelease() + + @Inject + ReleaseExtension(ObjectFactory objects) { + releaseBranchPatterns.convention([/master/, /HEAD/, /main/, /(release(-|\/))?\d+(\.\d+)?\.x/, /v?\d+\.\d+\.\d+/] as Set) + excludeBranchPatterns.convention([] as Set) + shortenedBranchPattern.convention(/(?:(?:bugfix|feature|hotfix|release)(?:-|\/))?(.+)/) + allowReleaseFromDetached.convention(false) + checkRemoteBranchOnRelease.convention(false) + } void addReleaseBranchPattern(String pattern) { releaseBranchPatterns.add(pattern) diff --git a/src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy b/src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy index bc26de0..086a216 100644 --- a/src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy +++ b/src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy @@ -30,6 +30,7 @@ import org.gradle.api.execution.TaskExecutionGraph import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging import org.gradle.api.plugins.JavaPlugin +import org.gradle.api.provider.Provider import org.gradle.api.provider.ProviderFactory import org.gradle.api.publish.ivy.IvyPublication import org.gradle.api.publish.ivy.plugins.IvyPublishPlugin @@ -51,16 +52,17 @@ class ReleasePlugin implements Plugin { static Logger logger = Logging.getLogger(ReleasePlugin) static final String GROUP = 'Nebula Release' - private final GitBuildService gitBuildService + private final Provider gitBuildService private final File gitRoot @CompileDynamic @Inject ReleasePlugin(Project project, ExecOperations execOperations, ProviderFactory providerFactory) { this.gitRoot = project.hasProperty('git.root') ? project.file(project.property('git.root')) : project.rootProject.projectDir + this.gitBuildService = project.getGradle().getSharedServices().registerIfAbsent("gitBuildService", GitBuildService.class, spec -> { spec.getParameters().getGitRootDir().set(gitRoot) - }).get() + }) } @CompileDynamic @@ -68,7 +70,7 @@ class ReleasePlugin implements Plugin { void apply(Project project) { this.project = project - boolean isGitRepo = gitBuildService.isGitRepo() + boolean isGitRepo = gitBuildService.get().isGitRepo() if(!isGitRepo) { this.project.version = '0.1.0-dev.0.uncommitted' logger.warn("Git repository not found at $gitRoot -- nebula-release tasks will not be available. Use the git.root Gradle property to specify a different directory.") @@ -79,7 +81,7 @@ class ReleasePlugin implements Plugin { // Verify user git config only when using release tags and 'release.useLastTag' property is not used boolean shouldVerifyUserGitConfig = isReleaseTaskThatRequiresTagging(project.gradle.startParameter.taskNames) && !isUsingLatestTag(project) if(shouldVerifyUserGitConfig) { - gitBuildService.verifyUserGitConfig() + gitBuildService.get().verifyUserGitConfig() } checkForBadBranchNames() @@ -89,10 +91,10 @@ class ReleasePlugin implements Plugin { ReleasePluginExtension releaseExtension = project.extensions.findByType(ReleasePluginExtension) SemVerStrategy defaultStrategy = replaceDevSnapshots ? NetflixOssStrategies.IMMUTABLE_SNAPSHOT(project) : NetflixOssStrategies.DEVELOPMENT(project) - def propertyBasedStrategy - if (project.hasProperty(DEFAULT_VERSIONING_STRATEGY)) { - propertyBasedStrategy = getPropertyBasedVersioningStrategy() - } + + def propertyBasedStrategy = project.providers.gradleProperty(DEFAULT_VERSIONING_STRATEGY) + .map { clazzName -> getPropertyBasedVersioningStrategy(clazzName) } + .getOrNull() releaseExtension.with { versionStrategy new OverrideStrategies.NoCommitStrategy() versionStrategy new OverrideStrategies.ReleaseLastTagStrategy(project) @@ -126,8 +128,8 @@ class ReleasePlugin implements Plugin { TaskProvider releaseCheck = project.tasks.register(RELEASE_CHECK_TASK_NAME, ReleaseCheck) { it.group = GROUP - it.branchName = gitBuildService.currentBranch - it.patterns = nebulaReleaseExtension + it.branchName.set(gitBuildService.map { it.currentBranch }) + it.patterns.set(nebulaReleaseExtension) } TaskProvider postReleaseTask = project.tasks.register(POST_RELEASE_TASK_NAME) { @@ -135,47 +137,57 @@ class ReleasePlugin implements Plugin { it.dependsOn project.tasks.named('release') } - TaskProvider snapshotSetupTask = project.tasks.register(SNAPSHOT_SETUP_TASK_NAME) - TaskProvider immutableSnapshotSetupTask = project.tasks.register(IMMUTABLE_SNAPSHOT_SETUP_TASK_NAME) - TaskProvider devSnapshotSetupTask = project.tasks.register(DEV_SNAPSHOT_SETUP_TASK_NAME) + TaskProvider snapshotSetupTask = project.tasks.register(SNAPSHOT_SETUP_TASK_NAME) { + it.group = GROUP + it.dependsOn releaseCheck + } + TaskProvider immutableSnapshotSetupTask = project.tasks.register(IMMUTABLE_SNAPSHOT_SETUP_TASK_NAME) { + it.group = GROUP + it.dependsOn releaseCheck + } + TaskProvider devSnapshotSetupTask = project.tasks.register(DEV_SNAPSHOT_SETUP_TASK_NAME) { + it.group = GROUP + it.dependsOn releaseCheck + } TaskProvider candidateSetupTask = project.tasks.register(CANDIDATE_SETUP_TASK_NAME) { + it.group = GROUP + it.dependsOn releaseCheck it.configure { project.allprojects.each { it.status = 'candidate' } } } TaskProvider finalSetupTask = project.tasks.register(FINAL_SETUP_TASK_NAME) { + it.group = GROUP + it.dependsOn releaseCheck it.configure { project.allprojects.each { it.status = 'release' } } } - [snapshotSetupTask, immutableSnapshotSetupTask, devSnapshotSetupTask, candidateSetupTask, finalSetupTask].each { - it.configure { - it.group = GROUP - it.dependsOn releaseCheck - } - } TaskProvider snapshotTask = project.tasks.register(SNAPSHOT_TASK_NAME) { + it.group = GROUP it.dependsOn snapshotSetupTask + it.dependsOn postReleaseTask } TaskProvider immutableSnapshotTask = project.tasks.register(IMMUTABLE_SNAPSHOT_TASK_NAME) { + it.group = GROUP it.dependsOn immutableSnapshotSetupTask + it.dependsOn postReleaseTask } TaskProvider devSnapshotTask = project.tasks.register(DEV_SNAPSHOT_TASK_NAME) { + it.group = GROUP it.dependsOn devSnapshotSetupTask + it.dependsOn postReleaseTask } TaskProvider candidateTask = project.tasks.register(CANDIDATE_TASK_NAME) { + it.group = GROUP it.dependsOn candidateSetupTask + it.dependsOn postReleaseTask } TaskProvider finalTask = project.tasks.register(FINAL_TASK_NAME) { + it.group = GROUP it.dependsOn finalSetupTask - } - - [snapshotTask, immutableSnapshotTask, devSnapshotTask, candidateTask, finalTask].each { - it.configure { - it.group = GROUP - it.dependsOn postReleaseTask - } + it.dependsOn postReleaseTask } List cliTasks = project.gradle.startParameter.taskNames @@ -187,7 +199,7 @@ class ReleasePlugin implements Plugin { } project.gradle.taskGraph.whenReady { TaskExecutionGraph g -> - if (!nebulaReleaseExtension.checkRemoteBranchOnRelease) { + if (!nebulaReleaseExtension.checkRemoteBranchOnRelease.get()) { removePrepLogic(project) } } @@ -220,8 +232,7 @@ class ReleasePlugin implements Plugin { configureArtifactoryGradlePluginIfPresent() } - private Object getPropertyBasedVersioningStrategy() { - String clazzName = project.property(DEFAULT_VERSIONING_STRATEGY).toString() + private Object getPropertyBasedVersioningStrategy(String clazzName) { try { return Class.forName(clazzName).getDeclaredConstructor().newInstance() } catch (ClassNotFoundException e) { @@ -260,7 +271,7 @@ class ReleasePlugin implements Plugin { def isSnapshotRelease = hasSnapshot || hasDevSnapshot || hasImmutableSnapshot || (!hasCandidate && !hasFinal) releaseCheck.configure { - it.isSnapshotRelease = isSnapshotRelease + it.isSnapshotRelease.set(isSnapshotRelease) } if (hasFinal) { @@ -286,7 +297,7 @@ class ReleasePlugin implements Plugin { private void checkStateForStage(boolean isSnapshotRelease) { if (!isSnapshotRelease) { - String status = gitBuildService.status + String status = gitBuildService.get().status if (!status.empty) { String message = new ErrorMessageFormatter().format(status) throw new GradleException(message) @@ -295,8 +306,12 @@ class ReleasePlugin implements Plugin { } private boolean shouldSkipGitChecks() { - def disableGit = project.hasProperty(DISABLE_GIT_CHECKS) && project.property(DISABLE_GIT_CHECKS) as Boolean - def travis = project.hasProperty('release.travisci') && project.property('release.travisci').toString().toBoolean() + def disableGit = project.providers.gradleProperty(DISABLE_GIT_CHECKS) + .map { it.toBoolean() } + .getOrElse(false) + def travis = project.providers.gradleProperty('release.travisci') + .map { it.toBoolean() } + .getOrElse(false) disableGit || travis } @@ -304,7 +319,7 @@ class ReleasePlugin implements Plugin { void setupStatus(String status) { project.plugins.withType(IvyPublishPlugin) { project.publishing { - publications.withType(IvyPublication) { + publications.withType(IvyPublication).configureEach { descriptor.status = status } } @@ -370,7 +385,7 @@ class ReleasePlugin implements Plugin { } void checkForBadBranchNames() { - String currentBranch = gitBuildService.currentBranch + String currentBranch = gitBuildService.get().currentBranch if (!currentBranch) { return } diff --git a/src/main/groovy/nebula/plugin/release/git/GitBuildService.groovy b/src/main/groovy/nebula/plugin/release/git/GitBuildService.groovy index e7cabf7..6ad7920 100644 --- a/src/main/groovy/nebula/plugin/release/git/GitBuildService.groovy +++ b/src/main/groovy/nebula/plugin/release/git/GitBuildService.groovy @@ -36,30 +36,30 @@ abstract class GitBuildService implements BuildService { DirectoryProperty getGitRootDir() } - private final boolean isGitRepo - private final boolean hasCommit - private final String currentBranch - private final String head - private final String status - private final boolean isCleanStatus + private final Provider isGitRepo + private final Provider hasCommit + private final Provider currentBranch + private final Provider head + private final Provider status + private final Provider isCleanStatus private final File gitRootDir private final ProviderFactory providerFactory - private final List headTags - private final Integer commitCountForHead + private final Provider> headTags + private final Provider commitCountForHead private static final Logger LOGGER = LoggerFactory.getLogger(GitBuildService.class) @Inject GitBuildService(ProviderFactory providers) { this.gitRootDir = getParameters().gitRootDir.get().asFile this.providerFactory = providers - this.isGitRepo = detectIsGitRepo() - this.currentBranch = detectCurrentBranch() - this.status = determineStatus() - this.hasCommit = determineHasCommit() - this.isCleanStatus = determineIsCleanStatus() - this.head = determineHead() - this.headTags = determineHeadTags() - this.commitCountForHead = determineCommitCountForHead() + this.isGitRepo = providers.provider { detectIsGitRepo() } + this.currentBranch = providers.provider { detectCurrentBranch() } + this.status = providers.provider { determineStatus() } + this.hasCommit = providers.provider { determineHasCommit() } + this.isCleanStatus = providers.provider { determineIsCleanStatus() } + this.head = providers.provider { determineHead() } + this.headTags = providers.provider { determineHeadTags() } + this.commitCountForHead = providers.provider { determineCommitCountForHead() } } /** @@ -109,7 +109,7 @@ abstract class GitBuildService implements BuildService { * git rev-parse --is-inside-work-tree -> fatal: not a git repository (or any of the parent directories): .git when there isn't a repo */ boolean isGitRepo() { - return this.isGitRepo + return this.isGitRepo.get() } /** @@ -117,14 +117,14 @@ abstract class GitBuildService implements BuildService { * ex. git rev-parse --abbrev-ref HEAD -> configuration-cache-support */ String getCurrentBranch() { - return this.currentBranch + return this.currentBranch.getOrNull() } /** * Uses to determine if a given repo has any commit */ boolean hasCommit() { - return this.hasCommit + return this.hasCommit.get() } /** @@ -132,23 +132,23 @@ abstract class GitBuildService implements BuildService { * ex. git rev-parse HEAD -> 8e6c4c925a54dbe827f043d21cd7a2a01b97fbac */ String getHead() { - return this.head + return this.head.getOrNull() } String getStatus() { - return this.status + return this.status.getOrNull() } boolean isCleanStatus() { - return this.isCleanStatus + return this.isCleanStatus.get() } List headTags() { - return this.headTags + return this.headTags.getOrElse(Collections.emptyList()) } Integer getCommitCountForHead() { - return this.commitCountForHead + return this.commitCountForHead.get() } String describeHeadWithTags(boolean excludePreReleases) { diff --git a/src/main/groovy/nebula/plugin/release/git/base/ReleasePluginExtension.groovy b/src/main/groovy/nebula/plugin/release/git/base/ReleasePluginExtension.groovy index bbd6920..beed214 100644 --- a/src/main/groovy/nebula/plugin/release/git/base/ReleasePluginExtension.groovy +++ b/src/main/groovy/nebula/plugin/release/git/base/ReleasePluginExtension.groovy @@ -17,10 +17,12 @@ package nebula.plugin.release.git.base import groovy.transform.CompileDynamic import nebula.plugin.release.git.GitBuildService -import nebula.plugin.release.util.ConfigureUtil +import org.gradle.api.Action import org.gradle.api.GradleException import org.gradle.api.Project +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -37,7 +39,7 @@ import javax.inject.Inject * * @see BaseReleasePlugin */ -class ReleasePluginExtension { +abstract class ReleasePluginExtension { private static final Logger logger = LoggerFactory.getLogger(ReleasePluginExtension) protected final Project project private final Map versionStrategies = [:] @@ -62,7 +64,7 @@ class ReleasePluginExtension { /** * The remote to fetch changes from and push changes to. */ - String remote = 'origin' + abstract Property getRemote() @CompileDynamic @Inject @@ -72,6 +74,7 @@ class ReleasePluginExtension { this.gitBuildService = project.getGradle().getSharedServices().registerIfAbsent("gitBuildService", GitBuildService.class, spec -> { spec.getParameters().getGitRootDir().set(gitRoot) }).get() + remote.convention('origin') def sharedVersion = new DelayedVersion() project.rootProject.allprojects { Project p -> p.version = sharedVersion @@ -94,18 +97,21 @@ class ReleasePluginExtension { } /** - * Configures the tag strategy with the provided closure. + * Configures the tag strategy with the provided action. */ - void tagStrategy(Closure closure) { - ConfigureUtil.configure(closure, tagStrategy) + void tagStrategy(Action action) { + action.execute(tagStrategy) } - // TODO: Decide if this should be thread-safe. private class DelayedVersion implements Serializable { - ReleaseVersion inferredVersion + private final Provider inferredVersionProvider + + DelayedVersion() { + this.inferredVersionProvider = project.provider { -> infer() } + } @CompileDynamic - private void infer() { + private ReleaseVersion infer() { VersionStrategy selectedStrategy = versionStrategies.find { strategy -> strategy.selector(project, gitBuildService) } @@ -126,15 +132,16 @@ class ReleasePluginExtension { } } - inferredVersion = selectedStrategy.infer(project, gitBuildService) + return selectedStrategy.infer(project, gitBuildService) + } + + ReleaseVersion getInferredVersion() { + return inferredVersionProvider.get() } @Override String toString() { - if (!inferredVersion) { - infer() - } - return inferredVersion.version + return inferredVersionProvider.get().version } } } diff --git a/src/main/groovy/nebula/plugin/release/util/ConfigureUtil.groovy b/src/main/groovy/nebula/plugin/release/util/ConfigureUtil.groovy deleted file mode 100644 index 59465c0..0000000 --- a/src/main/groovy/nebula/plugin/release/util/ConfigureUtil.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package nebula.plugin.release.util - -import groovy.transform.CompileDynamic -import org.codehaus.groovy.runtime.GeneratedClosure -import org.gradle.internal.metaobject.ConfigureDelegate -import org.gradle.util.Configurable -import org.gradle.util.internal.ClosureBackedAction - -import javax.annotation.Nullable - -class ConfigureUtil { - public static final int DELEGATE_FIRST = 1 - public static final int OWNER_ONLY = 2 - - /** - *

Configures {@code target} with {@code configureClosure}, via the {@link Configurable} interface if necessary.

- * - *

If {@code target} does not implement {@link Configurable} interface, it is set as the delegate of a clone of - * {@code configureClosure} with a resolve strategy of {@code DELEGATE_FIRST}.

- * - *

If {@code target} does implement the {@link Configurable} interface, the {@code configureClosure} will be passed to - * {@code delegate}'s {@link Configurable#configure(Closure)} method.

- * - * @param configureClosure The configuration closure - * @param target The object to be configured - * @return The delegate param - */ - static T configure(@Nullable Closure configureClosure, T target) { - if (configureClosure == null) { - return target - } - - if (target instanceof Configurable) { - ((Configurable) target).configure(configureClosure) - } else { - configureTarget(configureClosure, target, new ConfigureDelegate(configureClosure, target)) - } - - return target - } - - @CompileDynamic - private static void configureTarget(Closure configureClosure, T target, ConfigureDelegate closureDelegate) { - if (!(configureClosure instanceof GeneratedClosure)) { - new ClosureBackedAction(configureClosure, DELEGATE_FIRST, false).execute(target) - return; - } - - // Hackery to make closure execution faster, by short-circuiting the expensive property and method lookup on Closure - Closure withNewOwner = configureClosure.rehydrate(target, closureDelegate, configureClosure.getThisObject()) - new ClosureBackedAction(withNewOwner, OWNER_ONLY, false).execute(target) - } -} diff --git a/src/main/groovy/nebula/plugin/release/util/ObjectUtil.java b/src/main/groovy/nebula/plugin/release/util/ObjectUtil.java deleted file mode 100644 index e0ad311..0000000 --- a/src/main/groovy/nebula/plugin/release/util/ObjectUtil.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package nebula.plugin.release.util; - -import java.util.concurrent.Callable; - -import groovy.lang.Closure; - - -/** - * Utility class for general {@code Object} related operations. - * @since 0.1.0 - */ -public final class ObjectUtil { - /** - * Cannot instantiate - * @throws AssertionError always - */ - private ObjectUtil() { - throw new AssertionError("Cannot instantiate this class"); - } - - /** - * Unpacks the given object by recursively - * calling the {@code call()} method if the - * object is a {@code Closure} or {@code Callable}. - * @param obj the object to unpack - * @return the unpacked value of the object - */ - @SuppressWarnings("rawtypes") - public static Object unpack(Object obj) { - Object value = obj; - while (value != null) { - if (value instanceof Closure) { - value = ((Closure) value).call(); - } else if (value instanceof Callable) { - try { - value = ((Callable) value).call(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - return value; - } - } - return value; - } - - /** - * Unpacks the given object to its {@code String} - * value. Same behavior as the other {@code unpack} - * method ending with a call to {@code toString()}. - * @param obj the value to unpack - * @return the unpacked string value - * @see ObjectUtil#unpack(Object) - */ - public static String unpackString(Object obj) { - Object value = unpack(obj); - return value == null ? null : value.toString(); - } -} diff --git a/src/test/groovy/nebula/plugin/release/git/base/ReleasePluginExtensionSpec.groovy b/src/test/groovy/nebula/plugin/release/git/base/ReleasePluginExtensionSpec.groovy index 816e5d4..b07dfa0 100644 --- a/src/test/groovy/nebula/plugin/release/git/base/ReleasePluginExtensionSpec.groovy +++ b/src/test/groovy/nebula/plugin/release/git/base/ReleasePluginExtensionSpec.groovy @@ -27,7 +27,7 @@ class ReleasePluginExtensionSpec extends Specification { def 'infers default version if selector returns false for all but default'() { given: Project project = ProjectBuilder.builder().build() - ReleasePluginExtension extension = new ReleasePluginExtension(project) + ReleasePluginExtension extension = project.objects.newInstance(ReleasePluginExtension, project) extension.gitBuildService = GroovyMock(GitBuildService) extension.versionStrategy([ getName: { 'b' }, @@ -43,7 +43,7 @@ class ReleasePluginExtensionSpec extends Specification { def 'infers using first strategy selector returns true for'() { Project project = ProjectBuilder.builder().build() - ReleasePluginExtension extension = new ReleasePluginExtension(project) + ReleasePluginExtension extension = project.objects.newInstance(ReleasePluginExtension, project) extension.gitBuildService = GroovyMock(GitBuildService) extension.versionStrategy([ getName: { 'b' }, @@ -59,7 +59,7 @@ class ReleasePluginExtensionSpec extends Specification { def 'infers using first strategy selector returns true for in order'() { Project project = ProjectBuilder.builder().build() - ReleasePluginExtension extension = new ReleasePluginExtension(project) + ReleasePluginExtension extension = project.objects.newInstance(ReleasePluginExtension, project) extension.gitBuildService = GroovyMock(GitBuildService) extension.versionStrategy([ getName: { 'b' }, @@ -76,7 +76,7 @@ class ReleasePluginExtensionSpec extends Specification { def 'infer uses default if it has default selector that passes when selector doesnt'() { given: Project project = ProjectBuilder.builder().build() - ReleasePluginExtension extension = new ReleasePluginExtension(project) + ReleasePluginExtension extension = project.objects.newInstance(ReleasePluginExtension, project) extension.gitBuildService = GroovyMock(GitBuildService) extension.versionStrategy([ getName: { 'b' }, @@ -94,7 +94,7 @@ class ReleasePluginExtensionSpec extends Specification { def 'infer fails if no strategy selected including the default strategy'() { given: Project project = ProjectBuilder.builder().build() - ReleasePluginExtension extension = new ReleasePluginExtension(project) + ReleasePluginExtension extension = project.objects.newInstance(ReleasePluginExtension, project) extension.gitBuildService = GroovyMock(GitBuildService) extension.versionStrategy([ getName: { 'b' }, @@ -112,7 +112,7 @@ class ReleasePluginExtensionSpec extends Specification { def 'infer fails if no strategy selected and no default set'() { Project project = ProjectBuilder.builder().build() - ReleasePluginExtension extension = new ReleasePluginExtension(project) + ReleasePluginExtension extension = project.objects.newInstance(ReleasePluginExtension, project) extension.gitBuildService = GroovyMock(GitBuildService) extension.versionStrategy([ getName: { 'b' },