diff --git a/pom.xml b/pom.xml index 235b939..3e804d7 100644 --- a/pom.xml +++ b/pom.xml @@ -89,6 +89,11 @@ 1.3 + + org.apache.commons + commons-lang3 + + org.apache.httpcomponents httpclient diff --git a/src/main/java/org/springframework/data/release/announcement/AnnouncementOperations.java b/src/main/java/org/springframework/data/release/announcement/AnnouncementOperations.java index 269783f..f83ad1c 100644 --- a/src/main/java/org/springframework/data/release/announcement/AnnouncementOperations.java +++ b/src/main/java/org/springframework/data/release/announcement/AnnouncementOperations.java @@ -17,7 +17,6 @@ package org.springframework.data.release.announcement; import static org.springframework.data.release.model.Projects.*; -import org.springframework.data.release.build.MavenArtifact; import org.springframework.data.release.cli.StaticResources; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.TrainIteration; @@ -53,11 +52,6 @@ public class AnnouncementOperations { builder.append("`"); builder.append(" - "); - MavenArtifact artifact = new MavenArtifact(module); - - builder.append(getMarkDownLink("Artifacts", artifact.getRootUrl())); - builder.append(" - "); - StaticResources resources = new StaticResources(module); builder.append(getMarkDownLink("Javadoc", resources.getJavaDocUrl())).append(" - "); diff --git a/src/main/java/org/springframework/data/release/build/MavenArtifact.java b/src/main/java/org/springframework/data/release/build/MavenArtifact.java index 730a0d4..85bf60f 100644 --- a/src/main/java/org/springframework/data/release/build/MavenArtifact.java +++ b/src/main/java/org/springframework/data/release/build/MavenArtifact.java @@ -36,7 +36,6 @@ public class MavenArtifact { private static final GroupId GROUP_ID = GroupId.of("org.springframework.data"); private final Project project; - private final @Getter Repository repository; private final @Getter ArtifactVersion version; /** @@ -49,14 +48,12 @@ public class MavenArtifact { Assert.notNull(module, "Module iteration must not be null!"); this.project = module.getModule().getProject(); - this.repository = new Repository(module.getIteration()); this.version = ArtifactVersion.of(module); } public MavenArtifact(Project project, ArtifactVersion version) { this.project = project; - this.repository = new Repository(version); this.version = version; } @@ -80,12 +77,4 @@ public class MavenArtifact { return version.getNextDevelopmentVersion(); } - /** - * Returns the URL pointing to the artifacts. - * - * @return - */ - public String getRootUrl() { - return String.format("%s/%s/%s/%s", repository.getUrl(), GROUP_ID.asPath(), getArtifactId(), version); - } } diff --git a/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java b/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java index ce7cf8a..9d4caf8 100644 --- a/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java +++ b/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java @@ -112,13 +112,12 @@ class MavenBuildSystem implements BuildSystem { if (updater.isBuildProject()) { if (information.isBomInBuildProject()) { - updateBom(information, "bom/pom.xml", BUILD); + updateBom(updater, information, "bom/pom.xml", BUILD); } - updateParentPom(information); - + updateParentPom(updater, information); } else if (updater.isBomProject()) { - updateBom(information, "bom/pom.xml", BOM); + updateBom(updater, information, "bom/pom.xml", BOM); } else { doWithProjection(workspace.getFile(POM_XML, updater.getProject()), pom -> { @@ -458,7 +457,7 @@ class MavenBuildSystem implements BuildSystem { return module; } - private void updateBom(UpdateInformation updateInformation, String file, Project project) { + private void updateBom(PomUpdater updater, UpdateInformation updateInformation, String file, Project project) { TrainIteration iteration = updateInformation.getTrain(); @@ -499,10 +498,12 @@ class MavenBuildSystem implements BuildSystem { throw new IllegalStateException(String.format("Found snapshot dependencies %s!", snapshotDependencies)); } } + + updater.updateRepository(pom); }); } - private void updateParentPom(UpdateInformation information) { + private void updateParentPom(PomUpdater updater, UpdateInformation information) { // Fix version of shared resources to to-be-released version. doWithProjection(workspace.getFile("parent/pom.xml", BUILD), ParentPom.class, pom -> { @@ -512,6 +513,8 @@ class MavenBuildSystem implements BuildSystem { logger.log(BUILD, "Setting releasetrain property to %s.", information.getReleaseTrainVersion()); pom.setReleaseTrain(information.getReleaseTrainVersion()); + + updater.updateRepository(pom); }); } @@ -622,6 +625,9 @@ class MavenBuildSystem implements BuildSystem { s = s.replaceAll(Pattern.quote("standalone=\"no\"?><"), "standalone=\"no\"?>" + IOUtils.LINE_SEPARATOR + "<"); } + s = s.replace(String.format("%n\t\t%n\t"), + String.format("%n\t")); + if (!s.endsWith(IOUtils.LINE_SEPARATOR)) { s += IOUtils.LINE_SEPARATOR; } diff --git a/src/main/java/org/springframework/data/release/build/Pom.java b/src/main/java/org/springframework/data/release/build/Pom.java index 28d7458..212e582 100644 --- a/src/main/java/org/springframework/data/release/build/Pom.java +++ b/src/main/java/org/springframework/data/release/build/Pom.java @@ -15,9 +15,20 @@ */ package org.springframework.data.release.build; +import lombok.SneakyThrows; + +import java.util.Arrays; import java.util.List; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.data.release.model.ArtifactVersion; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xmlbeam.annotation.XBDelete; import org.xmlbeam.annotation.XBRead; import org.xmlbeam.annotation.XBValue; import org.xmlbeam.annotation.XBWrite; @@ -57,6 +68,12 @@ public interface Pom { @XBWrite("/project/repositories/repository[id=\"{0}\"]/url") void setRepositoryUrl(String id, @XBValue String url); + @XBDelete("/project/repositories/*") + void deleteRepositories(); + + @XBWrite("/project/repositories") + void setRepositories(Element repositories); + /** * Sets the version of the dependency with the given artifact identifier to the given {@link ArtifactVersion}. * @@ -78,13 +95,93 @@ public interface Pom { @XBRead("//dependency[substring(version, string-length(version) - string-length('-SNAPSHOT') + 1) = '-SNAPSHOT']") List getSnapshotDependencies(); - public interface Repository { + class RepositoryElementFactory { - @XBRead("child::id") - String getId(); + public static Element of(Repository... repositories) { + return of(Arrays.asList(repositories)); + } + + public static Element of(List repositories) { + + Document doc = createDocument(); + Element repos = doc.createElement("repositories"); + repos.appendChild(doc.createTextNode(IOUtils.LINE_SEPARATOR)); + repos.appendChild(doc.createTextNode("\t\t")); + + for (int i = 0; i < repositories.size(); i++) { + + Repository repo = repositories.get(i); + + repos.appendChild(toElement(doc, repo)); + repos.appendChild(doc.createTextNode(IOUtils.LINE_SEPARATOR)); + + if (i + 1 == repositories.size()) { + repos.appendChild(indent(doc, 1)); + } else { + repos.appendChild(indent(doc, 2)); + } + } + + return repos; + } + + private static Element toElement(Document doc, Repository repo) { + + Element repository = doc.createElement("repository"); + + repository.appendChild(doc.createTextNode(IOUtils.LINE_SEPARATOR)); + + repository.appendChild(indent(doc, 3)); + repository.appendChild(createElement(doc, "id", repo.getId())); + repository.appendChild(doc.createTextNode(IOUtils.LINE_SEPARATOR)); + + repository.appendChild(indent(doc, 3)); + repository.appendChild(createElement(doc, "url", repo.getUrl())); + repository.appendChild(doc.createTextNode(IOUtils.LINE_SEPARATOR)); + + if (repo.getSnapshots() != null) { + appendEnabledConfig(doc, "snapshots", repo.getSnapshots(), repository); + } + + if (repo.getReleases() != null) { + appendEnabledConfig(doc, "releases", repo.getReleases(), repository); + } + + repository.appendChild(indent(doc, 2)); + + return repository; + } + + private static void appendEnabledConfig(Document doc, String tagName, boolean value, Element repository) { + + Element snapshots = doc.createElement(tagName); + snapshots.appendChild(doc.createTextNode(IOUtils.LINE_SEPARATOR)); + + snapshots.appendChild(indent(doc, 4)); + snapshots.appendChild(createElement(doc, "enabled", Boolean.toString(value))); + snapshots.appendChild(doc.createTextNode(IOUtils.LINE_SEPARATOR)); + snapshots.appendChild(indent(doc, 3)); + + repository.appendChild(indent(doc, 3)); + repository.appendChild(snapshots); + repository.appendChild(doc.createTextNode(IOUtils.LINE_SEPARATOR)); + } + + private static Element createElement(Document doc, String name, String content) { + Element url = doc.createElement(name); + url.setTextContent(content); + return url; + } + + private static Node indent(Document doc, int indentSize) { + return doc.createTextNode(StringUtils.repeat("\t", indentSize)); + } + + @SneakyThrows + static Document createDocument() { + return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + } - @XBRead("child::url") - String getUrl(); } public interface Artifact { diff --git a/src/main/java/org/springframework/data/release/build/PomUpdater.java b/src/main/java/org/springframework/data/release/build/PomUpdater.java index d60ca06..4e31c18 100644 --- a/src/main/java/org/springframework/data/release/build/PomUpdater.java +++ b/src/main/java/org/springframework/data/release/build/PomUpdater.java @@ -15,12 +15,14 @@ */ package org.springframework.data.release.build; -import static org.springframework.data.release.model.Phase.*; import static org.springframework.data.release.model.Projects.*; import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.util.List; + +import org.springframework.data.release.build.Pom.RepositoryElementFactory; import org.springframework.data.release.model.ArtifactVersion; import org.springframework.data.release.model.Project; import org.springframework.data.release.utils.Logger; @@ -28,6 +30,7 @@ import org.springframework.util.Assert; /** * @author Oliver Gierke + * @author Mark Paluch */ @RequiredArgsConstructor class PomUpdater { @@ -71,7 +74,7 @@ class PomUpdater { /** * Updates the version of the parent project in the given {@link Pom}. - * + * * @param pom must not be {@literal null}. */ public void updateParentVersion(Pom pom) { @@ -86,29 +89,21 @@ class PomUpdater { /** * Updates the repository section in the given {@link Pom}. - * + * * @param pom must not be {@literal null}. */ public void updateRepository(Pom pom) { Assert.notNull(pom, "Pom must not be null!"); - String message = "Switching to Spring repository %s (%s)."; - Repository repository = information.getRepository(); - - if (PREPARE.equals(information.getPhase())) { - - logger.log(project, message, repository.getId(), repository.getUrl()); - - pom.setRepositoryId(repository.getSnapshotId(), repository.getId()); - pom.setRepositoryUrl(repository.getId(), repository.getUrl()); + List repositories = information.getRepositories(); + pom.deleteRepositories(); + if (repositories.isEmpty()) { + logger.log(project, "Removing declaration."); } else { - - logger.log(project, message, repository.getSnapshotId(), repository.getSnapshotUrl()); - - pom.setRepositoryId(repository.getId(), repository.getSnapshotId()); - pom.setRepositoryUrl(repository.getSnapshotId(), repository.getSnapshotUrl()); + logger.log(project, "Switching to Spring repositories %s.", repositories); + pom.setRepositories(RepositoryElementFactory.of(repositories)); } } } diff --git a/src/main/java/org/springframework/data/release/build/Repository.java b/src/main/java/org/springframework/data/release/build/Repository.java index 4100aaa..a119d08 100644 --- a/src/main/java/org/springframework/data/release/build/Repository.java +++ b/src/main/java/org/springframework/data/release/build/Repository.java @@ -17,10 +17,6 @@ package org.springframework.data.release.build; import lombok.Value; -import org.springframework.data.release.model.ArtifactVersion; -import org.springframework.data.release.model.Iteration; -import org.springframework.util.Assert; - /** * @author Oliver Gierke */ @@ -28,49 +24,12 @@ import org.springframework.util.Assert; @Value public class Repository { - private static final String ID_BASE = "spring-libs-"; - private static final String BASE = "https://repo.spring.io/libs-"; + static Repository SNAPSHOT = new Repository("spring-snapshot", "https://repo.spring.io/snapshot", true, false); + static Repository MILESTONE = new Repository("spring-milestone", "https://repo.spring.io/milestone", null, null); String id, url; + Boolean snapshots; + Boolean releases; - public Repository(Iteration iteration) { - Assert.notNull(iteration, "Iteration must not be null!"); - - this.id = ID_BASE.concat(iteration.isPublic() ? "release" : "milestone"); - this.url = BASE.concat(iteration.isPublic() ? "release" : "milestone"); - } - - public Repository(ArtifactVersion version) { - - String suffix = getSuffixFor(version); - - this.id = ID_BASE.concat(suffix); - this.url = BASE.concat(suffix); - } - - public String getSnapshotId() { - return ID_BASE.concat("snapshot"); - } - - public String getSnapshotUrl() { - return BASE.concat("snapshot"); - } - - private static String getSuffixFor(ArtifactVersion version) { - - if (version.isSnapshotVersion()) { - return "snapshot"; - } - - if (version.isMilestoneVersion() || version.isReleaseCandidateVersion()) { - return "milestone"; - } - - if (version.isReleaseVersion()) { - return "release"; - } - - throw new IllegalArgumentException(String.format("Unsupported ArtifactVersion %s!", version)); - } } diff --git a/src/main/java/org/springframework/data/release/build/UpdateInformation.java b/src/main/java/org/springframework/data/release/build/UpdateInformation.java index 00b1ded..4ba5697 100644 --- a/src/main/java/org/springframework/data/release/build/UpdateInformation.java +++ b/src/main/java/org/springframework/data/release/build/UpdateInformation.java @@ -21,6 +21,10 @@ import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import org.springframework.data.release.model.ArtifactVersion; import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Project; @@ -83,13 +87,20 @@ public class UpdateInformation { throw new IllegalStateException("Unexpected phase detected " + phase + " detected!"); } - /** - * Returns the {@link Repository} to use (milestone or release). - * - * @return will never be {@literal null}. - */ - public Repository getRepository() { - return new Repository(train.getIteration()); + public List getRepositories() { + + if (phase == Phase.PREPARE) { + + if (train.getIteration().isMilestone()) { + return Collections.singletonList(Repository.MILESTONE); + } + } + + if (phase == Phase.CLEANUP) { + return Arrays.asList(Repository.SNAPSHOT, Repository.MILESTONE); + } + + return Collections.emptyList(); } /** diff --git a/src/test/java/org/springframework/data/release/build/MavenBuildSystemUnitTests.java b/src/test/java/org/springframework/data/release/build/MavenBuildSystemUnitTests.java index 314d7a7..48dd467 100644 --- a/src/test/java/org/springframework/data/release/build/MavenBuildSystemUnitTests.java +++ b/src/test/java/org/springframework/data/release/build/MavenBuildSystemUnitTests.java @@ -21,9 +21,8 @@ import java.io.InputStream; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; - import org.springframework.core.io.ClassPathResource; - +import org.springframework.data.release.build.Pom.RepositoryElementFactory; import org.xmlbeam.XBProjector; /** @@ -49,4 +48,34 @@ class MavenBuildSystemUnitTests { .endsWith(IOUtils.LINE_SEPARATOR); } } + + @Test + void shouldRemoveRepositories() throws Exception { + + ClassPathResource resource = new ClassPathResource("sample-pom.xml"); + + try (InputStream is = resource.getInputStream()) { + + byte[] bytes = MavenBuildSystem.doWithProjection(projector, is, Pom.class, Pom::deleteRepositories); + + assertThat(new String(bytes)).contains("").doesNotContain(""); + } + } + + @Test + void shouldAddRepositories() throws Exception { + + ClassPathResource resource = new ClassPathResource("sample-pom.xml"); + + try (InputStream is = resource.getInputStream()) { + + byte[] bytes = MavenBuildSystem.doWithProjection(projector, is, Pom.class, pom -> { + pom.deleteRepositories(); + pom.setRepositories(RepositoryElementFactory.of(Repository.SNAPSHOT, Repository.MILESTONE)); + }); + + assertThat(new String(bytes)).containsSubsequence("repositories", "spring-snapshot", "", + "true", "", "false", "spring-milestone"); + } + } } diff --git a/src/test/java/org/springframework/data/release/build/UpdateInformationUnitTests.java b/src/test/java/org/springframework/data/release/build/UpdateInformationUnitTests.java index d55ae0c..f018986 100644 --- a/src/test/java/org/springframework/data/release/build/UpdateInformationUnitTests.java +++ b/src/test/java/org/springframework/data/release/build/UpdateInformationUnitTests.java @@ -17,11 +17,8 @@ package org.springframework.data.release.build; import static org.assertj.core.api.Assertions.*; -import java.util.Arrays; - import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; - import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Projects; @@ -48,22 +45,6 @@ class UpdateInformationUnitTests { Assertions.assertThatIllegalArgumentException().isThrownBy(() -> UpdateInformation.of(hopperM1, null)); } - @Test - void exposesMilestoneRepositoryForMilestone() { - assertThat(UpdateInformation.of(hopperM1, Phase.PREPARE).getRepository().getId()) - .isEqualTo("spring-libs-milestone"); - } - - @Test - void exposesReleaseRepositoryForGA() { - - Arrays.asList(Iteration.GA, Iteration.SR1).forEach(iteration -> { - TrainIteration trainIteration = new TrainIteration(ReleaseTrains.HOPPER, iteration); - assertThat(UpdateInformation.of(trainIteration, Phase.PREPARE).getRepository().getId()) - .isEqualTo("spring-libs-release"); - }); - } - @Test void calculatesProjectVersionToSetCorrectly() { @@ -74,6 +55,32 @@ class UpdateInformationUnitTests { assertThat(updateInformation.getProjectVersionToSet(Projects.JPA).toString()).isEqualTo("1.10.0.BUILD-SNAPSHOT"); } + @Test + void milestoneReposContainedForMilestoneRelease() { + + UpdateInformation updateInformation = UpdateInformation.of(hopperM1, Phase.PREPARE); + + assertThat(updateInformation.getRepositories()).containsOnly(Repository.MILESTONE); + } + + @Test + void noReposContainedForGaRelease() { + + UpdateInformation updateInformation = UpdateInformation.of(new TrainIteration(ReleaseTrains.HOPPER, Iteration.GA), + Phase.PREPARE); + + assertThat(updateInformation.getRepositories()).isEmpty(); + } + + @Test + void cleanupSetsMilestoneAndSnapshotRepos() { + + UpdateInformation updateInformation = UpdateInformation.of(new TrainIteration(ReleaseTrains.HOPPER, Iteration.GA), + Phase.CLEANUP); + + assertThat(updateInformation.getRepositories()).contains(Repository.MILESTONE, Repository.SNAPSHOT); + } + @Test // #155 void calculatesProjectCalverVersionToSetCorrectly() { diff --git a/src/test/resources/sample-pom.xml b/src/test/resources/sample-pom.xml index 43273ee..62ed375 100644 --- a/src/test/resources/sample-pom.xml +++ b/src/test/resources/sample-pom.xml @@ -14,18 +14,6 @@ org.springframework.shell.Bootstrap - - - - profile - - - spring-libs-snapshot - https://repo.spring.io/libs-snapshot - - - - @@ -38,7 +26,7 @@ org.springframework spring-web - + com.fasterxml.jackson.core jackson-databind @@ -54,7 +42,7 @@ spring-shell 1.1.0.BUILD-SNAPSHOT - + org.xmlbeam xmlprojector @@ -67,7 +55,7 @@ 1.12.4 provided - + @@ -109,4 +97,4 @@ - \ No newline at end of file +