diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/AssembleMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/AssembleMojo.java index ae7c683877..216f261644 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/AssembleMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/AssembleMojo.java @@ -32,6 +32,7 @@ import java.util.LinkedList; import java.util.function.BiConsumer; import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @@ -235,6 +236,14 @@ public final class AssembleMojo extends SafeMojo { @SuppressWarnings("PMD.ImmutableField") private boolean unrollExitError = true; + /** + * The current version of eo-maven-plugin. + * Maven 3 only. + * @checkstyle MemberNameCheck (7 lines) + */ + @Parameter(defaultValue = "${plugin}", readonly = true) + private PluginDescriptor plugin; + @Override public void exec() throws IOException { if (this.central == null) { diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/ParseMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/ParseMojo.java index 0d0474a5ba..4a3ff14990 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/ParseMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/ParseMojo.java @@ -32,6 +32,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; +import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @@ -43,6 +44,7 @@ import org.cactoos.iterable.Filtered; import org.cactoos.iterable.Mapped; import org.cactoos.number.SumOf; +import org.eolang.maven.footprint.CacheVersion; import org.eolang.maven.footprint.Footprint; import org.eolang.maven.footprint.FtCached; import org.eolang.maven.footprint.FtDefault; @@ -100,6 +102,16 @@ public final class ParseMojo extends SafeMojo implements CompilationStep { defaultValue = "true") private boolean failOnError = true; + /** + * The current version of eo-maven-plugin. + * Maven 3 only. + * You can read more about that property + * here. + * @checkstyle MemberNameCheck (7 lines) + */ + @Parameter(defaultValue = "${plugin}", readonly = true) + private PluginDescriptor plugin; + @Override public void exec() throws IOException { final int total = new SumOf( @@ -157,9 +169,6 @@ private boolean isNotParsed(final Tojo tojo) { * * @param tojo The tojo * @throws IOException If fails - * @todo #1226:30min new FtCached(hash, cache, origin) should be replaced with a new constructor - * that uses the current eo-maven-plugin version - new FtCached(CacheVersion, cache, origin). - * This will allow us to invalidate the cache when the plugin version changes. */ @SuppressWarnings({"PMD.AvoidCatchingGenericException", "PMD.ExceptionAsFlowControl"}) private void parse(final Tojo tojo) throws IOException { @@ -171,7 +180,7 @@ private void parse(final Tojo tojo) throws IOException { ); if (tojo.exists(AssembleMojo.ATTR_HASH)) { footprint = new FtCached( - tojo.get(AssembleMojo.ATTR_HASH), + new CacheVersion(this.plugin.getVersion(), tojo.get(AssembleMojo.ATTR_HASH)), this.cache.resolve(ParseMojo.PARSED), footprint ); diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/footprint/CacheVersion.java b/eo-maven-plugin/src/main/java/org/eolang/maven/footprint/CacheVersion.java index cb7b46872d..489e2c9e05 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/footprint/CacheVersion.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/footprint/CacheVersion.java @@ -39,7 +39,7 @@ * * @since 0.30 */ -final class CacheVersion { +public final class CacheVersion { /** * Not cacheable versions. @@ -66,7 +66,7 @@ final class CacheVersion { * @param ver Version of the eo-maven-plugin which currently builds a program. * @param hsh Hash of the objectionary tag. */ - CacheVersion(final String ver, final String hsh) { + public CacheVersion(final String ver, final String hsh) { this.version = ver; this.hash = hsh; } diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/footprint/FtCached.java b/eo-maven-plugin/src/main/java/org/eolang/maven/footprint/FtCached.java index 52d21f1dee..0cc9011c19 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/footprint/FtCached.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/footprint/FtCached.java @@ -79,7 +79,7 @@ public FtCached( * @param cache Cache root * @param origin Origin */ - FtCached( + public FtCached( final CacheVersion ver, final Path cache, final Footprint origin @@ -108,11 +108,15 @@ public String load(final String program, final String ext) throws IOException { public void save(final String program, final String ext, final Scalar content) throws IOException { final String text; - if (this.version.cacheable() && this.isCached(program, ext)) { - text = this.load(program, ext); + if (this.version.cacheable()) { + if (this.isCached(program, ext)) { + text = this.load(program, ext); + } else { + text = new IoChecked<>(content).value(); + new Home(this.cache).save(text, this.path(program, ext)); + } } else { text = new IoChecked<>(content).value(); - new Home(this.cache).save(text, this.path(program, ext)); } this.origin.save(program, ext, () -> text); } diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/AssembleMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/AssembleMojoTest.java index 8f8c6c153c..7d094c7cd4 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/AssembleMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/AssembleMojoTest.java @@ -70,6 +70,7 @@ void assemblesTogether(@TempDir final Path temp) throws Exception { .with("cache", temp.resolve("cache/parsed")) .with("skipZeroVersions", true) .with("central", Central.EMPTY) + .with("plugin", FakeMaven.pluginDescriptor()) .with("ignoreTransitive", true) .with( "objectionary", @@ -134,6 +135,7 @@ void assemblesNotFailWithFailOnErrorFlag(@TempDir final Path temp) throws Except .with("failOnError", false) .with("central", Central.EMPTY) .with("ignoreTransitive", true) + .with("plugin", FakeMaven.pluginDescriptor()) .with( "objectionary", new OyFake() diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/CleanMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/CleanMojoTest.java index 60912330e7..8450ae7154 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/CleanMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/CleanMojoTest.java @@ -90,6 +90,7 @@ void makesFullCompilingLifecycleSuccessfully(@TempDir final Path temp) throws IO .with("skipZeroVersions", true) .with("central", Central.EMPTY) .with("ignoreTransitive", true) + .with("plugin", FakeMaven.pluginDescriptor()) .with( "objectionary", new OyFake() diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/FakeMaven.java b/eo-maven-plugin/src/test/java/org/eolang/maven/FakeMaven.java index a8188945fb..b94d4a2769 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/FakeMaven.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/FakeMaven.java @@ -45,6 +45,7 @@ import java.util.stream.Stream; import javax.annotation.concurrent.NotThreadSafe; import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.testing.stubs.MavenProjectStub; import org.cactoos.Input; import org.cactoos.text.TextOf; @@ -95,46 +96,6 @@ public FakeMaven(final Path workspace) { this.current = new AtomicInteger(0); } - /** - * Adds correct 'Hello world' program to workspace. - * @return The same maven instance. - * @throws IOException If method can't save eo program to the workspace. - */ - public FakeMaven withHelloWorld() throws IOException { - return this.withProgram("+package f", "[args] > main", " (stdout \"Hello!\").print"); - } - - /** - * Adds eo program to a workspace. - * @param input Program as an input. - * @return The same maven instance. - * @throws IOException If method can't save eo program to the workspace. - */ - public FakeMaven withProgram(final Input input) throws IOException { - return this.withProgram(new UncheckedText(new TextOf(input)).asString()); - } - - /** - * Adds eo program to a workspace. - * @param program Program as a raw string. - * @return The same maven instance. - * @throws IOException If method can't save eo program to the workspace. - */ - public FakeMaven withProgram(final String... program) throws IOException { - return this.withProgram(String.join("\n", program)); - } - - /** - * Adds eo program to a workspace. - * - * @param path Path to the program - * @return The same maven instance - * @throws IOException If fails - */ - public FakeMaven withProgram(final Path path) throws IOException { - return this.withProgram(new UncheckedText(new TextOf(path)).asString()); - } - /** * Sets parameter for execution. * @@ -147,18 +108,6 @@ public FakeMaven with(final String param, final Object value) { return this; } - /** - * Sets tojo attribute. - * - * @param attribute Tojo attribute. - * @param value Attribute value. - * @return The same maven instance. - */ - public FakeMaven withTojoAttribute(final String attribute, final Object value) { - this.attributes.put(attribute, value); - return this; - } - /** * Executes mojos in the workspace. * You can use utility classes to run predefined maven pipelines: @@ -177,6 +126,17 @@ public FakeMaven execute(final Iterable> mojo) return this; } + /** + * Tojo for eo-foreign.* file. + * + * @return TjSmart of the current eo-foreign.file. + */ + public TjSmart foreign() { + return new TjSmart( + Catalogs.INSTANCE.make(this.foreignPath()) + ); + } + /** * Executes Mojo in the workspace. * @@ -222,6 +182,7 @@ public FakeMaven execute(final Class mojo) throws IO this.params.putIfAbsent("generateDotFiles", true); this.params.putIfAbsent("generatedDir", this.generatedPath().toFile()); this.params.putIfAbsent("placedFormat", "csv"); + this.params.putIfAbsent("plugin", FakeMaven.pluginDescriptor()); final Moja moja = new Moja<>(mojo); for (final Map.Entry entry : this.allowedParams(mojo).entrySet()) { moja.with(entry.getKey(), entry.getValue()); @@ -230,11 +191,63 @@ public FakeMaven execute(final Class mojo) throws IO return this; } + /** + * Adds correct 'Hello world' program to workspace. + * @return The same maven instance. + * @throws IOException If method can't save eo program to the workspace. + */ + FakeMaven withHelloWorld() throws IOException { + return this.withProgram("+package f", "[args] > main", " (stdout \"Hello!\").print"); + } + + /** + * Adds eo program to a workspace. + * @param input Program as an input. + * @return The same maven instance. + * @throws IOException If method can't save eo program to the workspace. + */ + FakeMaven withProgram(final Input input) throws IOException { + return this.withProgram(new UncheckedText(new TextOf(input)).asString()); + } + + /** + * Adds eo program to a workspace. + * @param program Program as a raw string. + * @return The same maven instance. + * @throws IOException If method can't save eo program to the workspace. + */ + FakeMaven withProgram(final String... program) throws IOException { + return this.withProgram(String.join("\n", program)); + } + + /** + * Adds eo program to a workspace. + * + * @param path Path to the program + * @return The same maven instance + * @throws IOException If fails + */ + FakeMaven withProgram(final Path path) throws IOException { + return this.withProgram(new UncheckedText(new TextOf(path)).asString()); + } + + /** + * Sets tojo attribute. + * + * @param attribute Tojo attribute. + * @param value Attribute value. + * @return The same maven instance. + */ + FakeMaven withTojoAttribute(final String attribute, final Object value) { + this.attributes.put(attribute, value); + return this; + } + /** * Path to compilation target directory. * @return Path to target dir. */ - public Path targetPath() { + Path targetPath() { return this.workspace.absolute(Paths.get("target")); } @@ -242,7 +255,7 @@ public Path targetPath() { * Path to generated directory. * @return Path to generated dir. */ - public Path generatedPath() { + Path generatedPath() { return this.targetPath().resolve("generated"); } @@ -250,27 +263,16 @@ public Path generatedPath() { * Path to 'eo-foreign.csv' or 'eo-foreign.json' file after all changes. * @return Path to eo-foreign.* file. */ - public Path foreignPath() { + Path foreignPath() { return this.workspace.absolute(Paths.get("eo-foreign.csv")); } - /** - * Tojo for eo-foreign.* file. - * - * @return TjSmart of the current eo-foreign.file. - */ - public TjSmart foreign() { - return new TjSmart( - Catalogs.INSTANCE.make(this.foreignPath()) - ); - } - /** * Tojo for placed.json file. * * @return TjSmart of the current placed.json file. */ - public TjSmart placed() { + TjSmart placed() { return new TjSmart( Catalogs.INSTANCE.make(this.workspace.absolute(Paths.get("placed.json"))) ); @@ -283,7 +285,7 @@ public TjSmart placed() { * @return Map of "relative UNIX path" (key) - "absolute path" (value). * @throws IOException If some problem with filesystem have happened. */ - public Map result() throws IOException { + Map result() throws IOException { final Path root = this.workspace.absolute(Paths.get("")); return Files.walk(root).collect( Collectors.toMap( @@ -296,6 +298,14 @@ public Map result() throws IOException { ); } + /** + * The version of eo-maven-plugin for tests. + * @return Version. + */ + static String pluginVersion() { + return "1.0-TEST"; + } + /** * Suffix for the program name or path. * - main_1.eo @@ -314,6 +324,18 @@ static String suffix(final int index) { return suffix; } + /** + * Plugin descriptor with test version. + * @return Plugin descriptor. + */ + static PluginDescriptor pluginDescriptor() { + final PluginDescriptor descriptor = new PluginDescriptor(); + descriptor.setGroupId("org.eolang"); + descriptor.setArtifactId("eo-maven-plugin"); + descriptor.setVersion(FakeMaven.pluginVersion()); + return descriptor; + } + /** * Adds eo program to a workspace. * @param content EO program content. diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/ParseMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/ParseMojoTest.java index 5cb6729a7b..4826fa2b90 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/ParseMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/ParseMojoTest.java @@ -32,6 +32,7 @@ import org.cactoos.io.ResourceOf; import org.cactoos.text.TextOf; import org.cactoos.text.UncheckedText; +import org.eolang.maven.footprint.CacheVersion; import org.eolang.maven.footprint.FtCached; import org.eolang.maven.footprint.FtDefault; import org.eolang.maven.hash.ChNarrow; @@ -89,7 +90,7 @@ void parsesWithCache(@TempDir final Path temp) throws Exception { ).asString(); final String hash = new ChNarrow(new ChRemote("0.25.0")).value(); new FtCached( - hash, + new CacheVersion(FakeMaven.pluginVersion(), hash), cache.resolve(ParseMojo.PARSED), new FtDefault(maven.targetPath()) ).save("foo.x.main", "xmir", () -> expected); diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/footprint/FtCachedTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/footprint/FtCachedTest.java index 690ce5901b..b66206e0fe 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/footprint/FtCachedTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/footprint/FtCachedTest.java @@ -28,6 +28,7 @@ import org.cactoos.Scalar; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; +import org.hamcrest.io.FileMatchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -42,31 +43,69 @@ final class FtCachedTest { */ private static final Scalar CONTENT = () -> "content"; + /** + * Default extension. + */ + private static final String EXTENSION = "xmir"; + + /** + * Default target folder. + */ + private static final String TARGET = "target"; + + /** + * Default cache folder. + */ + private static final String CACHE = "parsed"; + @Test void loadsContentOfCachedFile(@TempDir final Path temp) throws Exception { - final Path target = temp.resolve("target"); - final Path parsed = temp.resolve("parsed"); - final Footprint cached = new FtCached("abcde123", parsed, new FtDefault(target)); + final Footprint cached = FtCachedTest.footprint("0.29.1", temp); final String program = "org.eolang.txt.format"; - cached.save(program, "xmir", FtCachedTest.CONTENT); + cached.save(program, FtCachedTest.EXTENSION, FtCachedTest.CONTENT); MatcherAssert.assertThat( - cached.load(program, "xmir"), + cached.load(program, FtCachedTest.EXTENSION), Matchers.equalTo(FtCachedTest.CONTENT.value()) ); + MatcherAssert.assertThat( + temp.resolve(FtCachedTest.CACHE).toFile(), + FileMatchers.anExistingDirectory() + ); } @Test - void returnsListOfSavedFilesFromDelegate(@TempDir final Path temp) throws IOException { - final Path target = temp.resolve("target"); - final Footprint footprint = new FtCached( - "abcde123", - temp.resolve("parsed"), - new FtDefault(target) + void loadsContentOfRealFileCachingDoesNotWork(@TempDir final Path temp) throws Exception { + final Footprint cached = FtCachedTest.footprint("0.0.0", temp); + final String program = "org.eolang.txt.regex"; + cached.save(program, FtCachedTest.EXTENSION, FtCachedTest.CONTENT); + MatcherAssert.assertThat( + cached.load(program, FtCachedTest.EXTENSION), + Matchers.equalTo(FtCachedTest.CONTENT.value()) ); - footprint.save("prog", "xmir", FtCachedTest.CONTENT); MatcherAssert.assertThat( - footprint.list("xmir"), - Matchers.hasItem(target.resolve("prog.xmir")) + temp.resolve(FtCachedTest.CACHE).toFile(), + Matchers.not(FileMatchers.anExistingFileOrDirectory()) + ); + } + + @Test + void returnsListOfSavedFilesFromDelegate(@TempDir final Path temp) throws IOException { + final Footprint footprint = FtCachedTest.footprint("0.22.1", temp); + footprint.save("prog", FtCachedTest.EXTENSION, FtCachedTest.CONTENT); + MatcherAssert.assertThat( + footprint.list(FtCachedTest.EXTENSION), + Matchers.hasItem(temp.resolve(FtCachedTest.TARGET).resolve("prog.xmir")) + ); + } + + private static Footprint footprint( + final String eover, + final Path temp + ) { + return new FtCached( + new CacheVersion(eover, "abcde123"), + temp.resolve(FtCachedTest.CACHE), + new FtDefault(temp.resolve(FtCachedTest.TARGET)) ); } }