You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by si...@apache.org on 2019/06/03 16:20:44 UTC

[sling-slingfeature-maven-plugin] branch feature_diff created (now ca54947)

This is an automated email from the ASF dual-hosted git repository.

simonetripodi pushed a change to branch feature_diff
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git.


      at ca54947  SLING-8468 - [slingfeature-m-p] donate a new MOJO which is able to scan and detect differences between different versions of the same Feature model

This branch includes the following new commits:

     new ca54947  SLING-8468 - [slingfeature-m-p] donate a new MOJO which is able to scan and detect differences between different versions of the same Feature model

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-slingfeature-maven-plugin] 01/01: SLING-8468 - [slingfeature-m-p] donate a new MOJO which is able to scan and detect differences between different versions of the same Feature model

Posted by si...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

simonetripodi pushed a commit to branch feature_diff
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit ca5494721cbe3718f14d06217800de2be772c2d9
Author: Simo Tripodi <st...@adobe.com>
AuthorDate: Mon Jun 3 18:20:31 2019 +0200

    SLING-8468 - [slingfeature-m-p] donate a new MOJO which is able to scan
    and detect differences between different versions of the same Feature
    model
    
    initial checkin
---
 pom.xml                                            |  23 ++-
 .../feature/maven/mojos/FeaturesDiffMojo.java      | 199 +++++++++++++++++++++
 2 files changed, 217 insertions(+), 5 deletions(-)

diff --git a/pom.xml b/pom.xml
index 7d9f48a..0e30d91 100644
--- a/pom.xml
+++ b/pom.xml
@@ -172,6 +172,24 @@
             <version>1.0.2</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature.apiregions.model</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature.diff</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <!--
+         | JSON patch
+        -->
+        <dependency>
+            <groupId>com.flipkart.zjsonpatch</groupId>
+            <artifactId>zjsonpatch</artifactId>
+            <version>0.4.8</version>
+        </dependency>
+        <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-core</artifactId>
             <version>${maven.version}</version>
@@ -248,11 +266,6 @@
             <artifactId>json-schema-validator</artifactId>
             <version>2.2.10</version>
         </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-            <version>2.2.3</version>
-        </dependency>
         <!-- APIs JARs -->
         <dependency>
             <groupId>org.apache.felix</groupId>
