Skip to content

Commit

Permalink
Fix wrong ordering of files in rpm when using feature to generate int…
Browse files Browse the repository at this point in the history
…ermediate directories
  • Loading branch information
moedan authored and ctron committed Apr 2, 2024
1 parent a63995a commit 1331698
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 148 deletions.
29 changes: 15 additions & 14 deletions src/it/test19-intermediate-directories-collect/verify.groovy
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
def dump() {
Process proc = ('rpm -q --dump -p ' + basedir + "/target/*.rpm").execute()
def verifyFileInodes() {
Process proc = ['rpm', '-q', '--queryformat', '[%{FILEINODES} %{FILEMODES:perms} %{FILEUSERNAME} %{FILEGROUPNAME} %{FILENAMES}\n]', basedir.path + '/target/*.rpm'].execute() | 'sort -n'.execute()
proc.waitFor()
return proc.in.getText().trim()
}

def actual = dump()
println "Dump:\n" + actual
def actual = verifyFileInodes()
println "Verify file inodes:\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()
1 drwxrwxrwx myuser mygroup /opt/mycompany/myapp
2 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/a
3 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/a/b
4 -r-xr-xr-x myuser mygroup /opt/mycompany/myapp/a/b/x/y/foobar
5 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/c
6 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/c/d
7 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/c/d/x
8 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/c/d/x/y
9 -r-xr-xr-x myuser mygroup /opt/mycompany/myapp/c/d/x/y/foobar""".stripIndent()

if (actual != expected) {
System.out.format("RPM dump doesn't match - actual:%n%s%nexpected:%n%s%n", actual, expected);
System.out.format("RPM file inodes doesn't match - actual:%n%s%nexpected:%n%s%n", actual, expected);
return false;
}

Expand Down
8 changes: 4 additions & 4 deletions src/it/test19-intermediate-directories/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@

<entries>
<entry>
<name>/opt/mycompany/myapp/a/b/c/foobar</name>
<file>${project.basedir}/src/main/data/foobar</file>
<name>/opt/mycompany/myapp</name>
<directory>true</directory>
<ruleset>my-default</ruleset>
</entry>
<entry>
<name>/opt/mycompany/myapp</name>
<directory>true</directory>
<name>/opt/mycompany/myapp/a/b/c/foobar</name>
<file>${project.basedir}/src/main/data/foobar</file>
<ruleset>my-default</ruleset>
</entry>
<entry>
Expand Down
27 changes: 14 additions & 13 deletions src/it/test19-intermediate-directories/verify.groovy
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
def dump() {
Process proc = ('rpm -q --dump -p ' + basedir + "/target/*.rpm").execute()
def verifyFileInodes() {
Process proc = ['rpm', '-q', '--queryformat', '[%{FILEINODES} %{FILEMODES:perms} %-13{FILEUSERNAME} %-14{FILEGROUPNAME} %{FILENAMES}\n]', basedir.path + '/target/*.rpm'].execute() | 'sort -n'.execute()
proc.waitFor()
return proc.in.getText().trim()
}

def actual = dump()
println "Dump:\n" + actual
def actual = verifyFileInodes()
println "Verify file inodes:\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()
1 drwxrwxrwx myuser mygroup /opt/mycompany/myapp
2 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/a
3 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/a/b
4 drwxrwxrwx myuser mygroup /opt/mycompany/myapp/a/b/c
5 -r-xr-xr-x myuser mygroup /opt/mycompany/myapp/a/b/c/foobar
6 drwxr-xr-x root root /etc/mycompany/myapp
7 drwxr-xr-x root root /etc/mycompany/myapp/defaults
8 ---x--x--x mygeneraluser mygeneralgroup /opt/mycompany/otherapp/a/b/c/foobar""".stripIndent()

if (actual != expected) {
System.out.format("RPM dump doesn't match - actual:%n%s%nexpected:%n%s%n", actual, expected);
System.out.format("RPM file inodes doesn't match - actual:%n%s%nexpected:%n%s%n", actual, expected);
return false;
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,51 +11,78 @@
package de.dentrassi.rpm.builder;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
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 {
public class MissingDirectoryGeneratorInterceptor implements BuilderContext {

private final BuilderContext builderContext;

// keep track of explicit added directories
private final Set<String> explicitAddedDirectories;
// keep track of all missing directories which should be added after processing (without explicit added directories)
private final Map<String, FileInformationProvider<Object>> missingDirectories;
// base directories (prefixes) for which the intermediate directories should be generated
private final List<String> baseDirectories;
// keep track of explicit added directories
private final Set<String> explicitAddedDirectories;
// keep track of all additionally generated and added directories
private final Set<String> generatedDirectories;

public MissingDirectoryTracker(List<String> baseDirectories) {
this.explicitAddedDirectories = new HashSet<>();
this.missingDirectories = new HashMap<>();
public MissingDirectoryGeneratorInterceptor(BuilderContext builderContext, List<String> baseDirectories) {
this.builderContext = builderContext;
this.baseDirectories = baseDirectories;
explicitAddedDirectories = new HashSet<>();
generatedDirectories = new HashSet<>();
}

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

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

@Override
public void notifyFileAdded(String targetName, FileInformationProvider<Object> provider) {
public void addFile(String targetName, Path source, FileInformationProvider<? super Path> provider) throws IOException {
addMissingDirectoriesFromPath(targetName, provider);
builderContext.addFile(targetName, source, provider);
}

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

@Override
public void notifySymbolicLinkAdded(String targetName, FileInformationProvider<Object> provider) {
public void addFile(String targetName, ByteBuffer source, FileInformationProvider<Object> provider) throws IOException {
addMissingDirectoriesFromPath(targetName, provider);
builderContext.addFile(targetName, source, provider);
}

private void addMissingDirectoriesFromPath(String targetName, FileInformationProvider<Object> provider) {
@Override
public void addDirectory(String targetName, FileInformationProvider<? super Directory> provider) throws IOException {
addMissingDirectoriesFromPath(targetName, provider);
builderContext.addDirectory(targetName, provider);
explicitAddedDirectories.add(targetName);
}

@Override
public void addSymbolicLink(String targetName, String linkTo, FileInformationProvider<? super SymbolicLink> provider) throws IOException {
addMissingDirectoriesFromPath(targetName, provider);
builderContext.addSymbolicLink(targetName, linkTo, provider);
}

private void addMissingDirectoriesFromPath(String targetName, FileInformationProvider<?> provider) throws IOException {
if (provider instanceof MojoFileInformationProvider) {
MojoFileInformationProvider mojoProvider = (MojoFileInformationProvider) provider;

Expand All @@ -76,15 +103,17 @@ private void addMissingDirectoriesFromPath(String targetName, FileInformationPro
}
}

private void addIfIsMissingDirectory(String intermediateDirectory, MojoFileInformationProvider mojoProvider) {
if (startsPathWithPrefix(intermediateDirectory) && !explicitAddedDirectories.contains(intermediateDirectory)) {
missingDirectories.computeIfAbsent(intermediateDirectory,
(String directory) -> new MojoFileInformationProvider(
private void addIfIsMissingDirectory(String intermediateDirectory, MojoFileInformationProvider mojoProvider) throws IOException {
if (startsPathWithPrefix(intermediateDirectory)
&& !explicitAddedDirectories.contains(intermediateDirectory)
&& !generatedDirectories.contains(intermediateDirectory)) {
builderContext.addDirectory(intermediateDirectory, new MojoFileInformationProvider(
mojoProvider.getRulesetEval(),
mojoProvider.getRuleId(),
null,
mojoProvider.getLogger(),
mojoProvider.getTimestamp()));
generatedDirectories.add(intermediateDirectory);
}
}

Expand All @@ -96,12 +125,6 @@ private boolean startsPathWithPrefix(String directory) {
return baseDirectories.stream().anyMatch(directory::startsWith);
}

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);
Expand Down
14 changes: 6 additions & 8 deletions src/main/java/de/dentrassi/rpm/builder/RpmMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -1104,9 +1104,12 @@ protected void fillPayload(final RpmBuilder builder) throws MojoFailureException
return;
}

final ListenableBuilderContext ctx = new ListenableBuilderContext(builder.newContext());
final MissingDirectoryTracker missingDirectoryTracker = new MissingDirectoryTracker(this.generateIntermediateDirectories);
ctx.registerListener(missingDirectoryTracker);
final BuilderContext ctx;
if (this.generateIntermediateDirectories.isEmpty()) {
ctx = builder.newContext();
} else {
ctx = new MissingDirectoryGeneratorInterceptor(builder.newContext(), this.generateIntermediateDirectories);;
}

this.logger.debug("Building payload:");

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

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

private void customizeHeader(final RpmBuilder builder) {
Expand Down

0 comments on commit 1331698

Please sign in to comment.