diff --git a/gradle/changelog/changed_initializer_commits.yaml b/gradle/changelog/changed_initializer_commits.yaml new file mode 100644 index 0000000000..88441e507e --- /dev/null +++ b/gradle/changelog/changed_initializer_commits.yaml @@ -0,0 +1,2 @@ +- type: changed + description: Each repository initializer step is now executed with his own commit diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryContentInitializer.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryContentInitializer.java index a6eeab1004..cec6f24fe7 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryContentInitializer.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryContentInitializer.java @@ -59,6 +59,14 @@ public interface RepositoryContentInitializer { */ CreateFile create(String path); + /** + * create new file which will be included in initial repository commit. + * + * @param path full path of the file to be created + * @param useDefaultPath Wether the default path of the repository should be prefixed to the specified path. For example "/trunk", if it is a SVN repository. + */ + CreateFile createWithDefaultPath(String path, boolean useDefaultPath); + /** * Returns the context entry with the given key and unmarshalls it to the given type. * It no entry with the given key is available an empty optional is returned. diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java index 03913dd54f..4de502d807 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java @@ -157,6 +157,10 @@ public class ModifyCommandBuilder { } } + public boolean isEmpty() { + return request.isEmpty(); + } + /** * Set the commit message for the new commit. * @return This builder instance. diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommandRequest.java index 6a255fe645..848b09503e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommandRequest.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommandRequest.java @@ -65,6 +65,10 @@ public class ModifyCommandRequest implements Resetable, Validateable, CommandWit this.requests.add(request); } + public boolean isEmpty() { + return requests.isEmpty(); + } + public void setAuthor(Person author) { this.author = author; } diff --git a/scm-webapp/src/main/java/sonia/scm/repository/RepositoryInitializer.java b/scm-webapp/src/main/java/sonia/scm/repository/RepositoryInitializer.java index 1e1e3922a9..3ff4c4bda7 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/RepositoryInitializer.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/RepositoryInitializer.java @@ -60,18 +60,19 @@ public class RepositoryInitializer { public void initialize(Repository repository, Map contextEntries) { try (RepositoryService service = serviceFactory.create(repository)) { - ModifyCommandBuilder modifyCommandBuilder = service.getModifyCommand(); - - InitializerContextImpl initializerContext = new InitializerContextImpl(repository, modifyCommandBuilder, contextEntries); for (RepositoryContentInitializer initializer : contentInitializers) { + ModifyCommandBuilder modifyCommandBuilder = service.getModifyCommand(); + InitializerContextImpl initializerContext = new InitializerContextImpl(repository, modifyCommandBuilder, contextEntries); + initializer.initialize(initializerContext); + + if (!modifyCommandBuilder.isEmpty()) { + modifyCommandBuilder.setCommitMessage("initialize repository"); + String revision = modifyCommandBuilder.execute(); + LOG.info("initialized repository {} as revision {}", repository, revision); + } } - - modifyCommandBuilder.setCommitMessage("initialize repository"); - String revision = modifyCommandBuilder.execute(); - LOG.info("initialized repository {} as revision {}", repository, revision); - } catch (IOException e) { throw new InternalRepositoryException(repository, "failed to initialize repository", e); } @@ -109,6 +110,11 @@ public class RepositoryInitializer { public RepositoryContentInitializer.CreateFile create(String path) { return new CreateFileImpl(this, builder.useDefaultPath(true).createFile(path).setOverwrite(true)); } + + @Override + public RepositoryContentInitializer.CreateFile createWithDefaultPath(String path, boolean useDefaultPath) { + return new CreateFileImpl(this, builder.useDefaultPath(useDefaultPath).createFile(path).setOverwrite(true)); + } } private static class CreateFileImpl implements RepositoryContentInitializer.CreateFile { diff --git a/scm-webapp/src/test/java/sonia/scm/repository/RepositoryInitializerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/RepositoryInitializerTest.java index d0cc9cdd29..ebafa7f32e 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/RepositoryInitializerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/RepositoryInitializerTest.java @@ -79,6 +79,23 @@ class RepositoryInitializerTest { when(repositoryService.getModifyCommand()).thenReturn(modifyCommand); } + @Test + void shouldNotCommitIfInitializerDidNotMakeAnyChanges() { + when(modifyCommand.isEmpty()).thenReturn(true); + + Set repositoryContentInitializers = ImmutableSet.of( + new NoOpInitializer() + ); + + RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers); + initializer.initialize(repository, Collections.emptyMap()); + + verify(modifyCommand, never()).setCommitMessage("initialize repository"); + verify(modifyCommand, never()).execute(); + + verify(repositoryService).close(); + } + @Test void shouldCallRepositoryContentInitializer() throws IOException { ModifyCommandBuilder.WithOverwriteFlagContentLoader readmeContentLoader = mockContentLoader("README.md"); @@ -95,8 +112,8 @@ class RepositoryInitializerTest { verifyFileCreation(readmeContentLoader, "# HeartOfGold"); verifyFileCreation(licenseContentLoader, "MIT"); - verify(modifyCommand).setCommitMessage("initialize repository"); - verify(modifyCommand).execute(); + verify(modifyCommand, times(2)).setCommitMessage("initialize repository"); + verify(modifyCommand, times(2)).execute(); verify(repositoryService).close(); } @@ -257,6 +274,14 @@ class RepositoryInitializerTest { } } + @Priority(3) + private static class NoOpInitializer implements RepositoryContentInitializer { + + @Override + public void initialize(InitializerContext context) { + } + } + private static class StreamingContentInitializer implements RepositoryContentInitializer { @Override