<commit_before>package util

import org.eclipse.jgit.api.Git
import util.Directory._
import scala.collection.JavaConverters._
import javax.servlet.ServletContext
import org.eclipse.jgit.lib._
import org.eclipse.jgit.revwalk._
import org.eclipse.jgit.revwalk.filter.RevFilter
import org.eclipse.jgit.treewalk._
import org.eclipse.jgit.treewalk.filter.PathFilter
import org.eclipse.jgit.diff._
import org.eclipse.jgit.diff.DiffEntry.ChangeType
import org.eclipse.jgit.util.io.DisabledOutputStream
import org.eclipse.jgit.errors.MissingObjectException
import java.util.Date

/**
 * Provides complex JGit operations.
 */
object JGitUtil {

  /**
   * The repository data.
   *
   * @param owner the user name of the repository owner
   * @param name the repository name
   * @param url the repository URL
   * @param branchList the list of branch names
   * @param tags the list of tags
   */
  case class RepositoryInfo(owner: String, name: String, url: String, branchList: List[String], tags: List[TagInfo])

  /**
   * The file data for the file list of the repository viewer.
   *
   * @param id the object id
   * @param isDirectory whether is it directory
   * @param name the file (or directory) name
   * @param time the last modified time
   * @param message the last commit message
   * @param committer the last committer name
   */
  case class FileInfo(id: ObjectId, isDirectory: Boolean, name: String, time: Date, message: String, committer: String)

  /**
   * The commit data.
   *
   * @param id the commit id
   * @param time the commit time
   * @param committer  the commiter name
   * @param message the commit message
   */
  case class CommitInfo(id: String, time: Date, committer: String, message: String){
    def this(rev: org.eclipse.jgit.revwalk.RevCommit) =
      this(rev.getName, rev.getCommitterIdent.getWhen, rev.getCommitterIdent.getName, rev.getFullMessage)
  }

  case class DiffInfo(changeType: ChangeType, oldPath: String, newPath: String, oldContent: Option[String], newContent: Option[String])

  /**
   * The file content data for the file content view of the repository viewer.
   *
   * @param viewType "image", "large" or "other"
   * @param content the string content
   */
  case class ContentInfo(viewType: String, content: Option[String])

  /**
   * The tag data.
   *
   * @param name the tag name
   * @param time the tagged date
   * @param id the commit id
   */
  case class TagInfo(name: String, time: Date, id: String)

  /**
   * Use this method to use the Git object.
   * Repository resources are released certainly after processing.
   */
  def withGit[T](dir: java.io.File)(f: Git => T): T = withGit(Git.open(dir))(f)
  
  /**
   * Use this method to use the Git object.
   * Repository resources are released certainly after processing.
   */
  def withGit[T](git: Git)(f: Git => T): T = {
    try {
      f(git)
    } finally {
      git.getRepository.close
    }
  }
  
  /**
   * Returns RevCommit from the commit id.
   * 
   * @param git the Git object
   * @param commitId the ObjectId of the commit
   * @return the RevCommit for the specified commit
   */
  def getRevCommitFromId(git: Git, commitId: ObjectId): RevCommit = {
    val revWalk = new RevWalk(git.getRepository)
    val revCommit = revWalk.parseCommit(commitId)
    revWalk.dispose
    revCommit
  }
  
  /**
   * Returns the repository information. It contains branch names and tag names.
   */
  def getRepositoryInfo(owner: String, repository: String, servletContext: ServletContext): RepositoryInfo = {
    withGit(getRepositoryDir(owner, repository)){ git =>
      RepositoryInfo(
        owner, repository, "http://localhost:8080%s/git/%s/%s.git".format(servletContext.getContextPath, owner, repository),
        // branches
        git.branchList.call.asScala.map { ref =>
          ref.getName.replaceFirst("^refs/heads/", "")
        }.toList,
        // tags
        git.tagList.call.asScala.map { ref =>
          val revCommit = getRevCommitFromId(git, ref.getObjectId)
          TagInfo(ref.getName.replaceFirst("^refs/tags/", ""), revCommit.getCommitterIdent.getWhen, revCommit.getName)
        }.toList
      )
    }
  }
  
