Skip to content

Commit

Permalink
Add list-files task to stager-maven-plugin
Browse files Browse the repository at this point in the history
- Add a variant of FileUtils.walk that can follow symlinks (with FileVisitOption)
- Fix StagingElementFactory/ConfigReader to preserve order
  • Loading branch information
romain-grecourt committed Jan 3, 2024
1 parent db58709 commit 3916dea
Show file tree
Hide file tree
Showing 21 changed files with 701 additions and 302 deletions.
22 changes: 20 additions & 2 deletions common/common/src/main/java/io/helidon/build/common/FileUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023 Oracle and/or its affiliates.
* Copyright (c) 2019, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,6 +27,7 @@
import java.nio.file.FileSystem;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
Expand Down Expand Up @@ -271,11 +272,28 @@ public static List<Path> list(Path directory, int maxDepth) {
* @param directory The directory
* @param predicate predicate used to filter files and directories
* @return The normalized, absolute file paths.
* @see Files#walkFileTree(java.nio.file.Path, java.util.Set, int, java.nio.file.FileVisitor)
*/
public static List<Path> walk(Path directory, BiPredicate<Path, BasicFileAttributes> predicate) {
return walk(directory, Set.of(), predicate);
}

/**
* Walk the directory and return the files that match the given predicate.
* If a directory is filtered out by the predicate its subtree is skipped.
*
* @param directory The directory
* @param options options to configure the traversal
* @param predicate predicate used to filter files and directories
* @return The normalized, absolute file paths.
* @see Files#walkFileTree(java.nio.file.Path, java.util.Set, int, java.nio.file.FileVisitor)
*/
public static List<Path> walk(Path directory,
Set<FileVisitOption> options,
BiPredicate<Path, BasicFileAttributes> predicate) {
try {
List<Path> files = new ArrayList<>();
Files.walkFileTree(directory, new FileVisitor<>() {
Files.walkFileTree(directory, options, Integer.MAX_VALUE, new FileVisitor<>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if (predicate.test(dir, attrs)) {
Expand Down
45 changes: 45 additions & 0 deletions common/common/src/main/java/io/helidon/build/common/Patterns.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
*
* 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 io.helidon.build.common;

import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* {@link Pattern} utility.
*/
public final class Patterns {

private static final Pattern NAMED_GROUP_PATTERN = Pattern.compile("\\(\\?<([^!=].*?)>");

private Patterns() {
// cannot be instanciated
}

/**
* Get the group names defined in a regular expression.
*
* @param regex regular expression
* @return group names
*/
public static Set<String> groupNames(String regex) {
return NAMED_GROUP_PATTERN.matcher(regex)
.results()
.map(r -> r.group(1))
.collect(Collectors.toSet());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023 Oracle and/or its affiliates.
* Copyright (c) 2018, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,6 +31,8 @@
import java.util.Objects;
import java.util.stream.Collectors;

import static io.helidon.build.common.Strings.normalizePath;

/**
* Utility class to parse and match path segments.
*/
Expand Down Expand Up @@ -62,7 +64,16 @@ public SourcePath(File dir, File file) {
* @param file the filed contained in the directory
*/
public SourcePath(Path dir, Path file) {
segments = parseSegments(getRelativePath(dir, file));
this(dir.relativize(file));
}

/**
* Create a new {@link SourcePath} instance for the given path.
*
* @param path the path to use
*/
public SourcePath(Path path) {
this(normalizePath(path));
}

/**
Expand Down Expand Up @@ -95,10 +106,6 @@ public SourcePath(List<String> paths) {
.toArray(String[]::new);
}

private static String getRelativePath(Path sourceDir, Path source) {
return Strings.normalizePath(sourceDir.relativize(source));
}

/**
* Parse a {@code '/'} separated path into segments. Collapses empty or {@code '.'} only segments.
*
Expand Down
3 changes: 2 additions & 1 deletion maven-plugins/stager-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2020, 2023 Oracle and/or its affiliates.
Copyright (c) 2020, 2024 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,6 +31,7 @@
<packaging>maven-plugin</packaging>

<properties>
<maven.compiler.release>17</maven.compiler.release>
<spotbugs.exclude>etc/spotbugs/exclude.xml</spotbugs.exclude>
</properties>

Expand Down
23 changes: 22 additions & 1 deletion maven-plugins/stager-maven-plugin/src/it/projects/file/pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!--
Copyright (c) 2020, 2022 Oracle and/or its affiliates.
Copyright (c) 2020, 2024 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -43,6 +43,27 @@
<files>
<file target="CNAME">${cname}</file>
<file target="cli-data/latest">${cli.data.latest.version}</file>
<file target="docs/4.0.2/index.html"/>
<file target="docs/4.0.2/apidocs/index.html"/>
<file target="docs/4.0.2/images/foo.svg"/>
</files>
<symlinks join="true">
<symlink source="docs/4.0.2" target="docs/v4"/>
</symlinks>
<files join="true">
<file target="sitemap.txt">
<list-files dir=".">
<includes>
<include>**/docs/**/*.html</include>
</includes>
<excludes>
<exclude>**/images/**</exclude>
</excludes>
<substitutions>
<substitution match="^(.*)/index.html$" replace="$1" />
</substitutions>
</list-files>
</file>
</files>
</directory>
</directories>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,10 +16,10 @@
package io.helidon.build.maven.stager;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

Expand All @@ -28,7 +28,7 @@
*/
final class ConfigReader implements PlexusConfigNode.Visitor {

private final Map<PlexusConfigNode, Map<String, List<StagingElement>>> mappings;
private final Map<PlexusConfigNode, List<StagingElement>> mappings;
private final Deque<Scope> scopes;
private final StagingElementFactory factory;

Expand All @@ -46,9 +46,7 @@ final class ConfigReader implements PlexusConfigNode.Visitor {
*/
StagingTasks read(PlexusConfigNode node) {
node.visit(this);
StagingAction action = (StagingAction) mappings.get(node.parent())
.get(node.name())
.get(0);
StagingAction action = (StagingAction) mappings.get(node.parent()).iterator().next();
if (action instanceof StagingTasks) {
return (StagingTasks) action;
}
Expand All @@ -62,28 +60,26 @@ public void visitNode(PlexusConfigNode node) {

@Override
public void postVisitNode(PlexusConfigNode node) {
PlexusConfigNode nodeParent = node.parent();
String nodeName = node.name();
mappings.computeIfAbsent(node, n -> new LinkedHashMap<>());
mappings.computeIfAbsent(nodeParent, n -> new LinkedHashMap<>());
PlexusConfigNode parent = node.parent();
String name = node.name();
mappings.computeIfAbsent(node, n -> new ArrayList<>());
mappings.computeIfAbsent(parent, n -> new ArrayList<>());
Scope scope = scopes.peek();
if (scope == null) {
throw new IllegalStateException("Scope is not available");
}
StagingElement element = factory.create(
nodeName,
node.attributes(),
mappings.get(node),
node.value(),
scope);
if (element instanceof Variables) {
for (Variable variable : ((Variables) element)) {
StagingElement element = factory.create(name, node.attributes(), mappings.get(node), node.value(), scope);
if (element instanceof Variables variables) {
for (Variable variable : variables) {
scope.parent.variables.put(variable.name(), variable);
}
}
mappings.get(nodeParent)
.computeIfAbsent(nodeName, n -> new LinkedList<>())
.add(element);
List<StagingElement> siblings = mappings.computeIfAbsent(parent, n -> new ArrayList<>());
if (element instanceof StagingElements elements) {
siblings.addAll(elements.nested());
} else {
siblings.add(element);
}
scopes.pop();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,7 +32,7 @@ final class DryRunStagingElementFactory extends StagingElementFactory {
@Override
StagingAction createAction(String name,
Map<String, String> attrs,
Map<String, List<StagingElement>> children,
List<StagingElement> children,
String text) {

StagingAction action = super.createAction(name, attrs, children, text);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
*
* 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 io.helidon.build.maven.stager;

/**
* Exclude.
*/
record Exclude(String value) implements StagingElement {

static final String ELEMENT_NAME = "exclude";

@Override
public String elementName() {
return ELEMENT_NAME;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022 Oracle and/or its affiliates.
* Copyright (c) 2020, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,9 +15,11 @@
*/
package io.helidon.build.maven.stager;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;

/**
Expand All @@ -30,8 +32,8 @@ final class FileTask extends StagingTask {
private final String content;
private final String source;

FileTask(ActionIterators iterators, Map<String, String> attrs, String content) {
super(ELEMENT_NAME, null, iterators, attrs);
FileTask(ActionIterators iterators, List<TextAction> nested, Map<String, String> attrs, String content) {
super(ELEMENT_NAME, nested, iterators, attrs);
this.content = content;
this.source = attrs.get("source");
}
Expand All @@ -50,10 +52,16 @@ String source() {
*
* @return content, may be {@code null}
*/
public String content() {
String content() {
return content;
}

@Override
@SuppressWarnings("unchecked")
List<TextAction> tasks() {
return (List<TextAction>) super.tasks();
}

@Override
protected void doExecute(StagingContext ctx, Path dir, Map<String, String> vars) throws IOException {
String resolvedTarget = resolveVar(target(), vars);
Expand All @@ -72,6 +80,12 @@ protected void doExecute(StagingContext ctx, Path dir, Map<String, String> vars)
Files.createFile(targetFile);
if (resolvedContent != null && !resolvedContent.isEmpty()) {
Files.writeString(targetFile, resolvedContent);
} else {
try (BufferedWriter writer = Files.newBufferedWriter(targetFile)) {
for (TextAction task : tasks()) {
writer.write(task.text());
}
}
}
}
}
Expand Down
Loading

0 comments on commit 3916dea

Please sign in to comment.