Refactoring and many fixes to PR #378. (Broken)

This commit is broken due to a cleanup issue with NimScript eval.
This commit is contained in:
Dominik Picheta 2017-09-03 17:37:52 +01:00
commit 301a366dd2
18 changed files with 150 additions and 100 deletions

View file

@ -13,7 +13,8 @@ from sequtils import toSeq
import nimblepkg/packageinfo, nimblepkg/version, nimblepkg/tools, import nimblepkg/packageinfo, nimblepkg/version, nimblepkg/tools,
nimblepkg/download, nimblepkg/config, nimblepkg/common, nimblepkg/download, nimblepkg/config, nimblepkg/common,
nimblepkg/publish, nimblepkg/options, nimblepkg/packageparser, nimblepkg/publish, nimblepkg/options, nimblepkg/packageparser,
nimblepkg/cli, nimblepkg/packageinstaller, nimblepkg/reversedeps nimblepkg/cli, nimblepkg/packageinstaller, nimblepkg/reversedeps,
nimblepkg/nimscriptexecutor
import nimblepkg/nimscriptsupport import nimblepkg/nimscriptsupport
@ -529,28 +530,6 @@ proc execBackend(options: Options) =
[backend, args, bin], showOutput = true) [backend, args, bin], showOutput = true)
display("Success:", "Execution finished", Success, HighPriority) display("Success:", "Execution finished", Success, HighPriority)
proc tempOutArg(file: string): string =
## Returns the `--out` argument to pass to the compiler, using a temp file
let (_, name, _) = splitFile(file)
let dir = getNimbleTempDir() / "tests"
createDir(dir)
result = "--out:" & (dir / name)
proc test(options: Options) =
## Executes all tests
var files = toSeq(walkDir(getCurrentDir() / "tests"))
files.sort do (a, b: auto) -> int:
result = cmp(a.path, b.path)
for file in files:
if file.path.endsWith(".nim") and file.kind in { pcFile, pcLinkToFile }:
var optsCopy = options
optsCopy.action.file = file.path
optsCopy.action.backend = "c -r"
optsCopy.action.compileOptions.add("--path:.")
optsCopy.action.compileOptions.add(file.path.tempOutArg)
execBackend(optsCopy)
proc search(options: Options) = proc search(options: Options) =
## Searches for matches in ``options.action.search``. ## Searches for matches in ``options.action.search``.
## ##
@ -922,25 +901,23 @@ proc develop(options: Options) =
discard downloadPkg(url, pv.ver, meth, options, downloadDir) discard downloadPkg(url, pv.ver, meth, options, downloadDir)
developFromDir(downloadDir, options) developFromDir(downloadDir, options)
proc execHook(options: Options, before: bool): bool = proc test(options: Options) =
## Returns whether to continue. ## Executes all tests.
result = true var files = toSeq(walkDir(getCurrentDir() / "tests"))
var nimbleFile = "" files.sort((a, b) => cmp(a.path, b.path))
try:
nimbleFile = findNimbleFile(getCurrentDir(), true) for file in files:
except NimbleError: return true if file.path.endsWith(".nim") and file.kind in {pcFile, pcLinkToFile}:
# PackageInfos are cached so we can read them as many times as we want. var optsCopy = options.briefClone()
let pkgInfo = getPkgInfoFromFile(nimbleFile, options) optsCopy.action.typ = actionCompile
let actionName = optsCopy.action.file = file.path
if options.action.typ == actionCustom: options.action.command optsCopy.action.backend = "c"
else: ($options.action.typ)[6 .. ^1] optsCopy.action.compileOptions = @[]
let hookExists = optsCopy.action.compileOptions.add("-r")
if before: actionName.normalize in pkgInfo.preHooks optsCopy.action.compileOptions.add("--path:.")
else: actionName.normalize in pkgInfo.postHooks execBackend(optsCopy)
if pkgInfo.isNimScript and hookExists:
let res = execHook(nimbleFile, actionName, before, options) display("Success:", "All tests passed", Success, HighPriority)
if res.success:
result = res.retVal
proc doAction(options: Options) = proc doAction(options: Options) =
if options.showHelp: if options.showHelp:
@ -982,8 +959,6 @@ proc doAction(options: Options) =
listPaths(options) listPaths(options)
of actionBuild: of actionBuild:
build(options) build(options)
of actionTest:
test(options)
of actionCompile, actionDoc: of actionCompile, actionDoc:
execBackend(options) execBackend(options)
of actionInit: of actionInit:
@ -1000,37 +975,19 @@ proc doAction(options: Options) =
of actionNil: of actionNil:
assert false assert false
of actionCustom: of actionCustom:
# Custom command. Attempt to call a NimScript task. let isPreDefined = options.action.command.normalize == "test"
let nimbleFile = findNimbleFile(getCurrentDir(), true)
if not nimbleFile.isNimScript(options):
writeHelp()
let execResult = execTask(nimbleFile, options.action.command, options) var execResult: ExecutionResult[void]
if not execResult.success: if execCustom(options, execResult, failFast=not isPreDefined):
raiseNimbleError(msg = "Could not find task $1 in $2" % if execResult.hasTaskRequestedCommand():
[options.action.command, nimbleFile], doAction(execResult.getOptionsForCommand(options))
hint = "Run `nimble --help` and/or `nimble tasks` for" & else:
" a list of possible commands.") # If there is no task defined for the `test` task, we run the pre-defined
# fallback logic.
if execResult.command.normalize == "nop": if isPreDefined:
display("Warning:", "Using `setCommand 'nop'` is not necessary.", Warning, test(options)
HighPriority) # Run the post hook for `test` in case it exists.
return discard execHook(options, false)
if not execHook(options, false):
return
if execResult.hasTaskRequestedCommand():
var newOptions = initOptions()
newOptions.config = options.config
newOptions.nimbleData = options.nimbleData
parseCommand(execResult.command, newOptions)
for arg in execResult.arguments:
parseArgument(arg, newOptions)
for flag, vals in execResult.flags:
for val in vals:
parseFlag(flag, val, newOptions)
doAction(newOptions)
if options.action.typ != actionCustom: if options.action.typ != actionCustom:
discard execHook(options, false) discard execHook(options, false)

