Track META-INF/ files in state 20/103220/25
authorRuslan Kashapov <ruslan.kashapov@pantheon.tech>
Tue, 8 Nov 2022 09:39:35 +0000 (11:39 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 27 Feb 2023 17:42:21 +0000 (18:42 +0100)
Yang resources copied into META-INF folder now taken into
account as plugin output the same way as generated files.

JIRA: YANGTOOLS-1166
Change-Id: I815c1fc69c1220ce86efd319725470f11533c72b
Signed-off-by: Ruslan Kashapov <ruslan.kashapov@pantheon.tech>
plugin/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/FileState.java
plugin/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/GeneratorTask.java
plugin/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangProvider.java
plugin/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessor.java
plugin/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/AbstractCodeGeneratorTest.java

index e2357d8f74b3fa6302865a144b542e825e4b9499..e06e65e0af4e1b809c2c60a761300e92cc4cea24 100644 (file)
@@ -9,6 +9,10 @@ package org.opendaylight.yangtools.yang2sources.plugin;
 
 import static java.util.Objects.requireNonNull;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.nio.file.attribute.BasicFileAttributes;
 import org.eclipse.jdt.annotation.NonNull;
 
@@ -16,7 +20,28 @@ import org.eclipse.jdt.annotation.NonNull;
  * Hash of a single file state. {@link #size()} corresponds to {@link BasicFileAttributes#size()}.
  */
 record FileState(@NonNull String path, long size, int crc32) {
+    /**
+     * A simple interface describing the intended content of a file.
+     */
+    @FunctionalInterface
+    interface FileContent {
+        /**
+         * Write the content of this file to specified {@link OutputStream}.
+         *
+         * @param out OutputStream to write to, guaranteed to be non-null
+         * @throws IOException if any error occurs
+         */
+        void writeTo(@NonNull OutputStream out) throws IOException;
+    }
+
     FileState {
         requireNonNull(path);
     }
+
+    static @NonNull FileState ofWrittenFile(final File file, final FileContent content) throws IOException {
+        try (var out = new CapturingOutputStream(Files.newOutputStream(file.toPath()))) {
+            content.writeTo(out);
+            return new FileState(file.getPath(), out.size(), out.crc32c());
+        }
+    }
 }
index 43f2d7382a416833ac292d87e4d0efe4cee31af4..fe71b83d0460dee9ef8a4e3f3b5f15465f28f769 100644 (file)
@@ -189,12 +189,14 @@ final class GeneratorTask extends ParserConfigAware {
         }
 
         FileState generateFile() {
-            try (var out = new CapturingOutputStream(buildContext.newFileOutputStream(target))) {
-                file.writeBody(out);
-                return new FileState(target.getPath(), out.size(), out.crc32c());
+            final FileState ret;
+            try {
+                ret = FileState.ofWrittenFile(target, file::writeBody);
             } catch (IOException e) {
                 throw new IllegalStateException("Failed to generate file " + target, e);
             }
+            buildContext.refresh(target);
+            return ret;
         }
     }
 }
index 9d4c9721172288dde75000b0145c1bf3c234f276..f6cb95c680273bf4f501d5440fc342699646143e 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang2sources.plugin;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.io.Files;
 import java.io.File;
 import java.io.IOException;
@@ -22,8 +23,8 @@ abstract class YangProvider {
         private static final Logger LOG = LoggerFactory.getLogger(Default.class);
 
         @Override
-        void addYangsToMetaInf(final MavenProject project, final Collection<YangTextSchemaSource> modelsInProject)
-                throws IOException {
+        Collection<FileState> addYangsToMetaInf(final MavenProject project,
+                final Collection<YangTextSchemaSource> modelsInProject) throws IOException {
 
             final File generatedYangDir = new GeneratedDirectories(project).getYangDir();
             LOG.debug("Generated dir {}", generatedYangDir);
@@ -31,18 +32,21 @@ abstract class YangProvider {
             // copy project's src/main/yang/*.yang to ${project.builddir}/generated-sources/yang/META-INF/yang/
             // This honors setups like a Eclipse-profile derived one
             final File withMetaInf = new File(generatedYangDir, YangToSourcesProcessor.META_INF_YANG_STRING);
+            final var stateListBuilder = ImmutableList.<FileState>builder();
 
             for (YangTextSchemaSource source : modelsInProject) {
                 final String fileName = source.getIdentifier().toYangFilename();
                 final File file = new File(withMetaInf, fileName);
                 Files.createParentDirs(file);
 
-                source.copyTo(Files.asByteSink(file));
+                stateListBuilder.add(FileState.ofWrittenFile(file, source::copyTo));
                 LOG.debug("Created file {} for {}", file, source.getIdentifier());
             }
 
             setResource(generatedYangDir, project);
             LOG.debug("{} YANG files marked as resources: {}", YangToSourcesProcessor.LOG_PREFIX, generatedYangDir);
+
+            return stateListBuilder.build();
         }
     }
 
@@ -52,8 +56,8 @@ abstract class YangProvider {
         return DEFAULT;
     }
 
-    abstract void addYangsToMetaInf(MavenProject project, Collection<YangTextSchemaSource> modelsInProject)
-            throws IOException;
+    abstract Collection<FileState> addYangsToMetaInf(MavenProject project,
+            Collection<YangTextSchemaSource> modelsInProject) throws IOException;
 
     static void setResource(final File targetYangDir, final MavenProject project) {
         Resource res = new Resource();
index b0f7be018a969df8013028a4831b9550159d2e04..7641aa5514929246af19df207eb4348409354118 100644 (file)
@@ -193,6 +193,7 @@ class YangToSourcesProcessor {
         LOG.info("{} Project model files found: {} in {}", LOG_PREFIX, yangFilesInProject.size(), watch);
 
         final var outputFiles = ImmutableList.<FileState>builder();
+        boolean sourcesPersisted = false;
 
         for (YangParserConfiguration parserConfig : parserConfigs) {
             final Optional<ProcessorModuleReactor> optReactor = createReactor(yangFilesInProject,
@@ -215,18 +216,23 @@ class YangToSourcesProcessor {
                     LOG.info("{} {} YANG models processed in {}", LOG_PREFIX, holder.getContext().getModules().size(),
                         sw);
                     outputFiles.addAll(generateSources(holder, codeGenerators, parserConfig));
+
+                    if (!sourcesPersisted) {
+                        // add META_INF/yang once
+                        final var models = reactor.getModelsInProject();
+                        final Collection<FileState> sourceFileStates;
+                        try {
+                            sourceFileStates = yangProvider.addYangsToMetaInf(project, models);
+                        } catch (IOException e) {
+                            throw new MojoExecutionException("Failed write model files for " + models, e);
+                        }
+
+                        sourcesPersisted = true;
+                        outputFiles.addAll(sourceFileStates);
+                    }
                 } else {
                     LOG.info("{} Skipping YANG code generation because property yang.skip is true", LOG_PREFIX);
                 }
-
-                // FIXME: this is not right: we should be generating the models exactly once!
-                // add META_INF/yang
-                final Collection<YangTextSchemaSource> models = reactor.getModelsInProject();
-                try {
-                    yangProvider.addYangsToMetaInf(project, models);
-                } catch (IOException e) {
-                    throw new MojoExecutionException("Failed write model files for " + models, e);
-                }
             }
         }
 
index e6faef3ce3fc1158939999bc30e0cf3defa51230..b93eee5ab24281adda8e008c0a8ac7c0cd0007cb 100644 (file)
@@ -51,7 +51,8 @@ public abstract class AbstractCodeGeneratorTest {
         doReturn(plugin).when(project).getPlugin(YangToSourcesMojo.PLUGIN_NAME);
 
         try {
-            lenient().doNothing().when(yangProvider).addYangsToMetaInf(any(MavenProject.class), anyCollection());
+            lenient().when(yangProvider.addYangsToMetaInf(any(MavenProject.class), anyCollection()))
+                    .thenReturn(List.of());
         } catch (IOException e) {
             throw new AssertionError(e);
         }