From fec0073bb19c5ac3f1e72d8ee017332ae3571701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6ser=2C=20Daniel?= Date: Wed, 13 Dec 2023 12:14:10 +0100 Subject: [PATCH 1/7] Apply rules to implicitly created directories --- .../rpm/builder/BuilderContextListener.java | 22 +++++ .../rpm/builder/ListenableBuilderContext.java | 83 ++++++++++++++++ .../rpm/builder/MissingDirectoryTracker.java | 94 +++++++++++++++++++ .../builder/MojoFileInformationProvider.java | 20 ++++ .../de/dentrassi/rpm/builder/RpmMojo.java | 9 +- 5 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 src/main/java/de/dentrassi/rpm/builder/BuilderContextListener.java create mode 100644 src/main/java/de/dentrassi/rpm/builder/ListenableBuilderContext.java create mode 100644 src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java 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, " - ")); } From a7a69a3c6b4d71e73e6c3b0f755f672983e0b2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6ser=2C=20Daniel?= Date: Wed, 13 Dec 2023 15:29:20 +0100 Subject: [PATCH 2/7] Add plugin configuration parameter generateIntermediateDirectories --- .../de/dentrassi/rpm/builder/RpmMojo.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java index 48df840..9e3cc79 100644 --- a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java +++ b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java @@ -208,6 +208,28 @@ public void setGenerateDefaultSourcePackage(final boolean generateDefaultSourceP this.generateDefaultSourcePackage = generateDefaultSourcePackage; } + /** + * Whether implicitly created intermediate directories should explicitly + * added to package. + *

+ * If enabled, all from entries implicitly created intermediate directories + * are added as explicit entries to package. Also the rules with file + * information are applied to these directories. + *

+ *

+ * To exclude directories like {@code /usr} from being added, you have + * to add these as prefix property (see {@code prefixes}). Directories + * that match a whole prefix or a sub path of it, are not added. + *

+ */ + @Parameter(property = "rpm.generateIntermediateDirectories", defaultValue = "true") + boolean generateIntermediateDirectories = true; + + public void setGenerateIntermediateDirectories(final boolean generateIntermediateDirectories) { + this.generateIntermediateDirectories = generateIntermediateDirectories; + } + + /** * The prefix of the release if this is a snapshot build, will be suffixed * with the snapshot build id @@ -1096,7 +1118,9 @@ protected void fillPayload(final RpmBuilder builder) throws MojoFailureException } ctx.removeListener(missingDirectoryTracker); - missingDirectoryTracker.addMissingIntermediateDirectoriesToContext(ctx); + if (generateIntermediateDirectories) { + missingDirectoryTracker.addMissingIntermediateDirectoriesToContext(ctx); + } } private void customizeHeader(final RpmBuilder builder) { From 2e224588663857dfb5fc21da327ad195ef777c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6ser=2C=20Daniel?= Date: Mon, 26 Feb 2024 12:37:39 +0100 Subject: [PATCH 3/7] Use list of base directories for which intermediate directories should be generated --- .../test19-intermediate-directories/pom.xml | 141 ++++++++++++++++++ .../src/main/data/foobar | 0 .../verify.groovy | 24 +++ .../rpm/builder/MissingDirectoryTracker.java | 36 +++-- .../de/dentrassi/rpm/builder/RpmMojo.java | 51 ++++--- 5 files changed, 212 insertions(+), 40 deletions(-) create mode 100644 src/it/test19-intermediate-directories/pom.xml create mode 100644 src/it/test19-intermediate-directories/src/main/data/foobar create mode 100644 src/it/test19-intermediate-directories/verify.groovy diff --git a/src/it/test19-intermediate-directories/pom.xml b/src/it/test19-intermediate-directories/pom.xml new file mode 100644 index 0000000..b2fcb50 --- /dev/null +++ b/src/it/test19-intermediate-directories/pom.xml @@ -0,0 +1,141 @@ + + + 4.0.0 + + de.dentrassi.maven.rpm.test + test19 + 1.0.0-SNAPSHOT + jar + + Test Package #19 + + Test explicitly adding and applying rules for implicitly created intermediate directories. + + + http://dentrassi.de + + + Jens Reimann + http://dentrassi.de + + + + + Eclipse Public License - v 1.0 + repo + https://www.eclipse.org/legal/epl-v10.html + + + + + UTF-8 + UTF-8 + true + + 2009-01-01T12:00:00+01:00 + + + + + + + de.dentrassi.maven + rpm + @project.version@ + + + + rpm + + + false + Application/Misc + + + ${keyId} + ${user.home}/.gnupg/secring.gpg + ${passphrase} + SHA1 + ${skipSigning} + + + + /etc/mycompany/myapp + /opt/mycompany/myapp + + + + + my-default + + + + /opt/mycompany + + mygeneraluser + mygeneralgroup + 0111 + + + + /opt/mycompany/myapp + + myuser + mygroup + 0555 + + + + /opt/mycompany/myapp + directory + + 0777 + + + + + + + + /opt/mycompany/myapp/a/b/c/foobar + ${project.basedir}/src/main/data/foobar + my-default + + + /opt/mycompany/myapp + true + my-default + + + /etc/mycompany/myapp/defaults + true + my-default + + + /opt/mycompany/otherapp/a/b/c/foobar + ${project.basedir}/src/main/data/foobar + my-default + + + + + + + + + + + + + sign + + false + + + false + + + + + \ No newline at end of file diff --git a/src/it/test19-intermediate-directories/src/main/data/foobar b/src/it/test19-intermediate-directories/src/main/data/foobar new file mode 100644 index 0000000..e69de29 diff --git a/src/it/test19-intermediate-directories/verify.groovy b/src/it/test19-intermediate-directories/verify.groovy new file mode 100644 index 0000000..37f0515 --- /dev/null +++ b/src/it/test19-intermediate-directories/verify.groovy @@ -0,0 +1,24 @@ +def dump() { + Process proc = ('rpm -q --dump -p ' + basedir + "/target/*.rpm").execute() + return proc.in.getText().trim() +} + +def actual = dump() +println "Dump:\n" + actual + +def expected = """\ + /etc/mycompany/myapp 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040755 root root 0 0 0 X + /etc/mycompany/myapp/defaults 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040755 root root 0 0 0 X + /opt/mycompany/myapp 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/a 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/a/b 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/a/b/c 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/a/b/c/foobar 0 1230807600 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0100555 myuser mygroup 0 0 0 X + /opt/mycompany/otherapp/a/b/c/foobar 0 1230807600 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0100111 mygeneraluser mygeneralgroup 0 0 0 X""".stripIndent() + +if (actual != expected) { + System.out.format("RPM dump doesn't match - actual:%n%s%nexpected:%n%s%n", actual, expected); + return false; +} + +return true; diff --git a/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java b/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java index 6c9df4c..480f994 100644 --- a/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java +++ b/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java @@ -25,14 +25,17 @@ public class MissingDirectoryTracker implements BuilderContextListener { + // keep track of explicit added directories private final Set explicitAddedDirectories; + // keep track of all missing directories which should be added after processing (without explicit added directories) private final Map> missingDirectories; - private final List ignorePrefixes; + // base directories (prefixes) for which the intermediate directories should be generated + private final List baseDirectories; - public MissingDirectoryTracker(List ignorePrefixes) { + public MissingDirectoryTracker(List baseDirectories) { this.explicitAddedDirectories = new HashSet<>(); this.missingDirectories = new HashMap<>(); - this.ignorePrefixes = ignorePrefixes; + this.baseDirectories = baseDirectories; } @Override @@ -53,23 +56,25 @@ public void notifySymbolicLinkAdded(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())); + if (provider instanceof MojoFileInformationProvider) { + MojoFileInformationProvider mojoProvider = (MojoFileInformationProvider) provider; + + for (String intermediateDirectory : getIntermediateDirectories(targetName)) { + if (startsPathWithPrefix(intermediateDirectory) && !explicitAddedDirectories.contains(intermediateDirectory)) { + missingDirectories.computeIfAbsent(intermediateDirectory, + (String directory) -> 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; + private boolean startsPathWithPrefix(String directory) { + return baseDirectories.stream().anyMatch(directory::startsWith); } public void addMissingIntermediateDirectoriesToContext(BuilderContext ctx) throws IOException { @@ -90,5 +95,4 @@ private List getIntermediateDirectories(String targetName) { return intermediateDirectories; } - } diff --git a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java index 9e3cc79..fe06d1e 100644 --- a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java +++ b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java @@ -208,28 +208,6 @@ public void setGenerateDefaultSourcePackage(final boolean generateDefaultSourceP this.generateDefaultSourcePackage = generateDefaultSourcePackage; } - /** - * Whether implicitly created intermediate directories should explicitly - * added to package. - *

- * If enabled, all from entries implicitly created intermediate directories - * are added as explicit entries to package. Also the rules with file - * information are applied to these directories. - *

- *

- * To exclude directories like {@code /usr} from being added, you have - * to add these as prefix property (see {@code prefixes}). Directories - * that match a whole prefix or a sub path of it, are not added. - *

- */ - @Parameter(property = "rpm.generateIntermediateDirectories", defaultValue = "true") - boolean generateIntermediateDirectories = true; - - public void setGenerateIntermediateDirectories(final boolean generateIntermediateDirectories) { - this.generateIntermediateDirectories = generateIntermediateDirectories; - } - - /** * The prefix of the release if this is a snapshot build, will be suffixed * with the snapshot build id @@ -388,6 +366,31 @@ public void setGenerateIntermediateDirectories(final boolean generateIntermediat @Parameter(property = "rpm.prefixes") List prefixes; + /** + * Base paths for which implicitly created intermediate directories should + * explicitly added to package. + * + *
+     *       <generateIntermediateDirectories>
+     *           <baseDirectory>/opt/mycompany/myapp</baseDirectory>
+     *           <baseDirectory>/etc/mycompany</baseDirectory>
+     *       </generateIntermediateDirectories>
+     * 
+ * + *

+ * For given base directories, all from entries implicitly created + * intermediate directories are added as explicit entries to package. + * Also the rules with file information are applied to these added directories. + *

+ *

+ * To exclude directories like {@code /usr} from being added, you have + * to add these as prefix property (see {@code prefixes}). Directories + * that match a whole prefix or a sub path of it, are not added. + *

+ */ + @Parameter(property = "rpm.generateIntermediateDirectories") + List generateIntermediateDirectories; + /** * The actual payload/file entries *

@@ -1100,7 +1103,7 @@ protected void fillPayload(final RpmBuilder builder) throws MojoFailureException } final ListenableBuilderContext ctx = new ListenableBuilderContext(builder.newContext()); - final MissingDirectoryTracker missingDirectoryTracker = new MissingDirectoryTracker(this.prefixes); + final MissingDirectoryTracker missingDirectoryTracker = new MissingDirectoryTracker(this.generateIntermediateDirectories); ctx.registerListener(missingDirectoryTracker); this.logger.debug("Building payload:"); @@ -1118,7 +1121,7 @@ protected void fillPayload(final RpmBuilder builder) throws MojoFailureException } ctx.removeListener(missingDirectoryTracker); - if (generateIntermediateDirectories) { + if (!generateIntermediateDirectories.isEmpty()) { missingDirectoryTracker.addMissingIntermediateDirectoriesToContext(ctx); } } From ed46fc49464f364c11492448ae15b12f26628e88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6ser=2C=20Daniel?= Date: Wed, 28 Feb 2024 09:39:39 +0100 Subject: [PATCH 4/7] Handle intermediate directories of collect entries in MissingDirectoryTracker --- .../pom.xml | 136 ++++++++++++++++++ .../src/main/data/x/y/foobar | 0 .../verify.groovy | 25 ++++ .../rpm/builder/MissingDirectoryTracker.java | 46 ++++-- 4 files changed, 197 insertions(+), 10 deletions(-) create mode 100644 src/it/test19-intermediate-directories-collect/pom.xml create mode 100644 src/it/test19-intermediate-directories-collect/src/main/data/x/y/foobar create mode 100644 src/it/test19-intermediate-directories-collect/verify.groovy diff --git a/src/it/test19-intermediate-directories-collect/pom.xml b/src/it/test19-intermediate-directories-collect/pom.xml new file mode 100644 index 0000000..ffebda0 --- /dev/null +++ b/src/it/test19-intermediate-directories-collect/pom.xml @@ -0,0 +1,136 @@ + + + 4.0.0 + + de.dentrassi.maven.rpm.test + test19 + 1.0.0-SNAPSHOT + jar + + Test Package #19 + + Test explicitly adding and applying rules for implicitly created intermediate directories with collect entries. + + + http://dentrassi.de + + + Jens Reimann + http://dentrassi.de + + + + + Eclipse Public License - v 1.0 + repo + https://www.eclipse.org/legal/epl-v10.html + + + + + UTF-8 + UTF-8 + true + + 2009-01-01T12:00:00+01:00 + + + + + + + de.dentrassi.maven + rpm + @project.version@ + + + + rpm + + + false + Application/Misc + + + ${keyId} + ${user.home}/.gnupg/secring.gpg + ${passphrase} + SHA1 + ${skipSigning} + + + + /opt/mycompany/myapp + + + + + my-default + + + + /opt/mycompany + + mygeneraluser + mygeneralgroup + 0111 + + + + /opt/mycompany/myapp + + myuser + mygroup + 0555 + + + + /opt/mycompany/myapp + directory + + 0777 + + + + + + + + /opt/mycompany/myapp/a/b + + ${project.basedir}/src/main/data + false + + my-default + + + /opt/mycompany/myapp/c/d + + ${project.basedir}/src/main/data + true + + my-default + + + + + + + + + + + + + sign + + false + + + false + + + + + \ No newline at end of file diff --git a/src/it/test19-intermediate-directories-collect/src/main/data/x/y/foobar b/src/it/test19-intermediate-directories-collect/src/main/data/x/y/foobar new file mode 100644 index 0000000..e69de29 diff --git a/src/it/test19-intermediate-directories-collect/verify.groovy b/src/it/test19-intermediate-directories-collect/verify.groovy new file mode 100644 index 0000000..7fd6bb6 --- /dev/null +++ b/src/it/test19-intermediate-directories-collect/verify.groovy @@ -0,0 +1,25 @@ +def dump() { + Process proc = ('rpm -q --dump -p ' + basedir + "/target/*.rpm").execute() + return proc.in.getText().trim() +} + +def actual = dump() +println "Dump:\n" + actual + +def expected = """\ + /opt/mycompany/myapp 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/a 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/a/b 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/a/b/x/y/foobar 0 1230807600 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0100555 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/c 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/c/d 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/c/d/x 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/c/d/x/y 0 1230807600 0000000000000000000000000000000000000000000000000000000000000000 040777 myuser mygroup 0 0 0 X + /opt/mycompany/myapp/c/d/x/y/foobar 0 1230807600 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0100555 myuser mygroup 0 0 0 X""".stripIndent() + +if (actual != expected) { + System.out.format("RPM dump doesn't match - actual:%n%s%nexpected:%n%s%n", actual, expected); + return false; +} + +return true; diff --git a/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java b/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java index 480f994..c3d5789 100644 --- a/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java +++ b/src/main/java/de/dentrassi/rpm/builder/MissingDirectoryTracker.java @@ -59,20 +59,39 @@ private void addMissingDirectoriesFromPath(String targetName, FileInformationPro if (provider instanceof MojoFileInformationProvider) { MojoFileInformationProvider mojoProvider = (MojoFileInformationProvider) provider; - for (String intermediateDirectory : getIntermediateDirectories(targetName)) { - if (startsPathWithPrefix(intermediateDirectory) && !explicitAddedDirectories.contains(intermediateDirectory)) { - missingDirectories.computeIfAbsent(intermediateDirectory, - (String directory) -> new MojoFileInformationProvider( - mojoProvider.getRulesetEval(), - mojoProvider.getRuleId(), - null, - mojoProvider.getLogger(), - mojoProvider.getTimestamp())); - } + List intermediateDirectories; + if (containsCollectEntry(mojoProvider)) { + // collect handles intermediate directories by themselves via flag 'directories' + // -> only use base directory (entry name of collect) as target path to calculate + // intermediate directories + targetName = mojoProvider.getEntry().getName(); + intermediateDirectories = getIntermediateDirectoriesIncludingTarget(targetName); + } else { + intermediateDirectories = getIntermediateDirectories(targetName); } + + for (String intermediateDirectory : intermediateDirectories) { + addIfIsMissingDirectory(intermediateDirectory, mojoProvider); + } + } + } + + private void addIfIsMissingDirectory(String intermediateDirectory, MojoFileInformationProvider mojoProvider) { + if (startsPathWithPrefix(intermediateDirectory) && !explicitAddedDirectories.contains(intermediateDirectory)) { + missingDirectories.computeIfAbsent(intermediateDirectory, + (String directory) -> new MojoFileInformationProvider( + mojoProvider.getRulesetEval(), + mojoProvider.getRuleId(), + null, + mojoProvider.getLogger(), + mojoProvider.getTimestamp())); } } + private boolean containsCollectEntry(MojoFileInformationProvider mojoProvider) { + return mojoProvider.getEntry().getCollect() != null; + } + private boolean startsPathWithPrefix(String directory) { return baseDirectories.stream().anyMatch(directory::startsWith); } @@ -95,4 +114,11 @@ private List getIntermediateDirectories(String targetName) { return intermediateDirectories; } + private List getIntermediateDirectoriesIncludingTarget(String targetName) { + List intermediateDirectories = getIntermediateDirectories(targetName); + intermediateDirectories.add(targetName); + + return intermediateDirectories; + } + } From 73c94eb921ea7783bd79217d04ec1466957d5b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6ser=2C=20Daniel?= Date: Mon, 4 Mar 2024 15:43:08 +0100 Subject: [PATCH 5/7] Add documentation of generate intermediate directories feature --- .../de/dentrassi/rpm/builder/RpmMojo.java | 16 ++-- src/site/markdown/entry.md | 74 ++++++++++++++++++- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java index fe06d1e..6301c5c 100644 --- a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java +++ b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java @@ -368,7 +368,7 @@ public void setGenerateDefaultSourcePackage(final boolean generateDefaultSourceP /** * Base paths for which implicitly created intermediate directories should - * explicitly added to package. + * explicitly add to package. * *

      *       <generateIntermediateDirectories>
@@ -378,15 +378,17 @@ public void setGenerateDefaultSourcePackage(final boolean generateDefaultSourceP
      * 
* *

- * For given base directories, all from entries implicitly created - * intermediate directories are added as explicit entries to package. - * Also the rules with file information are applied to these added directories. + * For these given base directories, any intermediate directories created + * implicitly from {@code } elements are added to the package + * as explicit entries. + * The rules with file information are applied to these added directories as well. *

*

- * To exclude directories like {@code /usr} from being added, you have - * to add these as prefix property (see {@code prefixes}). Directories - * that match a whole prefix or a sub path of it, are not added. + * Note: In case of {@code } entries this feature is only applied to + * directories outside of the collection. *

+ * + * @since 1.11.1 (TODO: enter correct version) */ @Parameter(property = "rpm.generateIntermediateDirectories") List generateIntermediateDirectories; diff --git a/src/site/markdown/entry.md b/src/site/markdown/entry.md index 5c8d64b..095a315 100644 --- a/src/site/markdown/entry.md +++ b/src/site/markdown/entry.md @@ -51,7 +51,10 @@ In order to walk through a directory tree and add all files use: `` which defines the base path. In addition there is the optional element ``, which can be set to `false` in order to not record -directories explicitly. **Note:** the `` directory itself will never be added as explicit directory. This can be done using an additional `` element. +directories explicitly. **Note:** the `` directory itself will never be added as explicit directory. +This can be done using an additional `` element. +Alternatively the general configuration for [generating intermediate directories](#generate-intermediate-directories) +can be used to create intermediate directories when the package structure is built. **Note:** By default symbolic links in the file system will be ignored. Since not all platforms support symbolic links in the same way. It is recommended to create the manually using a `` style @@ -144,3 +147,72 @@ In order to use explicit information use the following elements: Also see [payload entry information](payload_information.html) for a full list. + +## Generate intermediate directories + +Since version `1.11.1 (TODO: enter correct version)` there is an option to automatically generate and add intermediate directories +explicitly for all paths added by `` elements. +Therefore, it is not necessary to manually configure each sub path to have it added explicitly to the package. + +To configure this optional function, a list of base paths must be specified by the configuration (TODO, ggf configuration streichen) property +``. +For these given base directories, any intermediate directories created implicitly from `` elements are added to the package +as explicit entries. +Sub paths of the base directories themselfs are not explicitly added to the package. + +**NOTE:** The [entry information](#entry-information) (explicit and ruleset) is applied to these intermediate directories as well. + +Example: + + + /usr/lib/foo + /some/other/basedirectory + + + + + /usr/lib/foo/bar/ + path/to/file/foobar.txt + + + +Result: + + /usr/lib/foo (dir - added by generateIntermediateDirectories) + /usr/lib/foo/bar (dir - added by generateIntermediateDirectories) + /usr/lib/foo/bar/foobar.txt (file - added by file entry) + +**Note**: In case of `` entries the feature of generating intermediate directories is only +applied to directories outside of the collection. +The behaviour of adding directories inside of `` is controlled independently by setting the +`` flag (see [file system collector](#file-system-collector)). + +Collection Example: + + + /usr/lib/foo + + + + + /usr/lib/foo/bar + + ${project.basedir}/src/main/data + ... + + + + +Result with `true`: + + /usr/lib/foo (dir - added by generateIntermediateDirectories) + /usr/lib/foo/bar (dir - added by generateIntermediateDirectories) + /usr/lib/foo/bar/x (dir - added by collect entry) + /usr/lib/foo/bar/x/y (dir - added by collect entry) + /usr/lib/foo/bar/x/y/foobar.txt (file - added by collect entry) + +Result with `false`: + + /usr/lib/foo (dir - added by generateIntermediateDirectories) + /usr/lib/foo/bar (dir - added by generateIntermediateDirectories) + /usr/lib/foo/bar/x/y/foobar.txt (file - added by collect entry) From d606068faef18fa6521e00f691e9dc1401911d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6ser=2C=20Daniel?= Date: Mon, 4 Mar 2024 15:51:53 +0100 Subject: [PATCH 6/7] Fix typos in file system collector documentation --- src/site/markdown/entry.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/site/markdown/entry.md b/src/site/markdown/entry.md index 095a315..1e594c8 100644 --- a/src/site/markdown/entry.md +++ b/src/site/markdown/entry.md @@ -49,7 +49,7 @@ symbolic link points to. If this link to path is relative, then it is relative o In order to walk through a directory tree and add all files use: ``. -The collect elements requires one additional element: `` which defines the base path. In addition +The collect elements requires one additional element: `` which defines the base path. In addition, there is the optional element ``, which can be set to `false` in order to not record directories explicitly. **Note:** the `` directory itself will never be added as explicit directory. This can be done using an additional `` element. @@ -57,8 +57,8 @@ Alternatively the general configuration for [generating intermediate directories can be used to create intermediate directories when the package structure is built. **Note:** By default symbolic links in the file system will be ignored. Since not all platforms support -symbolic links in the same way. It is recommended to create the manually using a `` style -entry. This behavior can be changed by changed by adding `true` to the +symbolic links in the same way. It is recommended to create them manually using a `` style +entry. This behavior can be changed by adding `true` to the collector configuration. The target file names will be constructed out the entry name, as base prefix, and the relative @@ -90,7 +90,7 @@ Will result in the following payload entries: /usr/lib/foo/dir2/foo3.txt (file) /usr/lib/foo/dir2/foo4.txt (file) -As of version 1.0.0 it is also possible to use the standard Maven `includes`/`excludes` elements +As of version `1.0.0` it is also possible to use the standard Maven `includes`/`excludes` elements which follow the standard Maven include/exclude pattern. For example: From b68dfc0b7c81cc997b27cad323b94105f3c3c095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6ser=2C=20Daniel?= Date: Mon, 4 Mar 2024 16:18:59 +0100 Subject: [PATCH 7/7] Fix version number in documentation for generate intermediate directories feature --- src/main/java/de/dentrassi/rpm/builder/RpmMojo.java | 2 +- src/site/markdown/entry.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java index 6301c5c..aaf19f2 100644 --- a/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java +++ b/src/main/java/de/dentrassi/rpm/builder/RpmMojo.java @@ -388,7 +388,7 @@ public void setGenerateDefaultSourcePackage(final boolean generateDefaultSourceP * directories outside of the collection. *

* - * @since 1.11.1 (TODO: enter correct version) + * @since 1.11.0 */ @Parameter(property = "rpm.generateIntermediateDirectories") List generateIntermediateDirectories; diff --git a/src/site/markdown/entry.md b/src/site/markdown/entry.md index 1e594c8..9b90de8 100644 --- a/src/site/markdown/entry.md +++ b/src/site/markdown/entry.md @@ -150,7 +150,7 @@ Also see [payload entry information](payload_information.html) for a full list. ## Generate intermediate directories -Since version `1.11.1 (TODO: enter correct version)` there is an option to automatically generate and add intermediate directories +Since version `1.11.0` there is an option to automatically generate and add intermediate directories explicitly for all paths added by `` elements. Therefore, it is not necessary to manually configure each sub path to have it added explicitly to the package.