SLING-5099 - Create 'New and Noteworthy' page for Sling 8
Enhance the launchpad-comparator to list fixed Jira issues for Sling
artifacts with version changes.
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1708567 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..89540d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/dependency-reduced-pom.xml
diff --git a/pom.xml b/pom.xml
index 2cc217e..528f4d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,6 +106,20 @@
<version>3.0.15</version>
</dependency>
+ <!-- Retrieve changelog data from SVN -->
+ <dependency>
+ <groupId>org.tmatesoft.svnkit</groupId>
+ <artifactId>svnkit</artifactId>
+ <version>1.8.11</version>
+ </dependency>
+
+ <!-- Parse Jira JSON responses -->
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.2.4</version>
+ </dependency>
+
</dependencies>
<build>
@@ -116,7 +130,8 @@
<version>2.4.1</version>
<configuration>
<transformers>
- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.apache.sling.tooling.lc.Main</mainClass>
</transformer>
</transformers>
@@ -130,6 +145,15 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>dependency-reduced-pom.xml</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
</plugins>
</build>
diff --git a/src/main/java/org/apache/sling/tooling/lc/LaunchpadComparer.java b/src/main/java/org/apache/sling/tooling/lc/LaunchpadComparer.java
new file mode 100644
index 0000000..df4c931
--- /dev/null
+++ b/src/main/java/org/apache/sling/tooling/lc/LaunchpadComparer.java
@@ -0,0 +1,171 @@
+/*
+ * 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.tooling.lc;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import org.apache.sling.maven.projectsupport.BundleListUtils;
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
+import org.apache.sling.provisioning.model.Artifact;
+import org.apache.sling.provisioning.model.Model;
+import org.apache.sling.provisioning.model.ModelUtility;
+import org.apache.sling.provisioning.model.io.ModelReader;
+import org.apache.sling.tooling.lc.aether.AetherSetup;
+import org.apache.sling.tooling.lc.aether.ArtifactKey;
+import org.apache.sling.tooling.lc.aether.Artifacts;
+import org.apache.sling.tooling.lc.aether.VersionChange;
+import org.apache.sling.tooling.lc.jira.IssueFinder;
+import org.apache.sling.tooling.lc.svn.SvnChangeLogFinder;
+import org.tmatesoft.svn.core.SVNException;
+
+import com.google.common.collect.Sets;
+
+public class LaunchpadComparer {
+
+ private static final Pattern JIRA_KEY_PATTERN = Pattern.compile("^(SLING-\\d+).*");
+
+ private final String firstVersion;
+ private final String secondVersion;
+
+ public LaunchpadComparer(String firstVersion, String secondVersion) {
+ this.firstVersion = firstVersion;
+ this.secondVersion = secondVersion;
+ }
+
+ public void run() throws Exception {
+
+ System.out.format("Computing differences between Launchpad versions %s and %s...%n",
+ firstVersion, secondVersion);
+
+ // 1. download artifacts
+ AetherSetup aether = new AetherSetup();
+
+ File fromFile = aether.download(Artifacts.launchpadCoordinates(firstVersion));
+ File toFile = aether.download(Artifacts.launchpadCoordinates(secondVersion));
+
+ // 2. parse artifact definitions
+ Model model;
+ try (BufferedReader reader = Files.newBufferedReader(toFile.toPath())) {
+ model = ModelUtility.getEffectiveModel(ModelReader.read(reader, null));
+ }
+
+ Map<ArtifactKey, Artifact> to = model.getFeatures().stream()
+ .flatMap( f -> f.getRunModes().stream())
+ .flatMap( r -> r.getArtifactGroups().stream())
+ .flatMap( g -> StreamSupport.stream(g.spliterator(), false))
+ .collect(Collectors.toMap( a -> new ArtifactKey(a), Function.identity()));
+
+ BundleList readBundleList = BundleListUtils.readBundleList(fromFile);
+
+ Map<ArtifactKey, Artifact> from = readBundleList.getStartLevels().stream()
+ .flatMap( sl -> sl.getBundles().stream() )
+ .collect(Collectors.toMap( b -> new ArtifactKey(b), LaunchpadComparer::newArtifact));
+
+ // 3. generate added / removed / changed
+ Set<Artifact> removed = Sets.difference(from.keySet(), to.keySet()).stream()
+ .map( k -> from.get(k))
+ .collect(Collectors.toSet());
+
+ Set<Artifact> added = Sets.difference(to.keySet(), from.keySet()).stream()
+ .map( k -> to.get(k))
+ .collect(Collectors.toSet());
+
+ Map<ArtifactKey, VersionChange> changed = to.values().stream()
+ .filter( k -> !added.contains(k) && !removed.contains(k))
+ .map( k -> new ArtifactKey(k))
+ .filter( k -> !Objects.equals(to.get(k).getVersion(), from.get(k).getVersion()))
+ .collect(Collectors.toMap( Function.identity(), k -> new VersionChange(from.get(k).getVersion(), to.get(k).getVersion())));
+
+ // 4. output changes
+
+ System.out.println("Added ");
+ added.stream().sorted().forEach(LaunchpadComparer::outputFormatted);
+
+ System.out.println("Removed ");
+ removed.stream().sorted().forEach(LaunchpadComparer::outputFormatted);
+
+ System.out.println("Changed");
+ changed.entrySet().stream()
+ .sorted( (a, b) -> a.getKey().compareTo(b.getKey()) )
+ .forEach(LaunchpadComparer::outputFormatted);
+
+ }
+
+ private static Artifact newArtifact(Bundle bundle) {
+
+ return new Artifact(bundle.getGroupId(), bundle.getArtifactId(), bundle.getVersion(), bundle.getClassifier(), bundle.getType());
+ }
+
+ private static void outputFormatted(Artifact a) {
+
+ System.out.format(" %-30s : %-55s : %s%n", a.getGroupId(), a.getArtifactId(), a.getVersion());
+
+ }
+
+ private static void outputFormatted(Map.Entry<ArtifactKey, VersionChange> e) {
+
+ ArtifactKey artifact = e.getKey();
+ VersionChange versionChange = e.getValue();
+
+ System.out.format(" %-30s : %-55s : %s -> %s%n", artifact.getGroupId(), artifact.getArtifactId(), versionChange.getFrom(), versionChange.getTo());
+
+ if ( !artifact.getGroupId().equals("org.apache.sling")) {
+ return;
+ }
+
+ SvnChangeLogFinder svn = new SvnChangeLogFinder();
+
+ String fromTag = artifact.getArtifactId()+"-"+versionChange.getFrom();
+ String toTag = artifact.getArtifactId()+"-"+ versionChange.getTo();
+ try {
+ List<String> issues = svn.getChanges(fromTag, toTag)
+ .stream()
+ .map(LaunchpadComparer::toJiraKey)
+ .filter( k -> k != null)
+ .collect(Collectors.toList());
+
+ IssueFinder issueFinder = new IssueFinder();
+ issueFinder.findIssues(issues).
+ forEach( i -> System.out.format(" %-10s - %s%n", i.getKey(), i.getSummary()));
+
+ } catch (SVNException | IOException e1) {
+ System.err.println("Failed retrieving changes : " + e1.getMessage());
+ }
+ }
+
+ private static String toJiraKey(String message) {
+ Matcher matcher = JIRA_KEY_PATTERN.matcher(message);
+ if ( !matcher.matches() ) {
+ return null;
+ }
+
+ return matcher.group(1);
+ }
+}
diff --git a/src/main/java/org/apache/sling/tooling/lc/Main.java b/src/main/java/org/apache/sling/tooling/lc/Main.java
index 7b7837b..91da961 100644
--- a/src/main/java/org/apache/sling/tooling/lc/Main.java
+++ b/src/main/java/org/apache/sling/tooling/lc/Main.java
@@ -16,26 +16,6 @@
*/
package org.apache.sling.tooling.lc;
-import java.io.BufferedReader;
-import java.io.File;
-import java.nio.file.Files;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-
-import org.apache.sling.maven.projectsupport.BundleListUtils;
-import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
-import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
-import org.apache.sling.provisioning.model.Artifact;
-import org.apache.sling.provisioning.model.Model;
-import org.apache.sling.provisioning.model.ModelUtility;
-import org.apache.sling.provisioning.model.io.ModelReader;
-
-import com.google.common.collect.Sets;
-
public class Main {
public static void main(String[] args) throws Exception {
@@ -48,77 +28,9 @@
secondVersion = args[1];
}
- System.out.format("Computing differences between Launchpad versions %s and %s...%n",
- firstVersion, secondVersion);
+ LaunchpadComparer comparer = new LaunchpadComparer(firstVersion, secondVersion);
+ comparer.run();
- // 1. download artifacts
- AetherSetup aether = new AetherSetup();
- File fromFile = aether.download(Artifacts.launchpadCoordinates(firstVersion));
- File toFile = aether.download(Artifacts.launchpadCoordinates(secondVersion));
-
- // 2. parse artifact definitions
- Model model;
- try (BufferedReader reader = Files.newBufferedReader(toFile.toPath())) {
- model = ModelUtility.getEffectiveModel(ModelReader.read(reader, null));
- }
-
- // TODO - versions are not interpolated
- Map<ArtifactKey, Artifact> to = model.getFeatures().stream()
- .flatMap( f -> f.getRunModes().stream())
- .flatMap( r -> r.getArtifactGroups().stream())
- .flatMap( g -> StreamSupport.stream(g.spliterator(), false))
- .collect(Collectors.toMap( a -> new ArtifactKey(a), Function.identity()));
-
- BundleList readBundleList = BundleListUtils.readBundleList(fromFile);
-
- // 3. generate added / removed / changed
- Map<ArtifactKey, Artifact> from = readBundleList.getStartLevels().stream()
- .flatMap( sl -> sl.getBundles().stream() )
- .collect(Collectors.toMap( b -> new ArtifactKey(b), Main::newArtifact));
-
- Set<Artifact> removed = Sets.difference(from.keySet(), to.keySet()).stream()
- .map( k -> from.get(k))
- .collect(Collectors.toSet());
-
- Set<Artifact> added = Sets.difference(to.keySet(), from.keySet()).stream()
- .map( k -> to.get(k))
- .collect(Collectors.toSet());
-
- Map<ArtifactKey, VersionChange> changed = to.values().stream()
- .filter( k -> !added.contains(k) && !removed.contains(k))
- .map( k -> new ArtifactKey(k))
- .filter( k -> !Objects.equals(to.get(k).getVersion(), from.get(k).getVersion()))
- .collect(Collectors.toMap( Function.identity(), k -> new VersionChange(from.get(k).getVersion(), to.get(k).getVersion())));
-
- // 4. output changes
-
- System.out.println("Added ");
- added.stream().sorted().forEach(Main::outputFormatted);
-
- System.out.println("Removed ");
- removed.stream().sorted().forEach(Main::outputFormatted);
-
- System.out.println("Changed");
- changed.entrySet().stream()
- .sorted( (a, b) -> a.getKey().compareTo(b.getKey()) )
- .forEach(Main::outputFormatted);
- }
-
- private static Artifact newArtifact(Bundle bundle) {
-
- return new Artifact(bundle.getGroupId(), bundle.getArtifactId(), bundle.getVersion(), bundle.getClassifier(), bundle.getType());
- }
-
- private static void outputFormatted(Artifact a) {
-
- System.out.format(" %-30s : %-55s : %s%n", a.getGroupId(), a.getArtifactId(), a.getVersion());
-
- }
-
- private static void outputFormatted(Map.Entry<ArtifactKey, VersionChange> e) {
-
- System.out.format(" %-30s : %-55s : %s -> %s%n", e.getKey().getGroupId(), e.getKey().getArtifactId(), e.getValue().getFrom(), e.getValue().getTo());
-
}
}
diff --git a/src/main/java/org/apache/sling/tooling/lc/AetherSetup.java b/src/main/java/org/apache/sling/tooling/lc/aether/AetherSetup.java
similarity index 97%
rename from src/main/java/org/apache/sling/tooling/lc/AetherSetup.java
rename to src/main/java/org/apache/sling/tooling/lc/aether/AetherSetup.java
index d529f3e..8d4679b 100644
--- a/src/main/java/org/apache/sling/tooling/lc/AetherSetup.java
+++ b/src/main/java/org/apache/sling/tooling/lc/aether/AetherSetup.java
@@ -14,7 +14,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.sling.tooling.lc;
+package org.apache.sling.tooling.lc.aether;
import java.io.File;
import java.util.Arrays;
@@ -36,7 +36,7 @@
import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
-class AetherSetup {
+public class AetherSetup {
private final List<RemoteRepository> repos = Arrays.asList(
new RemoteRepository.Builder("central", "default", "http://central.maven.org/maven2/").build(),
diff --git a/src/main/java/org/apache/sling/tooling/lc/ArtifactKey.java b/src/main/java/org/apache/sling/tooling/lc/aether/ArtifactKey.java
similarity index 96%
rename from src/main/java/org/apache/sling/tooling/lc/ArtifactKey.java
rename to src/main/java/org/apache/sling/tooling/lc/aether/ArtifactKey.java
index 047a1d2..112e10a 100644
--- a/src/main/java/org/apache/sling/tooling/lc/ArtifactKey.java
+++ b/src/main/java/org/apache/sling/tooling/lc/aether/ArtifactKey.java
@@ -14,14 +14,14 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.sling.tooling.lc;
+package org.apache.sling.tooling.lc.aether;
import java.util.Objects;
import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
import org.apache.sling.provisioning.model.Artifact;
-class ArtifactKey implements Comparable<ArtifactKey> {
+public class ArtifactKey implements Comparable<ArtifactKey> {
private String groupId;
private String artifactId;
diff --git a/src/main/java/org/apache/sling/tooling/lc/Artifacts.java b/src/main/java/org/apache/sling/tooling/lc/aether/Artifacts.java
similarity index 95%
rename from src/main/java/org/apache/sling/tooling/lc/Artifacts.java
rename to src/main/java/org/apache/sling/tooling/lc/aether/Artifacts.java
index 0ffc42a..8bbed53 100644
--- a/src/main/java/org/apache/sling/tooling/lc/Artifacts.java
+++ b/src/main/java/org/apache/sling/tooling/lc/aether/Artifacts.java
@@ -14,12 +14,12 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.sling.tooling.lc;
+package org.apache.sling.tooling.lc.aether;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-class Artifacts {
+public class Artifacts {
private static final Pattern VERSION_NUMBER = Pattern.compile("^(\\d+)(-SNAPSHOT)?");
diff --git a/src/main/java/org/apache/sling/tooling/lc/VersionChange.java b/src/main/java/org/apache/sling/tooling/lc/aether/VersionChange.java
similarity index 93%
rename from src/main/java/org/apache/sling/tooling/lc/VersionChange.java
rename to src/main/java/org/apache/sling/tooling/lc/aether/VersionChange.java
index 7c69d0b..671ff2e 100644
--- a/src/main/java/org/apache/sling/tooling/lc/VersionChange.java
+++ b/src/main/java/org/apache/sling/tooling/lc/aether/VersionChange.java
@@ -14,9 +14,9 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.sling.tooling.lc;
+package org.apache.sling.tooling.lc.aether;
-class VersionChange {
+public class VersionChange {
private String from;
private String to;
diff --git a/src/main/java/org/apache/sling/tooling/lc/VersionChange.java b/src/main/java/org/apache/sling/tooling/lc/jira/Fields.java
similarity index 65%
copy from src/main/java/org/apache/sling/tooling/lc/VersionChange.java
copy to src/main/java/org/apache/sling/tooling/lc/jira/Fields.java
index 7c69d0b..2215d06 100644
--- a/src/main/java/org/apache/sling/tooling/lc/VersionChange.java
+++ b/src/main/java/org/apache/sling/tooling/lc/jira/Fields.java
@@ -14,28 +14,18 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.sling.tooling.lc;
+package org.apache.sling.tooling.lc.jira;
-class VersionChange {
+public class Fields {
- private String from;
- private String to;
+ private final String summary;
+
+ public Fields(String summary) {
+ this.summary = summary;
+ }
- public VersionChange(String from, String to) {
- this.from = from;
- this.to = to;
+ public String getSummary() {
+ return summary;
}
- public String getFrom() {
- return from;
- }
-
- public String getTo() {
- return to;
- }
-
- @Override
- public String toString() {
- return "VersionChange [" +from + " -> " + to +"]";
- }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/apache/sling/tooling/lc/jira/Issue.java b/src/main/java/org/apache/sling/tooling/lc/jira/Issue.java
new file mode 100644
index 0000000..12e54b1
--- /dev/null
+++ b/src/main/java/org/apache/sling/tooling/lc/jira/Issue.java
@@ -0,0 +1,79 @@
+/*
+ * 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.tooling.lc.jira;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.google.inject.internal.util.Objects;
+
+public class Issue implements Comparable<Issue> {
+
+ private static final Pattern KEY_PATTERN = Pattern.compile("^([A-Z]+)-(\\d+)$");
+
+ private final String key;
+ private final Fields fields;
+
+ public Issue(String key, Fields fields) {
+ this.key = key;
+ this.fields = fields;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public Fields getFields() {
+ return fields;
+ }
+
+ public String getSummary() {
+ return fields.getSummary();
+ }
+
+ @Override
+ public String toString() {
+ return key + " - " + getSummary();
+ }
+
+ @Override
+ public int compareTo(Issue o) {
+
+ Matcher ourMatcher = KEY_PATTERN.matcher(key);
+ Matcher theirMatcher = KEY_PATTERN.matcher(o.key);
+
+ if ( !ourMatcher.matches()) {
+ throw new IllegalArgumentException("No match found for " + key);
+ }
+
+ if ( !theirMatcher.matches()) {
+ throw new IllegalArgumentException("No match found for " + o.key);
+ }
+
+ String ourProject = ourMatcher.group(1);
+ String theirProject = theirMatcher.group(1);
+
+ if ( !Objects.equal(ourProject, theirProject)) {
+ return ourProject.compareTo(theirProject);
+ }
+
+ int ourId = Integer.parseInt(ourMatcher.group(2));
+ int theirId = Integer.parseInt(theirMatcher.group(2));
+
+ return Integer.valueOf(ourId).compareTo(theirId);
+ }
+}
diff --git a/src/main/java/org/apache/sling/tooling/lc/jira/IssueFinder.java b/src/main/java/org/apache/sling/tooling/lc/jira/IssueFinder.java
new file mode 100644
index 0000000..69005b9
--- /dev/null
+++ b/src/main/java/org/apache/sling/tooling/lc/jira/IssueFinder.java
@@ -0,0 +1,79 @@
+/*
+ * 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.tooling.lc.jira;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.utils.HttpClientUtils;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+import com.google.gson.Gson;
+
+public class IssueFinder {
+
+ public static void main(String[] args) throws IOException {
+
+ new IssueFinder().findIssues(Arrays.asList("SLING-1", "SLING-2"))
+ .stream()
+ .forEach(System.out::println);
+ }
+
+ public List<Issue> findIssues(List<String> issueKeys) throws IOException{
+
+ HttpClient client = new DefaultHttpClient();
+
+ HttpGet get;
+ try {
+ URIBuilder builder = new URIBuilder("https://issues.apache.org/jira/rest/api/2/search")
+ .addParameter("jql", "key in (" + String.join(",", issueKeys) + ")")
+ .addParameter("fields", "key,summary");
+
+ get = new HttpGet(builder.build());
+ } catch (URISyntaxException e) {
+ // never happens
+ throw new RuntimeException(e);
+ }
+
+ HttpResponse response = client.execute(get);
+ try {
+ if ( response.getStatusLine().getStatusCode() != 200 ) {
+ throw new IOException("Search call returned status " + response.getStatusLine().getStatusCode());
+ }
+
+ try ( Reader reader = new InputStreamReader(response.getEntity().getContent(), "UTF-8") ) {
+ Response apiResponse = new Gson().fromJson(reader, Response.class);
+ List<Issue> issues = apiResponse.getIssues();
+ Collections.sort(issues);
+ return issues;
+
+ }
+ } finally {
+ HttpClientUtils.closeQuietly(client);
+ }
+
+ }
+}
diff --git a/src/main/java/org/apache/sling/tooling/lc/VersionChange.java b/src/main/java/org/apache/sling/tooling/lc/jira/Response.java
similarity index 64%
copy from src/main/java/org/apache/sling/tooling/lc/VersionChange.java
copy to src/main/java/org/apache/sling/tooling/lc/jira/Response.java
index 7c69d0b..e77407f 100644
--- a/src/main/java/org/apache/sling/tooling/lc/VersionChange.java
+++ b/src/main/java/org/apache/sling/tooling/lc/jira/Response.java
@@ -14,28 +14,19 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.sling.tooling.lc;
+package org.apache.sling.tooling.lc.jira;
-class VersionChange {
-
- private String from;
- private String to;
+import java.util.List;
- public VersionChange(String from, String to) {
- this.from = from;
- this.to = to;
+public class Response {
+
+ private final List<Issue> issues;
+
+ public Response(List<Issue> issues) {
+ this.issues = issues;
}
-
- public String getFrom() {
- return from;
+
+ public List<Issue> getIssues() {
+ return issues;
}
-
- public String getTo() {
- return to;
- }
-
- @Override
- public String toString() {
- return "VersionChange [" +from + " -> " + to +"]";
- }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/apache/sling/tooling/lc/svn/SvnChangeLogFinder.java b/src/main/java/org/apache/sling/tooling/lc/svn/SvnChangeLogFinder.java
new file mode 100644
index 0000000..dd1fc9c
--- /dev/null
+++ b/src/main/java/org/apache/sling/tooling/lc/svn/SvnChangeLogFinder.java
@@ -0,0 +1,62 @@
+/*
+ * 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.tooling.lc.svn;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.wc.SVNClientManager;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+public class SvnChangeLogFinder {
+
+ private static final String SLING_SVN_REPO_BASE = "https://svn.apache.org/repos/asf/sling";
+
+ public static void main(String[] args) throws SVNException {
+
+ new SvnChangeLogFinder().getChanges("org.apache.sling.adapter-2.1.2", "org.apache.sling.adapter-2.1.6")
+ .stream().forEach(System.out::println);
+ }
+
+ public List<String> getChanges(String first, String second) throws SVNException {
+
+ SVNURL svnUrl = SVNURL.parseURIEncoded(SLING_SVN_REPO_BASE);
+
+ List<String> changes = new ArrayList<>();
+
+ SVNClientManager manager = SVNClientManager.newInstance();
+
+ SVNRepository repo = manager.getRepositoryPool().createRepository(svnUrl, true);
+
+ SVNRevision from = SVNRevision.create(getRevision(first, repo));
+ SVNRevision to = SVNRevision.create(getRevision(second, repo));
+
+ repo.log(new String[] { "tags/" + second } ,from.getNumber(), to.getNumber(), false, false, (e) -> changes.add(e.getMessage()));
+
+ return changes;
+ }
+
+
+ private long getRevision(String tagName, SVNRepository repo) throws SVNException {
+
+ return repo.info("tags/" + tagName, -1).getRevision();
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/tooling/lc/ArtifactsTest.java b/src/test/java/org/apache/sling/tooling/lc/ArtifactsTest.java
index 9d41298..8b3b396 100644
--- a/src/test/java/org/apache/sling/tooling/lc/ArtifactsTest.java
+++ b/src/test/java/org/apache/sling/tooling/lc/ArtifactsTest.java
@@ -1,6 +1,22 @@
+/*
+ * 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.tooling.lc;
-import static org.apache.sling.tooling.lc.Artifacts.launchpadCoordinates;
+import static org.apache.sling.tooling.lc.aether.Artifacts.launchpadCoordinates;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;