Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply rules to implicitly created directories (Issue #85) #86

Merged
22 changes: 22 additions & 0 deletions src/main/java/de/dentrassi/rpm/builder/BuilderContextListener.java
Original file line number Diff line number Diff line change
@@ -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<Object> provider);

void notifyDirectoryAdded(String name, FileInformationProvider<Object> provider);

void notifySymbolicLinkAdded(String name, FileInformationProvider<Object> provider);
}
Original file line number Diff line number Diff line change
@@ -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<BuilderContextListener> listeners;

public ListenableBuilderContext(BuilderContext builderContext) {
this.builderContext = builderContext;
this.listeners = new HashSet<>();
}

@Override
public void setDefaultInformationProvider(FileInformationProvider<Object> provider) {
builderContext.setDefaultInformationProvider(provider);
}

@Override
public FileInformationProvider<Object> getDefaultInformationProvider() {
return builderContext.getDefaultInformationProvider();
}

@Override
public void addFile(String targetName, Path source, FileInformationProvider<? super Path> 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<Object> provider) throws IOException {
builderContext.addFile(targetName, source, provider);
listeners.forEach(listener -> listener.notifyFileAdded(targetName, provider));
}

@Override
public void addFile(String targetName, ByteBuffer source, FileInformationProvider<Object> provider) throws IOException {
builderContext.addFile(targetName, source, provider);
listeners.forEach(listener -> listener.notifyFileAdded(targetName, provider));
}

@Override
public void addDirectory(String targetName, FileInformationProvider<? super Directory> provider) throws IOException {
builderContext.addDirectory(targetName, provider);
listeners.forEach(listener -> listener.notifyDirectoryAdded(targetName, (MojoFileInformationProvider) provider));
}

@Override
public void addSymbolicLink(String targetName, String linkTo, FileInformationProvider<? super SymbolicLink> 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);
}

}
Original file line number Diff line number Diff line change
@@ -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<String> explicitAddedDirectories;
private final Map<String, FileInformationProvider<Object>> missingDirectories;
private final List<String> ignorePrefixes;

public MissingDirectoryTracker(List<String> ignorePrefixes) {
this.explicitAddedDirectories = new HashSet<>();
this.missingDirectories = new HashMap<>();
this.ignorePrefixes = ignorePrefixes;
}

@Override
public void notifyFileAdded(String targetName, FileInformationProvider<Object> provider) {
addMissingDirectoriesFromPath(targetName, provider);
}

@Override
public void notifyDirectoryAdded(String targetName, FileInformationProvider<Object> provider) {
explicitAddedDirectories.add(targetName);
missingDirectories.remove(targetName);
addMissingDirectoriesFromPath(targetName, provider);
}

@Override
public void notifySymbolicLinkAdded(String targetName, FileInformationProvider<Object> provider) {
addMissingDirectoriesFromPath(targetName, provider);
}

private void addMissingDirectoriesFromPath(String targetName, FileInformationProvider<Object> 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<String, FileInformationProvider<Object>> missingEntry : missingDirectories.entrySet()) {
ctx.addDirectory(missingEntry.getKey(), missingEntry.getValue());
}
}

private List<String> getIntermediateDirectories(String targetName) {
ArrayList<String> 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;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,24 @@ private FileInformation provideByRule(final String targetName, final Object obje

return result;
}

public RulesetEvaluator getRulesetEval() {
return rulesetEval;
}

public Consumer<String> getLogger() {
return logger;
}

public String getRuleId() {
return ruleId;
}

public PackageEntry getEntry() {
return entry;
}

public Instant getTimestamp() {
return timestamp;
}
}
33 changes: 31 additions & 2 deletions src/main/java/de/dentrassi/rpm/builder/RpmMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -207,6 +208,28 @@ public void setGenerateDefaultSourcePackage(final boolean generateDefaultSourceP
this.generateDefaultSourcePackage = generateDefaultSourcePackage;
}

/**
* Whether implicitly created intermediate directories should explicitly
* added to package.
* <p>
* 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.
* </p>
* <p>
* 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.
* </p>
*/
@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
Expand Down Expand Up @@ -1076,7 +1099,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:");

Expand All @@ -1091,6 +1116,11 @@ protected void fillPayload(final RpmBuilder builder) throws MojoFailureException
fillFromEntry(ctx, entry);
}
}

ctx.removeListener(missingDirectoryTracker);
if (generateIntermediateDirectories) {
missingDirectoryTracker.addMissingIntermediateDirectoriesToContext(ctx);
}
}

private void customizeHeader(final RpmBuilder builder) {
Expand Down Expand Up @@ -1133,7 +1163,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, " - "));
}

Expand Down
Loading