diff --git a/src/main/java/com/englishtown/bitbucket/hook/MirrorRepositoryHook.java b/src/main/java/com/englishtown/bitbucket/hook/MirrorRepositoryHook.java index e6c8a7d..5f0dbd9 100644 --- a/src/main/java/com/englishtown/bitbucket/hook/MirrorRepositoryHook.java +++ b/src/main/java/com/englishtown/bitbucket/hook/MirrorRepositoryHook.java @@ -1,9 +1,10 @@ package com.englishtown.bitbucket.hook; -import com.atlassian.bitbucket.hook.repository.AsyncPostReceiveRepositoryHook; -import com.atlassian.bitbucket.hook.repository.RepositoryHookContext; +import com.atlassian.bitbucket.hook.repository.PostRepositoryHook; +import com.atlassian.bitbucket.hook.repository.PostRepositoryHookContext; +import com.atlassian.bitbucket.hook.repository.RepositoryHookRequest; +import com.atlassian.bitbucket.hook.repository.StandardRepositoryHookTrigger; import com.atlassian.bitbucket.i18n.I18nService; -import com.atlassian.bitbucket.repository.RefChange; import com.atlassian.bitbucket.repository.Repository; import com.atlassian.bitbucket.repository.RepositoryService; import com.atlassian.bitbucket.scm.CommandExitHandler; @@ -11,9 +12,12 @@ import com.atlassian.bitbucket.scm.DefaultCommandExitHandler; import com.atlassian.bitbucket.scm.ScmCommandBuilder; import com.atlassian.bitbucket.scm.ScmService; import com.atlassian.bitbucket.scm.git.command.GitScmCommandBuilder; -import com.atlassian.bitbucket.setting.RepositorySettingsValidator; +import com.atlassian.bitbucket.scope.RepositoryScope; +import com.atlassian.bitbucket.scope.Scope; +import com.atlassian.bitbucket.scope.ScopeVisitor; import com.atlassian.bitbucket.setting.Settings; import com.atlassian.bitbucket.setting.SettingsValidationErrors; +import com.atlassian.bitbucket.setting.SettingsValidator; import com.atlassian.sal.api.pluginsettings.PluginSettings; import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory; import com.google.common.base.Strings; @@ -24,11 +28,14 @@ import javax.annotation.Nonnull; import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -public class MirrorRepositoryHook implements AsyncPostReceiveRepositoryHook, RepositorySettingsValidator { +public class MirrorRepositoryHook implements PostRepositoryHook, SettingsValidator { protected static class MirrorSettings { String mirrorRepoUrl; @@ -96,21 +103,19 @@ public class MirrorRepositoryHook implements AsyncPostReceiveRepositoryHook, Rep * Despite being asynchronous, the user who initiated this change is still available from * * @param context the context which the hook is being run with - * @param refChanges the refs that have just been updated + * @param request the repository hook request */ @Override - public void postReceive( - @Nonnull RepositoryHookContext context, - @Nonnull Collection refChanges) { + public void postUpdate(@Nonnull PostRepositoryHookContext context, @Nonnull RepositoryHookRequest request) { + if (request.getTrigger() == StandardRepositoryHookTrigger.REPO_PUSH) { + logger.debug("MirrorRepositoryHook: postReceive started."); - logger.debug("MirrorRepositoryHook: postReceive started."); + List mirrorSettings = getMirrorSettings(context.getSettings()); - List mirrorSettings = getMirrorSettings(context.getSettings()); - - for (MirrorSettings settings : mirrorSettings) { - runMirrorCommand(settings, context.getRepository()); + for (MirrorSettings settings : mirrorSettings) { + runMirrorCommand(settings, request.getRepository()); + } } - } void runMirrorCommand(MirrorSettings settings, final Repository repository) { @@ -212,13 +217,13 @@ public class MirrorRepositoryHook implements AsyncPostReceiveRepositoryHook, Rep * * @param settings to be validated * @param errors callback for reporting validation errors. - * @param repository the context {@code Repository} the settings will be associated with + * @param scope the scope the settings will be associated with */ @Override public void validate( @Nonnull Settings settings, @Nonnull SettingsValidationErrors errors, - @Nonnull Repository repository) { + @Nonnull Scope scope) { try { boolean ok = true; @@ -236,7 +241,13 @@ public class MirrorRepositoryHook implements AsyncPostReceiveRepositoryHook, Rep if (ok) { updateSettings(mirrorSettings, settings); for (MirrorSettings ms : mirrorSettings) { - runMirrorCommand(ms, repository); + scope.accept(new ScopeVisitor() { + @Override + public Void visit(@Nonnull RepositoryScope scope) { + runMirrorCommand(ms, scope.getRepository()); + return null; + } + }); } } diff --git a/src/test/java/com/englishtown/bitbucket/hook/MirrorRepositoryHookTest.java b/src/test/java/com/englishtown/bitbucket/hook/MirrorRepositoryHookTest.java index 98a0442..f8b0417 100644 --- a/src/test/java/com/englishtown/bitbucket/hook/MirrorRepositoryHookTest.java +++ b/src/test/java/com/englishtown/bitbucket/hook/MirrorRepositoryHookTest.java @@ -1,6 +1,9 @@ package com.englishtown.bitbucket.hook; -import com.atlassian.bitbucket.hook.repository.RepositoryHookContext; +import com.atlassian.bitbucket.hook.repository.PostRepositoryHookContext; +import com.atlassian.bitbucket.hook.repository.RepositoryHookRequest; +import com.atlassian.bitbucket.hook.repository.RepositoryHookTrigger; +import com.atlassian.bitbucket.hook.repository.StandardRepositoryHookTrigger; import com.atlassian.bitbucket.i18n.I18nService; import com.atlassian.bitbucket.repository.Repository; import com.atlassian.bitbucket.repository.RepositoryService; @@ -10,6 +13,7 @@ import com.atlassian.bitbucket.scm.CommandOutputHandler; import com.atlassian.bitbucket.scm.ScmService; import com.atlassian.bitbucket.scm.git.command.GitCommand; import com.atlassian.bitbucket.scm.git.command.GitScmCommandBuilder; +import com.atlassian.bitbucket.scope.Scope; import com.atlassian.bitbucket.setting.Settings; import com.atlassian.bitbucket.setting.SettingsValidationErrors; import com.atlassian.sal.api.pluginsettings.PluginSettings; @@ -24,7 +28,6 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; @@ -96,16 +99,25 @@ public class MirrorRepositoryHookTest { Repository repo = mock(Repository.class); - hook.postReceive(buildContext(repo), new ArrayList<>()); + hook.postUpdate(buildContext(), buildRequest(StandardRepositoryHookTrigger.REPO_PUSH, repo)); verifyExecutor(); } + @Test + public void testUnwantedEventsIgnored() { + Repository repo = mock(Repository.class); + + hook.postUpdate(buildContext(), buildRequest(StandardRepositoryHookTrigger.BRANCH_CREATE, repo)); + + verify(executor, never()).submit(ArgumentMatchers.any()); + } + @Test public void testEmptyRepositoriesNotMirrored() { Repository repo = mock(Repository.class); when(repositoryService.isEmpty(repo)).thenReturn(true); - hook.postReceive(buildContext(repo), new ArrayList<>()); + hook.postUpdate(buildContext(), buildRequest(StandardRepositoryHookTrigger.REPO_PUSH, repo)); verify(executor, never()).submit(ArgumentMatchers.any()); } @@ -214,16 +226,17 @@ public class MirrorRepositoryHookTest { .thenReturn("+refs/heads/master:refs/heads/master") .thenReturn(""); - Repository repo = mock(Repository.class); + Scope scope = mock(Scope.class); + SettingsValidationErrors errors; errors = mock(SettingsValidationErrors.class); - hook.validate(settings, errors, repo); + hook.validate(settings, errors, scope); verify(errors, times(1)).addFormError(anyString()); verify(errors, never()).addFieldError(anyString(), anyString()); errors = mock(SettingsValidationErrors.class); - hook.validate(settings, errors, repo); + hook.validate(settings, errors, scope); verify(errors, never()).addFormError(anyString()); verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL + "0"), anyString()); verify(errors, never()).addFieldError(eq(MirrorRepositoryHook.SETTING_USERNAME + "0"), anyString()); @@ -231,52 +244,58 @@ public class MirrorRepositoryHookTest { verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_REFSPEC + "0"), anyString()); errors = mock(SettingsValidationErrors.class); - hook.validate(settings, errors, repo); + hook.validate(settings, errors, scope); verify(errors, never()).addFormError(anyString()); verify(errors, never()).addFieldError(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL + "0"), anyString()); verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_USERNAME + "0"), anyString()); verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_PASSWORD + "0"), anyString()); errors = mock(SettingsValidationErrors.class); - hook.validate(settings, errors, repo); + hook.validate(settings, errors, scope); verify(errors, never()).addFormError(anyString()); verify(errors, never()).addFieldError(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL + "0"), anyString()); verify(errors, never()).addFieldError(anyString(), anyString()); errors = mock(SettingsValidationErrors.class); - hook.validate(settings, errors, repo); + hook.validate(settings, errors, scope); verify(errors, never()).addFormError(anyString()); verify(errors).addFieldError(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL + "0"), anyString()); verify(errors, never()).addFieldError(eq(MirrorRepositoryHook.SETTING_USERNAME + "0"), anyString()); verify(errors, never()).addFieldError(eq(MirrorRepositoryHook.SETTING_PASSWORD + "0"), anyString()); errors = mock(SettingsValidationErrors.class); - hook.validate(settings, errors, repo); + hook.validate(settings, errors, scope); verify(errors, never()).addFormError(anyString()); verify(errors, never()).addFieldError(eq(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL + "0"), anyString()); verify(errors, never()).addFieldError(eq(MirrorRepositoryHook.SETTING_USERNAME + "0"), anyString()); verify(errors, never()).addFieldError(eq(MirrorRepositoryHook.SETTING_PASSWORD + "0"), anyString()); errors = mock(SettingsValidationErrors.class); - hook.validate(settings, errors, repo); + hook.validate(settings, errors, scope); verify(errors, never()).addFormError(anyString()); verify(errors, never()).addFieldError(anyString(), anyString()); errors = mock(SettingsValidationErrors.class); - hook.validate(settings, errors, repo); + hook.validate(settings, errors, scope); verify(errors, never()).addFormError(anyString()); verify(errors, never()).addFieldError(anyString(), anyString()); } - private RepositoryHookContext buildContext(Repository repo) { - RepositoryHookContext context = mock(RepositoryHookContext.class); + private PostRepositoryHookContext buildContext() { + PostRepositoryHookContext context = mock(PostRepositoryHookContext.class); Settings settings = defaultSettings(); when(context.getSettings()).thenReturn(settings); - when(context.getRepository()).thenReturn(repo); return context; } + private RepositoryHookRequest buildRequest(RepositoryHookTrigger trigger, Repository repo) { + RepositoryHookRequest request = mock(RepositoryHookRequest.class); + when(request.getTrigger()).thenReturn(trigger); + when(request.getRepository()).thenReturn(repo); + return request; + } + private Settings defaultSettings() { Map map = new HashMap(); map.put(MirrorRepositoryHook.SETTING_MIRROR_REPO_URL, "");