Skip to content

Commit

Permalink
BatchFileMode: move file search logic from GitOps
Browse files Browse the repository at this point in the history
Since not all means to locate files actually use git, it seemed like a
suboptimal location.
  • Loading branch information
kitbellew committed Nov 29, 2021
1 parent bd2081d commit b88bb78
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 80 deletions.
25 changes: 10 additions & 15 deletions scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtRunner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.io.OutputStreamWriter
import java.nio.file.Path

import org.scalafmt.sysops.AbsoluteFile
import org.scalafmt.sysops.GitOps.Implicit
import org.scalafmt.sysops.BatchPathFinder

trait ScalafmtRunner {
private[cli] def run(
Expand Down Expand Up @@ -50,25 +50,20 @@ trait ScalafmtRunner {
canFormat: Path => Boolean
): Seq[AbsoluteFile] = {
val gitOps = options.gitOps
val files = options.fileFetchMode match {
val finder = options.fileFetchMode match {
case GitFiles =>
options.customFilesOpt.fold(gitOps.getFiles(canFormat))(
gitOps.getFiles(_, options.respectProjectFilters, canFormat)
)

new BatchPathFinder.GitFiles(gitOps)(canFormat)
case RecursiveSearch =>
options.customFilesOpt
.map(gitOps.getDirFiles(_, options.respectProjectFilters, canFormat))
.getOrElse(gitOps.getDirFiles(options.cwd, canFormat))

new BatchPathFinder.DirFiles(options.cwd)(canFormat)
case DiffFiles(branch) =>
options.customFilesOpt.fold(gitOps.getDiffFiles(branch, canFormat))(
gitOps.getDiffFiles(branch, options.respectProjectFilters, canFormat)
)

new BatchPathFinder.GitBranchFiles(gitOps, branch)(canFormat)
case ChangedFiles =>
gitOps.getChangedFiles(canFormat)
new BatchPathFinder.GitDirtyFiles(gitOps)(canFormat)
}
val files = finder.findMatchingFiles(
options.respectProjectFilters,
options.customFilesOpt.getOrElse(Seq.empty): _*
)
val excludeRegexp = options.excludeFilterRegexp
files.filter { f => excludeRegexp.findFirstIn(f.toString()).isEmpty }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.scalafmt.sysops

import java.nio.file.Path
import java.nio.file.attribute.BasicFileAttributes

trait BatchPathFinder {

val matches: Path => Boolean
def findFiles(dir: AbsoluteFile*): Seq[AbsoluteFile]

final def findFilesExplicit(dirs: Seq[AbsoluteFile]): Seq[AbsoluteFile] =
if (dirs.isEmpty) Seq.empty else findFiles(dirs: _*)

final def findMatchingFiles(
filterFilesToo: Boolean,
paths: AbsoluteFile*
): Seq[AbsoluteFile] = {
if (paths.isEmpty) findFiles()
else {
val files = Seq.newBuilder[AbsoluteFile]
val dirs = Seq.newBuilder[AbsoluteFile]
paths.foreach { x =>
if (!x.isRegularFile) dirs += x
// DESNOTE(2017-05-19, pjrt): A plain, fully passed file will (try to) be
// formatted regardless of what it is or where it is.
// NB: Unless respectProjectFilters is also specified.
else if (!filterFilesToo || matches(x.path)) files += x
}
files.result() ++ findFilesExplicit(dirs.result())
}
}
}

object BatchPathFinder {

final class DirFiles(val cwd: AbsoluteFile)(
val matches: Path => Boolean
) extends BatchPathFinder {
private def filter(path: Path, attrs: BasicFileAttributes): Boolean =
attrs.isRegularFile && matches(path)
override final def findFiles(dir: AbsoluteFile*): Seq[AbsoluteFile] = {
val dirs = if (dir.isEmpty) Seq(cwd.path) else dir.map(_.path)
dirs.flatMap(FileOps.listFiles(_, filter)).map(new AbsoluteFile(_))
}
}

final class GitFiles(git: GitOps)(val matches: Path => Boolean)
extends BatchPathFinder {
override final def findFiles(dir: AbsoluteFile*): Seq[AbsoluteFile] =
git.lsTree(dir: _*).filter(x => matches(x.path))
}

final class GitBranchFiles(git: GitOps, branch: String)(
val matches: Path => Boolean
) extends BatchPathFinder {
override final def findFiles(dir: AbsoluteFile*): Seq[AbsoluteFile] =
git.diff(branch, dir: _*).filter(x => matches(x.path))
}

final class GitDirtyFiles(git: GitOps)(val matches: Path => Boolean)
extends BatchPathFinder {
override final def findFiles(dir: AbsoluteFile*): Seq[AbsoluteFile] =
git.status(dir: _*).filter(x => matches(x.path))
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.scalafmt.sysops

import scala.language.implicitConversions
import scala.sys.process.ProcessLogger
import scala.util.{Failure, Success, Try}
import java.nio.file.Path
Expand All @@ -16,27 +15,6 @@ object GitOps {
new GitOpsImpl(workingDirectory)
}

private implicit def implicitPathToAbsoluteFileMatcher(
f: Path => Boolean
): AbsoluteFile => Boolean = (x: AbsoluteFile) => f(x.path)

private def getMatchingFiles(
files: Seq[AbsoluteFile],
respectProjectFilters: Boolean,
matches: Path => Boolean
)(listDir: Seq[AbsoluteFile] => Seq[AbsoluteFile]): Seq[AbsoluteFile] = {
val matchingFiles = Seq.newBuilder[AbsoluteFile]
val dirs = Seq.newBuilder[AbsoluteFile]
files.foreach { x =>
if (x.isDirectory) dirs += x
// DESNOTE(2017-05-19, pjrt): A plain, fully passed file will (try to) be
// formatted regardless of what it is or where it is.
// NB: Unless respectProjectFilters is also specified.
else if (!respectProjectFilters || matches(x.path)) matchingFiles += x
}
matchingFiles.result() ++ listDir(dirs.result()).filter(matches)
}

implicit class Implicit(obj: GitOps) {

def getCanonicalConfigFile(
Expand All @@ -48,49 +26,6 @@ object GitOps {
def getRootConfigFile: Option[Try[Path]] =
obj.rootDir.flatMap(FileOps.tryGetConfigInDir)

def getFiles(matches: Path => Boolean): Seq[AbsoluteFile] =
obj.lsTree().filter(matches)

def getFiles(
files: Seq[AbsoluteFile],
respectProjectFilters: Boolean,
matches: Path => Boolean
): Seq[AbsoluteFile] =
getMatchingFiles(files, respectProjectFilters, matches)(obj.lsTree)

def getDirFiles(
cwd: AbsoluteFile,
matches: Path => Boolean
): Seq[AbsoluteFile] =
cwd.listFiles.filter(matches)

def getDirFiles(
files: Seq[AbsoluteFile],
respectProjectFilters: Boolean,
matches: Path => Boolean
): Seq[AbsoluteFile] =
getMatchingFiles(files, respectProjectFilters, matches)(
_.flatMap(_.listFiles)
)

def getDiffFiles(
branch: String,
matches: Path => Boolean
): Seq[AbsoluteFile] =
obj.diff(branch).filter(matches)

def getDiffFiles(
branch: String,
respectProjectFilters: Boolean,
matches: Path => Boolean
)(files: Seq[AbsoluteFile]): Seq[AbsoluteFile] =
getMatchingFiles(files, respectProjectFilters, matches)(x =>
obj.diff(branch, x: _*)
)

def getChangedFiles(matches: Path => Boolean): Seq[AbsoluteFile] =
obj.status().filter(matches)

}

}
Expand Down

0 comments on commit b88bb78

Please sign in to comment.