diff --git a/scm-core/src/main/java/sonia/scm/repository/api/HookContext.java b/scm-core/src/main/java/sonia/scm/repository/api/HookContext.java index 8e68c9af28..a7c7e8354e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/HookContext.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/HookContext.java @@ -45,7 +45,7 @@ import sonia.scm.repository.spi.HookContextProvider; * The context for all repository hooks. With the {@link HookContext} class it * is able to send messages back to the client, retrieve {@link Changeset}s * which are added during this push/commit and gives informations about changed - * branches. + * branches and tags. * * @author Sebastian Sdorra * @since 1.33 @@ -100,6 +100,28 @@ public final class HookContext return provider.getBranchProvider(); } + + /** + * Returns a {@link HookTagProvider} which is able to return informations + * about changed tags during the current hook. + * + * @return {@link HookTagProvider} + * + * @throws HookFeatureIsNotSupportedException if the feature is not supported + * by the underlying provider + * + * @since 1.50 + */ + public HookTagProvider getTagProvider() + { + if (logger.isDebugEnabled()) + { + logger.debug("create tag provider for repository {}", + repository.getName()); + } + + return provider.getTagProvider(); + } /** * Returns a {@link HookChangesetBuilder} which is able to return all diff --git a/scm-core/src/main/java/sonia/scm/repository/api/HookFeature.java b/scm-core/src/main/java/sonia/scm/repository/api/HookFeature.java index 9594bbc168..15982022de 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/HookFeature.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/HookFeature.java @@ -55,5 +55,12 @@ public enum HookFeature * * @since 1.45 */ - BRANCH_PROVIDER; + BRANCH_PROVIDER, + + /** + * Hook tag provider + * + * @since 1.50 + */ + TAG_PROVIDER; } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/HookTagProvider.java b/scm-core/src/main/java/sonia/scm/repository/api/HookTagProvider.java new file mode 100644 index 0000000000..695cba9d2d --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/api/HookTagProvider.java @@ -0,0 +1,59 @@ +/*** + * Copyright (c) 2015, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * https://bitbucket.org/sdorra/scm-manager + * + */ + +package sonia.scm.repository.api; + +import java.util.List; +import sonia.scm.repository.Tag; + +/** + * The HookTagProvider returns informations about tags during the + * current hook. + * + * @since 1.50 + * @author Sebastian Sdorra + */ +public interface HookTagProvider { + + /** + * Return all tags which are delivered during the current hook. + * + * @return all tags of current hook + */ + public List getCreatedTags(); + + /** + * Return all tags which are deleted during the current hook. + * + * @return all deleted tags of current hook + */ + public List getDeletedTags(); +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HookContextProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/HookContextProvider.java index 0f1d039006..2419cd45ac 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HookContextProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HookContextProvider.java @@ -38,12 +38,15 @@ import sonia.scm.repository.api.HookException; import sonia.scm.repository.api.HookFeature; import sonia.scm.repository.api.HookFeatureIsNotSupportedException; import sonia.scm.repository.api.HookMessageProvider; +import sonia.scm.repository.api.HookContext; +import sonia.scm.repository.api.HookTagProvider; //~--- JDK imports ------------------------------------------------------------ import java.util.Set; /** + * Repository type specific provider for {@link HookContext}. * * @author Sebastian Sdorra * @since 1.33 @@ -52,10 +55,10 @@ public abstract class HookContextProvider { /** - * Method description - * - * - * @return + * Return the provider specific {@link HookMessageProvider} or throws a {@link HookFeatureIsNotSupportedException}. + * The method will throw a {@link HookException} if the client is already disconnected. + * + * @return provider specific {@link HookMessageProvider} */ public final HookMessageProvider getMessageProvider() { @@ -71,7 +74,7 @@ public abstract class HookContextProvider //~--- methods -------------------------------------------------------------- /** - * Method description + * Mark client connection as disconnected. * */ final void handleClientDisconnect() @@ -82,43 +85,52 @@ public abstract class HookContextProvider //~--- get methods ---------------------------------------------------------- /** - * Method description + * Returns a set of supported hook features of the client. * - * - * @return + * @return supported features */ public abstract Set getSupportedFeatures(); /** - * Method description - * - * - * @return + * Return the provider specific {@link HookBranchProvider} or throws a {@link HookFeatureIsNotSupportedException}. + * + * @return provider specific {@link HookBranchProvider} + * + * @since 1.45 */ public HookBranchProvider getBranchProvider() { throw new HookFeatureIsNotSupportedException(HookFeature.BRANCH_PROVIDER); } + + /** + * Return the provider specific {@link HookTagProvider} or throws a {@link HookFeatureIsNotSupportedException}. + * + * @return provider specific {@link HookTagProvider} + * + * @since 1.50 + */ + public HookTagProvider getTagProvider() + { + throw new HookFeatureIsNotSupportedException(HookFeature.TAG_PROVIDER); + } /** - * Method description - * - * - * @return + * Return the provider specific {@link HookChangesetProvider} or throws a {@link HookFeatureIsNotSupportedException}. + * + * @return provider specific {@link HookChangesetProvider} */ public HookChangesetProvider getChangesetProvider() { - throw new HookFeatureIsNotSupportedException( - HookFeature.CHANGESET_PROVIDER); + throw new HookFeatureIsNotSupportedException(HookFeature.CHANGESET_PROVIDER); } //~--- methods -------------------------------------------------------------- /** - * Method description - * - * - * @return + * Creates a new provider specific {@link HookMessageProvider} or throws a {@link HookFeatureIsNotSupportedException}. + * + * @return provider specific {@link HookChangesetProvider} */ protected HookMessageProvider createMessageProvider() { @@ -127,6 +139,5 @@ public abstract class HookContextProvider //~--- fields --------------------------------------------------------------- - /** Field description */ private boolean clientDisconnected = false; } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/HookContextTest.java b/scm-core/src/test/java/sonia/scm/repository/api/HookContextTest.java new file mode 100644 index 0000000000..2f746ec5ad --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/repository/api/HookContextTest.java @@ -0,0 +1,141 @@ +/*** + * Copyright (c) 2015, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * https://bitbucket.org/sdorra/scm-manager + * + */ + +package sonia.scm.repository.api; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import java.util.List; +import org.junit.Test; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import sonia.scm.repository.Changeset; +import sonia.scm.repository.Person; +import sonia.scm.repository.PreProcessorUtil; +import sonia.scm.repository.Repository; +import sonia.scm.repository.spi.HookChangesetProvider; +import sonia.scm.repository.spi.HookChangesetRequest; +import sonia.scm.repository.spi.HookChangesetResponse; +import sonia.scm.repository.spi.HookContextProvider; + +/** + * Unit tests for {@link HookContext}. + * + * @author Sebastian Sdorra + */ +@RunWith(MockitoJUnitRunner.class) +public class HookContextTest { + + @Mock + private HookContextProvider provider; + + @Mock + private Repository repository; + + @Mock + private PreProcessorUtil preProcessorUtil; + + @Mock + private HookChangesetProvider changesetProvider; + + @InjectMocks + private HookContext context; + + /** + * Set up mocks for upcoming test. + */ + @Before + public void setUpMocks(){ + when(repository.getName()).thenReturn("test"); + when(provider.getChangesetProvider()).thenReturn(changesetProvider); + when(provider.getSupportedFeatures()).thenReturn(Sets.newHashSet(HookFeature.CHANGESET_PROVIDER)); + + List changesets = Lists.newArrayList(new Changeset("1", Long.MIN_VALUE, new Person("Trillian"))); + HookChangesetResponse response = new HookChangesetResponse(changesets); + when(changesetProvider.handleRequest(any(HookChangesetRequest.class))).thenReturn(response); + } + + /** + * Tests {@link HookContext#getBranchProvider()}. + */ + @Test + public void testGetBranchProvider() { + context.getBranchProvider(); + + verify(provider).getBranchProvider(); + } + + /** + * Tests {@link HookContext#getTagProvider()}. + */ + @Test + public void testGetTagProvider() { + context.getTagProvider(); + + verify(provider).getTagProvider(); + } + + /** + * Tests {@link HookContext#getMessageProvider()}. + */ + @Test + public void testGetMessageProvider() { + context.getMessageProvider(); + + verify(provider).getMessageProvider(); + } + + /** + * Tests {@link HookContext#getChangesetProvider()}. + */ + @Test + public void testGetChangesetProvider() { + HookChangesetBuilder builder = context.getChangesetProvider(); + List changesets = builder.getChangesetList(); + assertNotNull(changesets); + assertEquals("1", changesets.get(0).getId()); + } + + /** + * Tests {@link HookContext#isFeatureSupported(sonia.scm.repository.api.HookFeature)}. + */ + @Test + public void testIsFeatureSupported(){ + assertTrue(context.isFeatureSupported(HookFeature.CHANGESET_PROVIDER)); + assertFalse(context.isFeatureSupported(HookFeature.BRANCH_PROVIDER)); + } + +} \ No newline at end of file diff --git a/scm-core/src/test/java/sonia/scm/repository/spi/HookContextProviderTest.java b/scm-core/src/test/java/sonia/scm/repository/spi/HookContextProviderTest.java new file mode 100644 index 0000000000..c6abae594e --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/repository/spi/HookContextProviderTest.java @@ -0,0 +1,136 @@ +/*** + * Copyright (c) 2015, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * https://bitbucket.org/sdorra/scm-manager + * + */ + +package sonia.scm.repository.spi; + +import java.util.Collections; +import java.util.Set; +import org.junit.Test; +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; +import org.junit.Rule; +import org.junit.rules.ExpectedException; +import sonia.scm.repository.api.HookException; +import sonia.scm.repository.api.HookFeature; +import sonia.scm.repository.api.HookFeatureIsNotSupportedException; + +/** + * Unit tests for {@link HookContextProvider}. + * + * @author Sebastian Sdorra + */ +public class HookContextProviderTest { + + /** + * Expected exception rule. + */ + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private final HookContextProvider simpleHookContextProvider = new HookContextProvider() { + + @Override + public Set getSupportedFeatures() { + return Collections.emptySet(); + } + + }; + + /** + * Tests {@link HookContextProvider#getSupportedFeatures()}. + */ + @Test + public void testGetSupportedFeatures() { + assertThat(simpleHookContextProvider.getSupportedFeatures(), empty()); + } + + /** + * Tests {@link HookContextProvider#getBranchProvider()}. + */ + @Test + public void testGetBranchProvider(){ + expectNotSupported(HookFeature.BRANCH_PROVIDER); + simpleHookContextProvider.getBranchProvider(); + } + + /** + * Tests {@link HookContextProvider#getTagProvider()}. + */ + @Test + public void testGetTagProvider(){ + expectNotSupported(HookFeature.TAG_PROVIDER); + simpleHookContextProvider.getTagProvider(); + } + + /** + * Tests {@link HookContextProvider#getChangesetProvider()}. + */ + @Test + public void testGetChangesetProvider(){ + expectNotSupported(HookFeature.CHANGESET_PROVIDER); + simpleHookContextProvider.getChangesetProvider(); + } + + /** + * Tests {@link HookContextProvider#createMessageProvider()}. + */ + @Test + public void testCreateMessageProvider(){ + expectNotSupported(HookFeature.MESSAGE_PROVIDER); + simpleHookContextProvider.createMessageProvider(); + } + + /** + * Tests {@link HookContextProvider#getMessageProvider()}. + */ + @Test + public void testGetMessageProvider(){ + expectNotSupported(HookFeature.MESSAGE_PROVIDER); + simpleHookContextProvider.getMessageProvider(); + } + + /** + * Tests {@link HookContextProvider#getMessageProvider()} with disconnected client. + */ + @Test + public void testGetMessageProviderDisconnected(){ + expectedException.expect(HookException.class); + expectedException.expectMessage(containsString("message provider")); + simpleHookContextProvider.handleClientDisconnect(); + simpleHookContextProvider.getMessageProvider(); + } + + private void expectNotSupported(HookFeature feature){ + expectedException.expect(HookFeatureIsNotSupportedException.class); + expectedException.expectMessage(containsString(feature.toString())); + } + +} \ No newline at end of file