From d0396e34977e92b6b752af41684b34e1651bbf3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sat, 19 Aug 2023 19:17:14 +0200 Subject: [PATCH] Make sure the last modified timestamp is set correctly Linux stores modification time with nano-seconds precision, but we currently set the timestamp of the cached file only in milliseconds. This can lead to the situation that the source is considered a few nanoseconds older than the cache file and therefore the cache is regenerated every time. --- .../m2e/pde/target/MavenTargetBundle.java | 2 +- .../pde/target/shared/MavenBundleWrapper.java | 23 +++++++++++-------- .../m2e/pde/target/shared/WrappedBundle.java | 19 +++++++++------ 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetBundle.java b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetBundle.java index dbf36b97c..2e8528815 100644 --- a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetBundle.java +++ b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetBundle.java @@ -147,7 +147,7 @@ private static TargetBundle getWrappedArtifact(Artifact artifact, MavenTargetLoc wrap.messages(true).map(ProcessingMessage::message).distinct().forEach(msg -> { bundleStatus.add(Status.warning(msg)); }); - return wrap.getFile(); + return wrap.getFile().get(); } if (directErrors.size() == 1) { throw new CoreException(Status.error(directErrors.get(0).message())); diff --git a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenBundleWrapper.java b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenBundleWrapper.java index d8e68f5ce..727ff83c9 100644 --- a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenBundleWrapper.java +++ b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenBundleWrapper.java @@ -136,10 +136,7 @@ public boolean visitEnter(DependencyNode n) { Map visited = new HashMap<>(); WrappedBundle wrappedNode = getWrappedNode(node, instructionsLookup, visited); for (WrappedBundle wrap : visited.values()) { - Jar jar = wrap.getJar(); - if (jar != null) { - jar.close(); - } + wrap.getJar().ifPresent(jar -> jar.close()); } return wrappedNode; } @@ -195,6 +192,7 @@ private static WrappedBundle getWrappedNode(DependencyNode node, if (cached == null) { List messages = new ArrayList<>(); wrapArtifactFile.getParentFile().mkdirs(); + boolean hasErrors = false; try (Analyzer analyzer = new Analyzer(analyzerJar);) { analyzer.setProperty("mvnGroupId", artifact.getGroupId()); analyzer.setProperty("mvnArtifactId", artifact.getArtifactId()); @@ -208,7 +206,7 @@ private static WrappedBundle getWrappedNode(DependencyNode node, analyzer.setProperty(property, trimValue); } for (WrappedBundle dep : depends) { - Jar depJar = dep.getJar(); + Jar depJar = dep.getJar().orElse(null); if (depJar == null) { messages.add(new ProcessingMessage(artifact, Type.WARN, "Dependency " + dep.getNode().getDependency() + " was ignored!")); @@ -225,14 +223,21 @@ private static WrappedBundle getWrappedNode(DependencyNode node, continue; } messages.add(new ProcessingMessage(artifact, Type.ERROR, err)); + hasErrors = true; } for (String warn : analyzer.getWarnings()) { messages.add(new ProcessingMessage(artifact, Type.WARN, warn)); } } - wrapArtifactFile.setLastModified(originalFile.lastModified()); - visited.put(node, wrappedNode = new WrappedBundle(node, depends, key, wrapArtifactFile.toPath(), - new Jar(wrapArtifactFile), messages)); + if (hasErrors) { + Files.deleteIfExists(wrapArtifactFile.toPath()); + visited.put(node, wrappedNode = new WrappedBundle(node, depends, key, null, null, messages)); + } else { + Files.setLastModifiedTime(wrapArtifactFile.toPath(), + Files.getLastModifiedTime(originalFile.toPath())); + visited.put(node, wrappedNode = new WrappedBundle(node, depends, key, wrapArtifactFile.toPath(), + new Jar(wrapArtifactFile), messages)); + } } else { visited.put(node, wrappedNode = new WrappedBundle(node, depends, key, wrapArtifactFile.toPath(), new Jar(wrapArtifactFile), List.of())); @@ -291,7 +296,7 @@ public static boolean isOutdated(Path cacheFile, Path sourceFile) throws IOExcep if (Files.exists(cacheFile)) { FileTime sourceTimeStamp = Files.getLastModifiedTime(sourceFile); FileTime cacheTimeStamp = Files.getLastModifiedTime(cacheFile); - return sourceTimeStamp.compareTo(cacheTimeStamp) > 0; + return sourceTimeStamp.toMillis() > cacheTimeStamp.toMillis(); } return true; } diff --git a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/WrappedBundle.java b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/WrappedBundle.java index 9f8824a96..63a661efa 100644 --- a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/WrappedBundle.java +++ b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/WrappedBundle.java @@ -15,6 +15,7 @@ import java.nio.file.Path; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.stream.Stream; import org.eclipse.aether.graph.DependencyNode; @@ -26,8 +27,8 @@ public final class WrappedBundle { private final DependencyNode node; private final List depends; private final String instructionsKey; - private final Path file; - private final Jar jar; + private final Optional file; + private final Optional jar; private final List messages; WrappedBundle(DependencyNode node, List depends, String key, Path file, Jar jar, @@ -35,8 +36,8 @@ public final class WrappedBundle { this.node = node; this.depends = depends; this.instructionsKey = key; - this.file = file; - this.jar = jar; + this.file = Optional.ofNullable(file); + this.jar = Optional.ofNullable(jar); this.messages = messages; } @@ -44,7 +45,7 @@ String getInstructionsKey() { return instructionsKey; } - Jar getJar() { + Optional getJar() { return jar; } @@ -52,8 +53,12 @@ DependencyNode getNode() { return node; } - /** @return the location of the wrapped bundle's files */ - public Path getFile() { + /** + * + * @return an optional describing the wrapped bundle, or an empty optional if + * the bundle was not wrapped because of errors in the generation phase. + */ + public Optional getFile() { return file; }