From bce393fdfc06a7d46c6f00b1c5c44f1946d8b742 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 19 Jul 2011 16:02:53 +0200 Subject: [PATCH] use lazy loading for changesets in git hook --- .../repository/GitRepositoryHookEvent.java | 177 ++++++++++++++++++ .../sonia/scm/web/GitPostReceiveHook.java | 113 ++--------- 2 files changed, 189 insertions(+), 101 deletions(-) create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryHookEvent.java diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryHookEvent.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryHookEvent.java new file mode 100644 index 0000000000..59201f117e --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryHookEvent.java @@ -0,0 +1,177 @@ +/** + * Copyright (c) 2010, 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; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevSort; +import org.eclipse.jgit.revwalk.RevWalk; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.util.IOUtil; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.File; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * + * @author Sebastian Sdorra + */ +public class GitRepositoryHookEvent extends AbstractRepositoryHookEvent +{ + + /** the logger for GitRepositoryHookEvent */ + private static final Logger logger = + LoggerFactory.getLogger(GitRepositoryHookEvent.class); + + //~--- get methods ---------------------------------------------------------- + + public GitRepositoryHookEvent(File directory, + ObjectId newId, ObjectId oldId) + { + this.directory = directory; + this.newId = newId; + this.oldId = oldId; + } + + + + /** + * Method description + * + * + * @return + */ + @Override + public Collection getChangesets() + { + if (changesets == null) + { + changesets = fetchChangesets(); + } + + return changesets; + } + + /** + * Method description + * + * + * @return + */ + @Override + public RepositoryHookType getType() + { + return RepositoryHookType.POST_RECEIVE; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + private List fetchChangesets() + { + List result = new ArrayList(); + + if (newId != null) + { + GitChangesetConverter converter = null; + RevWalk walk = null; + org.eclipse.jgit.lib.Repository repository = null; + + try + { + repository = GitUtil.open(directory); + converter = new GitChangesetConverter(repository, GitUtil.ID_LENGTH); + walk = new RevWalk(repository); + walk.reset(); + walk.sort(RevSort.NONE); + walk.markStart(walk.parseCommit(newId)); + + if (oldId != null) + { + walk.markUninteresting(walk.parseCommit(oldId)); + } + + RevCommit commit = walk.next(); + + while (commit != null) + { + result.add(converter.createChangeset(commit)); + commit = walk.next(); + } + } + catch (IOException ex) + { + logger.error("could not fetch changesets", ex); + } + finally + { + IOUtil.close(converter); + GitUtil.release(walk); + GitUtil.close(repository); + } + } + + return result; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private List changesets; + + /** Field description */ + private File directory; + + /** Field description */ + private ObjectId newId; + + /** Field description */ + private ObjectId oldId; +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPostReceiveHook.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPostReceiveHook.java index 23b0321fbd..2579c5f361 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPostReceiveHook.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPostReceiveHook.java @@ -35,9 +35,7 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevSort; -import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.transport.PostReceiveHook; import org.eclipse.jgit.transport.ReceiveCommand; import org.eclipse.jgit.transport.ReceivePack; @@ -45,23 +43,16 @@ import org.eclipse.jgit.transport.ReceivePack; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sonia.scm.repository.AbstractRepositoryHookEvent; -import sonia.scm.repository.Changeset; -import sonia.scm.repository.GitChangesetConverter; import sonia.scm.repository.GitRepositoryHandler; -import sonia.scm.repository.GitUtil; -import sonia.scm.repository.RepositoryHookType; +import sonia.scm.repository.GitRepositoryHookEvent; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryNotFoundException; -import sonia.scm.util.IOUtil; //~--- JDK imports ------------------------------------------------------------ -import java.io.IOException; +import java.io.File; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; /** * @@ -100,58 +91,34 @@ public class GitPostReceiveHook implements PostReceiveHook public void onPostReceive(ReceivePack rpack, Collection receiveCommands) { - GitChangesetConverter converter = null; - RevWalk walk = rpack.getRevWalk(); - try { - List changesets = new ArrayList(); - - converter = new GitChangesetConverter(rpack.getRepository(), - GitUtil.ID_LENGTH); - for (ReceiveCommand rc : receiveCommands) { if (rc.getResult() == ReceiveCommand.Result.OK) { - walk.reset(); - walk.sort(RevSort.NONE); - walk.markStart(walk.parseCommit(rc.getNewId())); + ObjectId newId = rc.getNewId(); + ObjectId oldId = null; if (isUpdateCommand(rc)) { - walk.markUninteresting(walk.parseCommit(rc.getOldId())); + oldId = rc.getOldId(); } - RevCommit commit = walk.next(); + File directory = rpack.getRepository().getDirectory(); + String repositoryName = directory.getName(); + GitRepositoryHookEvent e = new GitRepositoryHookEvent(directory, + newId, oldId); - while (commit != null) - { - changesets.add(converter.createChangeset(commit)); - commit = walk.next(); - } + repositoryManager.fireHookEvent(GitRepositoryHandler.TYPE_NAME, + repositoryName, e); } } - - String repositoryName = rpack.getRepository().getDirectory().getName(); - - repositoryManager.fireHookEvent(GitRepositoryHandler.TYPE_NAME, - repositoryName, - new GitRepositoryHook(changesets)); } catch (RepositoryNotFoundException ex) { logger.error("repository could not be found", ex); } - catch (IOException ex) - { - logger.error("could not parse PostReceiveHook", ex); - } - finally - { - IOUtil.close(converter); - GitUtil.release(walk); - } } //~--- get methods ---------------------------------------------------------- @@ -170,62 +137,6 @@ public class GitPostReceiveHook implements PostReceiveHook || (rc.getType() == ReceiveCommand.Type.UPDATE_NONFASTFORWARD); } - //~--- inner classes -------------------------------------------------------- - - /** - * Class description - * - * - * @version Enter version here..., 11/07/19 - * @author Enter your name here... - */ - private static class GitRepositoryHook extends AbstractRepositoryHookEvent - { - - /** - * Constructs ... - * - * - * @param changesets - */ - public GitRepositoryHook(Collection changesets) - { - this.changesets = changesets; - } - - //~--- get methods -------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ - @Override - public Collection getChangesets() - { - return changesets; - } - - /** - * Method description - * - * - * @return - */ - @Override - public RepositoryHookType getType() - { - return RepositoryHookType.POST_RECEIVE; - } - - //~--- fields ------------------------------------------------------------- - - /** Field description */ - private Collection changesets; - } - - //~--- fields --------------------------------------------------------------- /** Field description */