This commit is contained in:
Marcin Grzejszczak
2017-03-06 23:32:40 +01:00
parent 2c6d85c280
commit 563c134565
37 changed files with 678 additions and 713 deletions

View File

@@ -15,13 +15,34 @@
*/
package org.springframework.cloud.release;
import static org.slf4j.LoggerFactory.getLogger;
import java.io.File;
import java.lang.invoke.MethodHandles;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.release.internal.ProjectUpdater;
@SpringBootApplication
public class ReleaserApplication {
public class ReleaserApplication implements CommandLineRunner {
private static final Logger log = getLogger(MethodHandles.lookup().lookupClass());
public static void main(String[] args) {
SpringApplication.run(ReleaserApplication.class, args);
}
@Autowired ProjectUpdater projectUpdater;
@Override public void run(String... strings) throws Exception {
String workingDir = System.getProperty("user.dir");
log.info("Will run the application for root folder [{}]", workingDir);
log.info("Press any key to continue...");
System.in.read();
this.projectUpdater.updateProject(new File(workingDir));
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import java.io.File;
import java.io.IOException;
@@ -35,21 +35,21 @@ import org.slf4j.LoggerFactory;
*
* @author Marcin Grzejszczak
*/
class ProjectRepo {
class GitProjectRepo {
private static final Logger log = LoggerFactory
.getLogger(MethodHandles.lookup().lookupClass());
private final ProjectRepo.JGitFactory gitFactory;
private final GitProjectRepo.JGitFactory gitFactory;
private final File basedir;
ProjectRepo(File basedir) {
GitProjectRepo(File basedir) {
this.basedir = basedir;
this.gitFactory = new ProjectRepo.JGitFactory();
this.gitFactory = new GitProjectRepo.JGitFactory();
}
ProjectRepo(File basedir, ProjectRepo.JGitFactory factory) {
GitProjectRepo(File basedir, GitProjectRepo.JGitFactory factory) {
this.basedir = basedir;
this.gitFactory = factory;
}
@@ -61,12 +61,15 @@ class ProjectRepo {
*/
File cloneProject(URI projectUri) {
try {
log.debug("Cloning repo from [{}] to [{}]", projectUri, this.basedir);
Git git = cloneToBasedir(projectUri, this.basedir);
File file = new File(projectUri.getPath());
URI modifiedUri = file.getName().endsWith(File.separator) ?
projectUri : new File(file.getPath() + File.separator).toURI();
log.debug("Cloning repo from [{}] to [{}]", modifiedUri, this.basedir);
Git git = cloneToBasedir(modifiedUri, this.basedir);
if (git != null) {
git.close();
}
File clonedRepo = git.getRepository().getDirectory();
File clonedRepo = git.getRepository().getWorkTree();
log.debug("Cloned repo to [{}]", clonedRepo);
return clonedRepo;
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import java.io.File;
import java.io.FileReader;

View File

@@ -13,17 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.release;
import static org.springframework.cloud.release.SpringCloudConstants.BUILD_ARTIFACT_ID;
import static org.springframework.cloud.release.SpringCloudConstants.CLOUD_DEPENDENCIES_ARTIFACT_ID;
package org.springframework.cloud.release.internal;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.invoke.MethodHandles;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
@@ -36,8 +37,18 @@ class PomUpdater {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final PomReader pomReader = new PomReader();
private final PomWriter pomWriter = new PomWriter();
boolean shouldProjectBeUpdated(File rootPom, Versions versions) {
/**
* Basing on the contents of the root pom and the versions will decide whether
* the project should be updated or not.
*
* @param rootFolder - root folder of the project
* @param versions - list of dependencies to be updated
* @return {@code true} if the project is on the list of projects to be updated
*/
boolean shouldProjectBeUpdated(File rootFolder, Versions versions) {
File rootPom = new File(rootFolder, "pom.xml");
Model model = this.pomReader.readPom(rootPom);
if (!versions.shouldBeUpdated(model.getArtifactId())) {
log.info("Skipping project [{}] since it's not on the list of projects to update", model.getArtifactId());
@@ -47,41 +58,42 @@ class PomUpdater {
return true;
}
ModelWrapper updateParentPom(File pom, Versions versions) {
ModelWrapper readModel(File pom) {
return new ModelWrapper(this.pomReader.readPom(pom), false);
}
/**
* Updates the root / child module model
*
* @param rootProjectName - name of the artifactId of the root project
* @param pom - file with the pom
* @param versions - versions to update
* @return updated model
*/
ModelWrapper updateModel(String rootProjectName, File pom, Versions versions) {
Model model = this.pomReader.readPom(pom);
if (!isParentPom(model)) {
return new ModelWrapper(model, false);
}
boolean dirty = false;
dirty = updateRootParentIfPossible(versions, model) || dirty ;
dirty = updateVersionIfPossible(versions, model) || dirty ;
dirty = updateParentIfPossible(rootProjectName, versions, model) || dirty ;
dirty = updateVersionIfPossible(rootProjectName, versions, model) || dirty ;
dirty = updateProperties(versions, model) || dirty;
return new ModelWrapper(model, dirty);
}
ModelWrapper updateChildPom(String rootProjectName, File pom, Versions versions) {
Model model = this.pomReader.readPom(pom);
boolean dirty = false;
if (isParentPom(model)) {
dirty = updateRootParentIfPossible(versions, model) || dirty ;
dirty = updateVersionIfPossible(versions, model) || dirty ;
} else {
dirty = updateParentVersionIfPossible(rootProjectName, versions, model) || dirty;
/**
* Overwrites the pom.xml with data from {@link ModelWrapper} only if there were
* any changes in the model.
*
* @return - the pom file
*/
File overwritePomIfDirty(ModelWrapper wrapper, File pom) {
if (wrapper.dirty) {
log.debug("There were changes in the pom so file will be overridden");
this.pomWriter.write(wrapper.model, pom);
log.info("Successfully stored [{}]", pom);
}
dirty = updateProperties(versions, model) || dirty;
return new ModelWrapper(model, dirty);
return pom;
}
private boolean updateParentVersionIfPossible(String rootProjectName, Versions versions, Model model) {
String version = versions.versionForProject(rootProjectName);
if (StringUtils.isEmpty(version)) {
log.warn("There was no version set for project [{}], skipping parent version setting for project [{}]", rootProjectName, model.getArtifactId());
return false;
}
log.info("Setting parent [{}] version to [{}] for project [{}]", rootProjectName, version, model.getArtifactId());
model.getParent().setVersion(version);
return true;
}
private boolean updateProperties(Versions versions, Model model) {
final AtomicBoolean atomicBoolean = new AtomicBoolean();
@@ -99,36 +111,32 @@ class PomUpdater {
return atomicBoolean.get();
}
private boolean updateRootParentIfPossible(Versions versions, Model model) {
private boolean updateParentIfPossible(String rootProjectName, Versions versions, Model model) {
String parentArtifactId = model.getParent().getArtifactId();
if (BUILD_ARTIFACT_ID.equals(parentArtifactId) ||
CLOUD_DEPENDENCIES_ARTIFACT_ID.equals(parentArtifactId)) {
log.info("Setting version of parent to [{}]", parentArtifactId);
model.getParent().setVersion(versions.scBuildVersion);
return true;
String version = versions.versionForProject(parentArtifactId);
if (StringUtils.isEmpty(version)) {
if (StringUtils.hasText(model.getParent().getRelativePath())) {
version = versions.versionForProject(rootProjectName);
} else {
log.warn("There is no info on the [{}] version", model.getArtifactId());
return false;
}
}
log.warn("The parent pom should be referencing Spring Cloud Build but it's not. Won't update it");
return false;
log.info("Setting version of parent [{}] to [{}] for module [{}]", parentArtifactId, version, model.getArtifactId());
model.getParent().setVersion(version);
return true;
}
private boolean updateVersionIfPossible(Versions versions, Model model) {
String version = versions.versionForProject(model.getArtifactId());
private boolean updateVersionIfPossible(String rootProjectName, Versions versions, Model model) {
String version = versions.versionForProject(rootProjectName);
if (StringUtils.isEmpty(version)) {
log.warn("There was no version set for project [{}], skipping version setting", model.getArtifactId());
log.warn("There was no version set for project [{}], skipping version setting for module [{}]", rootProjectName, model.getArtifactId());
return false;
}
log.info("Setting [{}] version to [{}]", model.getArtifactId(), version);
model.setVersion(version);
return true;
}
/**
* All child poms have a relative path to a parent folder. The parent one
* has an empty path.
*/
private boolean isParentPom(Model model) {
return StringUtils.isEmpty(model.getParent().getRelativePath());
}
}
class ModelWrapper {
@@ -139,4 +147,20 @@ class ModelWrapper {
this.model = model;
this.dirty = dirty;
}
String projectName() {
return this.model.getArtifactId();
}
}
class PomWriter {
void write(Model model, File pom) {
try(Writer writer = new FileWriter(pom)) {
MavenXpp3Writer pomWriter = new MavenXpp3Writer();
pomWriter.write(writer, model);
}
catch (IOException e) {
throw new IllegalStateException("Failed to write file", e);
}
}
}

View File

@@ -0,0 +1,90 @@
package org.springframework.cloud.release.internal;
import java.io.File;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.net.URI;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Marcin Grzejszczak
*/
public class ProjectUpdater {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final File destinationDir;
private final ReleaserProperties properties;
private final GitProjectRepo gitProjectRepo;
private final PomUpdater pomUpdater = new PomUpdater();
public ProjectUpdater(ReleaserProperties properties) {
try {
this.destinationDir = properties.getCloneDestinationDir() != null ?
new File(properties.getCloneDestinationDir()) :
Files.createTempDirectory("releaser").toFile();
this.properties = properties;
this.gitProjectRepo = new GitProjectRepo(this.destinationDir);
}
catch (IOException e) {
throw new IllegalStateException("Failed to create a temporary folder", e);
}
}
public void updateProject(File projectRoot) {
File clonedScRelease = this.gitProjectRepo.cloneProject(
URI.create(this.properties.getSpringCloudReleaseGitUrl()));
this.gitProjectRepo.checkout(clonedScRelease, this.properties.getBranch());
SCReleasePomParser SCReleasePomParser = new SCReleasePomParser(clonedScRelease);
Versions versions = SCReleasePomParser.allVersions();
if (!this.pomUpdater.shouldProjectBeUpdated(projectRoot, versions)) {
log.info("Project is not on the list of projects to be updated. Skipping.");
return;
}
File rootPom = new File(projectRoot, "pom.xml");
ModelWrapper rootPomModel = this.pomUpdater.readModel(rootPom);
processAllPoms(projectRoot, new PomWalker(rootPomModel, versions, this.pomUpdater));
}
private void processAllPoms(File projectRoot, PomWalker pomWalker) {
try {
Files.walkFileTree(projectRoot.toPath(), pomWalker);
}
catch (IOException e) {
throw new IllegalStateException(e);
}
}
private class PomWalker extends SimpleFileVisitor<Path> {
private static final String POM_XML = "pom.xml";
private final ModelWrapper rootPom;
private final Versions versions;
private final PomUpdater pomUpdater;
private PomWalker(ModelWrapper rootPom, Versions versions, PomUpdater pomUpdater) {
this.rootPom = rootPom;
this.versions = versions;
this.pomUpdater = pomUpdater;
}
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attr) {
File file = path.toFile();
if (POM_XML.equals(file.getName())) {
ModelWrapper model = this.pomUpdater.updateModel(this.rootPom.projectName(), file, this.versions);
this.pomUpdater.overwritePomIfDirty(model, file);
}
return FileVisitResult.CONTINUE;
}
}
}

View File

@@ -0,0 +1,49 @@
package org.springframework.cloud.release.internal;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author Marcin Grzejszczak
*/
@ConfigurationProperties("releaser")
public class ReleaserProperties {
/**
* URL to Spring Cloud Release Git repository
*/
private String springCloudReleaseGitUrl = "https://github.com/spring-cloud/spring-cloud-release.git";
/**
* Where should the Spring Cloud Release repo get cloned to. If {@code null} defaults to a temporary directory
*/
private String cloneDestinationDir;
/**
* Which branch of Spring Cloud Release should be checked out. Defaults to {@code master}
*/
private String branch = "master";
public String getSpringCloudReleaseGitUrl() {
return this.springCloudReleaseGitUrl;
}
public void setSpringCloudReleaseGitUrl(String springCloudReleaseGitUrl) {
this.springCloudReleaseGitUrl = springCloudReleaseGitUrl;
}
public String getCloneDestinationDir() {
return this.cloneDestinationDir;
}
public void setCloneDestinationDir(String cloneDestinationDir) {
this.cloneDestinationDir = cloneDestinationDir;
}
public String getBranch() {
return this.branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import java.io.File;
import java.lang.invoke.MethodHandles;
@@ -30,11 +30,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Parses the poms for a given project and populates versions.
* Parses the poms for a given project and populates versions from Spring Cloud Release
*
* @author Marcin Grzejszczak
*/
class PomParser {
class SCReleasePomParser {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -42,17 +42,17 @@ class PomParser {
private static final String DEPENDENCIES_POM = "spring-cloud-dependencies/pom.xml";
private static final Pattern SC_VERSION_PATTERN = Pattern.compile("^(spring-cloud-.*)\\.version$");
private final File projectRootDir;
private final File springCloudReleaseDir;
private final String bootPom;
private final String dependenciesPom;
private final PomReader pomReader = new PomReader();
PomParser(File projectRootDir) {
this(projectRootDir, STARTER_POM, DEPENDENCIES_POM);
SCReleasePomParser(File springCloudReleaseDir) {
this(springCloudReleaseDir, STARTER_POM, DEPENDENCIES_POM);
}
PomParser(File projectRootDir, String bootPom, String dependenciesPom) {
this.projectRootDir = projectRootDir;
SCReleasePomParser(File springCloudReleaseDir, String bootPom, String dependenciesPom) {
this.springCloudReleaseDir = springCloudReleaseDir;
this.bootPom = bootPom;
this.dependenciesPom = dependenciesPom;
}
@@ -79,7 +79,7 @@ class PomParser {
if (pom == null) {
throw new IllegalStateException("Pom is not present");
}
File pomFile = new File(this.projectRootDir, pom);
File pomFile = new File(this.springCloudReleaseDir, pom);
if (!pomFile.exists()) {
throw new IllegalStateException("Pom is not present");
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
/**
* @author Marcin Grzejszczak

View File

@@ -1,4 +1,7 @@
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import static org.springframework.cloud.release.internal.SpringCloudConstants.BUILD_ARTIFACT_ID;
import static org.springframework.cloud.release.internal.SpringCloudConstants.CLOUD_DEPENDENCIES_ARTIFACT_ID;
import java.util.HashSet;
import java.util.Set;
@@ -23,12 +26,16 @@ class Versions {
Versions(String scBuildVersion, Set<Project> projects) {
this.scBuildVersion = scBuildVersion;
this.projects.add(new Project(BUILD_ARTIFACT_ID, scBuildVersion));
this.projects.add(new Project(CLOUD_DEPENDENCIES_ARTIFACT_ID, scBuildVersion));
this.projects.addAll(projects);
}
Versions(String bootVersion, String scBuildVersion, Set<Project> projects) {
this.bootVersion = bootVersion;
this.scBuildVersion = scBuildVersion;
this.projects.add(new Project(BUILD_ARTIFACT_ID, scBuildVersion));
this.projects.add(new Project(CLOUD_DEPENDENCIES_ARTIFACT_ID, scBuildVersion));
this.projects.addAll(projects);
}

View File

@@ -0,0 +1,20 @@
package org.springframework.cloud.release.spring;
/**
* @author Marcin Grzejszczak
*/
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.release.internal.ProjectUpdater;
import org.springframework.cloud.release.internal.ReleaserProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(ReleaserProperties.class)
class ReleaserConfiguration {
@Bean ProjectUpdater projectUpdater(ReleaserProperties properties) {
return new ProjectUpdater(properties);
}
}

View File

@@ -1,24 +1,95 @@
package org.springframework.cloud.release;
import static org.assertj.core.api.BDDAssertions.then;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import org.apache.maven.model.Model;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.cloud.release.internal.ProjectUpdater;
import org.springframework.cloud.release.internal.ReleaserProperties;
import org.springframework.cloud.release.internal.TestPomReader;
import org.springframework.cloud.release.internal.TestUtils;
import org.springframework.util.FileSystemUtils;
/**
* @author Marcin Grzejszczak
*/
public class AcceptanceTests {
/**
@Rule public TemporaryFolder tmp = new TemporaryFolder();
TestPomReader testPomReader = new TestPomReader();
File temporaryFolder;
@Before
public void setup() throws Exception {
this.temporaryFolder = this.tmp.newFolder();
TestUtils.prepareLocalRepo();
FileSystemUtils.copyRecursively(file("/projects/"), this.temporaryFolder);
}
- should clone spring cloud release (x)
- should check out a branch / tag (x)
- should parse spring-cloud-starter-parent/pom.xml and resolve:
- Boot version (x)
- should parse spring-cloud-dependencies/pom.xml and resolve:
- Project versions from properties (x)
- Spring Cloud Build version from parent (x)
- should update the existing poms with the taken versions
*/
@Test
public void should_update_all_versions_for_a_release_train() {
public void should_update_all_versions_for_a_release_train() throws Exception {
ReleaserProperties releaserProperties = releaserProperties();
ProjectUpdater projectUpdater = new ProjectUpdater(releaserProperties);
projectUpdater.updateProject(new File(this.temporaryFolder, "/spring-cloud-sleuth"));
then(this.temporaryFolder).exists();
Model rootPom = this.testPomReader.readPom(tmpFile("/spring-cloud-sleuth/pom.xml"));
Model depsPom = this.testPomReader.readPom(tmpFile("/spring-cloud-sleuth/spring-cloud-sleuth-dependencies/pom.xml"));
Model corePom = this.testPomReader.readPom(tmpFile("/spring-cloud-sleuth/spring-cloud-sleuth-core/pom.xml"));
Model zipkinStreamPom = this.testPomReader.readPom(tmpFile("/spring-cloud-sleuth/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/pom.xml"));
then(rootPom.getVersion()).isEqualTo("1.2.0.BUILD-SNAPSHOT");
then(rootPom.getProperties())
.containsEntry("spring-cloud-build.version","1.3.1.BUILD-SNAPSHOT")
.containsEntry("spring-cloud-commons.version","1.2.0.BUILD-SNAPSHOT")
.containsEntry("spring-cloud-stream.version","Chelsea.BUILD-SNAPSHOT")
.containsEntry("spring-cloud-netflix.version","1.3.0.BUILD-SNAPSHOT");
then(depsPom.getVersion()).isEqualTo("1.2.0.BUILD-SNAPSHOT");
then(depsPom.getParent().getVersion()).isEqualTo("1.3.1.BUILD-SNAPSHOT");
then(corePom.getParent().getVersion()).isEqualTo("1.2.0.BUILD-SNAPSHOT");
then(zipkinStreamPom.getParent().getVersion()).isEqualTo("1.2.0.BUILD-SNAPSHOT");
}
@Test
public void should_not_update_a_project_that_is_not_on_the_list() throws Exception {
ReleaserProperties releaserProperties = releaserProperties();
ProjectUpdater projectUpdater = new ProjectUpdater(releaserProperties);
File beforeProcessing = pom("/projects/project/");
projectUpdater.updateProject(new File(this.temporaryFolder, "/project/"));
then(this.temporaryFolder).exists();
File afterProcessing = tmpFile("/project/pom.xml");
then(asString(beforeProcessing)).isEqualTo(asString(afterProcessing));
}
private ReleaserProperties releaserProperties() throws URISyntaxException {
ReleaserProperties releaserProperties = new ReleaserProperties();
releaserProperties.setSpringCloudReleaseGitUrl(file("/projects/spring-cloud-release/").getPath());
return releaserProperties;
}
private File tmpFile(String relativePath) {
return new File(this.temporaryFolder, relativePath);
}
private File file(String relativePath) throws URISyntaxException {
return new File(AcceptanceTests.class.getResource(relativePath).toURI());
}
private File pom(String relativePath) throws URISyntaxException {
return new File(new File(AcceptanceTests.class.getResource(relativePath).toURI()), "pom.xml");
}
private String asString(File file) throws IOException {
return new String(Files.readAllBytes(file.toPath()));
}
}

View File

@@ -1,4 +1,8 @@
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.api.BDDAssertions.thenThrownBy;
import java.io.File;
import java.io.IOException;
@@ -11,45 +15,42 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.api.BDDAssertions.thenThrownBy;
/**
* @author Marcin Grzejszczak
*/
public class ProjectClonerTests {
public class GitProjectRepoTests {
@Rule public TemporaryFolder tmp = new TemporaryFolder();
File springCloudReleaseProject;
File tmpFolder;
ProjectRepo projectRepo;
GitProjectRepo gitProjectRepo;
@Before
public void setup() throws IOException, URISyntaxException {
this.tmpFolder = this.tmp.newFolder();
this.springCloudReleaseProject = new File(ProjectClonerTests.class.getResource("/projects/spring-cloud-release").toURI());
this.springCloudReleaseProject = new File(GitProjectRepoTests.class.getResource("/projects/spring-cloud-release").toURI());
TestUtils.prepareLocalRepo();
this.projectRepo = new ProjectRepo(this.tmpFolder);
this.gitProjectRepo = new GitProjectRepo(this.tmpFolder);
}
@Test
public void should_clone_the_project_from_a_given_location() throws IOException {
this.projectRepo.cloneProject(this.springCloudReleaseProject.toURI());
this.gitProjectRepo.cloneProject(this.springCloudReleaseProject.toURI());
then(new File(this.tmpFolder, ".git")).exists();
}
@Test
public void should_throw_exception_when_there_is_no_repo() throws IOException, URISyntaxException {
thenThrownBy(() -> this.projectRepo.cloneProject(ProjectClonerTests.class.getResource("/projects/").toURI()))
thenThrownBy(() -> this.gitProjectRepo
.cloneProject(GitProjectRepoTests.class.getResource("/projects/").toURI()))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("Exception occurred while cloning repo");
}
@Test
public void should_throw_an_exception_when_failed_to_initialize_the_repo() throws IOException {
thenThrownBy(() -> new ProjectRepo(this.tmpFolder, new ExceptionThrowingJGitFactory()).cloneProject(this.springCloudReleaseProject.toURI()))
thenThrownBy(() -> new GitProjectRepo(this.tmpFolder, new ExceptionThrowingJGitFactory()).cloneProject(this.springCloudReleaseProject.toURI()))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("Exception occurred while cloning repo")
.hasCauseInstanceOf(CustomException.class);
@@ -57,8 +58,8 @@ public class ProjectClonerTests {
@Test
public void should_check_out_a_branch_on_cloned_repo() throws IOException {
File project = this.projectRepo.cloneProject(this.springCloudReleaseProject.toURI());
this.projectRepo.checkout(project, "vCamden.SR3");
File project = this.gitProjectRepo.cloneProject(this.springCloudReleaseProject.toURI());
this.gitProjectRepo.checkout(project, "vCamden.SR3");
File pom = new File(this.tmpFolder, "pom.xml");
then(pom).exists();
@@ -67,9 +68,9 @@ public class ProjectClonerTests {
@Test
public void should_throw_an_exception_when_checking_out_nonexisting_branch() throws IOException {
File project = this.projectRepo.cloneProject(this.springCloudReleaseProject.toURI());
File project = this.gitProjectRepo.cloneProject(this.springCloudReleaseProject.toURI());
try {
this.projectRepo.checkout(project, "nonExistingBranch");
this.gitProjectRepo.checkout(project, "nonExistingBranch");
fail("should throw an exception");
} catch (IllegalStateException e) {
then(e).hasMessageContaining("Ref nonExistingBranch can not be resolved");
@@ -78,7 +79,7 @@ public class ProjectClonerTests {
}
class ExceptionThrowingJGitFactory extends ProjectRepo.JGitFactory {
class ExceptionThrowingJGitFactory extends GitProjectRepo.JGitFactory {
@Override CloneCommand getCloneCommandByCloneRepository() {
throw new CustomException("foo");
}

View File

@@ -14,7 +14,10 @@
* limitations under the License.
*/
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.api.BDDAssertions.thenThrownBy;
import java.io.File;
import java.io.IOException;
@@ -26,9 +29,6 @@ import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.junit.Before;
import org.junit.Test;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.api.BDDAssertions.thenThrownBy;
/**
* @author Marcin Grzejszczak
*/
@@ -40,7 +40,7 @@ public class PomReaderTests {
@Before
public void setup() throws URISyntaxException {
URI scRelease = ProjectClonerTests.class.getResource("/projects/spring-cloud-release").toURI();
URI scRelease = GitProjectRepoTests.class.getResource("/projects/spring-cloud-release").toURI();
this.springCloudReleaseProject = new File(scRelease.getPath(), "pom.xml");
this.licenseFile = new File(scRelease.getPath(), "LICENSE.txt");
}

View File

@@ -14,16 +14,22 @@
* limitations under the License.
*/
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import static org.assertj.core.api.BDDAssertions.then;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.util.FileSystemUtils;
/**
* @author Marcin Grzejszczak
@@ -32,17 +38,24 @@ public class PomUpdaterTests {
Versions versions = new Versions("0.0.1", "0.0.2", projects());
PomUpdater pomUpdater = new PomUpdater();
@Rule public TemporaryFolder tmp = new TemporaryFolder();
File temporaryFolder;
@Before
public void setup() throws IOException {
this.temporaryFolder = this.tmp.newFolder();
}
@Test
public void should_not_update_pom_when_project_is_not_on_the_versions_list() throws Exception {
File springCloudReleasePom = pom("/projects/spring-cloud-release");
File springCloudReleasePom = file("/projects/spring-cloud-release");
then(this.pomUpdater.shouldProjectBeUpdated(springCloudReleasePom, this.versions)).isFalse();
}
@Test
public void should_update_pom_when_project_is_not_on_the_versions_list() throws Exception {
File springCloudSleuthPom = pom("/projects/spring-cloud-sleuth");
File springCloudSleuthPom = file("/projects/spring-cloud-sleuth");
then(this.pomUpdater.shouldProjectBeUpdated(springCloudSleuthPom, this.versions)).isTrue();
}
@@ -51,7 +64,7 @@ public class PomUpdaterTests {
public void should_not_update_the_model_if_no_changes_were_made() throws Exception {
File nonMatchingPom = pom("/projects/project");
ModelWrapper model = this.pomUpdater.updateParentPom(nonMatchingPom, this.versions);
ModelWrapper model = this.pomUpdater.updateModel("foo", nonMatchingPom, this.versions);
then(model.dirty).isFalse();
}
@@ -60,7 +73,7 @@ public class PomUpdaterTests {
public void should_update_the_model_if_only_artifact_id_is_matched_in_the_root_pom() throws Exception {
File matchingArtifactId = pom("/projects/project", "pom_matching_artifact.xml");
ModelWrapper model = this.pomUpdater.updateParentPom(matchingArtifactId, this.versions);
ModelWrapper model = this.pomUpdater.updateModel("spring-cloud-sleuth", matchingArtifactId, this.versions);
then(model.dirty).isTrue();
then(model.model.getVersion()).isEqualTo("0.0.3.BUILD-SNAPSHOT");
@@ -75,7 +88,7 @@ public class PomUpdaterTests {
public void should_update_the_model_if_parent_is_matched_via_sc_build() throws Exception {
File matchingArtifactId = pom("/projects/project", "pom_matching_parent_v2.xml");
ModelWrapper model = this.pomUpdater.updateParentPom(matchingArtifactId, this.versions);
ModelWrapper model = this.pomUpdater.updateModel("spring-cloud-sleuth", matchingArtifactId, this.versions);
then(model.dirty).isTrue();
then(model.model.getVersion()).isEqualTo("0.0.3.BUILD-SNAPSHOT");
@@ -90,7 +103,7 @@ public class PomUpdaterTests {
public void should_update_the_model_if_parent_is_matched_via_sc_dependencies_parent() throws Exception {
File matchingArtifactId = pom("/projects/project", "pom_matching_parent.xml");
ModelWrapper model = this.pomUpdater.updateParentPom(matchingArtifactId, this.versions);
ModelWrapper model = this.pomUpdater.updateModel("spring-cloud-sleuth", matchingArtifactId, this.versions);
then(model.dirty).isTrue();
then(model.model.getVersion()).isEqualTo("0.0.3.BUILD-SNAPSHOT");
@@ -105,7 +118,7 @@ public class PomUpdaterTests {
public void should_update_the_model_if_properties_are_matched() throws Exception {
File matchingArtifactId = pom("/projects/project", "pom_matching_properties.xml");
ModelWrapper model = this.pomUpdater.updateParentPom(matchingArtifactId, this.versions);
ModelWrapper model = this.pomUpdater.updateModel("spring-cloud-sleuth", matchingArtifactId, this.versions);
then(model.dirty).isTrue();
then(model.model.getVersion()).isEqualTo("0.0.3.BUILD-SNAPSHOT");
@@ -117,32 +130,23 @@ public class PomUpdaterTests {
@Test
public void should_not_update_child_pom_when_project_is_not_on_the_versions_list() throws Exception {
File springCloudReleasePom = pom("/projects/spring-cloud-release");
File springCloudReleasePom = file("/projects/spring-cloud-release");
then(this.pomUpdater.shouldProjectBeUpdated(springCloudReleasePom, this.versions)).isFalse();
}
@Test
public void should_update_child_pom_when_project_is_not_on_the_versions_list() throws Exception {
File springCloudSleuthPom = pom("/projects/spring-cloud-sleuth");
File springCloudSleuthPom = file("/projects/spring-cloud-sleuth");
then(this.pomUpdater.shouldProjectBeUpdated(springCloudSleuthPom, this.versions)).isTrue();
}
@Test
public void should_not_update_the_child_model_if_no_changes_were_made() throws Exception {
File nonMatchingPom = pom("/projects/project");
ModelWrapper model = this.pomUpdater.updateChildPom("spring-cloud-sleuth", nonMatchingPom, this.versions);
then(model.dirty).isFalse();
}
@Test
public void should_update_the_child_model_if_parent_is_matched_via_sc_build() throws Exception {
File matchingArtifactId = pom("/projects/project/children", "pom_matching_parent_v2.xml");
ModelWrapper model = this.pomUpdater.updateChildPom("spring-cloud-sleuth", matchingArtifactId, this.versions);
ModelWrapper model = this.pomUpdater.updateModel("spring-cloud-sleuth", matchingArtifactId, this.versions);
then(model.dirty).isTrue();
then(model.model.getParent().getVersion()).isEqualTo("0.0.3.BUILD-SNAPSHOT");
@@ -156,7 +160,7 @@ public class PomUpdaterTests {
public void should_update_the_child_model_if_parent_is_matched_via_sc_dependencies_parent() throws Exception {
File matchingArtifactId = pom("/projects/project/children", "pom_matching_parent.xml");
ModelWrapper model = this.pomUpdater.updateChildPom("spring-cloud-sleuth", matchingArtifactId, this.versions);
ModelWrapper model = this.pomUpdater.updateModel("spring-cloud-sleuth", matchingArtifactId, this.versions);
then(model.dirty).isTrue();
then(model.model.getParent().getVersion()).isEqualTo("0.0.3.BUILD-SNAPSHOT");
@@ -170,7 +174,7 @@ public class PomUpdaterTests {
public void should_update_the_child_model_if_properties_are_matched() throws Exception {
File matchingArtifactId = pom("/projects/project/children", "pom_matching_properties.xml");
ModelWrapper model = this.pomUpdater.updateChildPom("spring-cloud-sleuth", matchingArtifactId, this.versions);
ModelWrapper model = this.pomUpdater.updateModel("spring-cloud-sleuth", matchingArtifactId, this.versions);
then(model.dirty).isTrue();
then(model.model.getParent().getVersion()).isEqualTo("0.0.3.BUILD-SNAPSHOT");
@@ -179,6 +183,34 @@ public class PomUpdaterTests {
.containsEntry("spring-cloud-vault.version", "0.0.4.BUILD-SNAPSHOT");
}
@Test
public void should_override_a_pom_when_there_was_a_change_in_the_model() throws Exception {
FileSystemUtils.copyRecursively(file("/projects/project"), this.temporaryFolder);
File beforeProcessing = pom("/projects/project/children", "pom_matching_properties.xml");
File afterProcessing = new File(this.temporaryFolder, "/children/pom_matching_properties.xml");
ModelWrapper model = this.pomUpdater.updateModel("spring-cloud-sleuth", afterProcessing, this.versions);
File processedPom = this.pomUpdater.overwritePomIfDirty(model, afterProcessing);
then(processedPom).isSameAs(afterProcessing);
String processedPomText = asString(processedPom);
String beforeProcessingText = asString(beforeProcessing);
then(processedPomText).isNotEqualTo(beforeProcessingText);
}
@Test
public void should_not_override_a_pom_when_there_was_no_change_in_the_model() throws Exception {
FileSystemUtils.copyRecursively(file("/projects/project"), this.temporaryFolder);
File beforeProcessing = pom("/projects/project/");
File afterProcessing = new File(this.temporaryFolder, "/pom.xml");
ModelWrapper model = this.pomUpdater.updateModel("foo", afterProcessing, this.versions);
File processedPom = this.pomUpdater.overwritePomIfDirty(model, afterProcessing);
then(processedPom).isSameAs(afterProcessing);
then(asString(processedPom)).isEqualTo(asString(beforeProcessing));
}
Set<Project> projects() {
Set<Project> projects = new HashSet<>();
projects.add(new Project("spring-cloud-sleuth", "0.0.3.BUILD-SNAPSHOT"));
@@ -186,11 +218,20 @@ public class PomUpdaterTests {
return projects;
}
private File file(String relativePath) throws URISyntaxException {
return new File(GitProjectRepoTests.class.getResource(relativePath).toURI());
}
private File pom(String relativePath) throws URISyntaxException {
return pom(relativePath, "pom.xml");
}
private File pom(String relativePath, String pomName) throws URISyntaxException {
return new File(new File(ProjectClonerTests.class.getResource(relativePath).toURI()), pomName);
return new File(new File(GitProjectRepoTests.class.getResource(relativePath).toURI()), pomName);
}
private String asString(File file) throws IOException {
return new String(Files.readAllBytes(file.toPath()));
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import java.io.File;
import java.io.IOException;
@@ -13,18 +13,18 @@ import static org.assertj.core.api.BDDAssertions.thenThrownBy;
/**
* @author Marcin Grzejszczak
*/
public class PomParserTests {
public class SCReleasePomParserTests {
File springCloudReleaseProject;
@Before
public void setup() throws IOException, URISyntaxException {
this.springCloudReleaseProject = new File(ProjectClonerTests.class.getResource("/projects/spring-cloud-release").toURI());
this.springCloudReleaseProject = new File(GitProjectRepoTests.class.getResource("/projects/spring-cloud-release").toURI());
}
@Test
public void should_throw_exception_when_boot_pom_is_missing() {
PomParser parser = new PomParser(new File("."));
SCReleasePomParser parser = new SCReleasePomParser(new File("."));
thenThrownBy(parser::bootVersion)
.isInstanceOf(IllegalStateException.class)
@@ -33,7 +33,7 @@ public class PomParserTests {
@Test
public void should_throw_exception_when_null_is_passed_to_boot() {
PomParser parser = new PomParser(this.springCloudReleaseProject, null, null);
SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject, null, null);
thenThrownBy(parser::bootVersion)
.isInstanceOf(IllegalStateException.class)
@@ -42,7 +42,7 @@ public class PomParserTests {
@Test
public void should_throw_exception_when_boot_version_is_missing_in_pom() {
PomParser parser = new PomParser(this.springCloudReleaseProject, "pom.xml", null);
SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject, "pom.xml", null);
thenThrownBy(parser::bootVersion)
.isInstanceOf(IllegalStateException.class)
@@ -51,7 +51,7 @@ public class PomParserTests {
@Test
public void should_populate_boot_version() {
PomParser parser = new PomParser(this.springCloudReleaseProject);
SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject);
String bootVersion = parser.bootVersion().bootVersion;
@@ -60,7 +60,7 @@ public class PomParserTests {
@Test
public void should_throw_exception_when_cloud_pom_is_missing() {
PomParser parser = new PomParser(new File("."));
SCReleasePomParser parser = new SCReleasePomParser(new File("."));
thenThrownBy(parser::springCloudVersions)
.isInstanceOf(IllegalStateException.class)
@@ -69,7 +69,7 @@ public class PomParserTests {
@Test
public void should_throw_exception_when_null_is_passed_to_cloud() {
PomParser parser = new PomParser(this.springCloudReleaseProject, null, null);
SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject, null, null);
thenThrownBy(parser::springCloudVersions)
.isInstanceOf(IllegalStateException.class)
@@ -78,7 +78,7 @@ public class PomParserTests {
@Test
public void should_throw_exception_when_cloud_version_is_missing_in_pom() {
PomParser parser = new PomParser(this.springCloudReleaseProject, null, "pom.xml");
SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject, null, "pom.xml");
thenThrownBy(parser::springCloudVersions)
.isInstanceOf(IllegalStateException.class)
@@ -87,7 +87,7 @@ public class PomParserTests {
@Test
public void should_populate_cloud_version() {
PomParser parser = new PomParser(this.springCloudReleaseProject);
SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject);
Versions cloudVersions = parser.springCloudVersions();
@@ -97,7 +97,7 @@ public class PomParserTests {
@Test
public void should_populate_boot_and_cloud_version() {
PomParser parser = new PomParser(this.springCloudReleaseProject);
SCReleasePomParser parser = new SCReleasePomParser(this.springCloudReleaseProject);
Versions cloudVersions = parser.allVersions();

View File

@@ -0,0 +1,17 @@
package org.springframework.cloud.release.internal;
import java.io.File;
import org.apache.maven.model.Model;
/**
* @author Marcin Grzejszczak
*/
public class TestPomReader {
PomReader pomReader = new PomReader();
public Model readPom(File pom) {
return this.pomReader.readPom(pom);
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import java.io.File;
import java.io.IOException;

View File

@@ -14,12 +14,14 @@
* limitations under the License.
*/
package org.springframework.cloud.release;
package org.springframework.cloud.release.internal;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import org.springframework.cloud.release.internal.Project;
import org.springframework.cloud.release.internal.Versions;
import static org.assertj.core.api.BDDAssertions.then;

View File

@@ -1,18 +0,0 @@
Going back to snapshots
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Mon Feb 6 12:02:16 2017 +0100
#
# On branch Camden.x
# Your branch is ahead of 'origin/Camden.x' by 2 commits.
# (use "git push" to publish your local commits)
#
# Changes to be committed:
# modified: docs/pom.xml
# modified: docs/src/main/asciidoc/spring-cloud-starters.adoc
# modified: pom.xml
# modified: spring-cloud-dependencies/pom.xml
# modified: spring-cloud-starter-parent/pom.xml
#

View File

@@ -1,7 +1,7 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
bare = true
logallrefupdates = true
[branch "master"]
[branch "Camden.x"]

View File

@@ -1,15 +0,0 @@
#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".
. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:

View File

@@ -1,24 +0,0 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}

View File

@@ -1,8 +0,0 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".
exec git update-server-info

View File

@@ -1,14 +0,0 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-applypatch".
. git-sh-setup
precommit="$(git rev-parse --git-path hooks/pre-commit)"
test -x "$precommit" && exec "$precommit" ${1+"$@"}
:

View File

@@ -1,49 +0,0 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

View File

@@ -1,53 +0,0 @@
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Handle delete
:
else
if [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Check for WIP commit
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
if [ -n "$commit" ]
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0

View File

@@ -1,169 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2006, 2008 Junio C Hamano
#
# The "pre-rebase" hook is run just before "git rebase" starts doing
# its job, and can prevent the command from running by exiting with
# non-zero status.
#
# The hook is called with the following parameters:
#
# $1 -- the upstream the series was forked from.
# $2 -- the branch being rebased (or empty when rebasing the current branch).
#
# This sample shows how to prevent topic branches that are already
# merged to 'next' branch from getting rebased, because allowing it
# would result in rebasing already published history.
publish=next
basebranch="$1"
if test "$#" = 2
then
topic="refs/heads/$2"
else
topic=`git symbolic-ref HEAD` ||
exit 0 ;# we do not interrupt rebasing detached HEAD
fi
case "$topic" in
refs/heads/??/*)
;;
*)
exit 0 ;# we do not interrupt others.
;;
esac
# Now we are dealing with a topic branch being rebased
# on top of master. Is it OK to rebase it?
# Does the topic really exist?
git show-ref -q "$topic" || {
echo >&2 "No such branch $topic"
exit 1
}
# Is topic fully merged to master?
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
if test -z "$not_in_master"
then
echo >&2 "$topic is fully merged to master; better remove it."
exit 1 ;# we could allow it, but there is no point.
fi
# Is topic ever merged to next? If so you should not be rebasing it.
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
only_next_2=`git rev-list ^master ${publish} | sort`
if test "$only_next_1" = "$only_next_2"
then
not_in_topic=`git rev-list "^$topic" master`
if test -z "$not_in_topic"
then
echo >&2 "$topic is already up-to-date with master"
exit 1 ;# we could allow it, but there is no point.
else
exit 0
fi
else
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
/usr/bin/perl -e '
my $topic = $ARGV[0];
my $msg = "* $topic has commits already merged to public branch:\n";
my (%not_in_next) = map {
/^([0-9a-f]+) /;
($1 => 1);
} split(/\n/, $ARGV[1]);
for my $elem (map {
/^([0-9a-f]+) (.*)$/;
[$1 => $2];
} split(/\n/, $ARGV[2])) {
if (!exists $not_in_next{$elem->[0]}) {
if ($msg) {
print STDERR $msg;
undef $msg;
}
print STDERR " $elem->[1]\n";
}
}
' "$topic" "$not_in_next" "$not_in_master"
exit 1
fi
<<\DOC_END
This sample hook safeguards topic branches that have been
published from being rewound.
The workflow assumed here is:
* Once a topic branch forks from "master", "master" is never
merged into it again (either directly or indirectly).
* Once a topic branch is fully cooked and merged into "master",
it is deleted. If you need to build on top of it to correct
earlier mistakes, a new topic branch is created by forking at
the tip of the "master". This is not strictly necessary, but
it makes it easier to keep your history simple.
* Whenever you need to test or publish your changes to topic
branches, merge them into "next" branch.
The script, being an example, hardcodes the publish branch name
to be "next", but it is trivial to make it configurable via
$GIT_DIR/config mechanism.
With this workflow, you would want to know:
(1) ... if a topic branch has ever been merged to "next". Young
topic branches can have stupid mistakes you would rather
clean up before publishing, and things that have not been
merged into other branches can be easily rebased without
affecting other people. But once it is published, you would
not want to rewind it.
(2) ... if a topic branch has been fully merged to "master".
Then you can delete it. More importantly, you should not
build on top of it -- other people may already want to
change things related to the topic as patches against your
"master", so if you need further changes, it is better to
fork the topic (perhaps with the same name) afresh from the
tip of "master".
Let's look at this example:
o---o---o---o---o---o---o---o---o---o "next"
/ / / /
/ a---a---b A / /
/ / / /
/ / c---c---c---c B /
/ / / \ /
/ / / b---b C \ /
/ / / / \ /
---o---o---o---o---o---o---o---o---o---o---o "master"
A, B and C are topic branches.
* A has one fix since it was merged up to "next".
* B has finished. It has been fully merged up to "master" and "next",
and is ready to be deleted.
* C has not merged to "next" at all.
We would want to allow C to be rebased, refuse A, and encourage
B to be deleted.
To compute (1):
git rev-list ^master ^topic next
git rev-list ^master next
if these match, topic has not merged in next at all.
To compute (2):
git rev-list master..topic
if this is empty, it is fully merged to "master".
DOC_END

View File

@@ -1,36 +0,0 @@
#!/bin/sh
#
# An example hook script to prepare the commit log message.
# Called by "git commit" with the name of the file that has the
# commit message, followed by the description of the commit
# message's source. The hook's purpose is to edit the commit
# message file. If the hook fails with a non-zero status,
# the commit is aborted.
#
# To enable this hook, rename this file to "prepare-commit-msg".
# This hook includes three examples. The first comments out the
# "Conflicts:" part of a merge commit.
#
# The second includes the output of "git diff --name-status -r"
# into the message, just before the "git status" output. It is
# commented because it doesn't cope with --amend or with squashed
# commits.
#
# The third example adds a Signed-off-by line to the message, that can
# still be edited. This is rarely a good idea.
case "$2,$3" in
merge,)
/usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
# ,|template,)
# /usr/bin/perl -i.bak -pe '
# print "\n" . `git diff --cached --name-status -r`
# if /^#/ && $first++ == 0' "$1" ;;
*) ;;
esac
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

View File

@@ -1,128 +0,0 @@
#!/bin/sh
#
# An example hook script to block unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
# hooks.allowdeletetag
# This boolean sets whether deleting tags will be allowed in the
# repository. By default they won't be.
# hooks.allowmodifytag
# This boolean sets whether a tag may be modified after creation. By default
# it won't be.
# hooks.allowdeletebranch
# This boolean sets whether deleting branches will be allowed in the
# repository. By default they won't be.
# hooks.denycreatebranch
# This boolean sets whether remotely creating branches will be denied
# in the repository. By default this is allowed.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Config
allowunannotated=$(git config --bool hooks.allowunannotated)
allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
denycreatebranch=$(git config --bool hooks.denycreatebranch)
allowdeletetag=$(git config --bool hooks.allowdeletetag)
allowmodifytag=$(git config --bool hooks.allowmodifytag)
# check for no description
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
case "$projectdesc" in
"Unnamed repository"* | "")
echo "*** Project description file hasn't been set" >&2
exit 1
;;
esac
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
short_refname=${refname##refs/tags/}
if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
fi
;;
refs/tags/*,delete)
# delete tag
if [ "$allowdeletetag" != "true" ]; then
echo "*** Deleting a tag is not allowed in this repository" >&2
exit 1
fi
;;
refs/tags/*,tag)
# annotated tag
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
then
echo "*** Tag '$refname' already exists." >&2
echo "*** Modifying a tag is not allowed in this repository." >&2
exit 1
fi
;;
refs/heads/*,commit)
# branch
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
echo "*** Creating a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/heads/*,delete)
# delete branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
exit 1
fi
;;
*)
# Anything else (is there anything else?)
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0

View File

@@ -1,6 +0,0 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@@ -1,40 +0,0 @@
# pack-refs with: peeled fully-peeled
fb730db9b3999e45c350015c6cf83be35910a159 refs/remotes/origin/1.0.0.M2
474b03693496665434ab2615d6500bbb0b575a5b refs/remotes/origin/1.0.0.M3
7fdc875cb2b1620e8bc87ef8a27da2858eef7cd1 refs/remotes/origin/1.0.0.RC1
75d0bc7cc0995ac76b6cfad962ea54d05262a664 refs/remotes/origin/1.0.0.RELEASE
8e8a2d41b4beb8985919bc5a2bca2aa66374bdbb refs/remotes/origin/1.0.1.RELEASE
59414747ee8c095753a0b8c5641b328f80d47d33 refs/remotes/origin/1.0.2.RELEASE
73ec179d7ce96d5a98c2acd5697cd81c49dfd7d5 refs/remotes/origin/1.0.x
08c95747e807212c605d758bbb360f6d671b2932 refs/remotes/origin/Angel.SR3
ccc57368d5e766e493c57f44333deae7eca6d864 refs/remotes/origin/Brixton
7745834b138ffe1f647b14dd3c7d4d71eee8aac3 refs/remotes/origin/Brixton.M1
f2036f13515dc6aa997cc15827919acec634eaae refs/remotes/origin/Brixton.M2
0c0731e8b5321ea69efa0f502e957cb29b6c428d refs/remotes/origin/Brixton.x
e1248f716b5656af04ded489b481db45ad3dfc8f refs/remotes/origin/master
7278841be008eb08c59ed0b5ae0b47ee33630ddd refs/tags/1.0.0.M1
75d0bc7cc0995ac76b6cfad962ea54d05262a664 refs/tags/Angel.RELEASE
8e8a2d41b4beb8985919bc5a2bca2aa66374bdbb refs/tags/Angel.SR1
59414747ee8c095753a0b8c5641b328f80d47d33 refs/tags/Angel.SR2
474b03693496665434ab2615d6500bbb0b575a5b refs/tags/v1.0.0.M3
7fdc875cb2b1620e8bc87ef8a27da2858eef7cd1 refs/tags/v1.0.0.RC1
e16c0781559188ef795c75614698966a6b62c6aa refs/tags/v1.0.0.RC2
34bdaee14455d0a8f2162722ac9c35fd2c8cea92 refs/tags/v1.0.0.RC3
93e1d3d5aec56a9b3294bb25785a415a56c4d3d2 refs/tags/v1.0.0.RELEASE
a55246b152357b7324198132afb7dc74f1d3d60f refs/tags/v1.0.1.RELEASE
05d773f74867550d7b1c5770b228c1378c297bd4 refs/tags/vAngel.SR4
7745834b138ffe1f647b14dd3c7d4d71eee8aac3 refs/tags/vBrixton.M1
f2036f13515dc6aa997cc15827919acec634eaae refs/tags/vBrixton.M2
94fdb6fb3cb94883ce1b2796bf2044499673dd7d refs/tags/vBrixton.M3
f5b63c2ba2b12ea301b1232346fbb9810e26544a refs/tags/vBrixton.M4
3ef5b554341221fee3d1758935c9dafac265a76c refs/tags/vBrixton.M5
52840c26d7c3e663b1f748000289869eebe59101 refs/tags/vBrixton.RC1
1aad0152d972955b2c26e1b25fb118eeed70bbdf refs/tags/vBrixton.RC2
bfa1f6c5d21e3fd7fdd6880d5e41629a7f036f88 refs/tags/vBrixton.RELEASE
7fe8e4aed951277365ec54ea14af11e2a3ede8c3 refs/tags/vBrixton.SR1
10aca045c80852cfca5afa77aef7e1621f348824 refs/tags/vBrixton.SR2
675b5d53b1237a72e3dcf49ad5f6d1f307789978 refs/tags/vBrixton.SR3
36ec6d4e210cc1e5305886d672911959ca702494 refs/tags/vBrixton.SR4
fdbc861e71699a05d05b9cdbb6928a2ed988dc33 refs/tags/vBrixton.SR5
e4d44f5a1a67429e37edbb57d3da96bb6717266c refs/tags/vCamden.M1
d563a890ea3e0e3642e6dce696b00ab634deed2b refs/tags/vCamden.RC1

View File

@@ -1 +1 @@
ref: refs/remotes/origin/master
ref: refs/heads/raw

View File

@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version>
<version>0.2.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud Sleuth</name>
<description>Spring Cloud Sleuth</description>
@@ -13,7 +13,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>1.3.1.BUILD-SNAPSHOT</version>
<version>0.3.1.BUILD-SNAPSHOT</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
@@ -229,10 +229,10 @@
<maven.compiler.testSource>1.8</maven.compiler.testSource>
<surefire.plugin.version>2.19.1</surefire.plugin.version>
<checkstyle.version>2.17</checkstyle.version>
<spring-cloud-build.version>1.3.1.BUILD-SNAPSHOT</spring-cloud-build.version>
<spring-cloud-commons.version>1.2.0.BUILD-SNAPSHOT</spring-cloud-commons.version>
<spring-cloud-stream.version>Chelsea.BUILD-SNAPSHOT</spring-cloud-stream.version>
<spring-cloud-netflix.version>1.3.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
<spring-cloud-build.version>0.3.1.BUILD-SNAPSHOT</spring-cloud-build.version>
<spring-cloud-commons.version>0.2.0.BUILD-SNAPSHOT</spring-cloud-commons.version>
<spring-cloud-stream.version>Foo.BUILD-SNAPSHOT</spring-cloud-stream.version>
<spring-cloud-netflix.version>0.3.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
</properties>
<profiles>

View File

@@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version>
<version>0.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -5,11 +5,11 @@
<parent>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>1.3.1.BUILD-SNAPSHOT</version>
<version>0.3.1.BUILD-SNAPSHOT</version>
<relativePath/>
</parent>
<artifactId>spring-cloud-sleuth-dependencies</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version>
<version>0.2.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>spring-cloud-sleuth-dependencies</name>
<description>Spring Cloud Sleuth Dependencies</description>

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<packaging>pom</packaging>
<name>Spring Cloud Sleuth Samples</name>
<description>Spring Cloud Sleuth Samples</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>0.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<modules>
<module>spring-cloud-sleuth-sample</module>
<module>spring-cloud-sleuth-sample-test-core</module>
<module>spring-cloud-sleuth-sample-messaging</module>
<module>spring-cloud-sleuth-sample-websocket</module>
<module>spring-cloud-sleuth-sample-feign</module>
<module>spring-cloud-sleuth-sample-ribbon</module>
<module>spring-cloud-sleuth-sample-zipkin</module>
<module>spring-cloud-sleuth-sample-stream</module>
<module>spring-cloud-sleuth-sample-zipkin-stream</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<!--skip deploy (this is just a test module) -->
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-dependencies</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-sample-test-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin</artifactId>
<version>1.19.2</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>1.19.2</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2016 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth-sample-zipkin-stream</artifactId>
<packaging>jar</packaging>
<name>spring-cloud-sleuth-sample-zipkin-stream</name>
<description>Spring Boot Zipkin Server</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<version>0.2.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<properties>
<docker.image.prefix>springio</docker.image.prefix>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<sonar.skip>true</sonar.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-sample-test-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
</project>