Package org.gitective.core

Source Code of org.gitective.core.CommitUtils

/*
* Copyright (c) 2011 Kevin Sawicki <kevinsawicki@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
package org.gitective.core;

import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.eclipse.jgit.lib.Constants.MASTER;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.lib.Constants.R_REMOTES;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
import static org.eclipse.jgit.revwalk.filter.RevFilter.MERGE_BASE;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.HashSet;

import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/**
* Utilities for dealing with Git commits.
* <p>
* This class provides helpers for finding the commits that branches and tags
* reference.
*/
public abstract class CommitUtils {

  /**
   * Get the commit that the revision references.
   *
   * @param repository
   * @param revision
   * @return commit
   */
  public static RevCommit getCommit(final Repository repository,
      final String revision) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));
    if (revision == null)
      throw new IllegalArgumentException(Assert.formatNotNull("Revision"));
    if (revision.length() == 0)
      throw new IllegalArgumentException(
          Assert.formatNotEmpty("Revision"));

    return parse(repository, resolve(repository, revision));
  }

  /**
   * Get the commit with the given id
   *
   * @param repository
   * @param commitId
   * @return commit
   */
  public static RevCommit getCommit(final Repository repository,
      final ObjectId commitId) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));
    if (commitId == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Commit id"));

    return parse(repository, commitId);
  }

  /**
   * Get the HEAD commit in the given repository.
   *
   * @param repository
   * @return commit never null
   */
  public static RevCommit getHead(final Repository repository) {
    return getCommit(repository, HEAD);
  }

  /**
   * Get the commit at the tip of the master branch in the given repository.
   *
   * @param repository
   * @return commit never null
   */
  public static RevCommit getMaster(final Repository repository) {
    return getCommit(repository, MASTER);
  }

  /**
   * Get the common base commit of the given commits.
   *
   * @param repository
   * @param commits
   * @return base commit or null if none
   */
  public static RevCommit getBase(final Repository repository,
      final ObjectId... commits) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));
    if (commits == null)
      throw new IllegalArgumentException(Assert.formatNotNull("Commits"));
    if (commits.length == 0)
      throw new IllegalArgumentException(Assert.formatNotEmpty("Commits"));

    return walkToBase(repository, commits);
  }

  /**
   * Get the common base commit between the given revisions.
   *
   * @param repository
   * @param revisions
   * @return base commit or null if none
   */
  public static RevCommit getBase(final Repository repository,
      final String... revisions) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));
    if (revisions == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Revisions"));
    if (revisions.length == 0)
      throw new IllegalArgumentException(
          Assert.formatNotEmpty("Revisions"));

    final int length = revisions.length;
    final ObjectId[] commits = new ObjectId[length];
    for (int i = 0; i < length; i++) {
      commits[i] = strictResolve(repository, revisions[i]);
    }
    return walkToBase(repository, commits);
  }

  /**
   * Get the commit that the given name references.
   *
   * @param repository
   * @param refName
   * @return commit, may be null
   */
  public static RevCommit getRef(final Repository repository,
      final String refName) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));
    if (refName == null)
      throw new IllegalArgumentException(Assert.formatNotNull("Ref name"));
    if (refName.length() == 0)
      throw new IllegalArgumentException(
          Assert.formatNotEmpty("Ref name"));

    Ref ref;
    try {
      ref = repository.getRef(refName);
    } catch (IOException e) {
      throw new GitException(e, repository);
    }
    return ref != null ? lookupRef(repository, ref) : null;
  }

  /**
   * Get the commit for the given reference.
   *
   * @param repository
   * @param ref
   * @return commit, may be null
   */
  public static RevCommit getRef(final Repository repository, final Ref ref) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));
    if (ref == null)
      throw new IllegalArgumentException(Assert.formatNotNull("Ref"));

    return lookupRef(repository, ref);
  }

  /**
   * Get all the commits that tags in the given repository reference.
   *
   * @param repository
   * @return non-null but possibly empty collection of commits
   */
  public static Collection<RevCommit> getTags(final Repository repository) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));

    final Collection<RevCommit> commits = new HashSet<RevCommit>();
    final RevWalk walk = new RevWalk(repository);
    final RefDatabase refDb = repository.getRefDatabase();
    try {
      getRefCommits(walk, refDb, R_TAGS, commits);
    } catch (IOException e) {
      throw new GitException(e, repository);
    } finally {
      walk.release();
    }
    return commits;
  }

  /**
   * Get all the commits that branches in the given repository reference.
   *
   * @param repository
   * @return non-null but possibly empty collection of commits
   */
  public static Collection<RevCommit> getBranches(final Repository repository) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));

    final Collection<RevCommit> commits = new HashSet<RevCommit>();
    final RevWalk walk = new RevWalk(repository);
    final RefDatabase refDb = repository.getRefDatabase();
    try {
      getRefCommits(walk, refDb, R_HEADS, commits);
      getRefCommits(walk, refDb, R_REMOTES, commits);
    } catch (IOException e) {
      throw new GitException(e, repository);
    } finally {
      walk.release();
    }
    return commits;
  }

  private static void getRefCommits(final RevWalk walk,
      final RefDatabase refDb, final String prefix,
      final Collection<RevCommit> commits) throws IOException {
    for (Ref ref : refDb.getRefs(prefix).values()) {
      final RevCommit commit = getRef(walk, ref);
      if (commit != null)
        commits.add(commit);
    }
  }

  private static RevCommit lookupRef(final Repository repository,
      final Ref ref) {
    final RevWalk walk = new RevWalk(repository);
    try {
      return getRef(walk, ref);
    } catch (IOException e) {
      throw new GitException(e, repository);
    } finally {
      walk.release();
    }
  }

  private static RevCommit getRef(final RevWalk walk, final Ref ref)
      throws IOException {
    ObjectId id = ref.getPeeledObjectId();
    if (id == null)
      id = ref.getObjectId();
    return id != null ? walk.parseCommit(id) : null;
  }

  /**
   * Resolve the revision string to a commit object id
   *
   * @param repository
   * @param revision
   * @return commit id
   */
  protected static ObjectId resolve(final Repository repository,
      final String revision) {
    try {
      return repository.resolve(revision);
    } catch (IOException e) {
      throw new GitException(e, repository);
    }
  }

  /**
   * Resolve the revision string to a commit object id.
   * <p>
   * A {@link GitException} will be thrown when the revision can not be
   * resolved to an {@link ObjectId}
   *
   * @param repository
   * @param revision
   * @return commit id
   */
  protected static ObjectId strictResolve(final Repository repository,
      final String revision) {
    final ObjectId resolved = resolve(repository, revision);
    if (resolved == null)
      throw new GitException(MessageFormat.format(
          "Revision ''{0}'' could not be resolved", revision),
          repository);
    return resolved;
  }

  private static RevCommit walkToBase(final Repository repository,
      final ObjectId... commits) {
    final RevWalk walk = new RevWalk(repository);
    walk.setRevFilter(MERGE_BASE);
    try {
      for (int i = 0; i < commits.length; i++)
        walk.markStart(walk.parseCommit(commits[i]));
      final RevCommit base = walk.next();
      if (base != null)
        walk.parseBody(base);
      return base;
    } catch (IOException e) {
      throw new GitException(e, repository);
    } finally {
      walk.release();
    }
  }

  /**
   * Parse a commit from the repository
   *
   * @param repository
   * @param commit
   * @return commit
   */
  protected static RevCommit parse(final Repository repository,
      final ObjectId commit) {
    final RevWalk walk = new RevWalk(repository);
    walk.setRetainBody(true);
    try {
      return walk.parseCommit(commit);
    } catch (IOException e) {
      throw new GitException(e, repository);
    } finally {
      walk.release();
    }
  }

  /**
   * Parse a commit from the object reader
   *
   * @param repository
   * @param reader
   * @param commit
   * @return commit
   */
  protected static RevCommit parse(final Repository repository,
      final ObjectReader reader, final ObjectId commit) {
    final RevWalk walk = new RevWalk(reader);
    walk.setRetainBody(true);
    try {
      return walk.parseCommit(commit);
    } catch (IOException e) {
      throw new GitException(e, repository);
    }
  }

  /**
   * Find the commit that last changed the given path starting at the commit
   * that HEAD currently points to
   *
   * @param repository
   * @param path
   * @return commit
   */
  public static RevCommit getLastCommit(final Repository repository,
      final String path) {
    return getLastCommit(repository, HEAD, path);
  }

  /**
   * Find the commit that last changed the given path starting with the commit
   * at the given revision
   *
   * @param repository
   * @param revision
   * @param path
   * @return commit
   */
  public static RevCommit getLastCommit(final Repository repository,
      final String revision, final String path) {
    if (repository == null)
      throw new IllegalArgumentException(
          Assert.formatNotNull("Repository"));
    if (revision == null)
      throw new IllegalArgumentException(Assert.formatNotNull("Revision"));
    if (revision.length() == 0)
      throw new IllegalArgumentException(
          Assert.formatNotEmpty("Revision"));
    if (path == null)
      throw new IllegalArgumentException(Assert.formatNotNull("Path"));
    if (path.length() == 0)
      throw new IllegalArgumentException(Assert.formatNotEmpty("Path"));

    final RevWalk walk = new RevWalk(repository);
    walk.setRetainBody(true);
    try {
      walk.markStart(walk
          .parseCommit(strictResolve(repository, revision)));
      walk.setTreeFilter(PathFilterUtils.and(path));
      return walk.next();
    } catch (IOException e) {
      throw new GitException(e, repository);
    } finally {
      walk.release();
    }
  }
}
TOP

Related Classes of org.gitective.core.CommitUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.