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:
parent
6a851f5b87
commit
301a366dd2
18 changed files with 150 additions and 100 deletions
105
src/nimble.nim
105
src/nimble.nim
|
|
@ -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)
|
||||||
|
|
|
||||||
70
src/nimblepkg/nimscriptexecutor.nim
Normal file
70
src/nimblepkg/nimscriptexecutor.nim
Normal 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
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
||||||
1
tests/testCommand/testOverride/myTester.nim
Normal file
1
tests/testCommand/testOverride/myTester.nim
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
echo("overriden")
|
||||||
9
tests/testCommand/testOverride/pkga.nimble
Normal file
9
tests/testCommand/testOverride/pkga.nimble
Normal 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"
|
||||||
|
|
@ -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")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue