From 3cc80e20b07e50a2b611f631e762544741ae0a24 Mon Sep 17 00:00:00 2001 From: Joshua B Date: Mon, 25 Oct 2021 21:42:49 -0600 Subject: [PATCH] remove unused classes, refactor JavaPublish to simplify, depend on yakworks:commons (#13) --- build.gradle | 30 +- build.yml | 6 + gradle.properties | 6 +- .../groovy/yakworks/commons/ConfigMap.groovy | 8 +- src/main/groovy/yakworks/commons/Maps.groovy | 67 -- .../groovy/yakworks/commons/NameUtils.java | 711 ------------------ src/main/groovy/yakworks/commons/Pogo.groovy | 67 -- src/main/groovy/yakworks/commons/Props.groovy | 26 - src/main/groovy/yakworks/commons/Shell.groovy | 29 - .../yakworks/gradle/GradleHelpers.groovy | 4 +- .../gradle/config/YamlConfigPlugin.groovy | 4 +- .../gradle/shipkit/GradlePluginPlugin.groovy | 12 +- .../gradle/shipkit/GrailsPlugin.groovy | 8 +- .../gradle/shipkit/GroovyLibPlugin.groovy | 3 - .../gradle/shipkit/JavaPublishPlugin.groovy | 184 +++++ .../gradle/shipkit/JavaPublishPlugin.java | 97 --- .../shipkit/PublishingRepoSetupPlugin.groovy | 54 -- .../gradle/util/ArgumentValidation.java | 31 - .../gradle/util/BuildConventions.java | 25 - .../gradle/util/GradleDSLHelper.groovy | 31 - .../groovy/yakworks/gradle/util/IOUtil.java | 148 ---- .../yakworks/gradle/util/PomCustomizer.groovy | 91 --- .../gradle/util/PropertiesUtil.groovy | 16 + .../yakworks/gradle/util/PropertiesUtil.java | 22 - .../yakworks/gradle/util/StringUtil.groovy | 44 -- .../yakworks/gradle/util/TaskMaker.java | 39 - .../yakworks/gradle/util/team/TeamParser.java | 4 +- .../commons/{ => map}/MapsSpec.groovy | 18 +- version.properties | 2 +- 29 files changed, 260 insertions(+), 1527 deletions(-) delete mode 100644 src/main/groovy/yakworks/commons/Maps.groovy delete mode 100644 src/main/groovy/yakworks/commons/NameUtils.java delete mode 100644 src/main/groovy/yakworks/commons/Pogo.groovy delete mode 100644 src/main/groovy/yakworks/commons/Props.groovy delete mode 100644 src/main/groovy/yakworks/commons/Shell.groovy create mode 100644 src/main/groovy/yakworks/gradle/shipkit/JavaPublishPlugin.groovy delete mode 100644 src/main/groovy/yakworks/gradle/shipkit/JavaPublishPlugin.java delete mode 100644 src/main/groovy/yakworks/gradle/shipkit/PublishingRepoSetupPlugin.groovy delete mode 100644 src/main/groovy/yakworks/gradle/util/ArgumentValidation.java delete mode 100644 src/main/groovy/yakworks/gradle/util/BuildConventions.java delete mode 100644 src/main/groovy/yakworks/gradle/util/GradleDSLHelper.groovy delete mode 100644 src/main/groovy/yakworks/gradle/util/IOUtil.java delete mode 100644 src/main/groovy/yakworks/gradle/util/PomCustomizer.groovy create mode 100644 src/main/groovy/yakworks/gradle/util/PropertiesUtil.groovy delete mode 100644 src/main/groovy/yakworks/gradle/util/PropertiesUtil.java delete mode 100644 src/main/groovy/yakworks/gradle/util/StringUtil.groovy delete mode 100644 src/main/groovy/yakworks/gradle/util/TaskMaker.java rename src/test/groovy/yakworks/commons/{ => map}/MapsSpec.groovy (92%) diff --git a/build.gradle b/build.gradle index 31a8f01..8bcddd1 100644 --- a/build.gradle +++ b/build.gradle @@ -6,17 +6,24 @@ buildscript { } dependencies { classpath "org.yakworks:gradle-plugins:$vShipyak" + classpath "io.github.gradle-nexus:publish-plugin:1.1.0" } } plugins { id "com.dorongold.task-tree" version "1.5" + id 'groovy' + id 'java-gradle-plugin' + // id 'maven-publish' id "com.gradle.plugin-publish" version "0.16.0" - id "java-gradle-plugin" } +apply plugin: 'signing' +apply plugin: "io.github.gradle-nexus.publish-plugin" apply plugin: 'yakworks.gradle-plugin' +group "org.yakworks" + repositories { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } @@ -31,6 +38,7 @@ dependencies { implementation gradleApi() implementation localGroovy() + implementation "org.yakworks:commons:$vYakworksCommon" implementation "com.diffplug.spotless:spotless-plugin-gradle:$vSpotless" implementation "com.adarshr:gradle-test-logger-plugin:$vTestLogger" implementation "org.yaml:snakeyaml:$vSnakeyaml" @@ -46,6 +54,17 @@ dependencies { testImplementation gradleTestKit() } +signing { + useGpgCmd() + sign publishing.publications.javaLibrary +} + +nexusPublishing { + repositories { + sonatype() + } +} + //if its a CI we need to get the gradle plugin credentials if(!findProperty('gradle.publish.key')) ext['gradle.publish.key'] = System.getenv('GRADLE_PUBLISH_KEY') if(!findProperty('gradle.publish.secret')) ext['gradle.publish.secret'] = System.getenv('GRADLE_PUBLISH_SECRET') @@ -54,6 +73,7 @@ def defTags = ['grails', 'groovy', 'shipkit', 'spotless', 'circleCI', 'continuou 'mkdocs', 'markdown', 'documentation'] gradlePlugin { + automatedPublishing = false plugins { defaultsPlugin { id = 'yakworks.defaults' @@ -118,13 +138,6 @@ gradlePlugin { description = 'Yakworks Groovydoc merges together all the groovydocs for shippable libs in a project' //tags = defTags } -// shipkitPlugin { //DEPRECATED -// id = 'yakworks.shipkit' -// implementationClass = 'yakworks.gradle.shipkit.ShipkitPlugin' -// displayName = 'DEPRECATED' -// description = 'DEPRECATED use yakworks.shipyak' -// //tags = defTags -// } yamlConfigPlugin { id = 'yakworks.yaml-config' implementationClass = 'yakworks.gradle.config.YamlConfigPlugin' @@ -141,6 +154,7 @@ pluginBundle { //description = 'Plugin providing opinionated defaults and shipkit setup for Groovy, Grails and Gradle library/plugin projects. ' + // 'Enables hooks for automated releases and versioning and tags with CircleCI. Yaml config properties' tags = defTags + mavenCoordinates { groupId = project.group artifactId = project.name diff --git a/build.yml b/build.yml index 7a82f5b..1067b5d 100644 --- a/build.yml +++ b/build.yml @@ -1,3 +1,8 @@ + +project: + # this is needed for url in pom for jar lib, doesnt pick up defaults from git + fullName: yakworks/gradle-plugins + bot: email: 9cibot@9ci.com user: 9cibot @@ -16,4 +21,5 @@ team: developers: ['basejump: Joshua Burnett'] maven: +# repoUrl: https://oss.sonatype.org/service/local/staging/deploy/maven2 snapshotUrl: http://repo.9ci.com/oss-snapshots diff --git a/gradle.properties b/gradle.properties index 5f7aefd..877551d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,10 @@ groovyVersion=2.5.14 +signing.gnupg.keyName=302AAEFA +# this turns off the sha256 and sha512 files that get published for now +systemProp.org.gradle.internal.publish.checksums.insecure=true -vShipyak=2.6.3 +vYakworksCommon=7.0.8-v.34 +vShipyak=2.6.5 vSpotless=5.12.5 vTestLogger=2.1.1 vSnakeyaml=1.27 diff --git a/src/main/groovy/yakworks/commons/ConfigMap.groovy b/src/main/groovy/yakworks/commons/ConfigMap.groovy index 505b956..a28ced3 100644 --- a/src/main/groovy/yakworks/commons/ConfigMap.groovy +++ b/src/main/groovy/yakworks/commons/ConfigMap.groovy @@ -12,8 +12,10 @@ import groovy.transform.EqualsAndHashCode import org.codehaus.groovy.runtime.DefaultGroovyMethods +import yakworks.commons.map.Maps + /** - * Copied from org.grails.config.ConfigMap so we can use it as a gradle plugin here + * Copied from org.grails.config.NavigableMap so we can use it as a gradle plugin here * This is like groovy's ConfigObject but better. */ @EqualsAndHashCode @@ -249,8 +251,8 @@ class ConfigMap implements Map, Cloneable { void addToBinding(Map vars){ bindingMap.putAll(vars) } - void addToBinding(String var, Object val){ - bindingMap.put(var, val) + void addToBinding(String varName, Object val){ + bindingMap.put(varName, val) } /** diff --git a/src/main/groovy/yakworks/commons/Maps.groovy b/src/main/groovy/yakworks/commons/Maps.groovy deleted file mode 100644 index f94d1b5..0000000 --- a/src/main/groovy/yakworks/commons/Maps.groovy +++ /dev/null @@ -1,67 +0,0 @@ -/* -* Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") -* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -*/ -package yakworks.commons - -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j - -/** - * Helpful methods for dealing with maps - */ - -@Slf4j -@CompileStatic -class Maps { - - /** - * https://gist.github.com/robhruska/4612278 - * Deeply merges the contents of each Map in sources, merging from - * "right to left" and returning the merged Map. - * - * Mimics 'extend()' functions often seen in JavaScript libraries. - * Any specific Map implementations (e.g. TreeMap, LinkedHashMap) - * are not guaranteed to be retained. The ordering of the keys in - * the result Map is not guaranteed. Only nested maps will be - * merged; primitives, objects, and other collection types will be - * overwritten. - * - * The source maps will not be modified. - */ - static Map merge(Map[] sources) { - if (sources.length == 0) return [:] - if (sources.length == 1) return sources[0] - - sources.inject([:]) { result, source -> - source.each { k, v -> - result[k] = result[k] instanceof Map ? merge(result[k] as Map, v as Map) : v - } - result - } as Map - } - - /** - * Deeply remove/prune all nulls and falsey` empty maps, lists and strings as well - * - * @param map the map to prune - * @param pruneEmpty default:true set to false to keep empty maps, lists and strings - * @return the pruned map - */ - static Map prune(Map map, boolean pruneEmpty = true) { - map.collectEntries { k, v -> - [k, v instanceof Map ? prune(v as Map, pruneEmpty) : v] - }.findAll { k, v -> - if(pruneEmpty){ - if (v instanceof List || v instanceof Map || v instanceof String) { - return v - } else { - return v != null - } - } else { - return v != null - } - - } - } -} diff --git a/src/main/groovy/yakworks/commons/NameUtils.java b/src/main/groovy/yakworks/commons/NameUtils.java deleted file mode 100644 index 9474a49..0000000 --- a/src/main/groovy/yakworks/commons/NameUtils.java +++ /dev/null @@ -1,711 +0,0 @@ -/* - * Copyright 2008 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 yakworks.commons; - -import java.util.*; - -/** - * Copied in from grails.util.GrailsNameUtils and converted to groovy - * Utility methods for converting between different name types, - * for example from class names -> property names and vice-versa. The - * key aspect of this class is that it has no dependencies outside stock groovy! - */ -public class NameUtils { - - private static final String PROPERTY_SET_PREFIX = "set"; - private static final String PROPERTY_GET_PREFIX = "get"; - - private NameUtils() { - } - - /** - * Retrieves the name of a setter for the specified property name - * @param propertyName The property name - * @return The setter equivalent - */ - public static String getSetterName(String propertyName) { - final String suffix = getSuffixForGetterOrSetter(propertyName); - return PROPERTY_SET_PREFIX+suffix; - } - - /** - * Calculate the name for a getter method to retrieve the specified property - * @param propertyName - * @return The name for the getter method for this property, if it were to exist, i.e. getConstraints - */ - public static String getGetterName(String propertyName) { - final String suffix = getSuffixForGetterOrSetter(propertyName); - return PROPERTY_GET_PREFIX + suffix; - } - - private static String getSuffixForGetterOrSetter(String propertyName) { - final String suffix; - if (propertyName.length() > 1 && - Character.isLowerCase(propertyName.charAt(0)) && - Character.isUpperCase(propertyName.charAt(1))) { - suffix = propertyName; - } else { - suffix = Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); - } - return suffix; - } - - /** - * Returns the class name for the given logical name and trailing name. For example "person" and "Controller" would evaluate to "PersonController" - * - * @param logicalName The logical name - * @param trailingName The trailing name - * @return The class name - */ - public static String getClassName(String logicalName, String trailingName) { - if (isBlank(logicalName)) { - throw new IllegalArgumentException("Argument [logicalName] cannot be null or blank"); - } - - String className = logicalName.substring(0,1).toUpperCase(Locale.ENGLISH) + logicalName.substring(1); - if (trailingName != null) { - className = className + trailingName; - } - return className; - } - - /** - * Returns the class name, including package, for the given class. This method will deals with proxies and closures. - * - * @param cls The class name - */ - public static String getFullClassName(Class cls) { - String className = cls.getName(); - - return getFullClassName(className); - } - - /** - * Returns the class name, including package, for the given class. This method will deals with proxies and closures. - * - * @param className The class name - */ - public static String getFullClassName(String className) { - final int i = className.indexOf('$'); - if(i > -1) { - className = className.substring(0, i); - } - return className; - } - - /** - * Return the class name for the given logical name. For example "person" would evaluate to "Person" - * - * @param logicalName The logical name - * @return The class name - */ - public static String getClassName(String logicalName) { - return getClassName(logicalName, ""); - } - - /** - * Returns the class name representation of the given name - * - * @param name The name to convert - * @return The property name representation - */ - public static String getClassNameRepresentation(String name) { - if (name == null || name.length() == 0) { - return ""; - } - - StringBuilder buf = new StringBuilder(); - String[] tokens = name.split("[^\\w\\d]"); - for (String token1 : tokens) { - String token = token1.trim(); - int length = token.length(); - if (length > 0) { - buf.append(token.substring(0, 1).toUpperCase(Locale.ENGLISH)); - if (length > 1) { - buf.append(token.substring(1)); - } - } - } - - return buf.toString(); - } - - /** - * Converts foo-bar into FooBar. Empty and null strings are returned as-is. - * - * @param name The lower case hyphen separated name - * @return The class name equivalent. - */ - private static String getClassNameForLowerCaseHyphenSeparatedName(String name) { - // Handle null and empty strings. - if (isBlank(name)) return name; - - if (name.indexOf('-') == -1) { - return name.substring(0,1).toUpperCase() + name.substring(1); - } - - StringBuilder buf = new StringBuilder(); - String[] tokens = name.split("-"); - for (String token : tokens) { - if (token == null || token.length() == 0) continue; - buf.append(token.substring(0, 1).toUpperCase()) - .append(token.substring(1)); - } - return buf.toString(); - } - - /** - * Retrieves the logical class name of a Grails artifact given the Grails class - * and a specified trailing name. - * - * @param clazz The class - * @param trailingName The trailing name such as "Controller" or "TagLib" - * @return The logical class name - */ - public static String getLogicalName(Class clazz, String trailingName) { - return getLogicalName(clazz.getName(), trailingName); - } - - /** - * Retrieves the logical name of the class without the trailing name - * @param name The name of the class - * @param trailingName The trailing name - * @return The logical name - */ - public static String getLogicalName(String name, String trailingName) { - if (isBlank(trailingName)) { - return name; - } - - String shortName = getShortName(name); - if (shortName.indexOf(trailingName) == - 1) { - return name; - } - - return shortName.substring(0, shortName.length() - trailingName.length()); - } - - public static String getLogicalPropertyName(String className, String trailingName) { - if (!isBlank(className) && !isBlank(trailingName)) { - if (className.length() == trailingName.length() + 1 && className.endsWith(trailingName)) { - return className.substring(0, 1).toLowerCase(); - } - } - return getLogicalName(getPropertyName(className), trailingName); - } - - /** - * Shorter version of getPropertyNameRepresentation. - * @param name The name to convert - * @return The property name version - */ - public static String getPropertyName(String name) { - return getPropertyNameRepresentation(name); - } - - /** - * Shorter version of getPropertyNameRepresentation. - * @param clazz The clazz to convert - * @return The property name version - */ - public static String getPropertyName(Class clazz) { - return getPropertyNameRepresentation(clazz); - } - - /** - * Returns the property name equivalent for the specified class. - * - * @param targetClass The class to get the property name for - * @return A property name reperesentation of the class name (eg. MyClass becomes myClass) - */ - public static String getPropertyNameRepresentation(Class targetClass) { - return getPropertyNameRepresentation(getShortName(targetClass)); - } - - /** - * Returns the property name representation of the given name. - * - * @param name The name to convert - * @return The property name representation - */ - public static String getPropertyNameRepresentation(String name) { - // Strip any package from the name. - int pos = name.lastIndexOf('.'); - if (pos != -1) { - name = name.substring(pos + 1); - } - - if (name.isEmpty()) { - return name; - } - - // Check whether the name begins with two upper case letters. - if (name.length() > 1 && Character.isUpperCase(name.charAt(0)) && - Character.isUpperCase(name.charAt(1))) { - return name; - } - - String propertyName = name.substring(0,1).toLowerCase(Locale.ENGLISH) + name.substring(1); - if (propertyName.indexOf(' ') > -1) { - propertyName = propertyName.replaceAll("\\s", ""); - } - return propertyName; - } - - /** - * Converts foo-bar into fooBar. - * - * @param name The lower case hyphen separated name - * @return The property name equivalent - */ - public static String getPropertyNameForLowerCaseHyphenSeparatedName(String name) { - return getPropertyName(getClassNameForLowerCaseHyphenSeparatedName(name)); - } - - /** - * Returns the class name without the package prefix. - * - * @param targetClass The class to get a short name for - * @return The short name of the class - */ - public static String getShortName(Class targetClass) { - return getShortName(targetClass.getName()); - } - - /** - * Returns the class name without the package prefix. - * - * @param className The class name to get a short name for - * @return The short name of the class - */ - public static String getShortName(String className) { - int i = className.lastIndexOf("."); - if (i > -1) { - className = className.substring(i + 1, className.length()); - } - return className; - } - - /** - * Returns the class name without the package prefix. - * - * @param className The class name to get a short name for - * @return The short name of the class - */ - public static String getPackageName(String className) { - int i = className.lastIndexOf("."); - String packageName = ""; - if (i > -1) { - packageName = className.substring(0, i); - } - return packageName; - } - - /** - * Retrieves the script name representation of the supplied class. For example - * MyFunkyGrailsScript would be my-funky-grails-script. - * - * @param clazz The class to convert - * @return The script name representation - */ - public static String getScriptName(Class clazz) { - return clazz == null ? null : getScriptName(clazz.getName()); - } - - /** - * Retrieves the script name representation of the given class name. - * For example MyFunkyGrailsScript would be my-funky-grails-script. - * - * @param name The class name to convert. - * @return The script name representation. - */ - public static String getScriptName(String name) { - if (name == null) { - return null; - } - - if (name.endsWith(".groovy")) { - name = name.substring(0, name.length()-7); - } - return getNaturalName(name).replaceAll("\\s", "-").toLowerCase(); - } - - /** - * Calculates the class name from a script name in the form my-funk-grails-script. - * - * @param scriptName The script name - * @return A class name - */ - public static String getNameFromScript(String scriptName) { - return getClassNameForLowerCaseHyphenSeparatedName(scriptName); - } - - /** - * Returns the name of a plugin given the name of the *GrailsPlugin.groovy - * descriptor file. For example, "DbUtilsGrailsPlugin.groovy" gives - * "db-utils". - * @param descriptorName The simple name of the plugin descriptor. - * @return The plugin name for the descriptor, or null - * if descriptorName is null, or an empty string - * if descriptorName is an empty string. - * @throws IllegalArgumentException if the given descriptor name is - * not valid, i.e. if it doesn't end with "GrailsPlugin.groovy". - */ - public static String getPluginName(String descriptorName) { - if (descriptorName == null || descriptorName.length() == 0) { - return descriptorName; - } - - if (!descriptorName.endsWith("GrailsPlugin.groovy")) { - throw new IllegalArgumentException("Plugin descriptor name is not valid: " + descriptorName); - } - - return getScriptName(descriptorName.substring(0, descriptorName.indexOf("GrailsPlugin.groovy"))); - } - - /** - * Converts a property name into its natural language equivalent eg ('firstName' becomes 'First Name') - * @param name The property name to convert - * @return The converted property name - */ - public static String getNaturalName(String name) { - name = getShortName(name); - List words = new ArrayList(); - int i = 0; - char[] chars = name.toCharArray(); - for (int j = 0; j < chars.length; j++) { - char c = chars[j]; - String w; - if (i >= words.size()) { - w = ""; - words.add(i, w); - } - else { - w = words.get(i); - } - - if (Character.isLowerCase(c) || Character.isDigit(c)) { - if (Character.isLowerCase(c) && w.length() == 0) { - c = Character.toUpperCase(c); - } - else if (w.length() > 1 && Character.isUpperCase(w.charAt(w.length() - 1))) { - w = ""; - words.add(++i,w); - } - - words.set(i, w + c); - } - else if (Character.isUpperCase(c)) { - if ((i == 0 && w.length() == 0) || (Character.isUpperCase(w.charAt(w.length() - 1)) && Character.isUpperCase(chars[j-1]))) { - words.set(i, w + c); - } - else { - words.add(++i, String.valueOf(c)); - } - } - } - - StringBuilder buf = new StringBuilder(); - for (Iterator j = words.iterator(); j.hasNext();) { - String word = j.next(); - buf.append(word); - if (j.hasNext()) { - buf.append(' '); - } - } - return buf.toString(); - } - - /** - *

Determines whether a given string is null, empty, - * or only contains whitespace. If it contains anything other than - * whitespace then the string is not considered to be blank and the - * method returns false.

- *

We could use Commons Lang for this, but we don't want GrailsNameUtils - * to have a dependency on any external library to minimise the number of - * dependencies required to bootstrap Grails.

- * @param str The string to test. - * @return true if the string is null, or - * blank. - */ - public static boolean isBlank(String str) { - return str == null || str.trim().length() == 0; - } - - /** - * Returns an appropriate property name for the given object. If the object is a collection will append List, Set, Collection or Map to the property name - * @param object The object - * @return The property name convention - */ - public static String getPropertyNameConvention(Object object) { - String suffix = ""; - - return getPropertyNameConvention(object, suffix); - } - - - /** - * Test whether the give package name is a valid Java package - * - * @param packageName The name of the package - * @return True if it is valid - */ - public static boolean isValidJavaPackage(String packageName) { - if(isBlank(packageName)) return false; - final String[] parts = packageName.split("\\."); - for (String part : parts) { - if(!isValidJavaIdentifier(part)) { - return false; - } - } - return true; - } - /** - * Test whether the given name is a valid Java identifier - * - * @param name The name - * @return True if it is - */ - public static boolean isValidJavaIdentifier(String name) { - if(isBlank(name)) return false; - - final char[] chars = name.toCharArray(); - if(!Character.isJavaIdentifierStart(chars[0])) { - return false; - } - - for (char c : chars) { - if(!Character.isJavaIdentifierPart(c)) { - return false; - } - } - - return true; - } - /** - * Returns an appropriate property name for the given object. If the object is a collection will append List, Set, Collection or Map to the property name - * @param object The object - * @param suffix The suffix to append to the name. - * @return The property name convention - */ - public static String getPropertyNameConvention(Object object, String suffix) { - if(object != null) { - Class type = object.getClass(); - if (type.isArray()) { - return getPropertyName(type.getComponentType()) + suffix + "Array"; - } - - if (object instanceof Collection) { - Collection coll = (Collection) object; - if (coll.isEmpty()) { - return "emptyCollection"; - } - - Object first = coll.iterator().next(); - if(coll instanceof List) { - return getPropertyName(first.getClass()) + suffix + "List"; - } - if(coll instanceof Set) { - return getPropertyName(first.getClass()) + suffix + "Set"; - } - return getPropertyName(first.getClass()) + suffix + "Collection"; - } - - if (object instanceof Map) { - Map map = (Map)object; - - if (map.isEmpty()) { - return "emptyMap"; - } - - Object entry = map.values().iterator().next(); - if (entry != null) { - return getPropertyName(entry.getClass()) + suffix + "Map"; - } - } - else { - return getPropertyName(object.getClass()) + suffix; - } - } - return null; - } - - /** - * Returns a property name equivalent for the given getter name or null if it is not a valid getter. If not null - * or empty the getter name is assumed to be a valid identifier. - * - * @param getterName The getter name - * @return The property name equivalent - */ - public static String getPropertyForGetter(String getterName) { - return getPropertyForGetter(getterName, boolean.class); - } - - /** - * Returns a property name equivalent for the given getter name and return type or null if it is not a valid getter. If not null - * or empty the getter name is assumed to be a valid identifier. - * - * @param getterName The getter name - * @param returnType The type the method returns - * @return The property name equivalent - */ - public static String getPropertyForGetter(String getterName, Class returnType) { - if (getterName == null || getterName.length() == 0) return null; - - if (getterName.startsWith("get")) { - String prop = getterName.substring(3); - return convertValidPropertyMethodSuffix(prop); - } - if (getterName.startsWith("is") && returnType == boolean.class) { - String prop = getterName.substring(2); - return convertValidPropertyMethodSuffix(prop); - } - return null; - } - - /** - * This method functions the same as {@link #isPropertyMethodSuffix(String)}, - * but in addition returns the property name, or null if not a valid property. - * - * @param suffix The suffix to inspect - * @return The property name or null - */ - static String convertValidPropertyMethodSuffix(String suffix) { - if (suffix.length() == 0) return null; - - // We assume all characters are Character.isJavaIdentifierPart, but the first one may not be a valid - // starting character. - if (!Character.isJavaIdentifierStart(suffix.charAt(0))) return null; - - if (suffix.length() == 1) { - return Character.isUpperCase(suffix.charAt(0)) ? suffix.toLowerCase() : null; - } - if (Character.isUpperCase(suffix.charAt(1))) { - // "aProperty", "AProperty" - return suffix; - } - if (Character.isUpperCase(suffix.charAt(0))) { - return Character.toLowerCase(suffix.charAt(0)) + suffix.substring(1); - } - if('_' == suffix.charAt(0)) { - return suffix; - } - return null; - } - - - /** - * Returns true if the name of the method specified and the number of arguments make it a javabean property getter. - * The name is assumed to be a valid Java method name, that is not verified. - * - * @param name The name of the method - * @param args The arguments - * @return true if it is a javabean property getter - * @deprecated use {@link #isGetter(String, Class, Class[])} instead because this method has a defect for "is.." method with Boolean return types. - */ - public static boolean isGetter(String name, Class[] args) { - return isGetter(name, boolean.class, args); - } - - /** - * Returns true if the name of the method specified and the number of arguments make it a javabean property getter. - * The name is assumed to be a valid Java method name, that is not verified. - * - * @param name The name of the method - * @param returnType The return type of the method - * @param args The arguments - * @return true if it is a javabean property getter - */ - public static boolean isGetter(String name, Class returnType, Class[] args) { - if (name == null || name.length() == 0 || args == null)return false; - if (args.length != 0)return false; - - if (name.startsWith("get")) { - name = name.substring(3); - if (isPropertyMethodSuffix(name)) return true; - } - else if (name.startsWith("is") && returnType == boolean.class) { - name = name.substring(2); - if (isPropertyMethodSuffix(name)) return true; - } - return false; - } - - /** - * This method is used when interrogating a method name to determine if the - * method represents a property getter. For example, if a method is named - * getSomeProperty, the value "SomeProperty" could - * be passed to this method to determine that the method should be considered - * a property getter. Examples of suffixes that would be considered property - * getters: - *
    - *
  • SomeProperty
  • - *
  • Word
  • - *
  • aProperty
  • - *
  • S
  • - *
  • X567
  • - *
- * - * Examples of suffixes that would not be considered property getters: - *
    - *
  • someProperty
  • - *
  • word
  • - *
  • s
  • - *
  • x567
  • - *
  • 2other
  • - *
  • 5
  • - *
- * - * A suffix like prop from a method getprop() is - * not recognized as a valid suffix. However Groovy will recognize such a - * method as a property getter but only if a method getProp() or - * a property prop does not also exist. The Java Beans - * specification is unclear on how to treat such method names, it only says - * that "by default" the suffix will start with a capital letter because of - * the camel case style usually used. (See the JavaBeans API specification - * sections 8.3 and 8.8.) - * - * This method assumes that all characters in the name are valid Java identifier - * letters. - * - * @param suffix The suffix to inspect - * @return true if suffix indicates a property name - */ - protected static boolean isPropertyMethodSuffix(String suffix) { - if(suffix.length() == 0) return false; - if(!Character.isJavaIdentifierStart(suffix.charAt(0))) return false; - if(suffix.length() == 1) return Character.isUpperCase(suffix.charAt(0)); - return Character.isUpperCase(suffix.charAt(0)) || Character.isUpperCase(suffix.charAt(1)); - } - - /** - * Returns a property name equivalent for the given setter name or null if it is not a valid setter. If not null - * or empty the setter name is assumed to be a valid identifier. - * - * @param setterName The setter name, must be null or empty or a valid identifier name - * @return The property name equivalent - */ - public static String getPropertyForSetter(String setterName) { - if (setterName == null || setterName.length() == 0) return null; - - if (setterName.startsWith("set")) { - String prop = setterName.substring(3); - return convertValidPropertyMethodSuffix(prop); - } - return null; - } - -} diff --git a/src/main/groovy/yakworks/commons/Pogo.groovy b/src/main/groovy/yakworks/commons/Pogo.groovy deleted file mode 100644 index f489094..0000000 --- a/src/main/groovy/yakworks/commons/Pogo.groovy +++ /dev/null @@ -1,67 +0,0 @@ -/* -* Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") -* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -*/ -package yakworks.commons - -import groovy.transform.CompileStatic - -import org.codehaus.groovy.runtime.InvokerHelper -import org.codehaus.groovy.runtime.InvokerInvocationException - -@CompileStatic -class Pogo { - - /** - * Merge the a map, nested or not, onto the pogo. Uses the InvokerHelper.setProperties(values) - */ - static void merge( Map args = [:], Object pogo, Map values){ - boolean ignoreNulls = args.containsKey('ignoreNulls') ? args['ignoreNulls'] : true - if(ignoreNulls){ - values = Maps.prune(values) - } - InvokerHelper.setProperties(pogo, values) - } - -// public static void setProperties(Object object, Map map) { -// MetaClass mc = getMetaClass(object); -// Iterator var3 = map.entrySet().iterator(); -// -// while(var3.hasNext()) { -// Object o = var3.next(); -// Map.Entry entry = (Map.Entry)o; -// String key = entry.getKey().toString(); -// Object value = entry.getValue(); -// setPropertySafe(object, mc, key, value); -// } -// -// } -// -// private static void setPropertySafe(Object object, MetaClass mc, String key, Object value) { -// try { -// mc.setProperty(object, key, value); -// } catch (MissingPropertyException var6) { -// ; -// } catch (InvokerInvocationException var7) { -// Throwable cause = var7.getCause(); -// if (cause == null || !(cause instanceof IllegalArgumentException)) { -// throw var7; -// } -// } -// -// } - - //standard deep copy implementation - //take from here https://stackoverflow.com/questions/13155127/deep-copy-map-in-groovy - //also see @groovy.transform.AutoClone - def deepcopy(Object orig) { - ByteArrayOutputStream bos = new ByteArrayOutputStream() - ObjectOutputStream oos = new ObjectOutputStream(bos) - oos.writeObject(orig) - oos.flush() - ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray()) - ObjectInputStream ois = new ObjectInputStream(bin) - return ois.readObject() - } - -} diff --git a/src/main/groovy/yakworks/commons/Props.groovy b/src/main/groovy/yakworks/commons/Props.groovy deleted file mode 100644 index 057a8dc..0000000 --- a/src/main/groovy/yakworks/commons/Props.groovy +++ /dev/null @@ -1,26 +0,0 @@ -/* -* Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") -* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -*/ -package yakworks.commons - -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j - -//import org.codehaus.groovy.runtime.MetaClassHelper -//import java.beans.Introspector - -@Slf4j -@CompileStatic -class Props { - - /** - * converts SOME_PROP to someProp - */ - static String toCamelCase( String text ) { - text = text.toLowerCase().replaceAll( "(_)([A-Za-z0-9])"){ List it -> it[2].toUpperCase() } - //println text - return text - } - -} diff --git a/src/main/groovy/yakworks/commons/Shell.groovy b/src/main/groovy/yakworks/commons/Shell.groovy deleted file mode 100644 index 1c22f3a..0000000 --- a/src/main/groovy/yakworks/commons/Shell.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* -* Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") -* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -*/ -package yakworks.commons - -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j - -/** - * Simple way to run shell scripts and some shell scripts that are helpful to have. - */ -@Slf4j -@CompileStatic -class Shell { - - /** - * shortcut call to ['sh', '-c', command].execute().text.trim() - */ - static String exec(String command){ - return ['sh', '-c', command].execute().text.trim() - } - - static String exec(String command, String workingDir){ - String cmd = "cd $workingDir && $command" - return ['sh', '-c', cmd].execute().text.trim() - } - -} diff --git a/src/main/groovy/yakworks/gradle/GradleHelpers.groovy b/src/main/groovy/yakworks/gradle/GradleHelpers.groovy index 08292f3..2c2b466 100644 --- a/src/main/groovy/yakworks/gradle/GradleHelpers.groovy +++ b/src/main/groovy/yakworks/gradle/GradleHelpers.groovy @@ -11,7 +11,7 @@ import groovy.transform.CompileStatic import org.gradle.api.Project -import yakworks.commons.Props +import yakworks.commons.lang.NameUtils @CompileStatic class GradleHelpers { @@ -57,7 +57,7 @@ class GradleHelpers { } else if (System.properties[prop]) { return System.properties[prop] } else { - return prj.findProperty(Props.toCamelCase(prop)) //returns null if not found + return prj.findProperty(NameUtils.toCamelCase(prop)) //returns null if not found } } diff --git a/src/main/groovy/yakworks/gradle/config/YamlConfigPlugin.groovy b/src/main/groovy/yakworks/gradle/config/YamlConfigPlugin.groovy index 53d062b..eebe5fc 100644 --- a/src/main/groovy/yakworks/gradle/config/YamlConfigPlugin.groovy +++ b/src/main/groovy/yakworks/gradle/config/YamlConfigPlugin.groovy @@ -79,8 +79,10 @@ class YamlConfigPlugin implements Plugin { //assign the config object GradleHelpers.prop(prj, 'config', config) - //setup core project items if they exit + + //setup core project items if they exist GradleHelpers.setPropIfEmpty(prj, 'description', config['description']) + //assign group if in config if(config['group']){ prj.allprojects { Project prjsub -> diff --git a/src/main/groovy/yakworks/gradle/shipkit/GradlePluginPlugin.groovy b/src/main/groovy/yakworks/gradle/shipkit/GradlePluginPlugin.groovy index 0001e1c..d7dd913 100644 --- a/src/main/groovy/yakworks/gradle/shipkit/GradlePluginPlugin.groovy +++ b/src/main/groovy/yakworks/gradle/shipkit/GradlePluginPlugin.groovy @@ -36,15 +36,9 @@ class GradlePluginPlugin implements Plugin { project.plugins.apply(ShippablePlugin) project.plugins.apply('groovy') project.plugins.apply(CodenarcPlugin) - //project.plugins.apply(GradlePortalReleasePlugin); - - if(!project.plugins.hasPlugin(NotShippablePlugin)){ - //JavaPublishPlugin has to get applied after the grails-plugin has been applied or it doesn't add the dependencies to the pom properly - project.plugins.apply(JavaPublishPlugin) - //this should come last after JavaPublishPlugin as it finalizes the maven setups - project.plugins.apply(PublishingRepoSetupPlugin) - // project.rootProject.plugins.apply(PublishingRepoSetupPlugin) - } + + project.plugins.apply(JavaPublishPlugin) + // project.plugins.apply(PublishingRepoSetupPlugin) } diff --git a/src/main/groovy/yakworks/gradle/shipkit/GrailsPlugin.groovy b/src/main/groovy/yakworks/gradle/shipkit/GrailsPlugin.groovy index e02419c..fcf6ab4 100644 --- a/src/main/groovy/yakworks/gradle/shipkit/GrailsPlugin.groovy +++ b/src/main/groovy/yakworks/gradle/shipkit/GrailsPlugin.groovy @@ -36,10 +36,6 @@ class GrailsPlugin implements Plugin { if(!project.plugins.hasPlugin(NotShippablePlugin)){ //JavaPublishPlugin has to get applied after the grails-plugin has been applied or it doesn't add the dependencies to the pom properly project.plugins.apply(JavaPublishPlugin) - //this should come last after JavaPublishPlugin as it finalizes the maven setups - project.plugins.apply(PublishingRepoSetupPlugin) - // project.rootProject.plugins.apply(PublishingRepoSetupPlugin) - //post processing cleanup cleanDepsInPom(project) } @@ -48,7 +44,7 @@ class GrailsPlugin implements Plugin { /** * Taken from GrailsCentralPublishGradlePlugin in grails-core. its the 'org.grails.grails-plugin-publish' - * Cleans up dependencies without versions and removes the bom dependencyManagement stuff and adds the grails-plugin.xml artefact + * Removes dependencies without versions and removes the bom dependencyManagement stuff */ @SuppressWarnings('NestedBlockDepth') @CompileDynamic @@ -56,7 +52,7 @@ class GrailsPlugin implements Plugin { project.extensions.configure PublishingExtension, new ClosureBackedAction({ publications { javaLibrary(MavenPublication) { - artifact getGrailsPluginArtifact(project) + // artifact getGrailsPluginArtifact(project) pom.withXml { Node pomNode = asNode() if (pomNode.dependencyManagement) { diff --git a/src/main/groovy/yakworks/gradle/shipkit/GroovyLibPlugin.groovy b/src/main/groovy/yakworks/gradle/shipkit/GroovyLibPlugin.groovy index fc22722..11671ad 100644 --- a/src/main/groovy/yakworks/gradle/shipkit/GroovyLibPlugin.groovy +++ b/src/main/groovy/yakworks/gradle/shipkit/GroovyLibPlugin.groovy @@ -29,9 +29,6 @@ class GroovyLibPlugin implements Plugin { if(!project.plugins.hasPlugin(NotShippablePlugin)){ //JavaPublishPlugin has to get applied after the grails-plugin has been applied or it doesn't add the dependencies to the pom properly project.plugins.apply(JavaPublishPlugin) - //this should come last after JavaPublishPlugin as it finalizes the maven setups - project.plugins.apply(PublishingRepoSetupPlugin) - // project.rootProject.plugins.apply(PublishingRepoSetupPlugin) } } } diff --git a/src/main/groovy/yakworks/gradle/shipkit/JavaPublishPlugin.groovy b/src/main/groovy/yakworks/gradle/shipkit/JavaPublishPlugin.groovy new file mode 100644 index 0000000..0a21af1 --- /dev/null +++ b/src/main/groovy/yakworks/gradle/shipkit/JavaPublishPlugin.groovy @@ -0,0 +1,184 @@ +/* +* Copyright 2021 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") +* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +*/ +package yakworks.gradle.shipkit + +import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic +import groovy.xml.QName + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.XmlProvider +import org.gradle.api.logging.Logger +import org.gradle.api.logging.Logging +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.specs.Spec +import org.gradle.api.tasks.bundling.Jar +import org.gradle.util.ClosureBackedAction + +import yakworks.commons.ConfigMap +import yakworks.gradle.util.team.TeamMember + +import static java.util.Arrays.asList +import static yakworks.gradle.util.team.TeamParser.parsePerson + +/** + * Publishing java libraries using 'maven-publish' plugin. + * Intended to be applied in individual Java submodule. + * Applies following plugins and tasks and configures them: + * + *
    + *
  • {@link JavaSourcesDocJarPlugin}
  • + *
  • maven-publish
  • + *
+ * + * Other features: + *
    + *
  • Configures Gradle's publications to publish java library
  • + *
  • Configures 'build' task to depend on 'publishJavaLibraryToMavenLocal' + * to flesh out publication issues during the build
  • + *
  • Configures 'snapshot' task to depend on 'publishJavaLibraryToMavenLocal'
  • + *
+ */ +@CompileStatic +class JavaPublishPlugin implements Plugin { + + private final static Logger LOG = Logging.getLogger(JavaPublishPlugin); + + public final static String JAVA_LIB_NAME = "javaLibrary"; + public final static String MAVEN_LOCAL_TASK = "publishJavaLibraryPublicationToMavenLocal"; + public static final String SNAPSHOT_TASK = "snapshot"; + + ConfigMap config + + @CompileDynamic + void apply(final Project project) { + + config = (ConfigMap)project.rootProject.findProperty('config') + + Task snapshotTask = project.tasks.create(SNAPSHOT_TASK) { + dependsOn MAVEN_LOCAL_TASK + description = "create local snapshot files." + group = "Shipyak" + } + + configureSnapshotTask(project, snapshotTask); + + project.getPlugins().apply(JavaSourcesDocJarPlugin); + project.getPlugins().apply("maven-publish"); + + configurePublications(project, config) + // so that we flesh out problems with maven publication during the build process + // project.getTasks().getByName("build").dependsOn(MAVEN_LOCAL_TASK); + } + + @CompileDynamic + void configurePublications(Project project, ConfigMap config) { + + final Jar sourcesJar = (Jar) project.getTasks().getByName(JavaSourcesDocJarPlugin.SOURCES_JAR_TASK); + final Jar javadocJar = (Jar) project.getTasks().getByName(JavaSourcesDocJarPlugin.JAVADOC_JAR_TASK); + + project.extensions.configure PublishingExtension, new ClosureBackedAction({ + repositories { + maven { + url config.maven.publishUrl + credentials { + username config.maven.user + password config.maven.key + } + } + } + publications { + "${JAVA_LIB_NAME}"(MavenPublication) { + from(project.components.java) + artifact(sourcesJar) + artifact(javadocJar) + setArtifactId(project.getTasks().getByName("jar").getArchiveBaseName().getOrNull()) + pom.withXml { + customizePom(project, config, it) + } + } + } + }) + } + + static boolean configureSnapshotTask(Project proj, Task snapshotTask) { + List taskNames = proj.getGradle().getStartParameter().getTaskNames() + boolean isSnapshot = taskNames.contains(SNAPSHOT_TASK); + if (isSnapshot) { + // if its not a snapshot version then make it one + String ver = proj.getVersion().toString() + if (!ver.endsWith("-SNAPSHOT")) { + proj.version = "${ver}-SNAPSHOT"; + } + // disable for now + // def withName = { Task t -> ["javadoc", "groovydoc"].contains(t.getName())} as Spec + // snapshotTask.getProject().getTasks().matching(withName("javadoc", "groovydoc")).all(doc -> { + // LOG.info("{} - disabled to speed up the 'snapshot' build", snapshotTask.getPath()); + // doc.setEnabled(false); + // }); + } + return isSnapshot; + } + + void customizePom(final Project project, final ConfigMap config, final XmlProvider xml) { + String archivesBaseName = (String) project.getProperties().get("archivesBaseName"); + File contributorsFile = new File(project.getBuildDir(), "/shipkit/all-contributors.json") + LOG.info(" Read project contributors from file: " + contributorsFile.getAbsolutePath()); + + String projjDesc = project.description ?: project.rootProject.description + + final boolean isAndroidLibrary = project.getPlugins().hasPlugin("com.android.library"); + customizePom(xml.asNode(), config, archivesBaseName, projjDesc, isAndroidLibrary); + } + + /** + * Customizes pom xml based on the provide configuration and settings + */ + @SuppressWarnings('ExplicitCallToGetAtMethod') + void customizePom(Node root, ConfigMap config, + String projectName, String projectDescription, + boolean isAndroidLibrary) { + //TODO: we need to conditionally append nodes because given node may already be on the root (issue 847) + //TODO: all root.appendNode() need to be conditional + root.appendNode("name", projectName); + + if (!isAndroidLibrary && root.getAt(new QName("packaging")).isEmpty()) { + root.appendNode("packaging", "jar"); + } + + String repoLink = config['project']['repoUrl'] + root.appendNode("url", repoLink); + + if (projectDescription != null) { + root.appendNode("description", projectDescription); + } + + Node license = root.appendNode("licenses").appendNode("license"); + license.appendNode("name", config['license']); + license.appendNode("url", repoLink + "/blob/master/LICENSE"); + license.appendNode("distribution", "repo"); + + root.appendNode("scm").appendNode("url", repoLink + ".git"); + + Node issues = root.appendNode("issueManagement"); + issues.appendNode("url", repoLink + "/issues"); + issues.appendNode("system", "GitHub issues"); + + if (config['team']['developers']) { + Node developers = root.appendNode("developers"); + for (String notation : config['team']['developers']) { + TeamMember person = parsePerson(notation); + Node d = developers.appendNode("developer"); + d.appendNode("id", person.gitHubUser); + d.appendNode("name", person.name); + d.appendNode("roles").appendNode("role", "Core developer"); + d.appendNode("url", "https://github.com/${person.gitHubUser}"); + } + } + } +} diff --git a/src/main/groovy/yakworks/gradle/shipkit/JavaPublishPlugin.java b/src/main/groovy/yakworks/gradle/shipkit/JavaPublishPlugin.java deleted file mode 100644 index 61ce2dc..0000000 --- a/src/main/groovy/yakworks/gradle/shipkit/JavaPublishPlugin.java +++ /dev/null @@ -1,97 +0,0 @@ -package yakworks.gradle.shipkit; - -import org.gradle.api.Plugin; -import org.gradle.api.Project; -import org.gradle.api.Task; -import org.gradle.api.logging.Logger; -import org.gradle.api.logging.Logging; -import org.gradle.api.publish.maven.MavenPublication; -import org.gradle.api.specs.Spec; -import org.gradle.api.tasks.bundling.Jar; - -import yakworks.commons.ConfigMap; -import yakworks.gradle.util.GradleDSLHelper; -import yakworks.gradle.util.PomCustomizer; -import yakworks.gradle.util.StringUtil; -import yakworks.gradle.util.TaskMaker; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static java.util.Arrays.asList; - -/** - * Publishing java libraries using 'maven-publish' plugin. - * Intended to be applied in individual Java submodule. - * Applies following plugins and tasks and configures them: - * - *
    - *
  • {@link JavaSourcesDocJarPlugin}
  • - *
  • maven-publish
  • - *
- * - * Other features: - *
    - *
  • Configures Gradle's publications to publish java library
  • - *
  • Configures 'build' task to depend on 'publishJavaLibraryToMavenLocal' - * to flesh out publication issues during the build
  • - *
  • Configures 'snapshot' task to depend on 'publishJavaLibraryToMavenLocal'
  • - *
- */ -public class JavaPublishPlugin implements Plugin { - - private final static Logger LOG = Logging.getLogger(JavaPublishPlugin.class); - - public final static String PUBLICATION_NAME = "javaLibrary"; - public final static String POM_TASK = "generatePomFileFor" + StringUtil.capitalize(PUBLICATION_NAME) + "Publication"; - public final static String MAVEN_LOCAL_TASK = "publish" + StringUtil.capitalize(PUBLICATION_NAME) + "PublicationToMavenLocal"; - public static final String SNAPSHOT_TASK = "snapshot"; - - public void apply(final Project project) { - - ConfigMap config = project.getRootProject().getPlugins().apply(YamlConfigShipYakPlugin.class).getConfig(); - - Task snapshotTask = TaskMaker.task(project, SNAPSHOT_TASK, t -> { - t.setDescription("create local snapshot files."); - }); - snapshotTask.dependsOn(MAVEN_LOCAL_TASK); - configureSnapshotTask(snapshotTask, project.getGradle().getStartParameter().getTaskNames()); - - project.getPlugins().apply(JavaSourcesDocJarPlugin.class); - project.getPlugins().apply("maven-publish"); - - final Jar sourcesJar = (Jar) project.getTasks().getByName(JavaSourcesDocJarPlugin.SOURCES_JAR_TASK); - final Jar javadocJar = (Jar) project.getTasks().getByName(JavaSourcesDocJarPlugin.JAVADOC_JAR_TASK); - - GradleDSLHelper.publications(project, publications -> { - MavenPublication p = publications.create(PUBLICATION_NAME, MavenPublication.class, publication -> { - publication.from(project.getComponents().getByName("java")); - publication.artifact(sourcesJar); - publication.artifact(javadocJar); - publication.setArtifactId(((Jar) project.getTasks().getByName("jar")).getArchiveBaseName().getOrNull()); - PomCustomizer.customizePom(project, config, publication); - }); - LOG.info("{} - configured '{}' publication", project.getPath(), p.getArtifactId()); - }); - - //so that we flesh out problems with maven publication during the build process - project.getTasks().getByName("build").dependsOn(MAVEN_LOCAL_TASK); - } - - static boolean configureSnapshotTask(Task snapshotTask, List taskNames) { - boolean isSnapshot = taskNames.contains(SNAPSHOT_TASK); - if (isSnapshot) { - snapshotTask.getProject().getTasks().matching(withName("javadoc", "groovydoc")).all(doc -> { - LOG.info("{} - disabled to speed up the 'snapshot' build", snapshotTask.getPath()); - doc.setEnabled(false); - }); - } - return isSnapshot; - } - - public static Spec withName(final String... names) { - Set namesSet = new HashSet<>(asList(names)); - return t -> namesSet.contains(t.getName()); - } -} diff --git a/src/main/groovy/yakworks/gradle/shipkit/PublishingRepoSetupPlugin.groovy b/src/main/groovy/yakworks/gradle/shipkit/PublishingRepoSetupPlugin.groovy deleted file mode 100644 index 77b5a3a..0000000 --- a/src/main/groovy/yakworks/gradle/shipkit/PublishingRepoSetupPlugin.groovy +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") -* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -*/ -package yakworks.gradle.shipkit - -import groovy.transform.CompileDynamic - -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.logging.Logger -import org.gradle.api.logging.Logging -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.plugins.MavenPublishPlugin -import org.gradle.util.ClosureBackedAction - -import yakworks.commons.ConfigMap - -/** - * Finalize setup for Maven (artifactory) based on isSnapshot - * Should be applied after JavaPublishPlugin so that can do the maven setups first - * only apply on rootprojects - */ -@CompileDynamic -class PublishingRepoSetupPlugin implements Plugin { - private final static Logger LOG = Logging.getLogger(PublishingRepoSetupPlugin) - - ConfigMap config - - void apply(Project project) { - // ProjectUtil.requireRootProject(rootProject, this.getClass()) - config = project.rootProject.config - - setupMavenPublishRepo(project) - } - - @CompileDynamic - void setupMavenPublishRepo(Project project){ - project.plugins.withType(MavenPublishPlugin) { - project.extensions.configure PublishingExtension, new ClosureBackedAction({ - repositories { - maven { - url config.maven.publishUrl - credentials { - username config.maven.user - password config.maven.key - } - } - } - }) - } - } - -} diff --git a/src/main/groovy/yakworks/gradle/util/ArgumentValidation.java b/src/main/groovy/yakworks/gradle/util/ArgumentValidation.java deleted file mode 100644 index 81bbb08..0000000 --- a/src/main/groovy/yakworks/gradle/util/ArgumentValidation.java +++ /dev/null @@ -1,31 +0,0 @@ -package yakworks.gradle.util; - -/** - * Utility for validation of arguments - */ -public abstract class ArgumentValidation { - - /** - * None of the input targets can not be null otherwise IllegalArgumentException is thrown. - * Every second argument must a String describing the previous element. - */ - public static void notNull(Object... targets) { - if (targets.length % 2 != 0) { - throw new IllegalArgumentException("notNull method requires pairs of argument + message"); - } - - boolean nullFound = false; - for (Object t : targets) { - if (t == null) { - nullFound = true; - continue; - } - if (nullFound) { - if (!(t instanceof String)) { - throw new IllegalArgumentException("notNull method requires pairs of argument + message"); - } - throw new IllegalArgumentException(((String) t).concat(" cannot be null.")); - } - } - } -} diff --git a/src/main/groovy/yakworks/gradle/util/BuildConventions.java b/src/main/groovy/yakworks/gradle/util/BuildConventions.java deleted file mode 100644 index bb28cdd..0000000 --- a/src/main/groovy/yakworks/gradle/util/BuildConventions.java +++ /dev/null @@ -1,25 +0,0 @@ -package yakworks.gradle.util; - -import org.gradle.api.Project; - -import java.io.File; - -/** - * Conventions and defaults used by the build - */ -public class BuildConventions { - - /** - * Returns file object for storing contributors. - */ - public static File contributorsFile(Project project) { - return outputFile(project.getRootProject(), "all-contributors.json"); - } - - /** - * Returns file object in a standard location where we put other output files generated during the build. - */ - private static File outputFile(Project project, String fileName) { - return new File(project.getBuildDir(), "/shipkit/" + fileName); - } -} diff --git a/src/main/groovy/yakworks/gradle/util/GradleDSLHelper.groovy b/src/main/groovy/yakworks/gradle/util/GradleDSLHelper.groovy deleted file mode 100644 index 5499deb..0000000 --- a/src/main/groovy/yakworks/gradle/util/GradleDSLHelper.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* -* Copyright 2021 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") -* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -*/ -package yakworks.gradle.util - -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic - -import org.gradle.api.Action -import org.gradle.api.Project -import org.gradle.api.publish.PublicationContainer - -/** - * Useful to work around Gradle API that requires the use of Groovy. - */ -@CompileStatic -class GradleDSLHelper { - - /** - * Needed because we cannot access publications or publishing normally via Java - * Doing so will "resolve" the publications too early and things would not work - * For example, pom would not have dependencies - */ - @CompileDynamic - static void publications(Project project, Action action) { - project.publishing { - action.execute(publications) - } - } -} diff --git a/src/main/groovy/yakworks/gradle/util/IOUtil.java b/src/main/groovy/yakworks/gradle/util/IOUtil.java deleted file mode 100644 index cd2a6af..0000000 --- a/src/main/groovy/yakworks/gradle/util/IOUtil.java +++ /dev/null @@ -1,148 +0,0 @@ -package yakworks.gradle.util; - -import java.io.BufferedInputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Scanner; - -/** - * IO utils. A bit of reinventing the wheel but we don't want extra dependencies at this stage and we want to be java. - */ -public class IOUtil { - - /** - * Reads string from the file - */ - public static String readFully(File input) { - try { - return readNow(new FileInputStream(input)); - } catch (Exception e) { - throw new RuntimeException("Problems reading file: " + input, e); - } - } - - /** - * Reads string from the file or returns empty text if file doesn't exist or can't open - */ - public static String readFullyOrDefault(File input, String defaultValue) { - try { - return readNow(new FileInputStream(input)); - } catch (Exception e) { - //TODO this potentially swallows exceptions - //if the file does not exist, we should just use default value - //if the file cannot be read, we should write a message to the log that we cannot use the file - // + stack trace in debug level - return defaultValue; - } - } - - /** - * Reads string from the stream and closes it - */ - public static String readFully(InputStream stream) { - try { - return readNow(stream); - } catch (Exception e) { - throw new RuntimeException("Problems reading stream", e); - } - } - - /** - * Closes the target. Does nothing when target is null. Is not silent, throws exception on IOException. - * - * @param closeable the target, may be null - */ - public static void close(Closeable closeable) { - close(closeable, false); - } - - private static void close(Closeable closeable, boolean quietly) { - if (closeable != null) { - try { - closeable.close(); - } catch (IOException e) { - if (!quietly) { - throw new RuntimeException("Problems closing closeable", e); - } - } - } - } - - /** - * Closes the target. Does nothing when target is null. Is silent. - * - * @param closeable the target, may be null - */ - public static void closeQuietly(Closeable closeable) { - close(closeable, true); - } - - public static void createParentDirectory(File file) { - createDirectory(file.getParentFile()); - } - - public static void createDirectory(File file) { - if (!file.exists()) { - createDirectory(file.getParentFile()); - file.mkdir(); - } - } - - /** - * Downloads resource and saves it to a given file - * @param url location of resource to download - * @param file destination file (not a directory!) where downloaded content will be stored - * (file or its parent directories don't need to exist) - */ - public static void downloadToFile(String url, File file) { - InputStream input = null; - try { - input = new BufferedInputStream(new URL(url).openStream()); - - IOUtil.createParentDirectory(file); - - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - byte[] buf = new byte[1024]; - int n; - while ((n = input.read(buf)) != -1) { - fos.write(buf, 0, n); - } - } finally { - closeQuietly(fos); - } - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - closeQuietly(input); - } - } - - private static String readNow(InputStream is) { - try (Scanner s = new Scanner(is, StandardCharsets.UTF_8.name()).useDelimiter("\\A")) { - return s.hasNext() ? s.next() : ""; - } - } - - public static void writeFile(File target, String content) { - PrintWriter p = null; - try { - target.getParentFile().mkdirs(); - p = new PrintWriter(new OutputStreamWriter(new FileOutputStream(target), StandardCharsets.UTF_8)); - p.write(content); - } catch (Exception e) { - throw new RuntimeException("Problems writing text to file: " + target, e); - } finally { - close(p); - } - } -} diff --git a/src/main/groovy/yakworks/gradle/util/PomCustomizer.groovy b/src/main/groovy/yakworks/gradle/util/PomCustomizer.groovy deleted file mode 100644 index 7d19e98..0000000 --- a/src/main/groovy/yakworks/gradle/util/PomCustomizer.groovy +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Copyright 2021 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") -* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -*/ -package yakworks.gradle.util - -import groovy.transform.CompileStatic -import groovy.xml.QName - -import org.gradle.api.Action -import org.gradle.api.Project -import org.gradle.api.XmlProvider -import org.gradle.api.logging.Logger -import org.gradle.api.logging.Logging -import org.gradle.api.publish.maven.MavenPublication - -import yakworks.commons.ConfigMap -import yakworks.gradle.util.team.TeamMember - -import static yakworks.gradle.util.BuildConventions.contributorsFile -import static yakworks.gradle.util.team.TeamParser.parsePerson - -/** - * Customizes the pom file. Intended to be used with Gradle's 'maven-publish' plugin. - */ -@CompileStatic -class PomCustomizer { - - private static final Logger LOG = Logging.getLogger(PomCustomizer); - - /** - * Customizes the pom. The method requires following properties on root project to function correctly: - */ - public static void customizePom(final Project project, final ConfigMap config, final MavenPublication publication) { - publication.getPom().withXml(new Action() { - public void execute(XmlProvider xml) { - String archivesBaseName = (String) project.getProperties().get("archivesBaseName"); - File contributorsFile = contributorsFile(project); - LOG.info(" Read project contributors from file: " + contributorsFile.getAbsolutePath()); - - final boolean isAndroidLibrary = project.getPlugins().hasPlugin("com.android.library"); - customizePom(xml.asNode(), config, archivesBaseName, project.getDescription(), isAndroidLibrary); - } - }); - } - - /** - * Customizes pom xml based on the provide configuration and settings - */ - @SuppressWarnings('ExplicitCallToGetAtMethod') - static void customizePom(Node root, ConfigMap config, - String projectName, String projectDescription, - boolean isAndroidLibrary) { - //TODO: we need to conditionally append nodes because given node may already be on the root (issue 847) - //TODO: all root.appendNode() need to be conditional - root.appendNode("name", projectName); - - if (!isAndroidLibrary && root.getAt(new QName("packaging")).isEmpty()) { - root.appendNode("packaging", "jar"); - } - - String repoLink = config['project']['repoUrl'] - root.appendNode("url", repoLink); - if (projectDescription != null) { - root.appendNode("description", projectDescription); - } - - Node license = root.appendNode("licenses").appendNode("license"); - license.appendNode("name", config['license']); - license.appendNode("url", repoLink + "/blob/master/LICENSE"); - license.appendNode("distribution", "repo"); - - root.appendNode("scm").appendNode("url", repoLink + ".git"); - - Node issues = root.appendNode("issueManagement"); - issues.appendNode("url", repoLink + "/issues"); - issues.appendNode("system", "GitHub issues"); - - if (config['team']['developers']) { - Node developers = root.appendNode("developers"); - for (String notation : config['team']['developers']) { - TeamMember person = parsePerson(notation); - Node d = developers.appendNode("developer"); - d.appendNode("id", person.gitHubUser); - d.appendNode("name", person.name); - d.appendNode("roles").appendNode("role", "Core developer"); - d.appendNode("url", "https://github.com/${person.gitHubUser}"); - } - } - } -} diff --git a/src/main/groovy/yakworks/gradle/util/PropertiesUtil.groovy b/src/main/groovy/yakworks/gradle/util/PropertiesUtil.groovy new file mode 100644 index 0000000..621ec5a --- /dev/null +++ b/src/main/groovy/yakworks/gradle/util/PropertiesUtil.groovy @@ -0,0 +1,16 @@ +/* +* Copyright 2021 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") +* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +*/ +package yakworks.gradle.util + +public class PropertiesUtil { + + public static Properties readProperties(File propertiesFile) { + Properties p = new Properties() + propertiesFile.withInputStream { + p.load(it) + } + return p + } +} diff --git a/src/main/groovy/yakworks/gradle/util/PropertiesUtil.java b/src/main/groovy/yakworks/gradle/util/PropertiesUtil.java deleted file mode 100644 index 39bd772..0000000 --- a/src/main/groovy/yakworks/gradle/util/PropertiesUtil.java +++ /dev/null @@ -1,22 +0,0 @@ -package yakworks.gradle.util; - -import java.io.File; -import java.io.FileReader; -import java.util.Properties; - -public class PropertiesUtil { - - public static Properties readProperties(File properties) { - Properties p = new Properties(); - FileReader reader = null; - try { - reader = new FileReader(properties); - p.load(reader); - } catch (Exception e) { - throw new RuntimeException("Problems reading properties file: " + properties, e); - } finally { - IOUtil.close(reader); - } - return p; - } -} diff --git a/src/main/groovy/yakworks/gradle/util/StringUtil.groovy b/src/main/groovy/yakworks/gradle/util/StringUtil.groovy deleted file mode 100644 index 6b80c7a..0000000 --- a/src/main/groovy/yakworks/gradle/util/StringUtil.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright 2021 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") -* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -*/ -package yakworks.gradle.util - -import groovy.transform.CompileStatic - -/** - * String utilities. - */ -@CompileStatic -class StringUtil { - - //TODO (maybe) convert to Java at some point - - /** - * Classic string join - */ - static String join(Collection collection, String separator) { - return collection.join(separator) - } - - /** - * Capitalizes string - */ - static String capitalize(String input) { - return input.capitalize() - } - - /** - * Checks if input is empty, if input is not null its 'toString()' value will be used. - */ - static boolean isEmpty(Object input) { - return input == null || isEmpty(input.toString()) - } - - /** - * Checks if input is empty - */ - static boolean isEmpty(String input) { - return input == null || input.isEmpty() - } -} diff --git a/src/main/groovy/yakworks/gradle/util/TaskMaker.java b/src/main/groovy/yakworks/gradle/util/TaskMaker.java deleted file mode 100644 index c5aaa77..0000000 --- a/src/main/groovy/yakworks/gradle/util/TaskMaker.java +++ /dev/null @@ -1,39 +0,0 @@ -package yakworks.gradle.util; - -import org.gradle.api.Action; -import org.gradle.api.Project; -import org.gradle.api.Task; - -/** - * Handy class that should be used to create tasks. - * It ensures the correct defaults are used by tasks. - * It also adds consistent logging for some kinds of tasks (like exec tasks). - */ -public class TaskMaker { - - /** - * Creates task with preconfigured defaults - */ - public static Task task(Project project, String name, Action configure) { - Task task = project.getTasks().create(name); - return configure(configure, task); - } - - /** - * Creates task of specific type with preconfigured defaults - */ - public static T task(Project project, String name, Class taskType, Action configure) { - T task = project.getTasks().create(name, taskType); - return configure(configure, task); - } - - private static T configure(Action configure, T task) { - task.setGroup("Shipkit"); - configure.execute(task); - if (task.getDescription() == null) { - //TODO unit testable - throw new IllegalArgumentException("Please provide description for the task!"); - } - return task; - } -} diff --git a/src/main/groovy/yakworks/gradle/util/team/TeamParser.java b/src/main/groovy/yakworks/gradle/util/team/TeamParser.java index bec0eb1..f575faf 100644 --- a/src/main/groovy/yakworks/gradle/util/team/TeamParser.java +++ b/src/main/groovy/yakworks/gradle/util/team/TeamParser.java @@ -4,7 +4,6 @@ import java.util.Collection; -import static yakworks.gradle.util.ArgumentValidation.notNull; public class TeamParser { @@ -21,7 +20,8 @@ public static class InvalidInput extends GradleException { } public static TeamMember parsePerson(String notation) throws InvalidInput { - notNull(notation, "Team member notation cannot be null"); + //FIXME replace with Validate + // notNull(notation, "Team member notation cannot be null"); String[] split = notation.split(":"); if (split.length != 2) { throw invalidInput(notation); diff --git a/src/test/groovy/yakworks/commons/MapsSpec.groovy b/src/test/groovy/yakworks/commons/map/MapsSpec.groovy similarity index 92% rename from src/test/groovy/yakworks/commons/MapsSpec.groovy rename to src/test/groovy/yakworks/commons/map/MapsSpec.groovy index 9f7516a..308e257 100644 --- a/src/test/groovy/yakworks/commons/MapsSpec.groovy +++ b/src/test/groovy/yakworks/commons/map/MapsSpec.groovy @@ -2,12 +2,12 @@ * Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License") * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 */ -package yakworks.commons +package yakworks.commons.map import spock.lang.Specification +import yakworks.commons.map.Maps class MapsSpec extends Specification { - def instance = new Maps() def "merge a single map should return it self"(){ @@ -35,7 +35,7 @@ class MapsSpec extends Specification { baz: 'qux' ] then: - assertMapsEqual(expected, instance.merge(m0, m1)) + assertMapsEqual(expected, Maps.merge(m0, m1)) } void testMerge_Two_NoNesting_WithOverwriting () { @@ -52,7 +52,7 @@ class MapsSpec extends Specification { foo: 'baz' ] then: - assertMapsEqual(expected, instance.merge(m0, m1)) + assertMapsEqual(expected, Maps.merge(m0, m1)) } @@ -74,7 +74,7 @@ class MapsSpec extends Specification { foo: 'qux' ] then: - assertMapsEqual(expected, instance.merge(m0, m1, m2)) + assertMapsEqual(expected, Maps.merge(m0, m1, m2)) } void testMerge_Two_NestedOneLevel_NoOverwriting () { @@ -100,7 +100,7 @@ class MapsSpec extends Specification { ] ] then: - assertMapsEqual(expected, instance.merge(m0, m1)) + assertMapsEqual(expected, Maps.merge(m0, m1)) } @@ -130,7 +130,7 @@ class MapsSpec extends Specification { ] ] then: - assertMapsEqual(expected, instance.merge(m0, m1)) + assertMapsEqual(expected, Maps.merge(m0, m1)) } @@ -190,7 +190,7 @@ class MapsSpec extends Specification { quiver: 'shatter' ] then: - assertMapsEqual(expected, instance.merge(m0, m1, m2)) + assertMapsEqual(expected, Maps.merge(m0, m1, m2)) } @@ -217,7 +217,7 @@ class MapsSpec extends Specification { ] ] then: - assertMapsEqual(expected, instance.merge(m0, m1)) + assertMapsEqual(expected, Maps.merge(m0, m1)) } void deepPrune () { diff --git a/version.properties b/version.properties index 00e6c12..5adab5c 100644 --- a/version.properties +++ b/version.properties @@ -10,4 +10,4 @@ publishedVersion=2.6.5 # when this is true will append -SNAPSHOT to version and 'publish' to snapshotUrl # when false production publish to repoUrl and ... # go through release process to automatically bump version and push a v tag to github -snapshot=true +snapshot=false