diff --git a/gradle/changelog/default_branch_changed_event.yaml b/gradle/changelog/default_branch_changed_event.yaml new file mode 100644 index 0000000000..91ef878a53 --- /dev/null +++ b/gradle/changelog/default_branch_changed_event.yaml @@ -0,0 +1,2 @@ +- type: Added + description: Event which is fired whenever the default branch of a repository changes ([#1763](https://github.com/scm-manager/scm-manager/pull/1763)) diff --git a/scm-core/src/main/java/sonia/scm/repository/DefaultBranchChangedEvent.java b/scm-core/src/main/java/sonia/scm/repository/DefaultBranchChangedEvent.java new file mode 100644 index 0000000000..1611be861b --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/DefaultBranchChangedEvent.java @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.repository; + +import lombok.Value; +import sonia.scm.event.Event; + +/** + * Event is fired whenever the default branch of a repository was modified. + * + * @since 2.23.0 + */ +@Event +@Value +public class DefaultBranchChangedEvent { + + Repository repository; + String oldDefaultBranch; + String newDefaultBranch; + +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangeClearRepositoryCacheListener.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangeClearRepositoryCacheListener.java index 0799ec4148..6358136cfd 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangeClearRepositoryCacheListener.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangeClearRepositoryCacheListener.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import com.github.legman.Subscribe; @@ -29,11 +29,20 @@ import sonia.scm.EagerSingleton; import sonia.scm.event.ScmEventBus; import sonia.scm.plugin.Extension; import sonia.scm.repository.ClearRepositoryCacheEvent; +import sonia.scm.repository.RepositoryModificationEvent; import java.util.Objects; -@EagerSingleton @Extension +@Extension +@EagerSingleton public class GitRepositoryConfigChangeClearRepositoryCacheListener { + + /** + * Receives {@link RepositoryModificationEvent} and fires a {@link ClearRepositoryCacheEvent} if + * the default branch of a git repository was modified. + * + * @param event repository modification event + */ @Subscribe public void sendClearRepositoryCacheEvent(GitRepositoryConfigChangedEvent event) { if (!Objects.equals(event.getOldConfig().getDefaultBranch(), event.getNewConfig().getDefaultBranch())) { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/DefaultBranchChangedDispatcher.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/DefaultBranchChangedDispatcher.java new file mode 100644 index 0000000000..b7581c0928 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/DefaultBranchChangedDispatcher.java @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.repository; + +import com.github.legman.Subscribe; +import com.google.common.base.Strings; +import sonia.scm.EagerSingleton; +import sonia.scm.api.v2.resources.GitRepositoryConfigChangedEvent; +import sonia.scm.event.ScmEventBus; +import sonia.scm.plugin.Extension; + +import javax.inject.Inject; + +@Extension +@EagerSingleton +public class DefaultBranchChangedDispatcher { + + private final ScmEventBus eventBus; + + @Inject + public DefaultBranchChangedDispatcher(ScmEventBus eventBus) { + this.eventBus = eventBus; + } + + @Subscribe + public void handleConfigUpdate(GitRepositoryConfigChangedEvent event) { + String oldDefaultBranch = event.getOldConfig().getDefaultBranch(); + String newDefaultBranch = event.getNewConfig().getDefaultBranch(); + if (hasChanged(oldDefaultBranch, newDefaultBranch)) { + eventBus.post(new DefaultBranchChangedEvent(event.getRepository(), oldDefaultBranch, newDefaultBranch)); + } + } + + private boolean hasChanged(String oldDefaultBranch, String newDefaultBranch) { + return !Strings.nullToEmpty(oldDefaultBranch).equals(Strings.nullToEmpty(newDefaultBranch)); + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java index 447f27d039..a5bd1c058a 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.repository; import com.github.legman.Subscribe; @@ -51,12 +51,6 @@ public class GitRepositoryModifyListener { this.storeProvider = storeProvider; } - /** - * Receives {@link RepositoryModificationEvent} and fires a {@link ClearRepositoryCacheEvent} if - * the default branch of a git repository was modified. - * - * @param event repository modification event - */ @Subscribe public void handleEvent(GitRepositoryConfigChangedEvent event){ Repository repository = event.getRepository(); diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/DefaultBranchChangedDispatcherTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/DefaultBranchChangedDispatcherTest.java new file mode 100644 index 0000000000..cd1597dab5 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/DefaultBranchChangedDispatcherTest.java @@ -0,0 +1,87 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.repository; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import sonia.scm.api.v2.resources.GitRepositoryConfigChangedEvent; +import sonia.scm.event.ScmEventBus; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; + +@ExtendWith(MockitoExtension.class) +class DefaultBranchChangedDispatcherTest { + + @Mock + private ScmEventBus eventBus; + + @InjectMocks + private DefaultBranchChangedDispatcher dispatcher; + + @Captor + private ArgumentCaptor eventCaptor; + + private final Repository repository = RepositoryTestData.createHeartOfGold(); + + @Test + void shouldFireDefaultBranchChangedEvent() { + dispatcher.handleConfigUpdate(changedEvent("master", "main")); + + verify(eventBus).post(eventCaptor.capture()); + assertThat(eventCaptor.getValue()) + .isInstanceOfSatisfying(DefaultBranchChangedEvent.class, event -> { + assertThat(event.getRepository()).isSameAs(repository); + assertThat(event.getOldDefaultBranch()).isEqualTo("master"); + assertThat(event.getNewDefaultBranch()).isEqualTo("main"); + }); + } + + @Test + void shouldNotFireEventIfDefaultBranchHasNotChanged() { + dispatcher.handleConfigUpdate(changedEvent("develop", "develop")); + + verifyNoInteractions(eventBus); + } + + private GitRepositoryConfigChangedEvent changedEvent(String oldDefaultBranch, String newDefaultBranch) { + return new GitRepositoryConfigChangedEvent( + repository, config(oldDefaultBranch), config(newDefaultBranch) + ); + } + + private GitRepositoryConfig config(String defaultBranch) { + GitRepositoryConfig config = new GitRepositoryConfig(); + config.setDefaultBranch(defaultBranch); + return config; + } + +}