From 436b27e8fc6e7f4dae865c92736dba83a7f29cfa Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 24 Jan 2015 11:08:16 +0100 Subject: [PATCH] introducing HookBranchProvider to get informations about changed branches during a hook, see issue #668 --- .../repository/api/HookBranchProvider.java | 61 ++++++ .../sonia/scm/repository/api/HookContext.java | 45 ++++- .../sonia/scm/repository/api/HookFeature.java | 21 +- .../repository/spi/HookContextProvider.java | 12 ++ .../repository/api/GitHookBranchProvider.java | 119 ++++++++++++ .../spi/GitHookContextProvider.java | 25 ++- .../repository/api/HgHookBranchProvider.java | 182 ++++++++++++++++++ .../repository/spi/HgHookContextProvider.java | 27 ++- .../spi/javahg/AbstractChangesetCommand.java | 4 +- 9 files changed, 480 insertions(+), 16 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/api/HookBranchProvider.java create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/api/GitHookBranchProvider.java create mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/api/HgHookBranchProvider.java diff --git a/scm-core/src/main/java/sonia/scm/repository/api/HookBranchProvider.java b/scm-core/src/main/java/sonia/scm/repository/api/HookBranchProvider.java new file mode 100644 index 0000000000..3ad52b995c --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/api/HookBranchProvider.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2014, 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. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository.api; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.List; + +/** + * The HookBranchProvider returns informations about branch changes during the + * current hook. + * + * @author Sebastian Sdorra + * @since 1.45 + */ +public interface HookBranchProvider +{ + + /** + * Returns the list of created or modified branch names. + * + * @return list of created or modified branches + */ + public List getCreatedOrModified(); + + /** + * Returns the list deleted or closed branch names. + * + * @return list of deleted or closed branches + */ + public List getDeletedOrClosed(); +} 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 b7e3e9c5e6..8e68c9af28 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 @@ -43,8 +43,9 @@ 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 and retrieve {@link Changeset}s - * which are added during this push/commit. + * 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. * * @author Sebastian Sdorra * @since 1.33 @@ -78,12 +79,37 @@ public final class HookContext //~--- get methods ---------------------------------------------------------- + /** + * Returns a {@link HookBranchProvider} which is able to return informations + * about changed branches during the current hook. + * + * @return {@link HookBranchProvider} + * + * @throws HookFeatureIsNotSupportedException if the feature is not supported + * by the underlying provider + * + * @since 1.45 + */ + public HookBranchProvider getBranchProvider() + { + if (logger.isDebugEnabled()) + { + logger.debug("create branch provider for repository {}", + repository.getName()); + } + + return provider.getBranchProvider(); + } + /** * Returns a {@link HookChangesetBuilder} which is able to return all * {@link Changeset}'s during this push/commit. * * * @return {@link HookChangesetBuilder} + * + * @throws HookFeatureIsNotSupportedException if the feature is not supported + * by the underlying provider */ public HookChangesetBuilder getChangesetProvider() { @@ -111,6 +137,9 @@ public final class HookContext * * @return {@link HookMessageProvider} which is able to send message back to * the scm client + * + * @throws HookFeatureIsNotSupportedException if the feature is not supported + * by the underlying provider */ public HookMessageProvider getMessageProvider() { @@ -138,12 +167,12 @@ public final class HookContext //~--- fields --------------------------------------------------------------- - /** Field description */ - private PreProcessorUtil preProcessorUtil; + /** pre processor util */ + private final PreProcessorUtil preProcessorUtil; - /** Field description */ - private HookContextProvider provider; + /** hook context provider */ + private final HookContextProvider provider; - /** Field description */ - private Repository repository; + /** repository */ + private final Repository repository; } 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 082f315a35..9594bbc168 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 @@ -37,4 +37,23 @@ package sonia.scm.repository.api; * @author Sebastian Sdorra * @since 1.33 */ -public enum HookFeature { MESSAGE_PROVIDER, CHANGESET_PROVIDER; } +public enum HookFeature +{ + + /** + * Hook message provider + */ + MESSAGE_PROVIDER, + + /** + * Hook changeset provider + */ + CHANGESET_PROVIDER, + + /** + * Hook branch provider + * + * @since 1.45 + */ + BRANCH_PROVIDER; +} 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 0bc91679b7..0f1d039006 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 @@ -33,6 +33,7 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- +import sonia.scm.repository.api.HookBranchProvider; import sonia.scm.repository.api.HookException; import sonia.scm.repository.api.HookFeature; import sonia.scm.repository.api.HookFeatureIsNotSupportedException; @@ -88,6 +89,17 @@ public abstract class HookContextProvider */ public abstract Set getSupportedFeatures(); + /** + * Method description + * + * + * @return + */ + public HookBranchProvider getBranchProvider() + { + throw new HookFeatureIsNotSupportedException(HookFeature.BRANCH_PROVIDER); + } + /** * Method description * diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/api/GitHookBranchProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/api/GitHookBranchProvider.java new file mode 100644 index 0000000000..ecc373e2b8 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/api/GitHookBranchProvider.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2014, 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. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository.api; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; + +import org.eclipse.jgit.transport.ReceiveCommand; +import org.eclipse.jgit.transport.ReceiveCommand.Type; + +import sonia.scm.repository.GitUtil; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.List; + +/** + * + * @author Sebastian Sdorra + */ +public class GitHookBranchProvider implements HookBranchProvider +{ + + /** + * Constructs ... + * + * + * @param commands + */ + public GitHookBranchProvider(List commands) + { + Builder createdOrModifiedBuilder = ImmutableList.builder(); + Builder deletedOrClosedBuilder = ImmutableList.builder(); + + for (ReceiveCommand command : commands) + { + Type type = command.getType(); + String branch = GitUtil.getBranch(command.getRefName()); + + if ((type == Type.CREATE) || (type == Type.UPDATE) + || (type == Type.UPDATE_NONFASTFORWARD)) + { + createdOrModifiedBuilder.add(branch); + } + else if (command.getType() == Type.DELETE) + { + deletedOrClosedBuilder.add(branch); + } + } + + createdOrModified = createdOrModifiedBuilder.build(); + deletedOrClosed = deletedOrClosedBuilder.build(); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public List getCreatedOrModified() + { + return createdOrModified; + } + + /** + * Method description + * + * + * @return + */ + @Override + public List getDeletedOrClosed() + { + return deletedOrClosed; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private final List createdOrModified; + + /** Field description */ + private final List deletedOrClosed; +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitHookContextProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitHookContextProvider.java index 824247e81f..62b88db1d3 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitHookContextProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitHookContextProvider.java @@ -36,7 +36,9 @@ package sonia.scm.repository.spi; import org.eclipse.jgit.transport.ReceiveCommand; import org.eclipse.jgit.transport.ReceivePack; +import sonia.scm.repository.api.GitHookBranchProvider; import sonia.scm.repository.api.GitHookMessageProvider; +import sonia.scm.repository.api.HookBranchProvider; import sonia.scm.repository.api.HookFeature; import sonia.scm.repository.api.HookMessageProvider; @@ -55,7 +57,8 @@ public class GitHookContextProvider extends HookContextProvider /** Field description */ private static final Set SUPPORTED_FEATURES = - EnumSet.of(HookFeature.MESSAGE_PROVIDER, HookFeature.CHANGESET_PROVIDER); + EnumSet.of(HookFeature.MESSAGE_PROVIDER, HookFeature.CHANGESET_PROVIDER, + HookFeature.BRANCH_PROVIDER); //~--- constructors --------------------------------------------------------- @@ -70,6 +73,7 @@ public class GitHookContextProvider extends HookContextProvider List receiveCommands) { this.receivePack = receivePack; + this.receiveCommands = receiveCommands; this.changesetProvider = new GitHookChangesetProvider(receivePack, receiveCommands); } @@ -90,6 +94,18 @@ public class GitHookContextProvider extends HookContextProvider //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + @Override + public HookBranchProvider getBranchProvider() + { + return new GitHookBranchProvider(receiveCommands); + } + /** * Method description * @@ -117,8 +133,11 @@ public class GitHookContextProvider extends HookContextProvider //~--- fields --------------------------------------------------------------- /** Field description */ - private GitHookChangesetProvider changesetProvider; + private final GitHookChangesetProvider changesetProvider; /** Field description */ - private ReceivePack receivePack; + private final List receiveCommands; + + /** Field description */ + private final ReceivePack receivePack; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/api/HgHookBranchProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/api/HgHookBranchProvider.java new file mode 100644 index 0000000000..05f05202e7 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/api/HgHookBranchProvider.java @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2014, 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. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository.api; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; + +import sonia.scm.repository.Changeset; +import sonia.scm.repository.spi.HgHookChangesetProvider; +import sonia.scm.repository.spi.HookChangesetRequest; +import sonia.scm.repository.spi.javahg.AbstractChangesetCommand; +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.List; + +/** + * + * @author Sebastian Sdorra + */ +public class HgHookBranchProvider implements HookBranchProvider +{ + + /** Field description */ + private static final HookChangesetRequest REQUEST = + new HookChangesetRequest(); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param changesetProvider + */ + public HgHookBranchProvider(HgHookChangesetProvider changesetProvider) + { + this.changesetProvider = changesetProvider; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public List getCreatedOrModified() + { + if (createdOrModified == null) + { + collect(); + } + + return createdOrModified; + } + + /** + * Method description + * + * + * @return + */ + @Override + public List getDeletedOrClosed() + { + if (deletedOrClosed == null) + { + collect(); + } + + return deletedOrClosed; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param builder + * @param c + * + * @return + */ + private List appendBranches(Builder builder, Changeset c) + { + List branches = c.getBranches(); + + if (Util.isEmpty(branches)) + { + builder.add(AbstractChangesetCommand.BRANCH_DEFAULT); + } + else + { + builder.addAll(branches); + } + + return branches; + } + + /** + * Method description + * + * + * @return + */ + private Iterable changesets() + { + return changesetProvider.handleRequest(REQUEST).getChangesets(); + } + + /** + * Method description + * + */ + private void collect() + { + Builder createdOrModifiedBuilder = ImmutableList.builder(); + Builder deletedOrClosedBuilder = ImmutableList.builder(); + + for (Changeset c : changesets()) + { + if (c.getProperty(AbstractChangesetCommand.PROPERTY_CLOSE) != null) + { + appendBranches(deletedOrClosedBuilder, c); + } + else + { + appendBranches(createdOrModifiedBuilder, c); + } + } + + createdOrModified = createdOrModifiedBuilder.build(); + deletedOrClosed = deletedOrClosedBuilder.build(); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private final HgHookChangesetProvider changesetProvider; + + /** Field description */ + private List createdOrModified; + + /** Field description */ + private List deletedOrClosed; +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookContextProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookContextProvider.java index 40d1ab5560..4087d08751 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookContextProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookContextProvider.java @@ -36,7 +36,9 @@ package sonia.scm.repository.spi; import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.RepositoryHookType; +import sonia.scm.repository.api.HgHookBranchProvider; import sonia.scm.repository.api.HgHookMessageProvider; +import sonia.scm.repository.api.HookBranchProvider; import sonia.scm.repository.api.HookFeature; import sonia.scm.repository.api.HookMessageProvider; @@ -54,7 +56,8 @@ public class HgHookContextProvider extends HookContextProvider /** Field description */ private static final Set SUPPORTED_FEATURES = - EnumSet.of(HookFeature.CHANGESET_PROVIDER, HookFeature.MESSAGE_PROVIDER); + EnumSet.of(HookFeature.CHANGESET_PROVIDER, HookFeature.MESSAGE_PROVIDER, + HookFeature.BRANCH_PROVIDER); //~--- constructors --------------------------------------------------------- @@ -78,6 +81,23 @@ public class HgHookContextProvider extends HookContextProvider //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + @Override + public HookBranchProvider getBranchProvider() + { + if (hookBranchProvider == null) + { + hookBranchProvider = new HgHookBranchProvider(hookChangesetProvider); + } + + return hookBranchProvider; + } + /** * Method description * @@ -134,9 +154,12 @@ public class HgHookContextProvider extends HookContextProvider //~--- fields --------------------------------------------------------------- + /** Field description */ + private final HgHookChangesetProvider hookChangesetProvider; + /** Field description */ private HgHookMessageProvider hgMessageProvider; /** Field description */ - private HgHookChangesetProvider hookChangesetProvider; + private HgHookBranchProvider hookBranchProvider; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/javahg/AbstractChangesetCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/javahg/AbstractChangesetCommand.java index b7aa64b801..827f86ded1 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/javahg/AbstractChangesetCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/javahg/AbstractChangesetCommand.java @@ -64,7 +64,7 @@ public abstract class AbstractChangesetCommand extends AbstractCommand { /** Field description */ - private static final String BRANCH_DEFAULT = "default"; + public static final String BRANCH_DEFAULT = "default"; /** * Character sequence that indicate the begin and end of the @@ -89,7 +89,7 @@ public abstract class AbstractChangesetCommand extends AbstractCommand "0000000000000000000000000000000000000000"; /** changeset property for closed branch */ - private static final String PROPERTY_CLOSE = "hg.close"; + public static final String PROPERTY_CLOSE = "hg.close"; /** changeset property for parent1 revision */ private static final String PROPERTY_PARENT1_REVISION = "hg.p1.rev";