lemval
2012-01-31 1c30dad2115fc513791d8a5b292ad0f7d7b85749
src/com/gitblit/utils/DiffUtils.java
@@ -25,21 +25,32 @@
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.models.AnnotatedLine;
/**
 * DiffUtils is a class of utility methods related to diff, patch, and blame.
 *
 * The diff methods support pluggable diff output types like Gitblit, Gitweb,
 * and Plain.
 *
 * @author James Moger
 *
 */
public class DiffUtils {
   private static final Logger LOGGER = LoggerFactory.getLogger(DiffUtils.class);
   /**
    * Enumeration for the diff output types.
    */
   public static enum DiffOutputType {
      PLAIN, GITWEB, GITBLIT;
@@ -53,42 +64,67 @@
      }
   }
   public static String getCommitDiff(Repository r, RevCommit commit, DiffOutputType outputType) {
      return getDiff(r, null, commit, null, outputType);
   /**
    * Returns the complete diff of the specified commit compared to its primary
    * parent.
    *
    * @param repository
    * @param commit
    * @param outputType
    * @return the diff as a string
    */
   public static String getCommitDiff(Repository repository, RevCommit commit,
         DiffOutputType outputType) {
      return getDiff(repository, null, commit, null, outputType);
   }
   public static String getDiff(Repository r, RevCommit commit, String path,
   /**
    * Returns the diff for the specified file or folder from the specified
    * commit compared to its primary parent.
    *
    * @param repository
    * @param commit
    * @param path
    * @param outputType
    * @return the diff as a string
    */
   public static String getDiff(Repository repository, RevCommit commit, String path,
         DiffOutputType outputType) {
      return getDiff(r, null, commit, path, outputType);
      return getDiff(repository, null, commit, path, outputType);
   }
   public static String getDiff(Repository r, RevCommit baseCommit, RevCommit commit,
   /**
    * Returns the complete diff between the two specified commits.
    *
    * @param repository
    * @param baseCommit
    * @param commit
    * @param outputType
    * @return the diff as a string
    */
   public static String getDiff(Repository repository, RevCommit baseCommit, RevCommit commit,
         DiffOutputType outputType) {
      return getDiff(r, baseCommit, commit, null, outputType);
      return getDiff(repository, baseCommit, commit, null, outputType);
   }
   public static String getDiff(Repository r, RevCommit baseCommit, RevCommit commit, String path,
         DiffOutputType outputType) {
   /**
    * Returns the diff between two commits for the specified file.
    *
    * @param repository
    * @param baseCommit
    *            if base commit is null the diff is to the primary parent of
    *            the commit.
    * @param commit
    * @param path
    *            if the path is specified, the diff is restricted to that file
    *            or folder. if unspecified, the diff is for the entire commit.
    * @param outputType
    * @return the diff as a string
    */
   public static String getDiff(Repository repository, RevCommit baseCommit, RevCommit commit,
         String path, DiffOutputType outputType) {
      String diff = null;
      try {
         RevTree baseTree;
         if (baseCommit == null) {
            final RevWalk rw = new RevWalk(r);
            RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
            rw.dispose();
            baseTree = parent.getTree();
         } else {
            baseTree = baseCommit.getTree();
         }
         RevTree commitTree = commit.getTree();
         final TreeWalk walk = new TreeWalk(r);
         walk.reset();
         walk.setRecursive(true);
         walk.addTree(baseTree);
         walk.addTree(commitTree);
         walk.setFilter(TreeFilter.ANY_DIFF);
         final ByteArrayOutputStream os = new ByteArrayOutputStream();
         RawTextComparator cmp = RawTextComparator.DEFAULT;
         DiffFormatter df;
@@ -104,21 +140,37 @@
            df = new DiffFormatter(os);
            break;
         }
         df.setRepository(r);
         df.setRepository(repository);
         df.setDiffComparator(cmp);
         df.setDetectRenames(true);
         List<DiffEntry> diffs = df.scan(baseTree, commitTree);
         RevTree commitTree = commit.getTree();
         RevTree baseTree;
         if (baseCommit == null) {
            if (commit.getParentCount() > 0) {
               final RevWalk rw = new RevWalk(repository);
               RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
               rw.dispose();
               baseTree = parent.getTree();
            } else {
               // FIXME initial commit. no parent?!
               baseTree = commitTree;
            }
         } else {
            baseTree = baseCommit.getTree();
         }
         List<DiffEntry> diffEntries = df.scan(baseTree, commitTree);
         if (path != null && path.length() > 0) {
            for (DiffEntry diff : diffs) {
               if (diff.getNewPath().equalsIgnoreCase(path)) {
                  df.format(diff);
            for (DiffEntry diffEntry : diffEntries) {
               if (diffEntry.getNewPath().equalsIgnoreCase(path)) {
                  df.format(diffEntry);
                  break;
               }
            }
         } else {
            df.format(diffs);
            df.format(diffEntries);
         }
         String diff;
         if (df instanceof GitWebDiffFormatter) {
            // workaround for complex private methods in DiffFormatter
            diff = ((GitWebDiffFormatter) df).getHtml();
@@ -126,65 +178,93 @@
            diff = os.toString();
         }
         df.flush();
         return diff;
      } catch (Throwable t) {
         LOGGER.error("failed to generate commit diff!", t);
      }
      return null;
      return diff;
   }
   public static String getCommitPatch(Repository r, RevCommit baseCommit, RevCommit commit,
         String path) {
   /**
    * Returns the diff between the two commits for the specified file or folder
    * formatted as a patch.
    *
    * @param repository
    * @param baseCommit
    *            if base commit is unspecified, the patch is generated against
    *            the primary parent of the specified commit.
    * @param commit
    * @param path
    *            if path is specified, the patch is generated only for the
    *            specified file or folder. if unspecified, the patch is
    *            generated for the entire diff between the two commits.
    * @return patch as a string
    */
   public static String getCommitPatch(Repository repository, RevCommit baseCommit,
         RevCommit commit, String path) {
      String diff = null;
      try {
         RevTree baseTree;
         if (baseCommit == null) {
            final RevWalk rw = new RevWalk(r);
            RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
            baseTree = parent.getTree();
         } else {
            baseTree = baseCommit.getTree();
         }
         RevTree commitTree = commit.getTree();
         final TreeWalk walk = new TreeWalk(r);
         walk.reset();
         walk.setRecursive(true);
         walk.addTree(baseTree);
         walk.addTree(commitTree);
         walk.setFilter(TreeFilter.ANY_DIFF);
         final ByteArrayOutputStream os = new ByteArrayOutputStream();
         RawTextComparator cmp = RawTextComparator.DEFAULT;
         PatchFormatter df = new PatchFormatter(os);
         df.setRepository(r);
         df.setRepository(repository);
         df.setDiffComparator(cmp);
         df.setDetectRenames(true);
         List<DiffEntry> diffs = df.scan(baseTree, commitTree);
         RevTree commitTree = commit.getTree();
         RevTree baseTree;
         if (baseCommit == null) {
            if (commit.getParentCount() > 0) {
               final RevWalk rw = new RevWalk(repository);
               RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
               baseTree = parent.getTree();
            } else {
               // FIXME initial commit. no parent?!
               baseTree = commitTree;
            }
         } else {
            baseTree = baseCommit.getTree();
         }
         List<DiffEntry> diffEntries = df.scan(baseTree, commitTree);
         if (path != null && path.length() > 0) {
            for (DiffEntry diff : diffs) {
               if (diff.getNewPath().equalsIgnoreCase(path)) {
                  df.format(diff);
            for (DiffEntry diffEntry : diffEntries) {
               if (diffEntry.getNewPath().equalsIgnoreCase(path)) {
                  df.format(diffEntry);
                  break;
               }
            }
         } else {
            df.format(diffs);
            df.format(diffEntries);
         }
         String diff = df.getPatch(commit);
         diff = df.getPatch(commit);
         df.flush();
         return diff;
      } catch (Throwable t) {
         LOGGER.error("failed to generate commit diff!", t);
      }
      return null;
      return diff;
   }
   public static List<AnnotatedLine> blame(Repository r, String blobPath, String objectId) {
   /**
    * Returns the list of lines in the specified source file annotated with the
    * source commit metadata.
    *
    * @param repository
    * @param blobPath
    * @param objectId
    * @return list of annotated lines
    */
   public static List<AnnotatedLine> blame(Repository repository, String blobPath, String objectId) {
      List<AnnotatedLine> lines = new ArrayList<AnnotatedLine>();
      try {
         BlameCommand blameCommand = new BlameCommand(r);
         ObjectId object;
         if (StringUtils.isEmpty(objectId)) {
            object = JGitUtils.getDefaultBranch(repository);
         } else {
            object = repository.resolve(objectId);
         }
         BlameCommand blameCommand = new BlameCommand(repository);
         blameCommand.setFilePath(blobPath);
         blameCommand.setStartCommit(r.resolve(objectId));
         blameCommand.setStartCommit(object);
         BlameResult blameResult = blameCommand.call();
         RawText rawText = blameResult.getResultContents();
         int length = rawText.size();