From 46dc98bb62d8250af9f13f2f3628d67a462f50d3 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 21 Sep 2019 23:52:28 +0100 Subject: [PATCH] Fixes #710. --- src/nimblepkg/nimscriptwrapper.nim | 61 ++++++++++++++-------- tests/invalidPackage/invalidPackage.nimble | 13 +++++ tests/tester.nim | 7 +++ 3 files changed, 60 insertions(+), 21 deletions(-) create mode 100644 tests/invalidPackage/invalidPackage.nimble diff --git a/src/nimblepkg/nimscriptwrapper.nim b/src/nimblepkg/nimscriptwrapper.nim index 23c23c9..baad4e7 100644 --- a/src/nimblepkg/nimscriptwrapper.nim +++ b/src/nimblepkg/nimscriptwrapper.nim @@ -4,9 +4,10 @@ ## Implements the new configuration system for Nimble. Uses Nim as a ## scripting language. -import version, options, cli, tools import hashes, json, os, strutils, tables, times, osproc, strtabs +import version, options, cli, tools + type Flags = TableRef[string, seq[string]] ExecutionResult*[T] = object @@ -15,13 +16,23 @@ type arguments*: seq[string] flags*: Flags retVal*: T + stdout*: string const internalCmd = "e" nimscriptApi = staticRead("nimscriptapi.nim") + printPkgInfo = "printPkgInfo" -proc execNimscript(nimsFile, projectDir, actionName: string, options: Options): - tuple[output: string, exitCode: int] = +proc isCustomTask(actionName: string, options: Options): bool = + 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 nimsFileCopied = projectDir / nimsFile.splitFile().name & "_" & getProcessId() & ".nims" outFile = getNimbleTempDir() & ".out" @@ -41,7 +52,7 @@ proc execNimscript(nimsFile, projectDir, actionName: string, options: Options): var cmd = ( "nim e $# -p:$# $# $# $#" % [ - "--hints:off --warning[UnusedImport]:off --verbosity:0", + "--hints:off --verbosity:0", (getTempDir() / "nimblecache").quoteShell, nimsFileCopied.quoteShell, outFile.quoteShell, @@ -49,7 +60,8 @@ proc execNimscript(nimsFile, projectDir, actionName: string, options: Options): ] ).strip() - if options.action.typ == actionCustom and actionName != "printPkgInfo": + let isCustomTask = isCustomTask(actionName, options) + if isCustomTask: for i in options.action.arguments: cmd &= " " & i.quoteShell() for key, val in options.action.flags.pairs(): @@ -59,7 +71,12 @@ proc execNimscript(nimsFile, projectDir, actionName: string, options: Options): 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(): result.output = outFile.readFile() if options.shouldRemoveTmp(outFile): @@ -112,27 +129,29 @@ proc getIniFile*(scriptName: string, options: Options): string = scriptName.getLastModificationTime() if not isIniResultCached: - let - (output, exitCode) = - execNimscript(nimsFile, scriptName.parentDir(), "printPkgInfo", options) + let (output, exitCode, stdout) = execNimscript( + nimsFile, scriptName.parentDir(), printPkgInfo, options, isHook=false + ) if exitCode == 0 and output.len != 0: result.writeFile(output) else: - raise newException(NimbleError, output & "\nprintPkgInfo() failed") + raise newException(NimbleError, stdout & "\nprintPkgInfo() failed") -proc execScript(scriptName, actionName: string, options: Options): - ExecutionResult[bool] = - let - nimsFile = getNimsFile(scriptName, options) +proc execScript( + scriptName, actionName: string, options: Options, isHook: bool +): ExecutionResult[bool] = + let nimsFile = getNimsFile(scriptName, options) - let - (output, exitCode) = execNimscript(nimsFile, scriptName.parentDir(), actionName, options) + let (output, exitCode, stdout) = + execNimscript( + nimsFile, scriptName.parentDir(), actionName, options, isHook + ) if exitCode != 0: let errMsg = - if output.len != 0: - output + if stdout.len != 0: + stdout else: "Exception raised during nimble script execution" raise newException(NimbleError, errMsg) @@ -164,7 +183,7 @@ proc execTask*(scriptName, taskName: string, display("Executing", "task $# in $#" % [taskName, scriptName], priority = HighPriority) - result = execScript(scriptName, taskName, options) + result = execScript(scriptName, taskName, options, isHook=false) proc execHook*(scriptName, actionName: string, before: bool, options: Options): ExecutionResult[bool] = @@ -178,11 +197,11 @@ proc execHook*(scriptName, actionName: string, before: bool, display("Attempting", "to execute hook $# in $#" % [hookName, scriptName], priority = MediumPriority) - result = execScript(scriptName, hookName, options) + result = execScript(scriptName, hookName, options, isHook=true) proc hasTaskRequestedCommand*(execResult: ExecutionResult): bool = ## Determines whether the last executed task used ``setCommand`` return execResult.command != internalCmd proc listTasks*(scriptName: string, options: Options) = - discard execScript(scriptName, "", options) + discard execScript(scriptName, "", options, isHook=false) diff --git a/tests/invalidPackage/invalidPackage.nimble b/tests/invalidPackage/invalidPackage.nimble new file mode 100644 index 0000000..08fcfcb --- /dev/null +++ b/tests/invalidPackage/invalidPackage.nimble @@ -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" diff --git a/tests/tester.nim b/tests/tester.nim index efa0107..32d16a0 100644 --- a/tests/tester.nim +++ b/tests/tester.nim @@ -86,6 +86,13 @@ test "depsOnly + flag order test": check(not output.contains("Success: packagebin2 installed successfully.")) 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": cd "caching": var (output, exitCode) = execNimble("dump")