View file

@ -0,0 +1,70 @@
# Copyright (C) Dominik Picheta. All rights reserved.
# BSD License. Look at license.txt for more info.
import os, tables, strutils, sets
import packageparser, common, packageinfo, options, nimscriptsupport, cli
proc execHook*(options: Options, before: bool): bool =
## Returns whether to continue.
result = true
var nimbleFile = ""
try:
nimbleFile = findNimbleFile(getCurrentDir(), true)
except NimbleError: return true
# PackageInfos are cached so we can read them as many times as we want.
let pkgInfo = getPkgInfoFromFile(nimbleFile, options)
let actionName =
if options.action.typ == actionCustom: options.action.command
else: ($options.action.typ)[6 .. ^1]
let hookExists =
if before: actionName.normalize in pkgInfo.preHooks
else: actionName.normalize in pkgInfo.postHooks
if pkgInfo.isNimScript and hookExists:
let res = execHook(nimbleFile, actionName, before, options)
if res.success:
result = res.retVal
proc execCustom*(options: Options,
execResult: var ExecutionResult[void],
failFast = true): bool =
## Executes the custom command using the nimscript backend.
##
## If failFast is true then exceptions will be raised when something is wrong.
## Otherwise this function will just return false.
# Custom command. Attempt to call a NimScript task.
let nimbleFile = findNimbleFile(getCurrentDir(), true)
if not nimbleFile.isNimScript(options) and failFast:
writeHelp()
execResult = execTask(nimbleFile, options.action.command, options)
if not execResult.success:
if not failFast:
return
raiseNimbleError(msg = "Could not find task $1 in $2" %
[options.action.command, nimbleFile],
hint = "Run `nimble --help` and/or `nimble tasks` for" &
" a list of possible commands.")
if execResult.command.normalize == "nop":
display("Warning:", "Using `setCommand 'nop'` is not necessary.", Warning,
HighPriority)
return
if not execHook(options, false):
return
return true
proc getOptionsForCommand*(execResult: ExecutionResult,
options: Options): Options =
## Creates an Options object for the requested command.
var newOptions = options.briefClone()
parseCommand(execResult.command, newOptions)
for arg in execResult.arguments:
parseArgument(arg, newOptions)
for flag, vals in execResult.flags:
for val in vals:
parseFlag(flag, val, newOptions)
return newOptions

View file

@ -454,6 +454,6 @@ proc listTasks*(scriptName: string, options: Options) =
setNimScriptCommand("help") setNimScriptCommand("help")
discard execScript(scriptName, nil, options) discard execScript(scriptName, nil, options)
# TODO: Make the 'task' template generate explicit data structure containing # TODO (#402): Make the 'task' template generate explicit data structure
# all the task names + descriptions. # containing all the task names + descriptions.
cleanup() cleanup()

View file

