From 4afe19285c8f7a0c11518baf0c4aa656695e5555 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 11 Jun 2012 14:24:19 +0200 Subject: [PATCH] start implementation of git log command --- .../java/sonia/scm/repository/GitUtil.java | 30 ++ .../repository/spi/AbstractGitCommand.java | 88 ++++++ .../scm/repository/spi/GitLogCommand.java | 263 ++++++++++++++++++ .../spi/GitRepositoryServiceProvider.java | 107 +++++++ .../spi/GitRepositoryServiceResolver.java | 94 +++++++ 5 files changed, 582 insertions(+) create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index bbfc5728ed..0566a48d1e 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -155,6 +155,36 @@ public class GitUtil //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @param repo + * @param branchName + * + * @return + * + * @throws IOException + */ + public static ObjectId getBranchId(org.eclipse.jgit.lib.Repository repo, + String branchName) + throws IOException + { + ObjectId branchId = null; + Ref ref = repo.getRef(branchName); + + if (ref != null) + { + branchId = ref.getObjectId(); + } + else if (logger.isWarnEnabled()) + { + logger.warn("could not find branch for {}", branchName); + } + + return branchId; + } + /** * Method description * diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java new file mode 100644 index 0000000000..f8b9a46198 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -0,0 +1,88 @@ +/** + * 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.spi; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.eclipse.jgit.lib.Repository; + +import sonia.scm.repository.GitUtil; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.File; +import java.io.IOException; + +/** + * + * @author Sebastian Sdorra + */ +public class AbstractGitCommand +{ + + /** + * Constructs ... + * + * + * @param repository + * @param repositoryDirectory + */ + protected AbstractGitCommand(sonia.scm.repository.Repository repository, + File repositoryDirectory) + { + this.repository = repository; + this.repositoryDirectory = repositoryDirectory; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + * + * @throws IOException + */ + protected Repository open() throws IOException + { + return GitUtil.open(repositoryDirectory); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + protected sonia.scm.repository.Repository repository; + + /** Field description */ + private File repositoryDirectory; +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java new file mode 100644 index 0000000000..9856eedc24 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java @@ -0,0 +1,263 @@ +/** + * 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.spi; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Strings; +import com.google.common.collect.Lists; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.NoHeadException; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.repository.Changeset; +import sonia.scm.repository.ChangesetPagingResult; +import sonia.scm.repository.GitChangesetConverter; +import sonia.scm.repository.GitUtil; +import sonia.scm.util.IOUtil; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.File; +import java.io.IOException; + +import java.util.List; + +/** + * + * @author Sebastian Sdorra + */ +public class GitLogCommand extends AbstractGitCommand implements LogCommand +{ + + /** + * the logger for GitLogCommand + */ + private static final Logger logger = + LoggerFactory.getLogger(GitLogCommand.class); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param repository + * @param repositoryDirectory + */ + GitLogCommand(sonia.scm.repository.Repository repository, + File repositoryDirectory) + { + super(repository, repositoryDirectory); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param revision + * + * @return + */ + @Override + public Changeset getChangeset(String revision) + { + if (logger.isDebugEnabled()) + { + logger.debug("fetch changeset {}", revision); + } + + Changeset changeset = null; + Repository gr = null; + GitChangesetConverter converter = null; + + try + { + gr = open(); + + if (!gr.getAllRefs().isEmpty()) + { + RevWalk revWalk = new RevWalk(gr); + ObjectId id = GitUtil.getRevisionId(gr, revision); + RevCommit commit = revWalk.parseCommit(id); + + if (commit != null) + { + converter = new GitChangesetConverter(gr, revWalk, GitUtil.ID_LENGTH); + changeset = converter.createChangeset(commit); + } + else if (logger.isWarnEnabled()) + { + logger.warn("could not find revision {}", revision); + } + } + } + catch (IOException ex) + { + logger.error("could not open repository", ex); + } + finally + { + IOUtil.close(converter); + GitUtil.close(gr); + } + + return changeset; + } + + /** + * Method description + * + * + * @param request + * + * @return + */ + @Override + public ChangesetPagingResult getChangesets(LogCommandRequest request) + { + if (logger.isDebugEnabled()) + { + logger.debug("fetch changesets for request: {}", request); + } + + ChangesetPagingResult changesets = null; + org.eclipse.jgit.lib.Repository gr = null; + GitChangesetConverter converter = null; + + try + { + gr = open(); + + if (!gr.getAllRefs().isEmpty()) + { + org.eclipse.jgit.api.LogCommand cmd = new Git(gr).log(); + + converter = new GitChangesetConverter(gr, GitUtil.ID_LENGTH); + + if (!Strings.isNullOrEmpty(request.getPath())) + { + cmd.addPath(request.getPath()); + } + + if (!Strings.isNullOrEmpty(request.getStartChangeset())) + { + ObjectId start = GitUtil.getRevisionId(gr, + request.getStartChangeset()); + + if (!Strings.isNullOrEmpty(request.getEndChangeset())) + { + ObjectId end = GitUtil.getRevisionId(gr, + request.getStartChangeset()); + + cmd.addRange(start, end); + } + else + { + cmd.add(start); + } + } + else + { + cmd.add(GitUtil.getRepositoryHead(gr)); + } + + if (!Strings.isNullOrEmpty(request.getBranch())) + { + ObjectId branchId = GitUtil.getBranchId(gr, request.getBranch()); + + if (branchId != null) + { + cmd.add(branchId); + } + } + + int counter = 0; + int start = request.getPagingStart(); + + if (start < 0) + { + if (logger.isErrorEnabled()) + { + logger.error("start parameter is negative, reset to 0"); + } + + start = 0; + } + + List changesetList = Lists.newArrayList(); + int limit = request.getPagingLimit(); + + for (RevCommit commit : cmd.call()) + { + if ((counter >= start) && ((limit < 0) || (counter < start + limit))) + { + changesetList.add(converter.createChangeset(commit)); + } + + counter++; + } + + changesets = new ChangesetPagingResult(start, changesetList); + } + else if (logger.isWarnEnabled()) + { + logger.warn("the repository {} seems to be empty", + repository.getName()); + } + } + catch (NoHeadException ex) + { + logger.error("could not read changesets", ex); + } + catch (IOException ex) + { + logger.error("could not open repository", ex); + } + finally + { + IOUtil.close(converter); + GitUtil.close(gr); + } + + return changesets; + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java new file mode 100644 index 0000000000..564c69df60 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -0,0 +1,107 @@ +/** + * 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.spi; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.collect.ImmutableSet; + +import sonia.scm.repository.GitRepositoryHandler; +import sonia.scm.repository.Repository; +import sonia.scm.repository.api.Command; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.File; + +import java.util.Set; + +/** + * + * @author Sebastian Sdorra + */ +public class GitRepositoryServiceProvider extends RepositoryServiceProvider +{ + + /** Field description */ + private static final Set COMMANDS = ImmutableSet.of(Command.LOG); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param handler + * @param repository + */ + public GitRepositoryServiceProvider(GitRepositoryHandler handler, + Repository repository) + { + this.repository = repository; + this.repositoryDirectory = handler.getDirectory(repository); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public LogCommand getLogCommand() + { + return new GitLogCommand(repository, repositoryDirectory); + } + + /** + * Method description + * + * + * @return + */ + @Override + public Set getSupportedCommands() + { + return COMMANDS; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Repository repository; + + /** Field description */ + private File repositoryDirectory; +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java new file mode 100644 index 0000000000..b6f922e07e --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java @@ -0,0 +1,94 @@ +/** + * 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.spi; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; + +import sonia.scm.plugin.ext.Extension; +import sonia.scm.repository.GitRepositoryHandler; +import sonia.scm.repository.Repository; + +/** + * + * @author Sebastian Sdorra + */ +@Extension +public class GitRepositoryServiceResolver implements RepositoryServiceResolver +{ + + /** Field description */ + public static final String TYPE = "git"; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param handler + */ + @Inject + public GitRepositoryServiceResolver(GitRepositoryHandler handler) + { + this.handler = handler; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param repository + * + * @return + */ + @Override + public GitRepositoryServiceProvider reslove(Repository repository) + { + GitRepositoryServiceProvider provider = null; + + if (TYPE.equalsIgnoreCase(repository.getType())) + { + provider = new GitRepositoryServiceProvider(handler, repository); + } + + return provider; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private GitRepositoryHandler handler; +}