diff --git a/src/main/java/de/dentrassi/rpm/builder/BuilderContextListener.java b/src/main/java/de/dentrassi/rpm/builder/BuilderContextListener.java new file mode 100644 index 0000000..5227a27 --- /dev/null +++ b/src/main/java/de/dentrassi/rpm/builder/BuilderContextListener.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2023 Fraunhofer-Institut fuer Optronik, Systemtechnik und Bildauswertung IOSB and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * Contributors: + * Fraunhofer-Institut fuer Optronik, Systemtechnik und Bildauswertung IOSB - initial API and implementation + *******************************************************************************/ +package de.dentrassi.rpm.builder; + +import org.eclipse.packager.rpm.build.FileInformationProvider; + +public interface BuilderContextListener { + + void notifyFileAdded(String name, FileInformationProvider provider); + + void notifyDirectoryAdded(String name, FileInformationProvider provider); + + void notifySymbolicLinkAdded(String name, FileInformationProvider provider); +} diff --git a/src/main/java/de/dentrassi/rpm/builder/ListenableBuilderContext.java b/src/main/java/de/dentrassi/rpm/builder/ListenableBuilderContext.java new file mode 100644 index 0000000..47aeb77 --- /dev/null +++ b/src/main/java/de/dentrassi/rpm/builder/ListenableBuilderContext.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2023 Fraunhofer-Institut fuer Optronik, Systemtechnik und Bildauswertung IOSB and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * Contributors: + * Fraunhofer-Institut fuer Optronik, Systemtechnik und Bildauswertung IOSB - initial API and implementation + *******************************************************************************/ +package de.dentrassi.rpm.builder; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.packager.rpm.build.BuilderContext; +import org.eclipse.packager.rpm.build.FileInformationProvider; + +public class ListenableBuilderContext implements BuilderContext { + + private final BuilderContext builderContext; + private final Set listeners; + + public ListenableBuilderContext(BuilderContext builderContext) { + this.builderContext = builderContext; + this.listeners = new HashSet<>(); + } + + @Override + public void setDefaultInformationProvider(FileInformationProvider provider) { + builderContext.setDefaultInformationProvider(provider); + } + + @Override + public FileInformationProvider getDefaultInformationProvider() { + return builderContext.getDefaultInformationProvider(); + } + + @Override + public void addFile(String targetName, Path source, FileInformationProvider provider) throws IOException { + builderContext.addFile(targetName, source, provider); + listeners.forEach(listener -> listener.notifyFileAdded(targetName, (MojoFileInformationProvider) provider)); + } + + @Override + public void addFile(String targetName, InputStream source, FileInformationProvider provider) throws IOException { + builderContext.addFile(targetName, source, provider); + listeners.forEach(listener -> listener.notifyFileAdded(targetName, provider)); + } + + @Override + public void addFile(String targetName, ByteBuffer source, FileInformationProvider provider) throws IOException { + builderContext.addFile(targetName, source, provider); + listeners.forEach(listener -> listener.notifyFileAdded(targetName, provider)); + } + + @Override + public void addDirectory(String targetName, FileInformationProvider provider) throws IOException { + builderContext.addDirectory(targetName, provider); + listeners.forEach(listener -> listener.notifyDirectoryAdded(targetName, (MojoFileInformationProvider) provider)); + } + + @Override + public void addSymbolicLink(String targetName, String linkTo, FileInformationProvider provider) throws IOException { + builderContext.addSymbolicLink(targetName, linkTo, provider); + listeners.forEach(listener -> listener.notifySymbolicLinkAdded(targetName, (MojoFileInformationProvider) provider)); + } + + public void registerListener(BuilderContextListener listener) { + if (listener != null) { + listeners.add(listener); + } + } + + public void removeListener(BuilderContextListener listener) { + listeners.remove(listener); + } + +} diff --git a/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java b/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java new file mode 100644 index 0000000..6c9df4c --- /dev/null +++ b/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2023 Fraunhofer-Institut fuer Optronik, Systemtechnik und Bildauswertung IOSB and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * Contributors: + * Fraunhofer-Institut fuer Optronik, Systemtechnik und Bildauswertung IOSB - initial API and implementation + *******************************************************************************/ +package de.dentrassi.rpm.builder; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.packager.rpm.build.BuilderContext; +import org.eclipse.packager.rpm.build.FileInformationProvider; + +public class MissingDirectoryTracker implements BuilderContextListener { + + private final Set explicitAddedDirectories; + private final Map> missingDirectories; + private final List ignorePrefixes; + + public MissingDirectoryTracker(List ignorePrefixes) { + this.explicitAddedDirectories = new HashSet<>(); + this.missingDirectories = new HashMap<>(); + this.ignorePrefixes = ignorePrefixes; + } + + @Override + public void notifyFileAdded(String targetName, FileInformationProvider provider) { + addMissingDirectoriesFromPath(targetName, provider); + } + + @Override + public void notifyDirectoryAdded(String targetName, FileInformationProvider provider) { + explicitAddedDirectories.add(targetName); + missingDirectories.remove(targetName); + addMissingDirectoriesFromPath(targetName, provider); + } + + @Override + public void notifySymbolicLinkAdded(String targetName, FileInformationProvider provider) { + addMissingDirectoriesFromPath(targetName, provider); + } + + private void addMissingDirectoriesFromPath(String targetName, FileInformationProvider provider) { + for (String intermediateDirectory : getIntermediateDirectories(targetName)) { + if (!shouldDirectoryIgnored(intermediateDirectory) && !explicitAddedDirectories.contains(intermediateDirectory)) { + if (provider instanceof MojoFileInformationProvider) { + MojoFileInformationProvider mojoProvider = (MojoFileInformationProvider) provider; + missingDirectories.computeIfAbsent(intermediateDirectory, k -> new MojoFileInformationProvider(mojoProvider.getRulesetEval(), mojoProvider.getRuleId(), null, mojoProvider.getLogger(), mojoProvider.getTimestamp())); + } + } + } + } + + private boolean shouldDirectoryIgnored(String directory) { + for (String ignorePrefix : ignorePrefixes) { + if (ignorePrefix.startsWith(directory)) { + return true; + } + } + return false; + } + + public void addMissingIntermediateDirectoriesToContext(BuilderContext ctx) throws IOException { + for (Map.Entry> missingEntry : missingDirectories.entrySet()) { + ctx.addDirectory(missingEntry.getKey(), missingEntry.getValue()); + } + } + + private List getIntermediateDirectories(String targetName) { + ArrayList intermediateDirectories = new ArrayList<>(); + Path path = Paths.get(targetName); + + for (int i = 1; i < path.getNameCount(); i++) { + Path subPath = path.subpath(0, i); + intermediateDirectories.add("/" + subPath); + } + + return intermediateDirectories; + } + + +} diff --git a/src/main/java/de/dentrassi/rpm/builder/MojoFileInformationProvider.java b/src/main/java/de/dentrassi/rpm/builder/MojoFileInformationProvider.java index 5ed5bce..c4db8f6 100644 --- a/src/main/java/de/dentrassi/rpm/builder/MojoFileInformationProvider.java +++ b/src/main/java/de/dentrassi/rpm/builder/MojoFileInformationProvider.java @@ -74,4 +74,24 @@ private FileInformation provideByRule(final String targetName, final Object obje return result; } + + public RulesetEvaluator getRulesetEval() { + return rulesetEval; + } + + public Consumer getLogger() { + return logger; + } + + public String getRuleId() { + return ruleId; + } + + public PackageEntry getEntry() { + return entry; + } + + public Instant getTimestamp() { + return timestamp; + } } diff --git a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java index 5be010a..48df840 100644 --- a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java +++ b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java @@ -14,6 +14,7 @@ * Peter Wilkinson - add skip entry flag * Daniel Singhal - Added primary artifact support * Jarkko Sonninen - Added outputFileNameProperty + * Fraunhofer-Institut fuer Optronik, Systemtechnik und Bildauswertung IOSB - apply rules to implicit created intermediate directories *******************************************************************************/ package de.dentrassi.rpm.builder; @@ -1076,7 +1077,9 @@ protected void fillPayload(final RpmBuilder builder) throws MojoFailureException return; } - final BuilderContext ctx = builder.newContext(); + final ListenableBuilderContext ctx = new ListenableBuilderContext(builder.newContext()); + final MissingDirectoryTracker missingDirectoryTracker = new MissingDirectoryTracker(this.prefixes); + ctx.registerListener(missingDirectoryTracker); this.logger.debug("Building payload:"); @@ -1091,6 +1094,9 @@ protected void fillPayload(final RpmBuilder builder) throws MojoFailureException fillFromEntry(ctx, entry); } } + + ctx.removeListener(missingDirectoryTracker); + missingDirectoryTracker.addMissingIntermediateDirectoriesToContext(ctx); } private void customizeHeader(final RpmBuilder builder) { @@ -1133,7 +1139,6 @@ private void fillFromEntryFile(final BuilderContext ctx, final PackageEntry entr this.logger.debug(" as file:"); final Path source = entry.getFile().toPath().toAbsolutePath(); this.logger.debug(" - source: %s", source); - ctx.addFile(entry.getName(), source, makeProvider(entry, " - ")); }