@ -27,7 +27,7 @@ type
actionNil, actionRefresh, actionInit, actionDump, actionPublish, actionNil, actionRefresh, actionInit, actionDump, actionPublish,
actionInstall, actionSearch, actionInstall, actionSearch,
actionList, actionBuild, actionPath, actionUninstall, actionCompile, actionList, actionBuild, actionPath, actionUninstall, actionCompile,
actionDoc, actionCustom, actionTasks, actionDevelop, actionTest actionDoc, actionCustom, actionTasks, actionDevelop
Action* = object Action* = object
case typ*: ActionType case typ*: ActionType
@ -41,7 +41,7 @@ type
search*: seq[string] # Search string. search*: seq[string] # Search string.
of actionInit, actionDump: of actionInit, actionDump:
projName*: string projName*: string
of actionCompile, actionDoc, actionBuild, actionTest: of actionCompile, actionDoc, actionBuild:
file*: string file*: string
backend*: string backend*: string
compileOptions*: seq[string] compileOptions*: seq[string]
@ -126,8 +126,6 @@ proc parseActionType*(action: string): ActionType =
result = actionPath result = actionPath
of "build": of "build":
result = actionBuild result = actionBuild
of "test":
result = actionTest
of "c", "compile", "js", "cpp", "cc": of "c", "compile", "js", "cpp", "cc":
result = actionCompile result = actionCompile
of "doc", "doc2": of "doc", "doc2":
@ -160,7 +158,7 @@ proc initAction*(options: var Options, key: string) =
case options.action.typ case options.action.typ
of actionInstall, actionPath, actionDevelop, actionUninstall: of actionInstall, actionPath, actionDevelop, actionUninstall:
options.action.packages = @[] options.action.packages = @[]
of actionCompile, actionDoc, actionBuild, actionTest: of actionCompile, actionDoc, actionBuild:
options.action.compileOptions = @[] options.action.compileOptions = @[]
options.action.file = "" options.action.file = ""
if keyNorm == "c" or keyNorm == "compile": options.action.backend = "" if keyNorm == "c" or keyNorm == "compile": options.action.backend = ""
@ -242,7 +240,7 @@ proc parseArgument*(key: string, result: var Options) =
result.action.projName = key result.action.projName = key
of actionCompile, actionDoc: of actionCompile, actionDoc:
result.action.file = key result.action.file = key
of actionList, actionBuild, actionTest, actionPublish: of actionList, actionBuild, actionPublish:
result.showHelp = true result.showHelp = true
of actionCustom: of actionCustom:
result.action.arguments.add(key) result.action.arguments.add(key)
@ -281,7 +279,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) =
result.depsOnly = true result.depsOnly = true
else: else:
wasFlagHandled = false wasFlagHandled = false
of actionCompile, actionDoc, actionBuild, actionTest: of actionCompile, actionDoc, actionBuild:
let prefix = if kind == cmdShortOption: "-" else: "--" let prefix = if kind == cmdShortOption: "-" else: "--"
if val == "": if val == "":
result.action.compileOptions.add(prefix & flag) result.action.compileOptions.add(prefix & flag)
@ -370,3 +368,10 @@ proc getProxy*(options: Options): Proxy =
return newProxy($parsed, auth) return newProxy($parsed, auth)
else: else:
return nil return nil
proc briefClone*(options: Options): Options =
## Clones the few important fields and creates a new Options object.
var newOptions = initOptions()
newOptions.config = options.config
newOptions.nimbleData = options.nimbleData
return newOptions

View file

@ -268,6 +268,7 @@ proc readPackageInfo(nf: NimbleFile, options: Options,
assert fileExists(nf) assert fileExists(nf)
# Check the cache. # Check the cache.
echo(nf, options.pkgInfoCache.hasKey(nf))
if options.pkgInfoCache.hasKey(nf): if options.pkgInfoCache.hasKey(nf):
return options.pkgInfoCache[nf] return options.pkgInfoCache[nf]

View file

@ -0,0 +1 @@
echo("overriden")

View file

@ -0,0 +1,9 @@
version = "0.1.0"
author = "John Doe"
description = "Nimble Test"
license = "BSD"
skipFiles = @["myTester.nim"]
task test, "Custom tester":
exec "nim c -r myTester.nim"

View file

@ -557,22 +557,29 @@ suite "develop feature":
createDir(cloneDir) createDir(cloneDir)
cd cloneDir: cd cloneDir:
let url = "https://github.com/nimble-test/packagea.git" let url = "https://github.com/nimble-test/packagea.git"
let (output, exitCode) = execNimble("develop", "-y", url) let (_, exitCode) = execNimble("develop", "-y", url)
check exitCode == QuitSuccess check exitCode == QuitSuccess
test "Runs passing unit tests": suite "test command":
cd "testsPass": test "Runs passing unit tests":
let (outp, exitCode) = execNimble("test") cd "testCommand/testsPass":
check: exitCode == QuitSuccess let (outp, exitCode) = execNimble("test")
check: outp.processOutput.inLines("First test") check exitCode == QuitSuccess
check: outp.processOutput.inLines("Second test") check outp.processOutput.inLines("First test")
check: outp.processOutput.inLines("Third test") check outp.processOutput.inLines("Second test")
check: outp.processOutput.inLines("Executing my func") check outp.processOutput.inLines("Third test")
check outp.processOutput.inLines("Executing my func")
test "Runs failing unit tests": test "Runs failing unit tests":
cd "testsFail": cd "testCommand/testsFail":
let (outp, exitCode) = execNimble("test") let (outp, exitCode) = execNimble("test")
check: exitCode == QuitFailure check exitCode == QuitFailure
check: outp.processOutput.inLines("First test") check outp.processOutput.inLines("First test")
check: outp.processOutput.inLines("Failing Second test") check outp.processOutput.inLines("Failing Second test")
check: not outp.processOutput.inLines("Third test") check(not outp.processOutput.inLines("Third test"))
test "test command can be overriden":
cd "testCommand/testOverride":
let (outp, exitCode) = execNimble("test")
check exitCode == QuitSuccess
check outp.processOutput.inLines("overriden")