diff --git a/core/jreleaser-assemblers/src/main/java/org/jreleaser/assemblers/JlinkAssemblerProcessor.java b/core/jreleaser-assemblers/src/main/java/org/jreleaser/assemblers/JlinkAssemblerProcessor.java index 5b00dbfe..acb12bf4 100644 --- a/core/jreleaser-assemblers/src/main/java/org/jreleaser/assemblers/JlinkAssemblerProcessor.java +++ b/core/jreleaser-assemblers/src/main/java/org/jreleaser/assemblers/JlinkAssemblerProcessor.java @@ -203,8 +203,8 @@ public class JlinkAssemblerProcessor extends AbstractAssemblerProcessor { // resolve all first paths.add(assembler.getMainJar().getEffectivePath(context, assembler)); for (Glob glob : assembler.getJars()) { - glob.getResolvedPaths(context).stream() - .filter(Files::isRegularFile) + glob.getResolvedArtifacts(context).stream() + .map(artifact -> artifact.getResolvedPath(context, assembler)) .forEach(paths::add); } @@ -227,8 +227,8 @@ public class JlinkAssemblerProcessor extends AbstractAssemblerProcessor { // resolve all first for (Glob glob : assembler.getFiles()) { - glob.getResolvedPaths(context).stream() - .filter(Files::isRegularFile) + glob.getResolvedArtifacts(context).stream() + .map(artifact -> artifact.getResolvedPath(context, assembler)) .forEach(paths::add); } diff --git a/core/jreleaser-assemblers/src/main/java/org/jreleaser/assemblers/NativeImageAssemblerProcessor.java b/core/jreleaser-assemblers/src/main/java/org/jreleaser/assemblers/NativeImageAssemblerProcessor.java index cd868b01..6975e001 100644 --- a/core/jreleaser-assemblers/src/main/java/org/jreleaser/assemblers/NativeImageAssemblerProcessor.java +++ b/core/jreleaser-assemblers/src/main/java/org/jreleaser/assemblers/NativeImageAssemblerProcessor.java @@ -204,8 +204,8 @@ public class NativeImageAssemblerProcessor extends AbstractAssemblerProcessor artifact.getResolvedPath(context, assembler)) .forEach(paths::add); } @@ -228,8 +228,8 @@ public class NativeImageAssemblerProcessor extends AbstractAssemblerProcessor artifact.getResolvedPath(context, assembler)) .forEach(paths::add); } diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/Glob.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/Glob.java index f90321ed..b803e17b 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/Glob.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/Glob.java @@ -17,6 +17,9 @@ */ package org.jreleaser.model; +import org.jreleaser.model.util.Artifacts; + +import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; @@ -30,26 +33,78 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static java.nio.file.FileVisitResult.CONTINUE; import static java.nio.file.FileVisitResult.SKIP_SUBTREE; import static java.nio.file.Files.exists; import static org.jreleaser.util.MustacheUtils.applyTemplate; +import static org.jreleaser.util.StringUtils.isBlank; import static org.jreleaser.util.StringUtils.isNotBlank; /** * @author Andres Almiray * @since 0.1.0 */ -public class Glob implements Domain { +public class Glob implements Domain, ExtraProperties { + private static final String GLOB_PREFIX = "glob:"; + private static final String REGEX_PREFIX = "regex:"; + + private final Map extraProperties = new LinkedHashMap<>(); + + private String pattern; + private Set artifacts; + private String directory; private String include; private String exclude; private Boolean recursive; - private Set paths; - public Set getResolvedPaths(JReleaserContext context) { - if (null == paths) { + void setAll(Glob glob) { + this.pattern = glob.pattern; + setExtraProperties(glob.extraProperties); + } + + @Override + public String getPrefix() { + return "glob"; + } + + @Override + public Map getExtraProperties() { + return extraProperties; + } + + @Override + public void setExtraProperties(Map extraProperties) { + this.extraProperties.clear(); + this.extraProperties.putAll(extraProperties); + } + + @Override + public void addExtraProperties(Map extraProperties) { + this.extraProperties.putAll(extraProperties); + } + + public Set getResolvedArtifacts(JReleaserContext context) { + return isNotBlank(pattern) ? getResolvedArtifactsPattern(context) : getResolvedArtifactsLegacy(context); + } + + public Set getResolvedArtifactsPattern(JReleaserContext context) { + if (null == artifacts) { + artifacts = Artifacts.resolveFiles(context, Collections.singletonList(pattern)); + artifacts.forEach(artifact -> { + if (context.isPlatformSelected(artifact)) artifact.activate(); + artifact.setExtraProperties(getExtraProperties()); + }); + } + + return artifacts; + } + + @Deprecated + public Set getResolvedArtifactsLegacy(JReleaserContext context) { + if (null == artifacts) { // resolve directory Path path = context.getBasedir(); if (isNotBlank(directory)) { @@ -73,16 +128,50 @@ public class Glob implements Domain { throw new JReleaserException("Could not resolve glob " + this.asMap(true)); } - paths = fileCollector.getFiles(); + artifacts = fileCollector.getFiles().stream() + .map(p -> Artifact.of(p, getExtraProperties())) + .peek(a -> { + if (context.isPlatformSelected(a)) a.activate(); + }) + .collect(Collectors.toSet()); + Artifact.sortArtifacts(artifacts); + } + return artifacts; + } + + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + if (isBlank(pattern)) return; + + if (pattern.startsWith(GLOB_PREFIX) || pattern.startsWith(REGEX_PREFIX)) { + this.pattern = pattern.trim(); + } else { + this.pattern = GLOB_PREFIX + pattern.trim(); + } + + if (this.pattern.startsWith(GLOB_PREFIX)) { + String path = this.pattern.substring(GLOB_PREFIX.length()); + if (!Paths.get(path).isAbsolute()) { + this.pattern = GLOB_PREFIX + "**" + File.separator + path; + } + } else { + String path = this.pattern.substring(REGEX_PREFIX.length()); + if (!Paths.get(path).isAbsolute()) { + this.pattern = REGEX_PREFIX + ".*" + File.separator + path; + } } - return paths; } public String getDirectory() { return directory; } + @Deprecated public void setDirectory(String directory) { + System.out.println("glob.directory has been deprecated since 0.6.0 and will be removed in the future. Use glob.pattern instead"); this.directory = directory; } @@ -90,7 +179,9 @@ public class Glob implements Domain { return include; } + @Deprecated public void setInclude(String include) { + System.out.println("glob.include has been deprecated since 0.6.0 and will be removed in the future. Use glob.pattern instead"); this.include = include; } @@ -98,7 +189,9 @@ public class Glob implements Domain { return exclude; } + @Deprecated public void setExclude(String exclude) { + System.out.println("glob.exclude has been deprecated since 0.6.0 and will be removed in the future. Use glob.pattern instead"); this.exclude = exclude; } @@ -106,7 +199,9 @@ public class Glob implements Domain { return recursive != null && recursive; } + @Deprecated public void setRecursive(Boolean recursive) { + System.out.println("glob.recursive has been deprecated since 0.6.0 and will be removed in the future. Use glob.pattern instead"); this.recursive = recursive; } @@ -116,12 +211,14 @@ public class Glob implements Domain { @Override public Map asMap(boolean full) { - Map map = new LinkedHashMap<>(); - map.put("directory", directory); - map.put("include", include); - map.put("exclude", exclude); - map.put("recursive", isRecursive()); - return map; + Map props = new LinkedHashMap<>(); + props.put("pattern", pattern); + props.put("extraProperties", getResolvedExtraProperties()); + props.put("directory", directory); + props.put("include", include); + props.put("exclude", exclude); + if (isBlank(pattern)) props.put("recursive", isRecursive()); + return props; } public static class FileCollector extends SimpleFileVisitor { @@ -165,7 +262,7 @@ public class Glob implements Domain { if (null != excludeMatcher && excludeMatcher.matches(fileName)) { return false; } - files.add(file); + if (java.nio.file.Files.isRegularFile(file)) files.add(file); } return null == excludeMatcher || !excludeMatcher.matches(fileName); } diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/SdkmanAnnouncer.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/SdkmanAnnouncer.java index 85445eb5..84af9417 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/SdkmanAnnouncer.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/SdkmanAnnouncer.java @@ -118,6 +118,7 @@ public class SdkmanAnnouncer extends AbstractAnnouncer { return command == Sdkman.Command.MAJOR; } + @Deprecated public void setMajor(boolean major) { System.out.println("announce.sdkman.major has been deprecated since 0.6.0 and will be removed in the future. Use announce.sdkman.command instead"); this.command = major? Sdkman.Command.MAJOR: Sdkman.Command.MINOR; diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/util/Artifacts.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/util/Artifacts.java index 8bb637ce..0eb5bf71 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/util/Artifacts.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/util/Artifacts.java @@ -37,11 +37,13 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import static java.nio.file.FileVisitResult.CONTINUE; import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static org.jreleaser.util.MustacheUtils.applyTemplate; /** * @author Andres Almiray @@ -78,9 +80,8 @@ public class Artifacts { // resolve globs for (Glob glob : files.getGlobs()) { - for (Path path : glob.getResolvedPaths(context)) { - Artifact artifact = Artifact.of(path); - artifact.activate(); + for (Artifact artifact : glob.getResolvedArtifacts(context)) { + if (!artifact.isActive()) continue; paths.add(artifact); } } @@ -114,6 +115,37 @@ public class Artifacts { } } + public static Set resolveFiles(JReleaserLogger logger, + Map props, + Path basedir, + Collection globs) throws JReleaserException { + if (null == globs || globs.isEmpty()) { + return Collections.emptySet(); + } + + FileSystem fileSystem = FileSystems.getDefault(); + List matchers = new ArrayList<>(); + for (String glob : globs) { + matchers.add(fileSystem.getPathMatcher(applyTemplate(glob, props))); + } + + GlobResolver resolver = new GlobResolver(logger, basedir, matchers); + try { + java.nio.file.Files.walkFileTree(basedir, resolver); + if (resolver.failed) { + throw new JReleaserException("Some globs failed to be resolved."); + } + + return Artifact.sortArtifacts(resolver.artifacts); + } catch (IOException e) { + throw new JReleaserException("Unexpected error when resolving globs", e); + } + } + + public static Set resolveFiles(JReleaserContext context, Collection globs) throws JReleaserException { + return resolveFiles(context.getLogger(), context.props(), context.getBasedir(), globs); + } + private static class GlobResolver extends SimpleFileVisitor { private final JReleaserLogger logger; private final List matchers; @@ -128,10 +160,9 @@ public class Artifacts { } private void match(Path path) { - if (matchers.stream().anyMatch(matcher -> matcher.matches(path))) { - Artifact artifact = Artifact.of(path); - artifact.activate(); - artifacts.add(artifact); + if (matchers.stream() + .anyMatch(matcher -> matcher.matches(path))) { + artifacts.add(Artifact.of(path)); } } diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/FilesValidator.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/FilesValidator.java index 62a7cad5..1e57493b 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/FilesValidator.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/FilesValidator.java @@ -17,12 +17,9 @@ */ package org.jreleaser.model.validation; -import org.jreleaser.model.Glob; import org.jreleaser.model.JReleaserContext; import org.jreleaser.util.Errors; -import static org.jreleaser.util.StringUtils.isBlank; - /** * @author Andres Almiray * @since 0.1.0 @@ -40,26 +37,6 @@ public abstract class FilesValidator extends Validator { if (context.isPlatformSelected(artifact)) artifact.activate(); }); - int i = 0; - for (Glob glob : context.getModel().getFiles().getGlobs()) { - boolean isBaseDir = false; - - if (isBlank(glob.getDirectory())) { - glob.setDirectory("."); - isBaseDir = true; - } - - boolean includeAll = false; - if (isBlank(glob.getInclude())) { - glob.setInclude("*"); - includeAll = true; - } - - if (isBlank(glob.getExclude()) && - includeAll && isBaseDir) { - // too broad! - errors.configuration("files.glob[" + i + "] must define either a directory or an include/exclude pattern"); - } - } + validateGlobs(context, context.getModel().getFiles().getGlobs(), "files.glob", errors); } } \ No newline at end of file diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/JlinkValidator.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/JlinkValidator.java index 0272960c..3d26a50d 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/JlinkValidator.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/JlinkValidator.java @@ -19,7 +19,6 @@ package org.jreleaser.model.validation; import org.jreleaser.model.Active; import org.jreleaser.model.Artifact; -import org.jreleaser.model.Glob; import org.jreleaser.model.JReleaserContext; import org.jreleaser.model.Jlink; import org.jreleaser.model.Project; @@ -120,27 +119,10 @@ public abstract class JlinkValidator extends Validator { errors.configuration("jlink." + jlink.getName() + ".mainJar.path must not be null"); } - i = 0; - for (Glob glob : jlink.getJars()) { - boolean isBaseDir = false; - - if (isBlank(glob.getDirectory())) { - glob.setDirectory("."); - isBaseDir = true; - } - - boolean includeAll = false; - if (isBlank(glob.getInclude())) { - glob.setInclude("*"); - includeAll = true; - } - - if (isBlank(glob.getExclude()) && - includeAll && isBaseDir) { - // too broad! - errors.configuration("jlink." + jlink.getName() + ".jars[" + i + "] must define either a directory or an include/exclude pattern"); - } - } + validateGlobs(context, + jlink.getJars(), + "jlink." + jlink.getName() + ".jars", + errors); if (mode != JReleaserContext.Mode.FULL) { validateTemplate(context, jlink, errors); diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/NativeImageValidator.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/NativeImageValidator.java index 15c89ed0..605688be 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/NativeImageValidator.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/NativeImageValidator.java @@ -18,7 +18,6 @@ package org.jreleaser.model.validation; import org.jreleaser.model.Active; -import org.jreleaser.model.Glob; import org.jreleaser.model.JReleaserContext; import org.jreleaser.model.NativeImage; import org.jreleaser.util.Errors; @@ -80,27 +79,10 @@ public abstract class NativeImageValidator extends Validator { errors.configuration("nativeImage." + nativeImage.getName() + ".mainJar.path must not be null"); } - int i = 0; - for (Glob glob : nativeImage.getJars()) { - boolean isBaseDir = false; - - if (isBlank(glob.getDirectory())) { - glob.setDirectory("."); - isBaseDir = true; - } - - boolean includeAll = false; - if (isBlank(glob.getInclude())) { - glob.setInclude("*"); - includeAll = true; - } - - if (isBlank(glob.getExclude()) && - includeAll && isBaseDir) { - // too broad! - errors.configuration("nativeImage." + nativeImage.getName() + ".jars[" + i + "] must define either a directory or an include/exclude pattern"); - } - } + validateGlobs(context, + nativeImage.getJars(), + "nativeImage." + nativeImage.getName() + ".jars", + errors); if (mode == JReleaserContext.Mode.ASSEMBLE) { validateTemplate(context, nativeImage, errors); diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/SdkmanValidator.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/SdkmanValidator.java index bfdddea6..7fbaaa85 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/SdkmanValidator.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/SdkmanValidator.java @@ -47,7 +47,7 @@ public abstract class SdkmanValidator extends Validator { boolean toolSet = tool.isActiveSet(); boolean parentToolSet = parentTool.isActiveSet(); - tool.getExtraProperties().put(MAGIC_SET, toolSet && parentToolSet); + tool.getExtraProperties().put(MAGIC_SET, toolSet || parentToolSet); if (!tool.isActiveSet() && parentTool.isActiveSet()) { tool.setActive(parentTool.getActive()); diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/Validator.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/Validator.java index 9d0b5ec1..56f794d3 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/Validator.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/Validator.java @@ -22,6 +22,7 @@ import org.jreleaser.model.CommitAuthorAware; import org.jreleaser.model.Distribution; import org.jreleaser.model.Environment; import org.jreleaser.model.GitService; +import org.jreleaser.model.Glob; import org.jreleaser.model.JReleaserContext; import org.jreleaser.model.OwnerAware; import org.jreleaser.model.RepositoryTap; @@ -30,6 +31,8 @@ import org.jreleaser.model.Tool; import org.jreleaser.util.Env; import org.jreleaser.util.Errors; +import java.util.Collection; + import static org.jreleaser.util.StringUtils.isBlank; import static org.jreleaser.util.StringUtils.isNotBlank; @@ -136,4 +139,29 @@ class Validator { tap.getBranch(), "HEAD")); } + + static void validateGlobs(JReleaserContext context, Collection globs, String property, Errors errors) { + int i = 0; + for (Glob glob : globs) { + if (isNotBlank(glob.getPattern())) continue; + + boolean isBaseDir = false; + if (isBlank(glob.getDirectory())) { + glob.setDirectory("."); + isBaseDir = true; + } + + boolean includeAll = false; + if (isBlank(glob.getInclude())) { + glob.setInclude("*"); + includeAll = true; + } + + if (isBlank(glob.getExclude()) && + includeAll && isBaseDir) { + // too broad! + errors.configuration(property + "[" + i + "] must define a pattern"); + } + } + } }