Adding in/out file validation
This commit is contained in:
@@ -11,5 +11,7 @@ lazy val root = project
|
||||
|
||||
libraryDependencies += "org.rogach" %% "scallop" % "5.2.0",
|
||||
libraryDependencies += "com.lihaoyi" %% "os-lib" % "0.11.5",
|
||||
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.6",
|
||||
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.5.19",
|
||||
libraryDependencies += "org.scalameta" %% "munit" % "1.2.0" % Test
|
||||
)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.minres.tgc.hammer
|
||||
|
||||
import org.rogach.scallop.{ValueConverter, listArgConverter, singleArgConverter}
|
||||
import org.rogach.scallop.{ScallopOption, Util, ValueConverter, listArgConverter, singleArgConverter}
|
||||
import os.*
|
||||
import Global.*
|
||||
|
||||
|
@@ -1,6 +1,9 @@
|
||||
package com.minres.tgc.hammer
|
||||
|
||||
import ch.qos.logback.classic.Level
|
||||
import com.minres.tgc.hammer.cli.{HammerConf, MySubcommand}
|
||||
import com.typesafe.scalalogging.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
import scala.compiletime.uninitialized
|
||||
|
||||
@@ -8,8 +11,19 @@ object Main {
|
||||
var conf: HammerConf = uninitialized
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
var logger = Logger("TGCHammer")
|
||||
conf = new HammerConf(args.toIndexedSeq)
|
||||
|
||||
val logLevel = conf.verbose() match {
|
||||
case 0 => Level.WARN
|
||||
case 1 => Level.INFO
|
||||
case 2 => Level.DEBUG
|
||||
case _ => Level.TRACE
|
||||
}
|
||||
LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).asInstanceOf[ch.qos.logback.classic.Logger].setLevel(logLevel)
|
||||
|
||||
os.makeDir(Global.OUT_DIR)
|
||||
os.makeDir(Global.TMP_DIR)
|
||||
conf.subcommand match {
|
||||
case Some(c: MySubcommand) =>
|
||||
val tasks = c.getRequiredTasks
|
||||
|
@@ -6,9 +6,12 @@ import com.minres.tgc.hammer.FileUtils.*
|
||||
|
||||
class HammerConf(arguments: Seq[String]) extends ScallopConf(arguments) {
|
||||
val outputDirectory: ScallopOption[Path] = opt[Path](default = Some("output".path()), descr = "The base output directory")
|
||||
val verbose: ScallopOption[Int] = tally()
|
||||
addSubcommand(new LongnailCommand)
|
||||
addSubcommand(new TreenailCommand)
|
||||
addSubcommand(new LongnailSchedCommand)
|
||||
|
||||
requireSubcommand()
|
||||
|
||||
verify()
|
||||
}
|
||||
|
@@ -10,7 +10,10 @@ import com.minres.tgc.hammer.tasks.longnail.LongnailMergeTask
|
||||
class LongnailMergeCommand extends MySubcommand("mergeISAX") {
|
||||
val inputFiles: ScallopOption[List[Path]] = trailArg[List[Path]]("inputFiles", group = mainGroup, descr = "One or multiple input files; Both .core_desc as well as .mlir are supported (also mixed)")
|
||||
val output: ScallopOption[Path] = opt[Path](short = 'o', default = Some("merged.mlir".path()), descr = "The .mlir file containing the merged ISAXes")
|
||||
val overwrite: ScallopOption[Boolean] = toggle()
|
||||
|
||||
check(inputFiles)(checkPathsIsFile)
|
||||
checkNotIf(overwrite)(output)(checkPathDoesNotExist)
|
||||
|
||||
override def getRequiredTasks: Seq[Task] = {
|
||||
val (coreDSLFiles, mlirFiles) = inputFiles().partition(_.ext == "core_desc")
|
||||
|
@@ -4,7 +4,7 @@ import com.minres.tgc.hammer.options.ConfigElement
|
||||
import com.minres.tgc.hammer.tasks.Task
|
||||
import org.rogach.scallop.{ScallopOption, ScallopOptionGroup, Subcommand, Util}
|
||||
|
||||
import java.nio.file.Files
|
||||
type Checker[T] = ScallopOption[T] => Either[String,Unit]
|
||||
|
||||
abstract class MySubcommand(name: String) extends Subcommand(name) {
|
||||
protected val mainGroup: ScallopOptionGroup = group()
|
||||
@@ -16,12 +16,42 @@ abstract class MySubcommand(name: String) extends Subcommand(name) {
|
||||
elem
|
||||
}
|
||||
|
||||
def validateOSPathIsDirectory(pathOption: ScallopOption[os.Path]): Unit = addValidation {
|
||||
pathOption.toOption
|
||||
.map {
|
||||
case path if Files.isDirectory(path.toNIO) => Right(())
|
||||
case path => Left(Util.format("File '%s' is not a directory", path))
|
||||
def checkPred[T](option: ScallopOption[T], predicate: T => Boolean, format: String): Either[String,Unit] = {
|
||||
option.toOption.map {
|
||||
case o if predicate(o) => (Right(()))
|
||||
case o => Left(Util.format(format, o))
|
||||
}.getOrElse(Right(()))
|
||||
}
|
||||
.getOrElse(Right(()))
|
||||
|
||||
def checkPredIt[T, CC <: Iterable](option: ScallopOption[CC[T]], predicate: T => Boolean, format: String): Either[String,Unit] = {
|
||||
option.toOption.map(options => {
|
||||
val problems = options.filterNot(predicate)
|
||||
problems match {
|
||||
case Nil => Right(())
|
||||
case problem :: Nil => Left(Util.format(format, problem))
|
||||
case _ => Left(s"Multiple: ${Util.format(format, problems.mkString(", "))}")
|
||||
}
|
||||
}).getOrElse(Right(()))
|
||||
}
|
||||
|
||||
def checkPathExists: Checker[os.Path] = path => checkPred(path, os.exists, "File '%s' does not exist")
|
||||
def checkPathDoesNotExist: Checker[os.Path] = path => checkPred(path, !os.exists(_), "File '%s' already exists")
|
||||
def checkPathIsFile: Checker[os.Path] = path => checkPred(path, os.isFile, "File '%s' is not a file")
|
||||
def checkPathIsDir: Checker[os.Path] = path => checkPred(path, os.isDir, "File '%s' is not a directory")
|
||||
|
||||
|
||||
def checkPathsExists: Checker[List[os.Path]] = path => checkPredIt(path, os.exists, "File(s) '%s' do not exist")
|
||||
def checkPathsDoesNotExists: Checker[List[os.Path]] = path => checkPredIt(path, !os.exists(_), "File(s) '%s' already exist")
|
||||
def checkPathsIsFile: Checker[List[os.Path]] = path => checkPredIt(path, os.isFile, "File(s) '%s' are not files")
|
||||
def checkPathsIsDir: Checker[List[os.Path]] = path => checkPredIt(path, os.isDir, "File(s) '%s' are not directories")
|
||||
|
||||
def check[T](option: ScallopOption[T])(check: Checker[T]): Unit = addValidation(check(option))
|
||||
def checkPred[T, U](condOpt: ScallopOption[U], cond: U => Boolean)(option: ScallopOption[T])(check: Checker[T]): Unit = addValidation {
|
||||
condOpt.toOption match {
|
||||
case Some(value) if cond(value) => check(option)
|
||||
case _ => Right(())
|
||||
}
|
||||
}
|
||||
def checkIf[T](condOpt: ScallopOption[Boolean])(option: ScallopOption[T])(check: Checker[T]): Unit = checkPred(condOpt, identity)(option)(check)
|
||||
def checkNotIf[T](condOpt: ScallopOption[Boolean])(option: ScallopOption[T])(check: Checker[T]): Unit = checkPred(condOpt, !_)(option)(check)
|
||||
}
|
||||
|
@@ -8,6 +8,10 @@ import os.Path
|
||||
class TreenailCommand extends MySubcommand("parseCoreDSL") {
|
||||
val coreDSL: ScallopOption[Path] = trailArg[Path]("coreDSL", descr = "The .core_desc input file to be converted")
|
||||
val output: ScallopOption[Path] = opt[Path](short = 'o', default = Some("isax.mlir".path()), descr = "The .mlir file containing the converted ISAX")
|
||||
val overwrite: ScallopOption[Boolean] = toggle()
|
||||
|
||||
check(coreDSL)(checkPathIsFile)
|
||||
checkNotIf(overwrite)(output)(checkPathDoesNotExist)
|
||||
|
||||
banner(
|
||||
"""Parse a CoreDSL input using Treenail into the MLIR representation
|
||||
|
Reference in New Issue
Block a user