  /**
   * Returns the file list of the specified path.
   * 
   * @param git the Git object
   * @param revision the branch name or commit id
   * @param path the directory path (optional)
   * @return HTML of the file list
   */
  def getFileList(git: Git, revision: String, path: String = "."): List[FileInfo] = {
    val revWalk = new RevWalk(git.getRepository)
    val objectId = git.getRepository.resolve(revision)
    val revCommit = revWalk.parseCommit(objectId)
      
    val treeWalk = new TreeWalk(git.getRepository)
    treeWalk.addTree(revCommit.getTree)
    if(path != "."){
      treeWalk.setRecursive(true)
      treeWalk.setFilter(PathFilter.create(path))
    }
      
    val list = new scala.collection.mutable.ListBuffer[FileInfo]
    
    while (treeWalk.next()) {
      val fileCommit = JGitUtil.getLatestCommitFromPath(git, treeWalk.getPathString, revision)
      list.append(FileInfo(
          treeWalk.getObjectId(0),
          treeWalk.getFileMode(0) == FileMode.TREE, 
          treeWalk.getNameString,
          fileCommit.getCommitterIdent.getWhen,
          fileCommit.getShortMessage, <commit_msg>Fix file list of the nested directory.<commit_after>package util

import org.eclipse.jgit.api.Git
import util.Directory._
import scala.collection.JavaConverters._
import javax.servlet.ServletContext
import org.eclipse.jgit.lib._
import org.eclipse.jgit.revwalk._
import org.eclipse.jgit.revwalk.filter.RevFilter
import org.eclipse.jgit.treewalk._
import org.eclipse.jgit.treewalk.filter.PathFilter
import org.eclipse.jgit.diff._
import org.eclipse.jgit.diff.DiffEntry.ChangeType
import org.eclipse.jgit.util.io.DisabledOutputStream
import org.eclipse.jgit.errors.MissingObjectException
import java.util.Date

/**
 * Provides complex JGit operations.
 */
object JGitUtil {

  /**
   * The repository data.
   *
   * @param owner the user name of the repository owner
   * @param name the repository name
   * @param url the repository URL
   * @param branchList the list of branch names
   * @param tags the list of tags
   */
  case class RepositoryInfo(owner: String, name: String, url: String, branchList: List[String], tags: List[TagInfo])

  /**
   * The file data for the file list of the repository viewer.
   *
   * @param id the object id
   * @param isDirectory whether is it directory
   * @param name the file (or directory) name
   * @param time the last modified time
   * @param message the last commit message
   * @param committer the last committer name
   */
  case class FileInfo(id: ObjectId, isDirectory: Boolean, name: String, time: Date, message: String, committer: String)

  /**
   * The commit data.
   *
   * @param id the commit id
   * @param time the commit time
   * @param committer  the commiter name
   * @param message the commit message
   */
  case class CommitInfo(id: String, time: Date, committer: String, message: String){
    def this(rev: org.eclipse.jgit.revwalk.RevCommit) =
      this(rev.getName, rev.getCommitterIdent.getWhen, rev.getCommitterIdent.getName, rev.getFullMessage)
  }

  case class DiffInfo(changeType: ChangeType, oldPath: String, newPath: String, oldContent: Option[String], newContent: Option[String])

  /**
   * The file content data for the file content view of the repository viewer.
   *
   * @param viewType "image", "large" or "other"
   * @param content the string content
   */
  case class ContentInfo(viewType: String, content: Option[String])

  /**
   * The tag data.
   *
   * @param name the tag name
   * @param time the tagged date
   * @param id the commit id
   */
  case class TagInfo(name: String, time: Date, id: String)

  /**
   * Use this method to use the Git object.
   * Repository resources are released certainly after processing.
   */
  def withGit[T](dir: java.io.File)(f: Git => T): T = withGit(Git.open(dir))(f)
  
  /**
   * Use this method to use the Git object.
   * Repository resources are released certainly after processing.
   */
  def withGit[T](git: Git)(f: Git => T): T = {
    try {
      f(git)
    } finally {
      git.getRepository.close
    }
  }
  
  /**
   * Returns RevCommit from the commit id.
   * 
   * @param git the Git object
   * @param commitId the ObjectId of the commit
   * @return the RevCommit for the specified commit
   */
  def getRevCommitFromId(git: Git, commitId: ObjectId): RevCommit = {
    val revWalk = new RevWalk(git.getRepository)
    val revCommit = revWalk.parseCommit(commitId)
    revWalk.dispose
    revCommit
  }
  
  /**
   * Returns the repository information. It contains branch names and tag names.
   */
  def getRepositoryInfo(owner: String, repository: String, servletContext: ServletContext): RepositoryInfo = {
    withGit(getRepositoryDir(owner, repository)){ git =>
      RepositoryInfo(
        owner, repository, "http://localhost:8080%s/git/%s/%s.git".format(servletContext.getContextPath, owner, repository),
        // branches
        git.branchList.call.asScala.map { ref =>
          ref.getName.replaceFirst("^refs/heads/", "")
        }.toList,
        // tags
        git.tagList.call.asScala.map { ref =>
          val revCommit = getRevCommitFromId(git, ref.getObjectId)
          TagInfo(ref.getName.replaceFirst("^refs/tags/", ""), revCommit.getCommitterIdent.getWhen, revCommit.getName)
        }.toList
      )
    }
  }
  
  /**
   * Returns the file list of the specified path.
   * 
   * @param git the Git object
   * @param revision the branch name or commit id
   * @param path the directory path (optional)
   * @return HTML of the file list
   */
  def getFileList(git: Git, revision: String, path: String = "."): List[FileInfo] = {
    val revWalk = new RevWalk(git.getRepository)
    val objectId = git.getRepository.resolve(revision)
    val revCommit = revWalk.parseCommit(objectId)
      
    val treeWalk = new TreeWalk(git.getRepository)
    treeWalk.addTree(revCommit.getTree)
    if(path != "."){
      treeWalk.setRecursive(true)
      treeWalk.setFilter(PathFilter.create(path))
      treeWalk.next()
      treeWalk.setRecursive(false)
    }
      
    val list = new scala.collection.mutable.ListBuffer[FileInfo]
    
    while (treeWalk.next()) {
      val fileCommit = JGitUtil.getLatestCommitFromPath(git, treeWalk.getPathString, revision)
      list.append(FileInfo(
          treeWalk.getObjectId(0),
          treeWalk.getFileMode(0) == FileMode.TREE, 
          treeWalk.getNameString,
          fileCommit.getCommitterIdent.getWhen,
          fileCommit.getShortMessage, 
{'fraction_non_alphanumeric': 0.10498220640569395, 'fraction_numerical': 0.0011238059561715678, 'mean_word_length': 3.1520217729393467, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5305847', 'n_tokens_mistral': 3249, 'n_tokens_neox': 3228, 'n_words': 928}