mirror of
				https://github.com/scm-manager/scm-manager.git
				synced 2025-11-03 20:15:52 +01:00 
			
		
		
		
	implement git post receive hooks
This commit is contained in:
		@@ -0,0 +1,244 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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.diff.DiffEntry;
 | 
			
		||||
import org.eclipse.jgit.lib.ObjectId;
 | 
			
		||||
import org.eclipse.jgit.lib.PersonIdent;
 | 
			
		||||
import org.eclipse.jgit.lib.Ref;
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevCommit;
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevTree;
 | 
			
		||||
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
 | 
			
		||||
import org.eclipse.jgit.treewalk.TreeWalk;
 | 
			
		||||
 | 
			
		||||
//~--- JDK imports ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import java.io.Closeable;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sebastian Sdorra
 | 
			
		||||
 */
 | 
			
		||||
public class GitChangesetConverter implements Closeable
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs ...
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param repository
 | 
			
		||||
   * @param idLength
 | 
			
		||||
   */
 | 
			
		||||
  public GitChangesetConverter(org.eclipse.jgit.lib.Repository repository,
 | 
			
		||||
                               int idLength)
 | 
			
		||||
  {
 | 
			
		||||
    this.idLength = idLength;
 | 
			
		||||
    createTagMap(repository);
 | 
			
		||||
    treeWalk = new TreeWalk(repository);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- methods --------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  public void close()
 | 
			
		||||
  {
 | 
			
		||||
    GitUtil.release(treeWalk);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param commit
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *
 | 
			
		||||
   * @throws IOException
 | 
			
		||||
   */
 | 
			
		||||
  public Changeset createChangeset(RevCommit commit) throws IOException
 | 
			
		||||
  {
 | 
			
		||||
    String id = commit.getId().abbreviate(idLength).name();
 | 
			
		||||
    long date = GitUtil.getCommitTime(commit);
 | 
			
		||||
    PersonIdent authorIndent = commit.getCommitterIdent();
 | 
			
		||||
    Person author = new Person(authorIndent.getName(),
 | 
			
		||||
                               authorIndent.getEmailAddress());
 | 
			
		||||
    String message = commit.getShortMessage();
 | 
			
		||||
    Changeset changeset = new Changeset(id, date, author, message);
 | 
			
		||||
    Modifications modifications = createModifications(treeWalk, commit);
 | 
			
		||||
 | 
			
		||||
    if (modifications != null)
 | 
			
		||||
    {
 | 
			
		||||
      changeset.setModifications(modifications);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    String tag = tags.get(commit.getId());
 | 
			
		||||
 | 
			
		||||
    if (tag != null)
 | 
			
		||||
    {
 | 
			
		||||
      changeset.getTags().add(tag);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return changeset;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * TODO: copy and rename
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param modifications
 | 
			
		||||
   * @param entry
 | 
			
		||||
   */
 | 
			
		||||
  private void appendModification(Modifications modifications, DiffEntry entry)
 | 
			
		||||
  {
 | 
			
		||||
    switch (entry.getChangeType())
 | 
			
		||||
    {
 | 
			
		||||
      case ADD :
 | 
			
		||||
        modifications.getAdded().add(entry.getNewPath());
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case MODIFY :
 | 
			
		||||
        modifications.getModified().add(entry.getNewPath());
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case DELETE :
 | 
			
		||||
        modifications.getRemoved().add(entry.getOldPath());
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param treeWalk
 | 
			
		||||
   * @param commit
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *
 | 
			
		||||
   * @throws IOException
 | 
			
		||||
   */
 | 
			
		||||
  private Modifications createModifications(TreeWalk treeWalk, RevCommit commit)
 | 
			
		||||
          throws IOException
 | 
			
		||||
  {
 | 
			
		||||
    Modifications modifications = null;
 | 
			
		||||
 | 
			
		||||
    treeWalk.reset();
 | 
			
		||||
    treeWalk.setRecursive(true);
 | 
			
		||||
 | 
			
		||||
    if (commit.getParentCount() > 0)
 | 
			
		||||
    {
 | 
			
		||||
      RevTree tree = commit.getParent(0).getTree();
 | 
			
		||||
 | 
			
		||||
      if (tree != null)
 | 
			
		||||
      {
 | 
			
		||||
        treeWalk.addTree(tree);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        treeWalk.addTree(new EmptyTreeIterator());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      treeWalk.addTree(new EmptyTreeIterator());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    treeWalk.addTree(commit.getTree());
 | 
			
		||||
 | 
			
		||||
    List<DiffEntry> entries = DiffEntry.scan(treeWalk);
 | 
			
		||||
 | 
			
		||||
    for (DiffEntry e : entries)
 | 
			
		||||
    {
 | 
			
		||||
      if (!e.getOldId().equals(e.getNewId()))
 | 
			
		||||
      {
 | 
			
		||||
        if (modifications == null)
 | 
			
		||||
        {
 | 
			
		||||
          modifications = new Modifications();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        appendModification(modifications, e);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return modifications;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param repository
 | 
			
		||||
   *
 | 
			
		||||
   */
 | 
			
		||||
  private void createTagMap(org.eclipse.jgit.lib.Repository repository)
 | 
			
		||||
  {
 | 
			
		||||
    tags = new HashMap<ObjectId, String>();
 | 
			
		||||
 | 
			
		||||
    Map<String, Ref> tagMap = repository.getTags();
 | 
			
		||||
 | 
			
		||||
    if (tagMap != null)
 | 
			
		||||
    {
 | 
			
		||||
      for (Map.Entry<String, Ref> e : tagMap.entrySet())
 | 
			
		||||
      {
 | 
			
		||||
        tags.put(e.getValue().getObjectId(), e.getKey());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- fields ---------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  private int idLength;
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  private Map<ObjectId, String> tags;
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  private TreeWalk treeWalk;
 | 
			
		||||
}
 | 
			
		||||
@@ -37,26 +37,20 @@ package sonia.scm.repository;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.api.Git;
 | 
			
		||||
import org.eclipse.jgit.api.errors.NoHeadException;
 | 
			
		||||
import org.eclipse.jgit.diff.DiffEntry;
 | 
			
		||||
import org.eclipse.jgit.lib.ObjectId;
 | 
			
		||||
import org.eclipse.jgit.lib.PersonIdent;
 | 
			
		||||
import org.eclipse.jgit.lib.Ref;
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevCommit;
 | 
			
		||||
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
 | 
			
		||||
import org.eclipse.jgit.treewalk.TreeWalk;
 | 
			
		||||
 | 
			
		||||
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.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
@@ -65,9 +59,6 @@ import java.util.Map;
 | 
			
		||||
public class GitChangesetViewer implements ChangesetViewer
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  public static final int ID_LENGTH = 20;
 | 
			
		||||
 | 
			
		||||
  /** the logger for GitChangesetViewer */
 | 
			
		||||
  private static final Logger logger =
 | 
			
		||||
    LoggerFactory.getLogger(GitChangesetViewer.class);
 | 
			
		||||
@@ -104,7 +95,7 @@ public class GitChangesetViewer implements ChangesetViewer
 | 
			
		||||
    ChangesetPagingResult changesets = null;
 | 
			
		||||
    File directory = handler.getDirectory(repository);
 | 
			
		||||
    org.eclipse.jgit.lib.Repository gr = null;
 | 
			
		||||
    TreeWalk treeWalk = null;
 | 
			
		||||
    GitChangesetConverter converter = null;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
@@ -112,19 +103,16 @@ public class GitChangesetViewer implements ChangesetViewer
 | 
			
		||||
 | 
			
		||||
      if (!gr.getAllRefs().isEmpty())
 | 
			
		||||
      {
 | 
			
		||||
        converter = new GitChangesetConverter(gr, GitUtil.ID_LENGTH);
 | 
			
		||||
        Git git = new Git(gr);
 | 
			
		||||
        List<Changeset> changesetList = new ArrayList<Changeset>();
 | 
			
		||||
        int counter = 0;
 | 
			
		||||
 | 
			
		||||
        treeWalk = new TreeWalk(gr);
 | 
			
		||||
 | 
			
		||||
        Map<ObjectId, String> tags = createTagMap(gr);
 | 
			
		||||
 | 
			
		||||
        for (RevCommit commit : git.log().call())
 | 
			
		||||
        {
 | 
			
		||||
          if ((counter >= start) && (counter < start + max))
 | 
			
		||||
          {
 | 
			
		||||
            changesetList.add(createChangeset(treeWalk, tags, commit));
 | 
			
		||||
            changesetList.add(converter.createChangeset(commit));
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          counter++;
 | 
			
		||||
@@ -143,158 +131,13 @@ public class GitChangesetViewer implements ChangesetViewer
 | 
			
		||||
    }
 | 
			
		||||
    finally
 | 
			
		||||
    {
 | 
			
		||||
      GitUtil.release(treeWalk);
 | 
			
		||||
      IOUtil.close(converter);
 | 
			
		||||
      GitUtil.close(gr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return changesets;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- methods --------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * TODO: copy and rename
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param modifications
 | 
			
		||||
   * @param entry
 | 
			
		||||
   */
 | 
			
		||||
  private void appendModification(Modifications modifications, DiffEntry entry)
 | 
			
		||||
  {
 | 
			
		||||
    switch (entry.getChangeType())
 | 
			
		||||
    {
 | 
			
		||||
      case ADD :
 | 
			
		||||
        modifications.getAdded().add(entry.getNewPath());
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case MODIFY :
 | 
			
		||||
        modifications.getModified().add(entry.getNewPath());
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case DELETE :
 | 
			
		||||
        modifications.getRemoved().add(entry.getOldPath());
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param treeWalk
 | 
			
		||||
   * @param tags
 | 
			
		||||
   * @param commit
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *
 | 
			
		||||
   * @throws IOException
 | 
			
		||||
   */
 | 
			
		||||
  private Changeset createChangeset(TreeWalk treeWalk,
 | 
			
		||||
                                    Map<ObjectId, String> tags,
 | 
			
		||||
                                    RevCommit commit)
 | 
			
		||||
          throws IOException
 | 
			
		||||
  {
 | 
			
		||||
    String id = commit.getId().abbreviate(ID_LENGTH).name();
 | 
			
		||||
    long date = GitUtil.getCommitTime(commit);
 | 
			
		||||
    PersonIdent authorIndent = commit.getCommitterIdent();
 | 
			
		||||
    Person author = new Person(authorIndent.getName(),
 | 
			
		||||
                               authorIndent.getEmailAddress());
 | 
			
		||||
    String message = commit.getShortMessage();
 | 
			
		||||
    Changeset changeset = new Changeset(id, date, author, message);
 | 
			
		||||
    Modifications modifications = createModifications(treeWalk, commit);
 | 
			
		||||
 | 
			
		||||
    if (modifications != null)
 | 
			
		||||
    {
 | 
			
		||||
      changeset.setModifications(modifications);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    String tag = tags.get(commit.getId());
 | 
			
		||||
 | 
			
		||||
    if (tag != null)
 | 
			
		||||
    {
 | 
			
		||||
      changeset.getTags().add(tag);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return changeset;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param treeWalk
 | 
			
		||||
   * @param commit
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *
 | 
			
		||||
   * @throws IOException
 | 
			
		||||
   */
 | 
			
		||||
  private Modifications createModifications(TreeWalk treeWalk, RevCommit commit)
 | 
			
		||||
          throws IOException
 | 
			
		||||
  {
 | 
			
		||||
    Modifications modifications = null;
 | 
			
		||||
 | 
			
		||||
    treeWalk.reset();
 | 
			
		||||
    treeWalk.setRecursive(true);
 | 
			
		||||
 | 
			
		||||
    if (commit.getParentCount() > 0)
 | 
			
		||||
    {
 | 
			
		||||
      treeWalk.addTree(commit.getParent(0).getTree());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      treeWalk.addTree(new EmptyTreeIterator());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    treeWalk.addTree(commit.getTree());
 | 
			
		||||
 | 
			
		||||
    List<DiffEntry> entries = DiffEntry.scan(treeWalk);
 | 
			
		||||
 | 
			
		||||
    for (DiffEntry e : entries)
 | 
			
		||||
    {
 | 
			
		||||
      if (!e.getOldId().equals(e.getNewId()))
 | 
			
		||||
      {
 | 
			
		||||
        if (modifications == null)
 | 
			
		||||
        {
 | 
			
		||||
          modifications = new Modifications();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        appendModification(modifications, e);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return modifications;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param repository
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   */
 | 
			
		||||
  private Map<ObjectId,
 | 
			
		||||
              String> createTagMap(org.eclipse.jgit.lib.Repository repository)
 | 
			
		||||
  {
 | 
			
		||||
    Map<ObjectId, String> tagMap = new HashMap<ObjectId, String>();
 | 
			
		||||
    Map<String, Ref> tags = repository.getTags();
 | 
			
		||||
 | 
			
		||||
    if (tags != null)
 | 
			
		||||
    {
 | 
			
		||||
      for (Map.Entry<String, Ref> e : tags.entrySet())
 | 
			
		||||
      {
 | 
			
		||||
        tagMap.put(e.getValue().getObjectId(), e.getKey());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return tagMap;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- fields ---------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,9 @@ import org.eclipse.jgit.util.FS;
 | 
			
		||||
public class GitUtil
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /** Field description */
 | 
			
		||||
  public static final int ID_LENGTH = 20;
 | 
			
		||||
  
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,163 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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.web;
 | 
			
		||||
 | 
			
		||||
//~--- non-JDK imports --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevCommit;
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevWalk;
 | 
			
		||||
import org.eclipse.jgit.transport.PostReceiveHook;
 | 
			
		||||
import org.eclipse.jgit.transport.ReceiveCommand;
 | 
			
		||||
import org.eclipse.jgit.transport.ReceivePack;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import sonia.scm.repository.Changeset;
 | 
			
		||||
import sonia.scm.repository.GitChangesetConverter;
 | 
			
		||||
import sonia.scm.repository.GitRepositoryHandler;
 | 
			
		||||
import sonia.scm.repository.GitUtil;
 | 
			
		||||
import sonia.scm.repository.RepositoryManager;
 | 
			
		||||
import sonia.scm.repository.RepositoryNotFoundException;
 | 
			
		||||
import sonia.scm.util.IOUtil;
 | 
			
		||||
 | 
			
		||||
//~--- JDK imports ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sebastian Sdorra
 | 
			
		||||
 */
 | 
			
		||||
public class GitPostReceiveHook implements PostReceiveHook
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  /** the logger for GitPostReceiveHook */
 | 
			
		||||
  private static final Logger logger =
 | 
			
		||||
    LoggerFactory.getLogger(GitPostReceiveHook.class);
 | 
			
		||||
 | 
			
		||||
  //~--- constructors ---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs ...
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param repositoryManager
 | 
			
		||||
   */
 | 
			
		||||
  public GitPostReceiveHook(RepositoryManager repositoryManager)
 | 
			
		||||
  {
 | 
			
		||||
    this.repositoryManager = repositoryManager;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- methods --------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param rpack
 | 
			
		||||
   * @param receiveCommands
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  public void onPostReceive(ReceivePack rpack,
 | 
			
		||||
                            Collection<ReceiveCommand> receiveCommands)
 | 
			
		||||
  {
 | 
			
		||||
    GitChangesetConverter converter = null;
 | 
			
		||||
    RevWalk walk = rpack.getRevWalk();
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
      List<Changeset> changesets = new ArrayList<Changeset>();
 | 
			
		||||
 | 
			
		||||
      converter = new GitChangesetConverter(rpack.getRepository(),
 | 
			
		||||
              GitUtil.ID_LENGTH);
 | 
			
		||||
 | 
			
		||||
      for (ReceiveCommand rc : receiveCommands)
 | 
			
		||||
      {
 | 
			
		||||
        if (isCreateCommand(rc))
 | 
			
		||||
        {
 | 
			
		||||
          RevCommit commit = walk.parseCommit(rc.getNewId());
 | 
			
		||||
 | 
			
		||||
          if (commit != null)
 | 
			
		||||
          {
 | 
			
		||||
            changesets.add(converter.createChangeset(commit));
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      String repositoryName = rpack.getRepository().getDirectory().getName();
 | 
			
		||||
 | 
			
		||||
      repositoryManager.firePostReceiveEvent(GitRepositoryHandler.TYPE_NAME,
 | 
			
		||||
              repositoryName, 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 ----------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param rc
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   */
 | 
			
		||||
  private boolean isCreateCommand(ReceiveCommand rc)
 | 
			
		||||
  {
 | 
			
		||||
    return (rc.getResult() == ReceiveCommand.Result.OK)
 | 
			
		||||
           && (rc.getType() == ReceiveCommand.Type.CREATE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- fields ---------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  private RepositoryManager repositoryManager;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,106 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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.web;
 | 
			
		||||
 | 
			
		||||
//~--- non-JDK imports --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory;
 | 
			
		||||
import org.eclipse.jgit.lib.Repository;
 | 
			
		||||
import org.eclipse.jgit.transport.ReceivePack;
 | 
			
		||||
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
 | 
			
		||||
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
 | 
			
		||||
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
 | 
			
		||||
 | 
			
		||||
import sonia.scm.repository.RepositoryManager;
 | 
			
		||||
 | 
			
		||||
//~--- JDK imports ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sebastian Sdorra
 | 
			
		||||
 */
 | 
			
		||||
public class GitReceivePackFactory
 | 
			
		||||
        implements ReceivePackFactory<HttpServletRequest>
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs ...
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param repositoryManager
 | 
			
		||||
   */
 | 
			
		||||
  @Inject
 | 
			
		||||
  public GitReceivePackFactory(RepositoryManager repositoryManager)
 | 
			
		||||
  {
 | 
			
		||||
    hook = new GitPostReceiveHook(repositoryManager);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- methods --------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Method description
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param request
 | 
			
		||||
   * @param repository
 | 
			
		||||
   *
 | 
			
		||||
   * @return
 | 
			
		||||
   *
 | 
			
		||||
   * @throws ServiceNotAuthorizedException
 | 
			
		||||
   * @throws ServiceNotEnabledException
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  public ReceivePack create(HttpServletRequest request, Repository repository)
 | 
			
		||||
          throws ServiceNotEnabledException, ServiceNotAuthorizedException
 | 
			
		||||
  {
 | 
			
		||||
    ReceivePack rpack = defaultFactory.create(request, repository);
 | 
			
		||||
 | 
			
		||||
    rpack.setPostReceiveHook(hook);
 | 
			
		||||
 | 
			
		||||
    return rpack;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- fields ---------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  private DefaultReceivePackFactory defaultFactory =
 | 
			
		||||
    new DefaultReceivePackFactory();
 | 
			
		||||
 | 
			
		||||
  /** Field description */
 | 
			
		||||
  private GitPostReceiveHook hook;
 | 
			
		||||
}
 | 
			
		||||
@@ -35,6 +35,8 @@ package sonia.scm.web;
 | 
			
		||||
 | 
			
		||||
//~--- non-JDK imports --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
 | 
			
		||||
import org.eclipse.jgit.lib.Repository;
 | 
			
		||||
import org.eclipse.jgit.lib.RepositoryCache;
 | 
			
		||||
@@ -78,6 +80,7 @@ public class GitRepositoryResolver
 | 
			
		||||
   *
 | 
			
		||||
   * @param handler
 | 
			
		||||
   */
 | 
			
		||||
  @Inject
 | 
			
		||||
  public GitRepositoryResolver(GitRepositoryHandler handler)
 | 
			
		||||
  {
 | 
			
		||||
    this.handler = handler;
 | 
			
		||||
 
 | 
			
		||||
@@ -36,8 +36,8 @@ package sonia.scm.web;
 | 
			
		||||
//~--- non-JDK imports --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
import com.google.inject.servlet.ServletModule;
 | 
			
		||||
import sonia.scm.plugin.ext.Extension;
 | 
			
		||||
 | 
			
		||||
import sonia.scm.plugin.ext.Extension;
 | 
			
		||||
import sonia.scm.web.filter.BasicAuthenticationFilter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -60,6 +60,10 @@ public class GitServletModule extends ServletModule
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void configureServlets()
 | 
			
		||||
  {
 | 
			
		||||
    bind(GitRepositoryResolver.class);
 | 
			
		||||
    bind(GitReceivePackFactory.class);
 | 
			
		||||
 | 
			
		||||
    // serlvelts and filters
 | 
			
		||||
    filter(PATTERN_GIT).through(BasicAuthenticationFilter.class);
 | 
			
		||||
    filter(PATTERN_GIT).through(GitPermissionFilter.class);
 | 
			
		||||
    serve(PATTERN_GIT).with(ScmGitServlet.class);
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,6 @@ import org.eclipse.jgit.http.server.GitServlet;
 | 
			
		||||
import org.eclipse.jgit.lib.Repository;
 | 
			
		||||
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
 | 
			
		||||
 | 
			
		||||
import sonia.scm.repository.GitRepositoryHandler;
 | 
			
		||||
import sonia.scm.util.HttpUtil;
 | 
			
		||||
 | 
			
		||||
//~--- JDK imports ------------------------------------------------------------
 | 
			
		||||
@@ -81,13 +80,16 @@ public class ScmGitServlet extends GitServlet
 | 
			
		||||
   * Constructs ...
 | 
			
		||||
   *
 | 
			
		||||
   *
 | 
			
		||||
   * @param handler
 | 
			
		||||
   *
 | 
			
		||||
   * @param repositoryResolver
 | 
			
		||||
   * @param receivePackFactory
 | 
			
		||||
   */
 | 
			
		||||
  @Inject
 | 
			
		||||
  public ScmGitServlet(GitRepositoryHandler handler)
 | 
			
		||||
  public ScmGitServlet(GitRepositoryResolver repositoryResolver,
 | 
			
		||||
                       GitReceivePackFactory receivePackFactory)
 | 
			
		||||
  {
 | 
			
		||||
    resolver = new GitRepositoryResolver(handler);
 | 
			
		||||
    setRepositoryResolver(resolver);
 | 
			
		||||
    setRepositoryResolver(repositoryResolver);
 | 
			
		||||
    setReceivePackFactory(receivePackFactory);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //~--- methods --------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user