This commit is contained in:
Dominik Picheta 2019-09-21 23:52:28 +01:00
commit 46dc98bb62
3 changed files with 60 additions and 21 deletions

View file

@ -4,9 +4,10 @@
## Implements the new configuration system for Nimble. Uses Nim as a ## Implements the new configuration system for Nimble. Uses Nim as a
## scripting language. ## scripting language.
import version, options, cli, tools
import hashes, json, os, strutils, tables, times, osproc, strtabs import hashes, json, os, strutils, tables, times, osproc, strtabs
import version, options, cli, tools
type type
Flags = TableRef[string, seq[string]] Flags = TableRef[string, seq[string]]
ExecutionResult*[T] = object ExecutionResult*[T] = object
@ -15,13 +16,23 @@ type
arguments*: seq[string] arguments*: seq[string]
flags*: Flags flags*: Flags
retVal*: T retVal*: T
stdout*: string
const const
internalCmd = "e" internalCmd = "e"
nimscriptApi = staticRead("nimscriptapi.nim") nimscriptApi = staticRead("nimscriptapi.nim")
printPkgInfo = "printPkgInfo"
proc execNimscript(nimsFile, projectDir, actionName: string, options: Options): proc isCustomTask(actionName: string, options: Options): bool =
tuple[output: string, exitCode: int] = options.action.typ == actionCustom and actionName != printPkgInfo
proc needsLiveOutput(actionName: string, options: Options, isHook: bool): bool =
let isCustomTask = isCustomTask(actionName, options)
return isCustomTask or isHook or actionName == ""
proc execNimscript(
nimsFile, projectDir, actionName: string, options: Options, isHook: bool
): tuple[output: string, exitCode: int, stdout: string] =
let let
nimsFileCopied = projectDir / nimsFile.splitFile().name & "_" & getProcessId() & ".nims" nimsFileCopied = projectDir / nimsFile.splitFile().name & "_" & getProcessId() & ".nims"
outFile = getNimbleTempDir() & ".out" outFile = getNimbleTempDir() & ".out"
@ -41,7 +52,7 @@ proc execNimscript(nimsFile, projectDir, actionName: string, options: Options):
var cmd = ( var cmd = (
"nim e $# -p:$# $# $# $#" % [ "nim e $# -p:$# $# $# $#" % [
"--hints:off --warning[UnusedImport]:off --verbosity:0", "--hints:off --verbosity:0",
(getTempDir() / "nimblecache").quoteShell, (getTempDir() / "nimblecache").quoteShell,
nimsFileCopied.quoteShell, nimsFileCopied.quoteShell,
outFile.quoteShell, outFile.quoteShell,
@ -49,7 +60,8 @@ proc execNimscript(nimsFile, projectDir, actionName: string, options: Options):
] ]
).strip() ).strip()
if options.action.typ == actionCustom and actionName != "printPkgInfo": let isCustomTask = isCustomTask(actionName, options)
if isCustomTask:
for i in options.action.arguments: for i in options.action.arguments:
cmd &= " " & i.quoteShell() cmd &= " " & i.quoteShell()
for key, val in options.action.flags.pairs(): for key, val in options.action.flags.pairs():
@ -59,7 +71,12 @@ proc execNimscript(nimsFile, projectDir, actionName: string, options: Options):
displayDebug("Executing " & cmd) displayDebug("Executing " & cmd)
result.exitCode = execCmd(cmd) if needsLiveOutput(actionName, options, isHook):
result.exitCode = execCmd(cmd)
else:
# We want to capture any possible errors when parsing a .nimble
# file's metadata. See #710.
(result.stdout, result.exitCode) = execCmdEx(cmd)
if outFile.fileExists(): if outFile.fileExists():
result.output = outFile.readFile() result.output = outFile.readFile()
if options.shouldRemoveTmp(outFile): if options.shouldRemoveTmp(outFile):
@ -112,27 +129,29 @@ proc getIniFile*(scriptName: string, options: Options): string =
scriptName.getLastModificationTime() scriptName.getLastModificationTime()
if not isIniResultCached: if not isIniResultCached:
let let (output, exitCode, stdout) = execNimscript(
(output, exitCode) = nimsFile, scriptName.parentDir(), printPkgInfo, options, isHook=false
execNimscript(nimsFile, scriptName.parentDir(), "printPkgInfo", options) )
if exitCode == 0 and output.len != 0: if exitCode == 0 and output.len != 0:
result.writeFile(output) result.writeFile(output)
else: else:
raise newException(NimbleError, output & "\nprintPkgInfo() failed") raise newException(NimbleError, stdout & "\nprintPkgInfo() failed")
proc execScript(scriptName, actionName: string, options: Options): proc execScript(
ExecutionResult[bool] = scriptName, actionName: string, options: Options, isHook: bool
let ): ExecutionResult[bool] =
nimsFile = getNimsFile(scriptName, options) let nimsFile = getNimsFile(scriptName, options)
let let (output, exitCode, stdout) =
(output, exitCode) = execNimscript(nimsFile, scriptName.parentDir(), actionName, options) execNimscript(
nimsFile, scriptName.parentDir(), actionName, options, isHook
)
if exitCode != 0: if exitCode != 0:
let errMsg = let errMsg =
if output.len != 0: if stdout.len != 0:
output stdout
else: else:
"Exception raised during nimble script execution" "Exception raised during nimble script execution"
raise newException(NimbleError, errMsg) raise newException(NimbleError, errMsg)
@ -164,7 +183,7 @@ proc execTask*(scriptName, taskName: string,
display("Executing", "task $# in $#" % [taskName, scriptName], display("Executing", "task $# in $#" % [taskName, scriptName],
priority = HighPriority) priority = HighPriority)
result = execScript(scriptName, taskName, options) result = execScript(scriptName, taskName, options, isHook=false)
proc execHook*(scriptName, actionName: string, before: bool, proc execHook*(scriptName, actionName: string, before: bool,
options: Options): ExecutionResult[bool] = options: Options): ExecutionResult[bool] =
@ -178,11 +197,11 @@ proc execHook*(scriptName, actionName: string, before: bool,
display("Attempting", "to execute hook $# in $#" % [hookName, scriptName], display("Attempting", "to execute hook $# in $#" % [hookName, scriptName],
priority = MediumPriority) priority = MediumPriority)
result = execScript(scriptName, hookName, options) result = execScript(scriptName, hookName, options, isHook=true)
proc hasTaskRequestedCommand*(execResult: ExecutionResult): bool = proc hasTaskRequestedCommand*(execResult: ExecutionResult): bool =
## Determines whether the last executed task used ``setCommand`` ## Determines whether the last executed task used ``setCommand``
return execResult.command != internalCmd return execResult.command != internalCmd
proc listTasks*(scriptName: string, options: Options) = proc listTasks*(scriptName: string, options: Options) =
discard execScript(scriptName, "", options) discard execScript(scriptName, "", options, isHook=false)

View file

@ -0,0 +1,13 @@
# Package
version = "0.1.0"
author = "Dominik Picheta"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"
thisFieldDoesNotExist = "hello"
# Dependencies
requires "nim >= 0.20.0"

View file

@ -86,6 +86,13 @@ test "depsOnly + flag order test":
check(not output.contains("Success: packagebin2 installed successfully.")) check(not output.contains("Success: packagebin2 installed successfully."))
check exitCode == QuitSuccess check exitCode == QuitSuccess
test "nimscript evaluation error message":
cd "invalidPackage":
var (output, exitCode) = execNimble("check")
let lines = output.strip.processOutput()
check(lines[^2].endsWith("Error: undeclared identifier: 'thisFieldDoesNotExist'"))
check exitCode == QuitFailure
test "caching of nims and ini detects changes": test "caching of nims and ini detects changes":
cd "caching": cd "caching":
var (output, exitCode) = execNimble("dump") var (output, exitCode) = execNimble("dump")