diff --git a/src/nimble.nim b/src/nimble.nim index 3a933aa..883468a 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -13,7 +13,8 @@ from sequtils import toSeq import nimblepkg/packageinfo, nimblepkg/version, nimblepkg/tools, nimblepkg/download, nimblepkg/config, nimblepkg/common, nimblepkg/publish, nimblepkg/options, nimblepkg/packageparser, - nimblepkg/cli, nimblepkg/packageinstaller, nimblepkg/reversedeps + nimblepkg/cli, nimblepkg/packageinstaller, nimblepkg/reversedeps, + nimblepkg/nimscriptexecutor import nimblepkg/nimscriptsupport @@ -529,28 +530,6 @@ proc execBackend(options: Options) = [backend, args, bin], showOutput = true) 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) = ## Searches for matches in ``options.action.search``. ## @@ -922,25 +901,23 @@ proc develop(options: Options) = discard downloadPkg(url, pv.ver, meth, options, downloadDir) developFromDir(downloadDir, options) -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 test(options: Options) = + ## Executes all tests. + var files = toSeq(walkDir(getCurrentDir() / "tests")) + files.sort((a, b) => cmp(a.path, b.path)) + + for file in files: + if file.path.endsWith(".nim") and file.kind in {pcFile, pcLinkToFile}: + var optsCopy = options.briefClone() + optsCopy.action.typ = actionCompile + optsCopy.action.file = file.path + optsCopy.action.backend = "c" + optsCopy.action.compileOptions = @[] + optsCopy.action.compileOptions.add("-r") + optsCopy.action.compileOptions.add("--path:.") + execBackend(optsCopy) + + display("Success:", "All tests passed", Success, HighPriority) proc doAction(options: Options) = if options.showHelp: @@ -982,8 +959,6 @@ proc doAction(options: Options) = listPaths(options) of actionBuild: build(options) - of actionTest: - test(options) of actionCompile, actionDoc: execBackend(options) of actionInit: @@ -1000,37 +975,19 @@ proc doAction(options: Options) = of actionNil: assert false of actionCustom: - # Custom command. Attempt to call a NimScript task. - let nimbleFile = findNimbleFile(getCurrentDir(), true) - if not nimbleFile.isNimScript(options): - writeHelp() + let isPreDefined = options.action.command.normalize == "test" - let execResult = execTask(nimbleFile, options.action.command, options) - if not execResult.success: - 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 - - 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) + var execResult: ExecutionResult[void] + if execCustom(options, execResult, failFast=not isPreDefined): + if execResult.hasTaskRequestedCommand(): + doAction(execResult.getOptionsForCommand(options)) + else: + # If there is no task defined for the `test` task, we run the pre-defined + # fallback logic. + if isPreDefined: + test(options) + # Run the post hook for `test` in case it exists. + discard execHook(options, false) if options.action.typ != actionCustom: discard execHook(options, false) diff --git a/src/nimblepkg/nimscriptexecutor.nim b/src/nimblepkg/nimscriptexecutor.nim new file mode 100644 index 0000000..4e1e3c2 --- /dev/null +++ b/src/nimblepkg/nimscriptexecutor.nim @@ -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 diff --git a/src/nimblepkg/nimscriptsupport.nim b/src/nimblepkg/nimscriptsupport.nim index 6bcf763..7188479 100644 --- a/src/nimblepkg/nimscriptsupport.nim +++ b/src/nimblepkg/nimscriptsupport.nim @@ -454,6 +454,6 @@ proc listTasks*(scriptName: string, options: Options) = setNimScriptCommand("help") discard execScript(scriptName, nil, options) - # TODO: Make the 'task' template generate explicit data structure containing - # all the task names + descriptions. - cleanup() + # TODO (#402): Make the 'task' template generate explicit data structure + # containing all the task names + descriptions. + cleanup() \ No newline at end of file diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index 97eb870..2609254 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -27,7 +27,7 @@ type actionNil, actionRefresh, actionInit, actionDump, actionPublish, actionInstall, actionSearch, actionList, actionBuild, actionPath, actionUninstall, actionCompile, - actionDoc, actionCustom, actionTasks, actionDevelop, actionTest + actionDoc, actionCustom, actionTasks, actionDevelop Action* = object case typ*: ActionType @@ -41,7 +41,7 @@ type search*: seq[string] # Search string. of actionInit, actionDump: projName*: string - of actionCompile, actionDoc, actionBuild, actionTest: + of actionCompile, actionDoc, actionBuild: file*: string backend*: string compileOptions*: seq[string] @@ -126,8 +126,6 @@ proc parseActionType*(action: string): ActionType = result = actionPath of "build": result = actionBuild - of "test": - result = actionTest of "c", "compile", "js", "cpp", "cc": result = actionCompile of "doc", "doc2": @@ -160,7 +158,7 @@ proc initAction*(options: var Options, key: string) = case options.action.typ of actionInstall, actionPath, actionDevelop, actionUninstall: options.action.packages = @[] - of actionCompile, actionDoc, actionBuild, actionTest: + of actionCompile, actionDoc, actionBuild: options.action.compileOptions = @[] options.action.file = "" if keyNorm == "c" or keyNorm == "compile": options.action.backend = "" @@ -242,7 +240,7 @@ proc parseArgument*(key: string, result: var Options) = result.action.projName = key of actionCompile, actionDoc: result.action.file = key - of actionList, actionBuild, actionTest, actionPublish: + of actionList, actionBuild, actionPublish: result.showHelp = true of actionCustom: result.action.arguments.add(key) @@ -281,7 +279,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = result.depsOnly = true else: wasFlagHandled = false - of actionCompile, actionDoc, actionBuild, actionTest: + of actionCompile, actionDoc, actionBuild: let prefix = if kind == cmdShortOption: "-" else: "--" if val == "": result.action.compileOptions.add(prefix & flag) @@ -370,3 +368,10 @@ proc getProxy*(options: Options): Proxy = return newProxy($parsed, auth) else: 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 \ No newline at end of file diff --git a/src/nimblepkg/packageparser.nim b/src/nimblepkg/packageparser.nim index befa513..d7096b5 100644 --- a/src/nimblepkg/packageparser.nim +++ b/src/nimblepkg/packageparser.nim @@ -268,6 +268,7 @@ proc readPackageInfo(nf: NimbleFile, options: Options, assert fileExists(nf) # Check the cache. + echo(nf, options.pkgInfoCache.hasKey(nf)) if options.pkgInfoCache.hasKey(nf): return options.pkgInfoCache[nf] diff --git a/tests/testCommand/testOverride/myTester.nim b/tests/testCommand/testOverride/myTester.nim new file mode 100644 index 0000000..0e1a8f3 --- /dev/null +++ b/tests/testCommand/testOverride/myTester.nim @@ -0,0 +1 @@ +echo("overriden") \ No newline at end of file diff --git a/tests/testCommand/testOverride/pkga.nimble b/tests/testCommand/testOverride/pkga.nimble new file mode 100644 index 0000000..74bef6c --- /dev/null +++ b/tests/testCommand/testOverride/pkga.nimble @@ -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" \ No newline at end of file diff --git a/tests/testsFail/testing123.nim b/tests/testCommand/testsFail/testing123.nim similarity index 100% rename from tests/testsFail/testing123.nim rename to tests/testCommand/testsFail/testing123.nim diff --git a/tests/testsFail/testing123.nimble b/tests/testCommand/testsFail/testing123.nimble similarity index 100% rename from tests/testsFail/testing123.nimble rename to tests/testCommand/testsFail/testing123.nimble diff --git a/tests/testsFail/tests/a.nim b/tests/testCommand/testsFail/tests/a.nim similarity index 100% rename from tests/testsFail/tests/a.nim rename to tests/testCommand/testsFail/tests/a.nim diff --git a/tests/testsFail/tests/b.nim b/tests/testCommand/testsFail/tests/b.nim similarity index 100% rename from tests/testsFail/tests/b.nim rename to tests/testCommand/testsFail/tests/b.nim diff --git a/tests/testsFail/tests/c.nim b/tests/testCommand/testsFail/tests/c.nim similarity index 100% rename from tests/testsFail/tests/c.nim rename to tests/testCommand/testsFail/tests/c.nim diff --git a/tests/testsPass/testing123.nim b/tests/testCommand/testsPass/testing123.nim similarity index 100% rename from tests/testsPass/testing123.nim rename to tests/testCommand/testsPass/testing123.nim diff --git a/tests/testsPass/testing123.nimble b/tests/testCommand/testsPass/testing123.nimble similarity index 100% rename from tests/testsPass/testing123.nimble rename to tests/testCommand/testsPass/testing123.nimble diff --git a/tests/testsPass/tests/one.nim b/tests/testCommand/testsPass/tests/one.nim similarity index 100% rename from tests/testsPass/tests/one.nim rename to tests/testCommand/testsPass/tests/one.nim diff --git a/tests/testsPass/tests/three.nim b/tests/testCommand/testsPass/tests/three.nim similarity index 100% rename from tests/testsPass/tests/three.nim rename to tests/testCommand/testsPass/tests/three.nim diff --git a/tests/testsPass/tests/two.nim b/tests/testCommand/testsPass/tests/two.nim similarity index 100% rename from tests/testsPass/tests/two.nim rename to tests/testCommand/testsPass/tests/two.nim diff --git a/tests/tester.nim b/tests/tester.nim index aed84c2..582e5ac 100644 --- a/tests/tester.nim +++ b/tests/tester.nim @@ -557,22 +557,29 @@ suite "develop feature": createDir(cloneDir) cd cloneDir: 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 -test "Runs passing unit tests": - cd "testsPass": - let (outp, exitCode) = execNimble("test") - check: exitCode == QuitSuccess - check: outp.processOutput.inLines("First test") - check: outp.processOutput.inLines("Second test") - check: outp.processOutput.inLines("Third test") - check: outp.processOutput.inLines("Executing my func") +suite "test command": + test "Runs passing unit tests": + cd "testCommand/testsPass": + let (outp, exitCode) = execNimble("test") + check exitCode == QuitSuccess + check outp.processOutput.inLines("First test") + check outp.processOutput.inLines("Second test") + check outp.processOutput.inLines("Third test") + check outp.processOutput.inLines("Executing my func") -test "Runs failing unit tests": - cd "testsFail": - let (outp, exitCode) = execNimble("test") - check: exitCode == QuitFailure - check: outp.processOutput.inLines("First test") - check: outp.processOutput.inLines("Failing Second test") - check: not outp.processOutput.inLines("Third test") + test "Runs failing unit tests": + cd "testCommand/testsFail": + let (outp, exitCode) = execNimble("test") + check exitCode == QuitFailure + check outp.processOutput.inLines("First test") + check outp.processOutput.inLines("Failing Second 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") \ No newline at end of file