diff --git a/pom.xml b/pom.xml
index bfbff66..1fd91bc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
org.springframework.boot
spring-boot-starter-parent
- 1.0.0.RC4
+ 1.0.2.RELEASE
diff --git a/src/main/java/org/springframework/data/release/cli/ReleaseCommands.java b/src/main/java/org/springframework/data/release/cli/ReleaseCommands.java
index 2b4667c..8de7c1e 100644
--- a/src/main/java/org/springframework/data/release/cli/ReleaseCommands.java
+++ b/src/main/java/org/springframework/data/release/cli/ReleaseCommands.java
@@ -19,8 +19,10 @@ import static org.springframework.data.release.model.Projects.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.release.docs.DocumentationOperations;
import org.springframework.data.release.git.GitOperations;
import org.springframework.data.release.git.Tags;
+import org.springframework.data.release.gradle.GradleOperations;
import org.springframework.data.release.maven.MavenOperations;
import org.springframework.data.release.maven.Pom;
import org.springframework.data.release.misc.ReleaseOperations;
@@ -43,8 +45,10 @@ import org.springframework.stereotype.Component;
public class ReleaseCommands implements CommandMarker {
private final MavenOperations maven;
+ private final GradleOperations gradle;
private final GitOperations git;
private final ReleaseOperations misc;
+ private final DocumentationOperations docs;
@CliCommand("release predict")
public String predictTrainAndIteration() throws Exception {
@@ -95,18 +99,24 @@ public class ReleaseCommands implements CommandMarker {
public void prepare(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
git.prepare(iteration);
+
misc.prepareChangelogs(iteration);
+ misc.updateResources(iteration);
+ docs.updateDockbookIncludes(iteration);
+
maven.updatePom(iteration, Phase.PREPARE);
+ gradle.updateProject(iteration, Phase.PREPARE);
}
@CliCommand(value = "release conclude")
public void conclude(@CliOption(key = "", mandatory = true) TrainIteration iteration) throws Exception {
- // - pull updates
- // - tag release
+ git.tagRelease(iteration);
+
// - post release pom updates
maven.updatePom(iteration, Phase.CLEANUP);
+ gradle.updateProject(iteration, Phase.CLEANUP);
// - push
}
diff --git a/src/main/java/org/springframework/data/release/cli/TrainIterationConverter.java b/src/main/java/org/springframework/data/release/cli/TrainIterationConverter.java
index 61ab822..6850c2a 100644
--- a/src/main/java/org/springframework/data/release/cli/TrainIterationConverter.java
+++ b/src/main/java/org/springframework/data/release/cli/TrainIterationConverter.java
@@ -65,11 +65,6 @@ public class TrainIterationConverter implements Converter {
for (Train train : ReleaseTrains.TRAINS) {
- // if (!StringUtils.hasText(existingData) &&
- // !train.getName().toLowerCase().startsWith(existingData.toLowerCase())) {
- // continue;
- // }
-
for (Iteration iteration : train.getIterations()) {
completions.add(new Completion(new TrainIteration(train, iteration).toString()));
}
diff --git a/src/main/java/org/springframework/data/release/docs/DocumentationOperations.java b/src/main/java/org/springframework/data/release/docs/DocumentationOperations.java
new file mode 100644
index 0000000..584cf89
--- /dev/null
+++ b/src/main/java/org/springframework/data/release/docs/DocumentationOperations.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed 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.springframework.data.release.docs;
+
+import static org.springframework.data.release.model.Projects.*;
+import lombok.RequiredArgsConstructor;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.release.git.GitOperations;
+import org.springframework.data.release.git.GitProject;
+import org.springframework.data.release.git.Tag;
+import org.springframework.data.release.git.Tags;
+import org.springframework.data.release.io.Workspace;
+import org.springframework.data.release.io.Workspace.LineCallback;
+import org.springframework.data.release.model.ModuleIteration;
+import org.springframework.data.release.model.Project;
+import org.springframework.data.release.model.TrainIteration;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Oliver Gierke
+ */
+@Component
+@RequiredArgsConstructor(onConstructor = @__(@Autowired))
+public class DocumentationOperations {
+
+ private static final String INDEX_LOCATION = "/src/docbkx/index.xml";
+
+ private final Workspace workspace;
+ private final GitOperations git;
+
+ public void updateDockbookIncludes(TrainIteration iteration) throws Exception {
+
+ Tags tags = git.getTags(COMMONS);
+
+ ModuleIteration commons = iteration.getModule(COMMONS);
+ ModuleIteration previousIteration = iteration.getPreviousIteration(commons);
+
+ final GitProject gitProject = git.getGitProject(COMMONS);
+ final Tag previousTag = tags.createTag(previousIteration);
+ final Tag newTag = tags.createTag(commons);
+
+ for (ModuleIteration module : iteration) {
+
+ Project project = module.getProject();
+
+ if (!project.dependsOn(COMMONS)) {
+ continue;
+ }
+
+ workspace.processFile(INDEX_LOCATION, project, new LineCallback() {
+
+ @Override
+ public String doWith(String line, long number) {
+
+ boolean isInclude = line.contains("xi:include");
+ boolean containsGitRepo = line.contains(gitProject.getRepositoryName());
+
+ return isInclude && containsGitRepo ? line.replace(previousTag.toString(), newTag.toString()) : line;
+ }
+ });
+ }
+ }
+}
diff --git a/src/main/java/org/springframework/data/release/git/GitCommands.java b/src/main/java/org/springframework/data/release/git/GitCommands.java
index 0afaf99..e78077b 100644
--- a/src/main/java/org/springframework/data/release/git/GitCommands.java
+++ b/src/main/java/org/springframework/data/release/git/GitCommands.java
@@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.ReleaseTrains;
+import org.springframework.data.release.model.Train;
import org.springframework.data.release.model.TrainIteration;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.annotation.CliCommand;
@@ -55,9 +56,14 @@ public class GitCommands implements CommandMarker {
return StringUtils.collectionToDelimitedString(git.getTags(project).asList(), "\n");
}
+ /**
+ * Resets all projects contained in the given {@link Train}.
+ *
+ * @param trainName
+ * @throws Exception
+ */
@CliCommand("git reset")
- public void reset(@CliOption(key = { "", "train" }, mandatory = true) String trainName, @CliOption(key = "iteration",
- mandatory = true) String iterationName) throws Exception {
+ public void reset(@CliOption(key = { "", "train" }, mandatory = true) String trainName) throws Exception {
git.reset(ReleaseTrains.getTrainByName(trainName));
}
diff --git a/src/main/java/org/springframework/data/release/git/GitOperations.java b/src/main/java/org/springframework/data/release/git/GitOperations.java
index 3b8cd7d..1c80a2d 100644
--- a/src/main/java/org/springframework/data/release/git/GitOperations.java
+++ b/src/main/java/org/springframework/data/release/git/GitOperations.java
@@ -27,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.release.io.CommandResult;
import org.springframework.data.release.io.OsCommandOperations;
import org.springframework.data.release.io.Workspace;
+import org.springframework.data.release.jira.IssueTracker;
+import org.springframework.data.release.jira.Ticket;
import org.springframework.data.release.model.ArtifactVersion;
import org.springframework.data.release.model.Iteration;
import org.springframework.data.release.model.Module;
@@ -35,6 +37,7 @@ import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.Train;
import org.springframework.data.release.model.TrainIteration;
import org.springframework.data.release.utils.Logger;
+import org.springframework.plugin.core.PluginRegistry;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -52,6 +55,7 @@ public class GitOperations {
private final OsCommandOperations osCommandOperations;
private final Workspace workspace;
private final Logger logger;
+ private final PluginRegistry issueTracker;
public GitProject getGitProject(Project project) {
return new GitProject(project, server);
@@ -168,6 +172,49 @@ public class GitOperations {
return new Tags(tags);
}
+ public void tagRelease(TrainIteration iteration) throws Exception {
+
+ for (ModuleIteration module : iteration) {
+
+ Branch branch = Branch.from(module);
+ Project project = module.getProject();
+
+ String checkoutCommand = String.format("git checkout %s", branch);
+ osCommandOperations.executeCommand(checkoutCommand, project).get();
+
+ String updateCommand = String.format("git pull origin %s", branch);
+ osCommandOperations.executeCommand(updateCommand, project).get();
+
+ String hash = getReleaseHash(module);
+ Tag tag = getTags(project).createTag(module);
+ String tagCommand = String.format("git tag %s %s", tag, hash);
+ osCommandOperations.executeCommand(tagCommand, project).get();
+ }
+ }
+
+ private String getReleaseHash(ModuleIteration module) throws Exception {
+
+ Project project = module.getProject();
+
+ String result = osCommandOperations.executeForResult("git log --pretty=format:'%h %s'", project);
+ Ticket releaseTicket = issueTracker.getPluginFor(project).getReleaseTicketFor(module);
+ String trigger = String.format("%s - Release", releaseTicket.getId());
+
+ logger.log(project, "Looking up release commit (ticket id %s)", releaseTicket.getId());
+
+ for (String line : result.split("\n")) {
+
+ int summaryStart = line.indexOf(" ");
+
+ if (line.substring(summaryStart + 1).startsWith(trigger)) {
+ return line.substring(0, summaryStart);
+ }
+ }
+
+ throw new IllegalStateException(String.format("Did not find a release commit for project %s (ticket id %s)",
+ project, releaseTicket.getId()));
+ }
+
/**
* Returns the {@link Tag} that represents the {@link ArtifactVersion} of the given {@link Project}.
*
diff --git a/src/main/java/org/springframework/data/release/git/Tag.java b/src/main/java/org/springframework/data/release/git/Tag.java
index 77172c6..c09210f 100644
--- a/src/main/java/org/springframework/data/release/git/Tag.java
+++ b/src/main/java/org/springframework/data/release/git/Tag.java
@@ -45,6 +45,16 @@ public class Tag implements Comparable {
return ArtifactVersion.parse(getVersionSource());
}
+ /**
+ * Creates a new {@link Tag} for the given {@link ArtifactVersion} based on the format of the current one.
+ *
+ * @param version
+ * @return
+ */
+ public Tag createNew(ArtifactVersion version) {
+ return new Tag(name.startsWith("v") ? "v".concat(version.toString()) : version.toString());
+ }
+
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
diff --git a/src/main/java/org/springframework/data/release/git/Tags.java b/src/main/java/org/springframework/data/release/git/Tags.java
index 231b68c..ec2fde6 100644
--- a/src/main/java/org/springframework/data/release/git/Tags.java
+++ b/src/main/java/org/springframework/data/release/git/Tags.java
@@ -22,6 +22,8 @@ import java.util.List;
import lombok.EqualsAndHashCode;
+import org.springframework.data.release.model.ArtifactVersion;
+import org.springframework.data.release.model.ModuleIteration;
import org.springframework.util.Assert;
/**
@@ -58,6 +60,10 @@ public class Tags implements Iterable {
return tags.get(0);
}
+ public Tag createTag(ModuleIteration iteration) {
+ return getLatest().createNew(ArtifactVersion.from(iteration));
+ }
+
/**
* Returns all {@link Tag}s as {@link List}.
*
diff --git a/src/main/java/org/springframework/data/release/gradle/GradleOperations.java b/src/main/java/org/springframework/data/release/gradle/GradleOperations.java
new file mode 100644
index 0000000..ba32109
--- /dev/null
+++ b/src/main/java/org/springframework/data/release/gradle/GradleOperations.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed 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.springframework.data.release.gradle;
+
+import static org.springframework.data.release.model.Projects.*;
+import lombok.RequiredArgsConstructor;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.release.io.Workspace;
+import org.springframework.data.release.io.Workspace.LineCallback;
+import org.springframework.data.release.maven.Repository;
+import org.springframework.data.release.model.ArtifactVersion;
+import org.springframework.data.release.model.ModuleIteration;
+import org.springframework.data.release.model.Phase;
+import org.springframework.data.release.model.Project;
+import org.springframework.data.release.model.TrainIteration;
+import org.springframework.data.release.utils.Logger;
+import org.springframework.stereotype.Component;
+
+/**
+ * Gradle specific operations.
+ *
+ * @author Oliver Gierke
+ */
+@Component
+@RequiredArgsConstructor(onConstructor = @__(@Autowired))
+public class GradleOperations {
+
+ private static final String BUILD_GRADLE = "build.gradle";
+ private static final String GRADLE_PROPERTIES = "gradle.properties";
+ private static final String COMMONS_PROPERTY = "springDataCommonsVersion";
+
+ private final Workspace workspace;
+ private final Logger logger;
+
+ /**
+ * Updates all Gradle projects contained in the release.
+ *
+ * @param iteration
+ * @param phase
+ * @throws Exception
+ */
+ public void updateProject(TrainIteration iteration, final Phase phase) throws Exception {
+
+ final Repository repository = new Repository(iteration.getIteration());
+ final ArtifactVersion commonsVersion = iteration.getModuleVersion(COMMONS);
+
+ for (ModuleIteration module : iteration.getModulesExcept(BUILD)) {
+
+ final Project project = module.getProject();
+
+ if (!isGradleProject(project)) {
+ continue;
+ }
+
+ workspace.processFile(GRADLE_PROPERTIES, project, new LineCallback() {
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.release.io.Workspace.LineCallback#doWith(java.lang.String, long)
+ */
+ @Override
+ public String doWith(String line, long number) {
+
+ if (!line.contains(COMMONS_PROPERTY)) {
+ return line;
+ }
+
+ ArtifactVersion version = phase.equals(Phase.PREPARE) ? commonsVersion : commonsVersion
+ .getNextDevelopmentVersion();
+
+ logger.log(project, "Setting Spring Data Commons version in %s to %s.", GRADLE_PROPERTIES, version);
+ return String.format("%s=%s", COMMONS_PROPERTY, version);
+ }
+ });
+
+ workspace.processFile(BUILD_GRADLE, project, new LineCallback() {
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.release.io.Workspace.LineCallback#doWith(java.lang.String, long)
+ */
+ @Override
+ public String doWith(String line, long number) {
+
+ String snapshotUrl = repository.getSnapshotUrl();
+ String releaseUrl = repository.getUrl();
+ String message = "Switching to Spring repository %s";
+
+ switch (phase) {
+ case CLEANUP:
+ logger.log(project, message, snapshotUrl);
+ return line.contains(releaseUrl) ? line.replace(releaseUrl, snapshotUrl) : line;
+ case PREPARE:
+ default:
+ logger.log(project, message, releaseUrl);
+ return line.contains(snapshotUrl) ? line.replace(snapshotUrl, releaseUrl) : line;
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Returns whether the given project is a Gradle project (checks for the presence of a build.gradle file).
+ *
+ * @param project
+ * @return
+ */
+ private boolean isGradleProject(Project project) {
+ return workspace.getFile(BUILD_GRADLE, project).exists();
+ }
+}
diff --git a/src/main/java/org/springframework/data/release/io/Workspace.java b/src/main/java/org/springframework/data/release/io/Workspace.java
index 6e924d2..34366bc 100644
--- a/src/main/java/org/springframework/data/release/io/Workspace.java
+++ b/src/main/java/org/springframework/data/release/io/Workspace.java
@@ -17,8 +17,9 @@ package org.springframework.data.release.io;
import java.io.File;
import java.io.IOException;
-import java.nio.file.Files;
+import java.nio.charset.Charset;
import java.nio.file.Path;
+import java.util.Scanner;
import javax.annotation.PostConstruct;
@@ -30,6 +31,8 @@ import org.springframework.data.release.model.Project;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
+import com.google.common.io.Files;
+
/**
* Abstraction of the workspace that is used to work with the {@link Project}'s repositories, execute builds, etc.
*
@@ -39,6 +42,8 @@ import org.springframework.util.Assert;
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class Workspace {
+ private static final Charset UTF_8 = Charset.forName("UTF-8");
+
public static final String WORK_DIR_PROPERTY = "io.workDir";
private final Environment environment;
@@ -93,6 +98,40 @@ public class Workspace {
return new File(getProjectDirectory(project), name);
}
+ public boolean processFile(String filename, Project project, LineCallback callback) throws Exception {
+
+ File file = getFile(filename, project);
+
+ if (!file.exists()) {
+ return false;
+ }
+
+ StringBuilder builder = new StringBuilder();
+
+ try (Scanner scanner = new Scanner(file)) {
+
+ long number = 0;
+
+ while (scanner.hasNextLine()) {
+
+ String result = callback.doWith(scanner.nextLine(), number++);
+
+ if (result != null) {
+ builder.append(result).append("\n");
+ }
+ }
+ }
+
+ writeContentToFile(filename, project, builder.toString());
+ return true;
+ }
+
+ private void writeContentToFile(String name, Project project, String content) throws IOException {
+
+ File file = getFile(name, project);
+ Files.write(content, file, UTF_8);
+ }
+
/**
* Initializes the working directory and creates the folders if necessary.
*
@@ -103,8 +142,12 @@ public class Workspace {
Path path = getWorkingDirectory().toPath();
- if (!Files.exists(path)) {
- Files.createDirectories(path);
+ if (!java.nio.file.Files.exists(path)) {
+ java.nio.file.Files.createDirectories(path);
}
}
+
+ public interface LineCallback {
+ String doWith(String line, long number);
+ }
}
diff --git a/src/main/java/org/springframework/data/release/maven/MavenOperations.java b/src/main/java/org/springframework/data/release/maven/MavenOperations.java
index 012454c..febd8ef 100644
--- a/src/main/java/org/springframework/data/release/maven/MavenOperations.java
+++ b/src/main/java/org/springframework/data/release/maven/MavenOperations.java
@@ -31,10 +31,12 @@ import org.springframework.data.release.model.ArtifactVersion;
import org.springframework.data.release.model.ModuleIteration;
import org.springframework.data.release.model.Phase;
import org.springframework.data.release.model.Project;
+import org.springframework.data.release.model.Projects;
import org.springframework.data.release.model.Train;
import org.springframework.data.release.model.TrainIteration;
import org.springframework.data.release.utils.Logger;
import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
import org.xmlbeam.ProjectionFactory;
import org.xmlbeam.io.XBFileIO;
@@ -59,8 +61,25 @@ public class MavenOperations {
return projectionFactory.io().file(file).read(Pom.class);
}
+ /**
+ * Updates the POM files for all Maven projects contained in the iteration:
+ *
+ * - Updates the BOM POM.
+ * - Updates the dependency version to Spring Data Commons to the current release version for all projects depending
+ * on it.
+ * - Switches to the Spring release Maven repository.
+ *
+ * If {@link Phase} is {@link Phase#CLEANUP} the changes will be rolled back.
+ *
+ * @param iteration must not be {@literal null}.
+ * @param phase must not be {@literal null}.
+ * @throws Exception
+ */
public void updatePom(TrainIteration iteration, final Phase phase) throws Exception {
+ Assert.notNull(iteration, "Train iteration must not be null!");
+ Assert.notNull(phase, "Phase must not be null!");
+
updateBomPom(iteration, phase);
final Repository repository = new Repository(iteration.getIteration());
@@ -70,20 +89,31 @@ public class MavenOperations {
for (ModuleIteration module : iteration.getModulesExcept(BUILD)) {
final Project project = module.getProject();
- File pomFile = workspace.getFile(POM_XML, project);
- execute(pomFile, new PomCallback() {
+ if (!isMavenProject(project)) {
+ logger.log(module, "No pom.xml file found, skipping project.");
+ continue;
+ }
+
+ execute(workspace.getFile(POM_XML, project), new PomCallback() {
@Override
public Pom doWith(Pom pom) {
- if (!project.equals(COMMONS)) {
- pom.setProperty(COMMONS_VERSION_PROPERTY,
- CLEANUP.equals(phase) ? commonsVersion.getNextDevelopmentVersion() : commonsVersion);
+ if (project.dependsOn(Projects.COMMONS)) {
+
+ ArtifactVersion version = CLEANUP.equals(phase) ? commonsVersion.getNextDevelopmentVersion()
+ : commonsVersion;
+ logger.log(project, "Updating Spring Data Commons version dependecy to %s (setting property %s).", version,
+ COMMONS_VERSION_PROPERTY);
+ pom.setProperty(COMMONS_VERSION_PROPERTY, version);
}
- pom.setParentVersion(CLEANUP.equals(phase) ? buildVersion.getNextDevelopmentVersion() : buildVersion);
- updateRepository(pom, repository, phase);
+ ArtifactVersion version = CLEANUP.equals(phase) ? buildVersion.getNextDevelopmentVersion() : buildVersion;
+ logger.log(project, "Updating Spring Data Build Parent version to %s.", version);
+ pom.setParentVersion(version);
+
+ updateRepository(project, pom, repository, phase);
return pom;
}
@@ -144,6 +174,8 @@ public class MavenOperations {
File bomPomFile = workspace.getFile("bom/pom.xml", BUILD);
+ logger.log(BUILD, "Updating BOM pom.xml…");
+
execute(bomPomFile, new PomCallback() {
@Override
@@ -155,6 +187,8 @@ public class MavenOperations {
ArtifactVersion version = artifact.getVersion();
version = PREPARE.equals(phase) ? version : version.getNextDevelopmentVersion();
+ logger.log(BUILD, "%s", module);
+
pom.setDependencyVersion(artifact.getArtifactId(), version);
}
@@ -163,12 +197,21 @@ public class MavenOperations {
});
}
- private void updateRepository(Pom pom, Repository repository, Phase phase) {
+ private void updateRepository(Project project, Pom pom, Repository repository, Phase phase) {
+
+ String message = "Switching to Spring repository %s (%s).";
if (PREPARE.equals(phase)) {
+
+ logger.log(project, message, repository.getId(), repository.getUrl());
+
pom.setRepositoryId(repository.getSnapshotId(), repository.getId());
pom.setRepositoryUrl(repository.getId(), repository.getUrl());
+
} else {
+
+ logger.log(project, message, repository.getSnapshotId(), repository.getSnapshotUrl());
+
pom.setRepositoryId(repository.getId(), repository.getSnapshotId());
pom.setRepositoryUrl(repository.getSnapshotId(), repository.getSnapshotUrl());
}
diff --git a/src/main/java/org/springframework/data/release/misc/ReleaseOperations.java b/src/main/java/org/springframework/data/release/misc/ReleaseOperations.java
index 6c02351..fc78f47 100644
--- a/src/main/java/org/springframework/data/release/misc/ReleaseOperations.java
+++ b/src/main/java/org/springframework/data/release/misc/ReleaseOperations.java
@@ -15,14 +15,15 @@
*/
package org.springframework.data.release.misc;
-import java.io.File;
-import java.nio.charset.Charset;
-import java.util.Scanner;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.release.io.Workspace;
+import org.springframework.data.release.io.Workspace.LineCallback;
import org.springframework.data.release.jira.Changelog;
import org.springframework.data.release.jira.IssueTracker;
import org.springframework.data.release.model.Iteration;
@@ -30,12 +31,11 @@ import org.springframework.data.release.model.ModuleIteration;
import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.Train;
import org.springframework.data.release.model.TrainIteration;
+import org.springframework.data.release.utils.Logger;
import org.springframework.plugin.core.PluginRegistry;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
-import com.google.common.io.Files;
-
/**
* @author Oliver Gierke
*/
@@ -43,8 +43,20 @@ import com.google.common.io.Files;
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ReleaseOperations {
+ private static final Set CHANGELOG_LOCATIONS;
+
+ static {
+
+ Set locations = new HashSet<>();
+ locations.add("src/main/resources/changelog.txt"); // for Maven projects
+ locations.add("docs/src/info/changelog.txt"); // for Gradle projects
+
+ CHANGELOG_LOCATIONS = Collections.unmodifiableSet(locations);
+ }
+
private final PluginRegistry trackers;
private final Workspace workspace;
+ private final Logger logger;
/**
* Creates {@link Changelog} instances for all modules of the given {@link Train} and {@link Iteration}.
@@ -59,26 +71,53 @@ public class ReleaseOperations {
for (ModuleIteration module : iteration) {
- Changelog changelog = trackers.getPluginFor(module.getProject()).getChangelogFor(module);
- File file = workspace.getFile("src/main/resources/changelog.txt", module.getProject());
- StringBuilder builder = new StringBuilder();
+ final Changelog changelog = trackers.getPluginFor(module.getProject()).getChangelogFor(module);
- try (Scanner scanner = new Scanner(file)) {
+ for (String location : CHANGELOG_LOCATIONS) {
- // Copy headline
- builder.append(scanner.nextLine()).append("\n");
- builder.append(scanner.nextLine()).append("\n");
+ boolean processed = workspace.processFile(location, module.getProject(), new LineCallback() {
- // Add new changelog
- builder.append(changelog.toString());
+ @Override
+ public String doWith(String line, long number) {
- // Append existing
- while (scanner.hasNextLine()) {
- builder.append(scanner.nextLine()).append("\n");
+ if (line.startsWith("=")) {
+
+ StringBuilder builder = new StringBuilder();
+ builder.append(line).append("\n\n");
+ builder.append(changelog.toString());
+
+ return builder.toString();
+ } else {
+ return line;
+ }
+ }
+ });
+
+ if (processed) {
+ logger.log(module.getProject(), "Updated changelog %s.", location);
}
}
+ }
+ }
- Files.write(builder, file, Charset.forName("UTF-8"));
+ public void updateResources(TrainIteration iteration) throws Exception {
+
+ for (final ModuleIteration module : iteration) {
+
+ workspace.processFile("src/main/resources/notice.txt", module.getProject(), new LineCallback() {
+
+ @Override
+ public String doWith(String line, long number) {
+
+ if (number != 0) {
+ return line;
+ }
+
+ return module.toString();
+ }
+ });
+
+ logger.log(module, "Updated notice.txt.");
}
}
}
diff --git a/src/main/java/org/springframework/data/release/model/Iteration.java b/src/main/java/org/springframework/data/release/model/Iteration.java
index 935a1d4..90bdf31 100644
--- a/src/main/java/org/springframework/data/release/model/Iteration.java
+++ b/src/main/java/org/springframework/data/release/model/Iteration.java
@@ -62,6 +62,10 @@ public class Iteration {
return name.startsWith("SR");
}
+ public boolean isNext(Iteration iteration) {
+ return next.equals(iteration);
+ }
+
public int getBugfixValue() {
return name.startsWith("SR") ? Integer.parseInt(name.substring(2)) : 0;
}
diff --git a/src/main/java/org/springframework/data/release/model/Project.java b/src/main/java/org/springframework/data/release/model/Project.java
index 8cb89d2..76cdf62 100644
--- a/src/main/java/org/springframework/data/release/model/Project.java
+++ b/src/main/java/org/springframework/data/release/model/Project.java
@@ -22,6 +22,8 @@ import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
+import org.springframework.util.Assert;
+
/**
* @author Oliver Gierke
*/
@@ -53,4 +55,16 @@ public class Project {
public String getFullName() {
return "Spring Data ".concat(name);
}
+
+ /**
+ * Returns whether the current project depends on the given one.
+ *
+ * @param project must not be {@literal null}.
+ * @return
+ */
+ public boolean dependsOn(Project project) {
+
+ Assert.notNull(project, "Project must not be null!");
+ return dependencies.contains(project);
+ }
}
diff --git a/src/main/java/org/springframework/data/release/model/Train.java b/src/main/java/org/springframework/data/release/model/Train.java
index 7f06b5b..6622c5a 100644
--- a/src/main/java/org/springframework/data/release/model/Train.java
+++ b/src/main/java/org/springframework/data/release/model/Train.java
@@ -139,6 +139,10 @@ public class Train implements Iterable {
return ArtifactVersion.from(new ModuleIteration(module, iteration, this));
}
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
@Override
public String toString() {
@@ -157,7 +161,7 @@ public class Train implements Iterable {
*/
@EqualsAndHashCode
@ToString
- private static class Iterations implements Iterable {
+ public static class Iterations implements Iterable {
public static Iterations DEFAULT = new Iterations(M1, RC1, GA, SR1, SR2, SR3, SR4);
@@ -191,6 +195,17 @@ public class Train implements Iterable {
return null;
}
+ Iteration getPreviousIteration(Iteration iteration) {
+
+ for (Iteration candidate : iterations) {
+ if (candidate.isNext(iteration)) {
+ return candidate;
+ }
+ }
+
+ throw new IllegalArgumentException(String.format("Could not find previous iteration for %s!", iteration));
+ }
+
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
diff --git a/src/main/java/org/springframework/data/release/model/TrainIteration.java b/src/main/java/org/springframework/data/release/model/TrainIteration.java
index b00372c..1d89850 100644
--- a/src/main/java/org/springframework/data/release/model/TrainIteration.java
+++ b/src/main/java/org/springframework/data/release/model/TrainIteration.java
@@ -53,6 +53,12 @@ public class TrainIteration implements Iterable {
return train.getModuleIterations(iteration, exclusions);
}
+ public ModuleIteration getPreviousIteration(ModuleIteration module) {
+
+ Iteration previousIteration = train.getIterations().getPreviousIteration(iteration);
+ return train.getModuleIteration(previousIteration, module.getProject().getName());
+ }
+
/*
* (non-Javadoc)
* @see java.lang.Object#toString()