diff --git a/README.adoc b/README.adoc
index 1286672a..1c1402d1 100644
--- a/README.adoc
+++ b/README.adoc
@@ -242,7 +242,7 @@ http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.ht
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html[Java 7 JCE]
-http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html[Java 8 JCE]
+http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html[Java 8 JCE]
Extract files into JDK/jre/lib/security folder (whichever version of JRE/JDK x64/x86 you are using).
@@ -305,11 +305,11 @@ a modified file in the correct place. Just commit it and push the change.
If you don't have an IDE preference we would recommend that you use
http://www.springsource.com/developer/sts[Spring Tools Suite] or
http://eclipse.org[Eclipse] when working with the code. We use the
-http://eclipse.org/m2e/[m2eclipe] eclipse plugin for maven support. Other IDEs and tools
+http://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools
should also work without issue as long as they use Maven 3.3.3 or better.
==== Importing into eclipse with m2eclipse
-We recommend the http://eclipse.org/m2e/[m2eclipe] eclipse plugin when working with
+We recommend the http://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with
eclipse. If you don't already have m2eclipse installed it is available from the "eclipse
marketplace".
diff --git a/docs/pom.xml b/docs/pom.xml
index 708b34fc..ff6fb294 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -6,7 +6,7 @@
org.springframework.cloud
spring-cloud-config
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
pom
Spring Cloud Config Docs
diff --git a/pom.xml b/pom.xml
index 798ecb33..70351dea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
org.springframework.cloud
spring-cloud-config
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
pom
Spring Cloud Config
Spring Cloud Config
@@ -22,7 +22,7 @@
config
- 1.1.5.BUILD-SNAPSHOT
+ 1.1.6.BUILD-SNAPSHOT
spring-cloud-config-dependencies
diff --git a/spring-cloud-config-client/pom.xml b/spring-cloud-config-client/pom.xml
index 7323d870..f27b03be 100644
--- a/spring-cloud-config-client/pom.xml
+++ b/spring-cloud-config-client/pom.xml
@@ -10,7 +10,7 @@
org.springframework.cloud
spring-cloud-config
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
..
diff --git a/spring-cloud-config-dependencies/pom.xml b/spring-cloud-config-dependencies/pom.xml
index f07f6a90..b479ae7b 100644
--- a/spring-cloud-config-dependencies/pom.xml
+++ b/spring-cloud-config-dependencies/pom.xml
@@ -9,7 +9,7 @@
spring-cloud-config-dependencies
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
pom
spring-cloud-config-dependencies
Spring Cloud Config Dependencies
diff --git a/spring-cloud-config-monitor/pom.xml b/spring-cloud-config-monitor/pom.xml
index f7466b8f..e9b6dc67 100644
--- a/spring-cloud-config-monitor/pom.xml
+++ b/spring-cloud-config-monitor/pom.xml
@@ -5,7 +5,7 @@
org.springframework.cloud
spring-cloud-config
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
..
spring-cloud-config-monitor
diff --git a/spring-cloud-config-sample/pom.xml b/spring-cloud-config-sample/pom.xml
index 79f773fa..5514e1bc 100644
--- a/spring-cloud-config-sample/pom.xml
+++ b/spring-cloud-config-sample/pom.xml
@@ -12,7 +12,7 @@
org.springframework.cloud
spring-cloud-config
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
..
diff --git a/spring-cloud-config-server/pom.xml b/spring-cloud-config-server/pom.xml
index 4c399c6e..5b8752ed 100644
--- a/spring-cloud-config-server/pom.xml
+++ b/spring-cloud-config-server/pom.xml
@@ -12,7 +12,7 @@
org.springframework.cloud
spring-cloud-config
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
..
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java
index 015615c5..e624f1fa 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java
@@ -31,7 +31,8 @@ import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.api.ListBranchCommand.ListMode;
-import org.eclipse.jgit.api.PullCommand;
+import org.eclipse.jgit.api.MergeCommand;
+import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.api.ResetCommand;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.api.Status;
@@ -40,10 +41,8 @@ import org.eclipse.jgit.api.TransportCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.transport.JschConfigSessionFactory;
+import org.eclipse.jgit.transport.*;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
-import org.eclipse.jgit.transport.SshSessionFactory;
-import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.util.FileUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.env.ConfigurableEnvironment;
@@ -60,6 +59,7 @@ import com.jcraft.jsch.Session;
* @author Roy Clarkson
* @author Marcos Barbero
* @author Daniel Lavoie
+ * @author Ryan Lynch
*/
public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
implements EnvironmentRepository, SearchPathLocator, InitializingBean {
@@ -141,11 +141,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
if (label == null) {
label = this.defaultLabel;
}
- Ref ref = refresh(application, label);
- String version = null;
- if (ref != null) {
- version = ref.getObjectId().getName();
- }
+ String version = refresh(label);
return new Locations(application, profile, label, version,
getSearchLocations(getWorkingDirectory(), application, profile, label));
}
@@ -162,25 +158,31 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
/**
* Get the working directory ready.
*/
- private Ref refresh(String application, String label) {
+ private String refresh(String label) {
initialize();
Git git = null;
try {
git = createGitClient();
- git.getRepository().getConfig().setString("branch", label, "merge", label);
- Ref ref = checkout(git, label);
- if (shouldPull(git, ref)) {
- pull(git, label, ref);
-
- if (!isClean(git)) {
- logger.warn("The local repository is dirty. Reseting it to origin/"
- + label + ".");
-
- fetch(git, label, "origin");
- resetHard(git, label, "refs/remotes/origin/" + label);
+ if (shouldPull(git)) {
+ fetch(git, label);
+ //checkout after fetch so we can get any new branches, tags, ect.
+ checkout(git, label);
+ if(isBranch(git, label)) {
+ //merge results from fetch
+ merge(git, label);
+ if (!isClean(git)) {
+ logger.warn("The local repository is dirty. Resetting it to origin/"
+ + label + ".");
+ resetHard(git, label, "refs/remotes/origin/" + label);
+ }
}
}
- return ref;
+ else{
+ //nothing to update so just checkout
+ checkout(git, label);
+ }
+ //always return what is currently HEAD as the version
+ return git.getRepository().getRef("HEAD").getObjectId().getName();
}
catch (RefNotFoundException e) {
throw new NoSuchLabelException("No such label: " + label);
@@ -235,7 +237,8 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
return checkout.call();
}
- /* for testing */ boolean shouldPull(Git git, Ref ref) throws GitAPIException {
+
+ public /*public for testing*/ boolean shouldPull(Git git) throws GitAPIException {
boolean shouldPull;
Status gitStatus = git.status().call();
boolean isWorkingTreeClean = gitStatus.isClean();
@@ -247,7 +250,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
logDirty(gitStatus);
}
else {
- shouldPull = isWorkingTreeClean && ref != null && originUrl != null;
+ shouldPull = isWorkingTreeClean && originUrl != null;
}
if (!isWorkingTreeClean && !this.forcePull) {
this.logger.info("Cannot pull from remote " + originUrl
@@ -277,56 +280,64 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
return isBranch(git, label) && !isLocalBranch(git, label);
}
- private void fetch(Git git, String label, String remote) {
- FetchCommand fetch = git.fetch().setRemote(remote);
+ private FetchResult fetch(Git git, String label) {
+ FetchCommand fetch = git.fetch();
+ fetch.setRemote("origin");
+ fetch.setTagOpt(TagOpt.FETCH_TAGS);
+
setTimeout(fetch);
try {
if (hasText(getUsername())) {
setCredentialsProvider(fetch);
}
- fetch.call();
+ FetchResult result = fetch.call();
+ if(result.getTrackingRefUpdates() != null && result.getTrackingRefUpdates().size() > 0) {
+ this.logger.info("Fetched for remote " + label + " and found " + result.getTrackingRefUpdates().size()
+ + " updates");
+ }
+ return result;
}
catch (Exception ex) {
this.logger.warn("Could not fetch remote for " + label + " remote: " + git
.getRepository().getConfig().getString("remote", "origin", "url"));
+ return null;
}
}
- private void resetHard(Git git, String label, String ref) {
+ private MergeResult merge(Git git, String label) {
+ try {
+ MergeCommand merge = git.merge();
+ merge.include(git.getRepository().getRef("origin/" + label));
+ MergeResult result = merge.call();
+ if(!result.getMergeStatus().isSuccessful()) {
+ this.logger.warn("Merged from remote " + label + " with result " + result.getMergeStatus());
+ }
+ return result;
+ }
+ catch (Exception ex) {
+ this.logger.warn("Could not merge remote for " + label + " remote: " + git
+ .getRepository().getConfig().getString("remote", "origin", "url"));
+ return null;
+ }
+ }
+
+ private Ref resetHard(Git git, String label, String ref) {
ResetCommand reset = git.reset();
reset.setRef(ref);
reset.setMode(ResetType.HARD);
try {
- reset.call();
+ Ref resetRef = reset.call();
+ if(resetRef != null) {
+ this.logger.info("Reset label " + label + " to version " + resetRef.getObjectId());
+ }
+ return resetRef;
}
catch (Exception ex) {
this.logger.warn("Could not reset to remote for " + label + " (current ref="
+ ref + "), remote: " + git.getRepository().getConfig()
.getString("remote", "origin", "url"));
- }
- }
-
- /**
- * Assumes we are on a tracking branch (should be safe)
- */
- private void pull(Git git, String label, Ref ref) {
- PullCommand pull = git.pull();
- setTimeout(pull);
- try {
- if (hasText(getUsername())) {
- setCredentialsProvider(pull);
- }
- pull.call();
- }
- catch (Exception e) {
- this.logger
- .warn("Could not pull remote for " + label + " (current ref=" + ref
- + "), remote: "
- + git.getRepository().getConfig().getString("remote",
- "origin", "url")
- + ", cause: (" + e.getClass().getSimpleName() + ") "
- + e.getMessage());
+ return null;
}
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/test/ConfigServerTestUtils.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/test/ConfigServerTestUtils.java
index 80b4d520..717bc5c7 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/test/ConfigServerTestUtils.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/test/ConfigServerTestUtils.java
@@ -19,6 +19,8 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
+import org.springframework.cloud.config.environment.Environment;
+import org.springframework.cloud.config.environment.PropertySource;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StringUtils;
@@ -111,4 +113,13 @@ public class ConfigServerTestUtils {
return FileSystemUtils.deleteRecursively(dest);
}
+ public static Object getProperty(Environment env, String sourceNameEndsWith, String property) {
+ for(PropertySource source: env.getPropertySources()) {
+ if(source.getName().endsWith(sourceNameEndsWith)) {
+ return source.getSource().get(property);
+ }
+ }
+ return null;
+ }
+
}
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitConfigServerTestData.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitConfigServerTestData.java
new file mode 100644
index 00000000..dc4c06fd
--- /dev/null
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitConfigServerTestData.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2013-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.cloud.config.server.environment;
+
+
+import org.eclipse.jgit.api.Git;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.cloud.config.server.test.ConfigServerTestUtils;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.util.FileSystemUtils;
+import org.springframework.util.ResourceUtils;
+
+import java.io.File;
+
+/**
+ * Class that holds objects that can be used for testing
+ * @author Ryan Lynch
+ */
+public class JGitConfigServerTestData {
+
+ private LocalGit serverGit;
+ private LocalGit clonedGit;
+ private JGitEnvironmentRepository repository;
+ private ConfigurableApplicationContext context;
+
+ public static class LocalGit {
+ private Git git;
+ private File gitWorkingDirectory;
+
+ public LocalGit(Git git, File gitWorkingDirectory) {
+ this.git = git;
+ this.gitWorkingDirectory = gitWorkingDirectory;
+ }
+
+ public Git getGit() {
+ return this.git;
+ }
+
+ public File getGitWorkingDirectory() {
+ return this.gitWorkingDirectory;
+ }
+ }
+
+ public JGitConfigServerTestData(LocalGit serverGit, LocalGit clonedGit,
+ JGitEnvironmentRepository repository, ConfigurableApplicationContext context) {
+ this.serverGit = serverGit;
+ this.clonedGit = clonedGit;
+ this.repository = repository;
+ this.context = context;
+ }
+
+ public LocalGit getServerGit() {
+ return this.serverGit;
+ }
+
+ public LocalGit getClonedGit() {
+ return this.clonedGit;
+ }
+
+ public JGitEnvironmentRepository getRepository() {
+ return this.repository;
+ }
+
+ public ConfigurableApplicationContext getContext() {
+ return this.context;
+ }
+
+ public static JGitConfigServerTestData prepareClonedGitRepository(Object... sources) throws Exception {
+ //setup remote repository
+ String remoteUri = ConfigServerTestUtils.prepareLocalRepo();
+ File remoteRepoDir = ResourceUtils.getFile(remoteUri);
+ Git remoteGit = Git.open(remoteRepoDir.getAbsoluteFile());
+ remoteGit.checkout().setName("master").call();
+
+ //setup local repository
+ File clonedRepoDir = new File("target/repos/cloned");
+ if(clonedRepoDir.exists()) {
+ FileSystemUtils.deleteRecursively(clonedRepoDir);
+ }else{
+ clonedRepoDir.mkdirs();
+ }
+ Git clonedGit = Git.cloneRepository()
+ .setURI( "file://" + remoteRepoDir.getAbsolutePath() )
+ .setDirectory( clonedRepoDir )
+ .setBranch("master")
+ .setCloneAllBranches(true)
+ .call();
+
+ //setup our test spring application pointing to the local repo
+ ConfigurableApplicationContext context = new SpringApplicationBuilder(sources).web(false)
+ .properties("spring.cloud.config.server.git.uri:" + "file://" + clonedRepoDir.getAbsolutePath()).run();
+ JGitEnvironmentRepository repository = context.getBean(JGitEnvironmentRepository.class);
+
+ return new JGitConfigServerTestData(
+ new JGitConfigServerTestData.LocalGit(remoteGit, remoteRepoDir),
+ new JGitConfigServerTestData.LocalGit(clonedGit, clonedRepoDir),
+ repository, context);
+ }
+
+
+}
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryIntegrationTests.java
index 1fc1247d..6f1fde9d 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryIntegrationTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryIntegrationTests.java
@@ -19,6 +19,7 @@ package org.springframework.cloud.config.server.environment;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -33,14 +34,16 @@ import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
+import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.util.FileUtils;
import org.hamcrest.Matchers;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
@@ -60,6 +63,7 @@ import org.springframework.util.StreamUtils;
* @author Dave Syer
* @author Roy Clarkson
* @author Daniel Lavoie
+ * @author Ryan Lynch
*/
public class JGitEnvironmentRepositoryIntegrationTests {
@@ -155,7 +159,8 @@ public class JGitEnvironmentRepositoryIntegrationTests {
.getBean(JGitEnvironmentRepository.class);
// Fetches the repository for the first time.
- repository.getLocations("bar", "test", "raw");
+ SearchPathLocator.Locations locations = repository.getLocations("bar", "test", "raw");
+ assertEquals(locations.getVersion(), commitToRevertBeforePull);
// Resets to the original commit.
git.reset().setMode(ResetType.HARD).setRef("master").call();
@@ -170,14 +175,17 @@ public class JGitEnvironmentRepositoryIntegrationTests {
git.add().addFilepattern(".").call();
git.commit().setMessage("Conflicting commit.").call();
git.push().setForce(true).call();
+ String conflictingCommit = git.log().setMaxCount(1).call().iterator()
+ .next().getName();
// Reset to the raw branch.
git.reset().setMode(ResetType.HARD).setRef(commitToRevertBeforePull).call();
// Triggers the repository refresh.
- repository.getLocations("bar", "test", "raw");
+ locations = repository.getLocations("bar", "test", "raw");
+ assertEquals(locations.getVersion(), conflictingCommit);
- Assert.assertTrue("Local repository is not cleaned after retreiving resources.",
+ assertTrue("Local repository is not cleaned after retrieving resources.",
git.status().call().isClean());
}
@@ -326,6 +334,155 @@ public class JGitEnvironmentRepositoryIntegrationTests {
repository.findOne("bar", "staging", "unknownlabel");
}
+ @Test
+ public void testVersionUpdate() throws Exception {
+ JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
+
+ //get our starting versions
+ String startingLocalVersion = getCommitID(testData.getClonedGit().getGit(), "master");
+ String startingRemoteVersion = getCommitID(testData.getServerGit().getGit(), "master");
+
+ //make sure we get the right version out of the gate
+ Environment environment = testData.getRepository().findOne("bar", "staging", "master");
+
+ //make sure the environments version is the same as the remote repo version
+ assertEquals(environment.getVersion(), startingRemoteVersion);
+
+ //update the remote repo
+ FileOutputStream out = new FileOutputStream(new File(testData.getServerGit().getGitWorkingDirectory(), "bar.properties"));
+ StreamUtils.copy("foo: foo", Charset.defaultCharset(), out);
+ testData.getServerGit().getGit().add().addFilepattern("bar.properties").call();
+ testData.getServerGit().getGit().commit().setMessage("Updated for pull").call();
+
+ //pull the environment again which should update the local repo from the just updated remote repo
+ environment = testData.getRepository().findOne("bar", "staging", "master");
+
+ //do some more check outs to get updated version numbers
+ String updatedLocalVersion = getCommitID(testData.getClonedGit().getGit(), "master");
+ String updatedRemoteVersion = getCommitID(testData.getClonedGit().getGit(), "master");
+
+ //make sure our versions have been updated
+ assertEquals(updatedRemoteVersion, updatedLocalVersion);
+ assertNotEquals(updatedRemoteVersion, startingRemoteVersion);
+ assertNotEquals(updatedLocalVersion, startingLocalVersion);
+
+ //make sure our environment also reflects the updated version
+ //this used to have a bug
+ assertEquals(environment.getVersion(), updatedRemoteVersion);
+ }
+
+ @Test
+ public void testNewRemoteBranch() throws Exception {
+ JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
+
+ Environment environment = testData.getRepository().findOne("bar", "staging", "master");
+ Object fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
+ assertEquals(fooProperty, "bar");
+
+ testData.getServerGit().getGit().branchCreate()
+ .setName("testNewRemoteBranch")
+ .call();
+
+ testData.getServerGit().getGit().checkout()
+ .setName("testNewRemoteBranch")
+ .call();
+
+ //update the remote repo
+ FileOutputStream out = new FileOutputStream(
+ new File(testData.getServerGit().getGitWorkingDirectory(), "/bar.properties"));
+ StreamUtils.copy("foo: branchBar", Charset.defaultCharset(), out);
+ testData.getServerGit().getGit().add().addFilepattern("bar.properties").call();
+ testData.getServerGit().getGit().commit().setMessage("Updated for branch test").call();
+
+ environment = testData.getRepository().findOne("bar", "staging", "testNewRemoteBranch");
+ fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
+ assertEquals(fooProperty, "branchBar");
+ }
+
+ @Test
+ public void testNewRemoteTag() throws Exception {
+ JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
+
+ Git serverGit = testData.getServerGit().getGit();
+
+ Environment environment = testData.getRepository().findOne("bar", "staging", "master");
+ Object fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
+ assertEquals(fooProperty, "bar");
+
+ serverGit.checkout().setName("master").call();
+
+ //create a new tag
+ serverGit.tag().setName("testTag").setMessage("Testing a tag").call();
+
+ //update the remote repo
+ FileOutputStream out = new FileOutputStream(
+ new File(testData.getServerGit().getGitWorkingDirectory(), "/bar.properties"));
+ StreamUtils.copy("foo: testAfterTag", Charset.defaultCharset(), out);
+ testData.getServerGit().getGit().add().addFilepattern("bar.properties").call();
+ testData.getServerGit().getGit().commit().setMessage("Updated for branch test").call();
+
+ environment = testData.getRepository().findOne("bar", "staging", "master");
+ fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
+ assertEquals(fooProperty, "testAfterTag");
+
+ environment = testData.getRepository().findOne("bar", "staging", "testTag");
+ fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
+ assertEquals(fooProperty, "bar");
+
+ //now move the tag and test again
+ serverGit.tag().setName("testTag").setForceUpdate(true).setMessage("Testing a moved tag").call();
+
+ environment = testData.getRepository().findOne("bar", "staging", "testTag");
+ fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
+ assertEquals(fooProperty, "testAfterTag");
+
+ }
+
+ @Test
+ public void testNewCommitID() throws Exception {
+ JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
+
+ //get our starting versions
+ String startingRemoteVersion = getCommitID(testData.getServerGit().getGit(), "master");
+
+ //make sure we get the right version out of the gate
+ Environment environment = testData.getRepository().findOne("bar", "staging", "master");
+ assertEquals(environment.getVersion(), startingRemoteVersion);
+
+ //update the remote repo
+ FileOutputStream out = new FileOutputStream(new File(testData.getServerGit().getGitWorkingDirectory(), "bar.properties"));
+ StreamUtils.copy("foo: barNewCommit", Charset.defaultCharset(), out);
+ testData.getServerGit().getGit().add().addFilepattern("bar.properties").call();
+ testData.getServerGit().getGit().commit().setMessage("Updated for pull").call();
+ String updatedRemoteVersion = getCommitID(testData.getServerGit().getGit(), "master");
+
+ //do a normal request and verify we get the new version
+ environment = testData.getRepository().findOne("bar", "staging", "master");
+ assertEquals(environment.getVersion(), updatedRemoteVersion);
+ Object fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
+ assertEquals(fooProperty, "barNewCommit");
+
+ //request the prior commit ID and make sure we get it
+ environment = testData.getRepository().findOne("bar", "staging", startingRemoteVersion);
+ assertEquals(environment.getVersion(), startingRemoteVersion);
+ fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
+ assertEquals(fooProperty, "bar");
+ }
+
+
+ @Test(expected = NoSuchLabelException.class)
+ public void testUnknownLabelWithRemote() throws Exception {
+ JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
+ testData.getRepository().findOne("bar", "staging", "BADLabel");
+ }
+
+ private String getCommitID(Git git, String label) throws GitAPIException {
+ CheckoutCommand checkout = git.checkout();
+ checkout.setName(label);
+ Ref localRef = checkout.call();
+ return localRef.getObjectId().getName();
+ }
+
@Configuration
@EnableConfigurationProperties(ConfigServerProperties.class)
@Import({ PropertyPlaceholderAutoConfiguration.class,
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java
index 49f5a436..9607be17 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java
@@ -18,15 +18,28 @@ package org.springframework.cloud.config.server.environment;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.CloneCommand;
+import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.ListBranchCommand;
+import org.eclipse.jgit.api.MergeCommand;
+import org.eclipse.jgit.api.ResetCommand;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.StatusCommand;
import org.eclipse.jgit.api.errors.TransportException;
+import org.eclipse.jgit.api.errors.InvalidRemoteException;
+import org.eclipse.jgit.api.errors.NotMergedException;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.util.FileUtils;
import org.junit.Before;
import org.junit.Test;
@@ -38,15 +51,11 @@ import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
/**
* @author Dave Syer
@@ -141,8 +150,7 @@ public class JGitEnvironmentRepositoryTests {
assertEquals(2, environment.getPropertySources().size());
assertEquals(this.repository.getUri() + "/bar.properties", environment
.getPropertySources().get(0).getName());
- //TODO: why is the version null in tag?
- assertNull("version was not null", environment.getVersion());
+ assertVersion(environment);
}
@Test
@@ -255,41 +263,16 @@ public class JGitEnvironmentRepositoryTests {
this.environment);
repo.setForcePull(true);
- boolean shouldPull = repo.shouldPull(git, null);
+ boolean shouldPull = repo.shouldPull(git);
assertThat("shouldPull was false", shouldPull, is(true));
}
- @Test
- public void shouldPullForcepullClean() throws Exception {
- Git git = mock(Git.class);
- StatusCommand statusCommand = mock(StatusCommand.class);
- Status status = mock(Status.class);
- Repository repository = mock(Repository.class);
- StoredConfig storedConfig = mock(StoredConfig.class);
-
- when(git.status()).thenReturn(statusCommand);
- when(git.getRepository()).thenReturn(repository);
- when(repository.getConfig()).thenReturn(storedConfig);
- when(storedConfig.getString("remote", "origin", "url")).thenReturn("http://example/git");
- when(statusCommand.call()).thenReturn(status);
- when(status.isClean()).thenReturn(true);
-
- JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
- this.environment);
- repo.setForcePull(true);
-
- boolean shouldPull = repo.shouldPull(git, null);
-
- assertThat("shouldPull was true", shouldPull, is(false));
- }
-
@Test
public void shouldPullNotClean() throws Exception {
Git git = mock(Git.class);
StatusCommand statusCommand = mock(StatusCommand.class);
Status status = mock(Status.class);
- Ref ref = mock(Ref.class);
Repository repository = mock(Repository.class);
StoredConfig storedConfig = mock(StoredConfig.class);
@@ -303,7 +286,7 @@ public class JGitEnvironmentRepositoryTests {
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
this.environment);
- boolean shouldPull = repo.shouldPull(git, ref);
+ boolean shouldPull = repo.shouldPull(git);
assertThat("shouldPull was true", shouldPull, is(false));
}
@@ -313,7 +296,6 @@ public class JGitEnvironmentRepositoryTests {
Git git = mock(Git.class);
StatusCommand statusCommand = mock(StatusCommand.class);
Status status = mock(Status.class);
- Ref ref = mock(Ref.class);
Repository repository = mock(Repository.class);
StoredConfig storedConfig = mock(StoredConfig.class);
@@ -327,10 +309,188 @@ public class JGitEnvironmentRepositoryTests {
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
this.environment);
- boolean shouldPull = repo.shouldPull(git, ref);
+ boolean shouldPull = repo.shouldPull(git);
assertThat("shouldPull was false", shouldPull, is(true));
}
+
+ @Test
+ public void testFetchException() throws Exception {
+
+ Git git = mock(Git.class);
+ CloneCommand cloneCommand = mock(CloneCommand.class);
+ MockGitFactory factory = new MockGitFactory(git, cloneCommand);
+ JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
+ this.environment);
+ this.repository.setGitFactory(factory);
+
+ //refresh()->shouldPull
+ StatusCommand statusCommand = mock(StatusCommand.class);
+ Status status = mock(Status.class);
+ when(git.status()).thenReturn(statusCommand);
+ Repository repository = mock(Repository.class);
+ when(git.getRepository()).thenReturn(repository);
+ StoredConfig storedConfig = mock(StoredConfig.class);
+ when(repository.getConfig()).thenReturn(storedConfig);
+ when(storedConfig.getString("remote", "origin", "url")).thenReturn("http://example/git");
+ when(statusCommand.call()).thenReturn(status);
+ when(status.isClean()).thenReturn(true);
+
+ //refresh()->fetch
+ FetchCommand fetchCommand = mock(FetchCommand.class);
+ when(git.fetch()).thenReturn(fetchCommand);
+ when(fetchCommand.setRemote(anyString())).thenReturn(fetchCommand);
+ when(fetchCommand.call()).thenThrow(new InvalidRemoteException("invalid mock remote")); //here is our exception we are testing
+
+ //refresh()->checkout
+ CheckoutCommand checkoutCommand = mock(CheckoutCommand.class);
+ //refresh()->checkout->containsBranch
+ ListBranchCommand listBranchCommand = mock(ListBranchCommand.class);
+ when(git.checkout()).thenReturn(checkoutCommand);
+ when(git.branchList()).thenReturn(listBranchCommand);
+ List[ refs = new ArrayList<>();
+ Ref ref = mock(Ref.class);
+ refs.add(ref);
+ when(ref.getName()).thenReturn("/master");
+ when(listBranchCommand.call()).thenReturn(refs);
+
+ //refresh()->merge
+ MergeCommand mergeCommand = mock(MergeCommand.class);
+ when(git.merge()).thenReturn(mergeCommand);
+ when(mergeCommand.call()).thenThrow(new NotMergedException()); //here is our exception we are testing
+
+ //refresh()->return git.getRepository().getRef("HEAD").getObjectId().getName();
+ Ref headRef = mock(Ref.class);
+ when(repository.getRef(anyString())).thenReturn(headRef);
+
+ ObjectId newObjectId = ObjectId.fromRaw(new int[]{1,2,3,4,5});
+ when(headRef.getObjectId()).thenReturn(newObjectId);
+
+ SearchPathLocator.Locations locations = this.repository.getLocations("bar", "staging", null);
+ assertEquals(locations.getVersion(),newObjectId.getName());
+ }
+
+
+ @Test
+ public void testMergeException() throws Exception {
+
+ Git git = mock(Git.class);
+ CloneCommand cloneCommand = mock(CloneCommand.class);
+ MockGitFactory factory = new MockGitFactory(git, cloneCommand);
+ JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
+ this.environment);
+ this.repository.setGitFactory(factory);
+
+ //refresh()->shouldPull
+ StatusCommand statusCommand = mock(StatusCommand.class);
+ Status status = mock(Status.class);
+ when(git.status()).thenReturn(statusCommand);
+ Repository repository = mock(Repository.class);
+ when(git.getRepository()).thenReturn(repository);
+ StoredConfig storedConfig = mock(StoredConfig.class);
+ when(repository.getConfig()).thenReturn(storedConfig);
+ when(storedConfig.getString("remote", "origin", "url")).thenReturn("http://example/git");
+ when(statusCommand.call()).thenReturn(status);
+ when(status.isClean()).thenReturn(true);
+
+ //refresh()->fetch
+ FetchCommand fetchCommand = mock(FetchCommand.class);
+ FetchResult fetchResult = mock(FetchResult.class);
+ when(git.fetch()).thenReturn(fetchCommand);
+ when(fetchCommand.setRemote(anyString())).thenReturn(fetchCommand);
+ when(fetchCommand.call()).thenReturn(fetchResult);
+ when(fetchResult.getTrackingRefUpdates()).thenReturn(Collections.EMPTY_LIST);
+
+ //refresh()->checkout
+ CheckoutCommand checkoutCommand = mock(CheckoutCommand.class);
+ //refresh()->checkout->containsBranch
+ ListBranchCommand listBranchCommand = mock(ListBranchCommand.class);
+ when(git.checkout()).thenReturn(checkoutCommand);
+ when(git.branchList()).thenReturn(listBranchCommand);
+ List][ refs = new ArrayList<>();
+ Ref ref = mock(Ref.class);
+ refs.add(ref);
+ when(ref.getName()).thenReturn("/master");
+ when(listBranchCommand.call()).thenReturn(refs);
+
+ //refresh()->merge
+ MergeCommand mergeCommand = mock(MergeCommand.class);
+ when(git.merge()).thenReturn(mergeCommand);
+ when(mergeCommand.call()).thenThrow(new NotMergedException()); //here is our exception we are testing
+
+ //refresh()->return git.getRepository().getRef("HEAD").getObjectId().getName();
+ Ref headRef = mock(Ref.class);
+ when(repository.getRef(anyString())).thenReturn(headRef);
+
+ ObjectId newObjectId = ObjectId.fromRaw(new int[]{1,2,3,4,5});
+ when(headRef.getObjectId()).thenReturn(newObjectId);
+
+ SearchPathLocator.Locations locations = this.repository.getLocations("bar", "staging", "master");
+ assertEquals(locations.getVersion(),newObjectId.getName());
+ }
+
+ @Test
+ public void testResetHardException() throws Exception {
+
+ Git git = mock(Git.class);
+ CloneCommand cloneCommand = mock(CloneCommand.class);
+ MockGitFactory factory = new MockGitFactory(git, cloneCommand);
+ JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
+ this.environment);
+ this.repository.setGitFactory(factory);
+
+ //refresh()->shouldPull
+ StatusCommand statusCommand = mock(StatusCommand.class);
+ Status status = mock(Status.class);
+ when(git.status()).thenReturn(statusCommand);
+ Repository repository = mock(Repository.class);
+ when(git.getRepository()).thenReturn(repository);
+ StoredConfig storedConfig = mock(StoredConfig.class);
+ when(repository.getConfig()).thenReturn(storedConfig);
+ when(storedConfig.getString("remote", "origin", "url")).thenReturn("http://example/git");
+ when(statusCommand.call()).thenReturn(status);
+ when(status.isClean()).thenReturn(true).thenReturn(false);
+
+ //refresh()->fetch
+ FetchCommand fetchCommand = mock(FetchCommand.class);
+ FetchResult fetchResult = mock(FetchResult.class);
+ when(git.fetch()).thenReturn(fetchCommand);
+ when(fetchCommand.setRemote(anyString())).thenReturn(fetchCommand);
+ when(fetchCommand.call()).thenReturn(fetchResult);
+ when(fetchResult.getTrackingRefUpdates()).thenReturn(Collections.EMPTY_LIST);
+
+ //refresh()->checkout
+ CheckoutCommand checkoutCommand = mock(CheckoutCommand.class);
+ //refresh()->checkout->containsBranch
+ ListBranchCommand listBranchCommand = mock(ListBranchCommand.class);
+ when(git.checkout()).thenReturn(checkoutCommand);
+ when(git.branchList()).thenReturn(listBranchCommand);
+ List][ refs = new ArrayList<>();
+ Ref ref = mock(Ref.class);
+ refs.add(ref);
+ when(ref.getName()).thenReturn("/master");
+ when(listBranchCommand.call()).thenReturn(refs);
+
+ //refresh()->merge
+ MergeCommand mergeCommand = mock(MergeCommand.class);
+ when(git.merge()).thenReturn(mergeCommand);
+ when(mergeCommand.call()).thenThrow(new NotMergedException()); //here is our exception we are testing
+
+ //refresh()->hardReset
+ ResetCommand resetCommand = mock(ResetCommand.class);
+ when(git.reset()).thenReturn(resetCommand);
+ when(resetCommand.call()).thenReturn(ref);
+
+ //refresh()->return git.getRepository().getRef("HEAD").getObjectId().getName();
+ Ref headRef = mock(Ref.class);
+ when(repository.getRef(anyString())).thenReturn(headRef);
+
+ ObjectId newObjectId = ObjectId.fromRaw(new int[]{1,2,3,4,5});
+ when(headRef.getObjectId()).thenReturn(newObjectId);
+
+ SearchPathLocator.Locations locations = this.repository.getLocations("bar", "staging", "master");
+ assertEquals(locations.getVersion(),newObjectId.getName());
+ }
@Test
public void shouldDeleteBaseDirWhenCloneFails() throws Exception {
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryTests.java
index 9649881f..5a38a50c 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryTests.java
@@ -109,7 +109,7 @@ public class MultipleJGitEnvironmentRepositoryTests {
assertEquals(2, environment.getPropertySources().size());
assertEquals(this.repository.getUri() + "/bar.properties", environment
.getPropertySources().get(0).getName());
- assertNull("version was not null", environment.getVersion());
+ assertVersion(environment);
}
@Test
diff --git a/spring-cloud-starter-config/pom.xml b/spring-cloud-starter-config/pom.xml
index e24d77f6..9760a1c1 100644
--- a/spring-cloud-starter-config/pom.xml
+++ b/spring-cloud-starter-config/pom.xml
@@ -5,10 +5,10 @@
org.springframework.cloud
spring-cloud-config
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
spring-cloud-starter-config
- 1.2.2.BUILD-SNAPSHOT
+ 1.2.3.BUILD-SNAPSHOT
spring-cloud-starter-config
Spring Cloud Starter
https://projects.spring.io/spring-cloud
]