diff --git a/src/main/java/org/apache/sling/feature/maven/mojos/FeaturesDiffMojo.java b/src/main/java/org/apache/sling/feature/maven/mojos/FeaturesDiffMojo.java
new file mode 100644
index 0000000..cc76ccb
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/FeaturesDiffMojo.java
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven.mojos;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
+import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
+import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionException;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.diff.FeatureDiff;
+import org.apache.sling.feature.diff.io.json.FeatureDiffJSONSerializer;
+import org.apache.sling.feature.io.json.FeatureJSONReader;
+
+/**
+ * Compares different versions of the same Feature Model.
+ */
+@Mojo(name = "features-diff",
+    defaultPhase = LifecyclePhase.PACKAGE,
+    requiresDependencyResolution = ResolutionScope.TEST,
+    threadSafe = true
+)
+@SuppressWarnings("deprecation")
+public final class FeaturesDiffMojo extends AbstractIncludingFeatureMojo {
+
+    @Parameter
+    private FeatureSelectionConfig selection;
+
+    @Parameter(defaultValue = "${project.build.directory}/features-diff", readonly = true)
+    private File mainOutputDir;
+
+    @Parameter(defaultValue = "(,${project.version})")
+    protected String comparisonVersion;
+
+    @Component
+    protected ArtifactResolver resolver;
+
+    @Component
+    protected ArtifactFactory factory;
+
+    @Component
+    private ArtifactMetadataSource metadataSource;
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        getLog().debug("Retrieving Feature files...");
+        final Collection<Feature> features = getSelectedFeatures(selection).values();
+
+        if (features.isEmpty()) {
+            getLog().debug("There are no assciated Feature files to current project, plugin execution will be interrupted");
+            return;
+        }
+
+        if (!mainOutputDir.exists()) {
+            mainOutputDir.mkdirs();
+        }
+
+        getLog().debug("Starting Feature(s) analysis...");
+
+        for (final Feature feature : features) {
+            onFeature(feature);
+        }
+    }
+
+    private void onFeature(Feature current) throws MojoExecutionException, MojoFailureException {
+        Feature previous = getPreviousFeature(current);
+
+        if (previous == null) {
+            getLog().info("There is no previous verion available of " + current + " model");
+            return;
+        }
+
+        getLog().info("Comparing current " + current + " to previous " + previous);
+
+        FeatureDiff featureDiff = FeatureDiff.compareFeatures(previous, current);
+
+        if (featureDiff.isEmpty()) {
+            getLog().info("There are no differences between current " + current + " and previous " + previous + " models");
+            return;
+        }
+
+        File outputDiffFile = new File(mainOutputDir, current.getId().getClassifier() + ".diff.json");
+
+        getLog().info("Rendering differences to file " + outputDiffFile);
+
+        try (FileOutputStream output = new FileOutputStream(outputDiffFile)) {
+            FeatureDiffJSONSerializer.serializeFeatureDiff(featureDiff, output);
+        } catch (IOException e) {
+            throw new MojoExecutionException("An error occurred while serializing Feature diff to " + outputDiffFile, e);
+        }
+    }
+
+    private Feature getPreviousFeature(Feature current) throws MojoExecutionException, MojoFailureException {
+        VersionRange range;
+        try {
+            range = VersionRange.createFromVersionSpec(comparisonVersion);
+        } catch (InvalidVersionSpecificationException e) {
+            throw new MojoFailureException("Invalid comparison version: " + e.getMessage());
+        }
+
+        Artifact previousArtifact;
+
+        try {
+            previousArtifact = factory.createDependencyArtifact(current.getId().getGroupId(),
+                                                                current.getId().getArtifactId(),
+                                                                range,
+                                                                current.getId().getType(),
+                                                                current.getId().getClassifier(),
+                                                                Artifact.SCOPE_COMPILE);
+
+            if (!previousArtifact.getVersionRange().isSelectedVersionKnown(previousArtifact)) {
+                getLog().debug("Searching for versions in range: " + previousArtifact.getVersionRange());
+                List<ArtifactVersion> availableVersions = metadataSource.retrieveAvailableVersions(previousArtifact,
+                                                                                                   mavenSession.getLocalRepository(),
+                                                                                                   project.getRemoteArtifactRepositories());
+                filterSnapshots(availableVersions);
+                ArtifactVersion version = range.matchVersion(availableVersions);
+                if (version != null) {
+                    previousArtifact.selectVersion(version.toString());
+                }
+            }
+        } catch (OverConstrainedVersionException ocve) {
+            throw new MojoFailureException("Invalid comparison version: " + ocve.getMessage());
+        } catch (ArtifactMetadataRetrievalException amre) {
+            throw new MojoExecutionException("Error determining previous version: " + amre.getMessage(), amre);
+        }
+
+        if (previousArtifact.getVersion() == null) {
+            getLog().info("Unable to find a previous version of the " + current + " Feature in the repository");
+            return null;
+        }
+
+        try {
+            resolver.resolve(previousArtifact, project.getRemoteArtifactRepositories(), mavenSession.getLocalRepository());
+        } catch (ArtifactResolutionException are) {
+            getLog().warn("Artifact " + previousArtifact + " cannot be resolved : " + are.getMessage(), are);
+        } catch (ArtifactNotFoundException anfe) {
+            getLog().warn("Artifact " + previousArtifact + " does not exist on local/remote repositories", anfe);
+        }
+
+        File featureFile = previousArtifact.getFile();
+
+        if (featureFile == null || !featureFile.exists()) {
+            return null;
+        }
+
+        try (FileReader reader = new FileReader(featureFile)) {
+            return FeatureJSONReader.read(reader, featureFile.getAbsolutePath());
+        } catch (IOException e) {
+            throw new MojoExecutionException("An error occurred while reading the " + featureFile + " Feature file:", e);
+        }
+    }
+
+    private void filterSnapshots(List<ArtifactVersion> versions) {
+        Iterator<ArtifactVersion> versionIterator = versions.iterator();
+        while (versionIterator.hasNext()) {
+            ArtifactVersion version = versionIterator.next();
+            if (version.getQualifier() != null && version.getQualifier().endsWith("SNAPSHOT")) {
+                versionIterator.remove();
+            }
+        }
+    }
+
+}