From c7b97bb206c459715fdfe5b082928d21191cd7ab Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 15 Oct 2017 15:28:29 +0100 Subject: [PATCH] Implements `check` command. --- readme.markdown | 14 +++++++++++ src/nimble.nim | 21 +++++++++++++++++ src/nimblepkg/cli.nim | 1 - src/nimblepkg/nimscriptexecutor.nim | 5 ++++ src/nimblepkg/options.nim | 12 +++++++--- src/nimblepkg/packageparser.nim | 10 ++++++++ tests/tester.nim | 36 ++++++++++++++++++++++++++++- 7 files changed, 94 insertions(+), 5 deletions(-) diff --git a/readme.markdown b/readme.markdown index b479d77..4ebadcf 100644 --- a/readme.markdown +++ b/readme.markdown @@ -129,6 +129,20 @@ a third-party package list. Package lists can be specified in Nimble's config. Take a look at the config section below to see how to do this. +### nimble check + +The ``check`` command will read your package's .nimble file. It will then +verify that the package's structure is valid. + +Example: + + $ nimble check + Error: Package 'x' has an incorrect structure. It should contain a single directory hierarchy for source files, named 'x', but file 'foobar.nim' is in a directory named 'incorrect' instead. This will be an error in the future. + Hint: If 'incorrect' contains source files for building 'x', rename it to 'x'. Otherwise, prevent its installation by adding `skipDirs = @["incorrect"]` to the .nimble file. + Failure: Validation failed + + + ### nimble install The ``install`` command will download and install a package. You need to pass diff --git a/src/nimble.nim b/src/nimble.nim index 985f1fe..f27410a 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -919,6 +919,25 @@ proc test(options: Options) = display("Success:", "All tests passed", Success, HighPriority) +proc check(options: Options) = + ## Validates a package a in the current working directory. + let nimbleFile = findNimbleFile(getCurrentDir(), true) + var error: ValidationError + var pkgInfo: PackageInfo + var validationResult = false + try: + validationResult = validate(nimbleFile, options, error, pkgInfo) + except: + raiseNimbleError("Could not validate package:\n" & getCurrentExceptionMsg()) + + if validationResult: + display("Success:", pkgInfo.name & " is valid!", Success, HighPriority) + else: + display("Error:", error.msg, Error, HighPriority) + display("Hint:", error.hint, Warning, HighPriority) + display("Failure:", "Validation failed", Error, HighPriority) + quit(QuitFailure) + proc doAction(options: Options) = if options.showHelp: writeHelp() @@ -972,6 +991,8 @@ proc doAction(options: Options) = listTasks(options) of actionDevelop: develop(options) + of actionCheck: + check(options) of actionNil: assert false of actionCustom: diff --git a/src/nimblepkg/cli.nim b/src/nimblepkg/cli.nim index 0d2a906..0bd16cc 100644 --- a/src/nimblepkg/cli.nim +++ b/src/nimblepkg/cli.nim @@ -82,7 +82,6 @@ proc displayLine(category, line: string, displayType: DisplayType, proc display*(category, msg: string, displayType = Message, priority = MediumPriority) = - # Don't print any Warning, Message or Success messages when suppression of # warnings is enabled. That is, unless the user asked for --verbose output. if globalCLI.suppressMessages and displayType >= Warning and diff --git a/src/nimblepkg/nimscriptexecutor.nim b/src/nimblepkg/nimscriptexecutor.nim index 4e1e3c2..70fc165 100644 --- a/src/nimblepkg/nimscriptexecutor.nim +++ b/src/nimblepkg/nimscriptexecutor.nim @@ -8,6 +8,11 @@ import packageparser, common, packageinfo, options, nimscriptsupport, cli proc execHook*(options: Options, before: bool): bool = ## Returns whether to continue. result = true + + # For certain commands hooks should not be evaluated. + if options.action.typ in noHookActions: + return + var nimbleFile = "" try: nimbleFile = findNimbleFile(getCurrentDir(), true) diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index 81115da..3b2c465 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -27,11 +27,11 @@ type actionNil, actionRefresh, actionInit, actionDump, actionPublish, actionInstall, actionSearch, actionList, actionBuild, actionPath, actionUninstall, actionCompile, - actionDoc, actionCustom, actionTasks, actionDevelop + actionDoc, actionCustom, actionTasks, actionDevelop, actionCheck Action* = object case typ*: ActionType - of actionNil, actionList, actionPublish, actionTasks: nil + of actionNil, actionList, actionPublish, actionTasks, actionCheck: nil of actionRefresh: optionalURL*: string # Overrides default package list. of actionInstall, actionPath, actionUninstall, actionDevelop: @@ -60,6 +60,8 @@ Commands: develop [pkgname, ...] Clones a list of packages for development. Symlinks the cloned packages or any package in the current working directory. + check Verifies the validity of a package in the + current working directory. init [pkgname] Initializes a new Nimble project. publish Publishes a package on nim-lang/packages. The current working directory needs to be the @@ -105,6 +107,8 @@ For more information read the Github readme: https://github.com/nim-lang/nimble#readme """ +const noHookActions* = {actionCheck} + proc writeHelp*(quit=true) = echo(help) if quit: @@ -151,6 +155,8 @@ proc parseActionType*(action: string): ActionType = result = actionTasks of "develop": result = actionDevelop + of "check": + result = actionCheck else: result = actionCustom @@ -178,7 +184,7 @@ proc initAction*(options: var Options, key: string) = options.action.command = key options.action.arguments = @[] options.action.flags = newStringTable() - of actionPublish, actionList, actionTasks, + of actionPublish, actionList, actionTasks, actionCheck, actionNil: discard proc prompt*(options: Options, question: string): bool = diff --git a/src/nimblepkg/packageparser.nim b/src/nimblepkg/packageparser.nim index befa513..f3e10f6 100644 --- a/src/nimblepkg/packageparser.nim +++ b/src/nimblepkg/packageparser.nim @@ -329,6 +329,16 @@ proc readPackageInfo(nf: NimbleFile, options: Options, validateVersion(result.version) validatePackageInfo(result, options) +proc validate*(file: NimbleFile, options: Options, + error: var ValidationError, pkgInfo: var PackageInfo): bool = + try: + pkgInfo = readPackageInfo(file, options) + except ValidationError as exc: + error = exc[] + return false + + return true + proc getPkgInfoFromFile*(file: NimbleFile, options: Options): PackageInfo = ## Reads the specified .nimble file and returns its data as a PackageInfo ## object. Any validation errors are handled and displayed as warnings. diff --git a/tests/tester.nim b/tests/tester.nim index ac38812..d780f40 100644 --- a/tests/tester.nim +++ b/tests/tester.nim @@ -593,4 +593,38 @@ suite "test command": cd "testCommand/testOverride": let (outp, exitCode) = execNimble("test") check exitCode == QuitSuccess - check outp.processOutput.inLines("overriden") \ No newline at end of file + check outp.processOutput.inLines("overriden") + +suite "check command": + test "can succeed package": + cd "binaryPackage/v1": + let (outp, exitCode) = execNimble("check") + check exitCode == QuitSuccess + check outp.processOutput.inLines("success") + check outp.processOutput.inLines("binaryPackage is valid") + + cd "packageStructure/a": + let (outp, exitCode) = execNimble("check") + check exitCode == QuitSuccess + check outp.processOutput.inLines("success") + check outp.processOutput.inLines("a is valid") + + cd "packageStructure/b": + let (outp, exitCode) = execNimble("check") + check exitCode == QuitSuccess + check outp.processOutput.inLines("success") + check outp.processOutput.inLines("b is valid") + + cd "packageStructure/c": + let (outp, exitCode) = execNimble("check") + check exitCode == QuitSuccess + check outp.processOutput.inLines("success") + check outp.processOutput.inLines("c is valid") + + test "can fail package": + cd "packageStructure/x": + let (outp, exitCode) = execNimble("check") + check exitCode == QuitFailure + check outp.processOutput.inLines("failure") + check outp.processOutput.inLines("validation failed") + check outp.processOutput.inLines("package 'x' has an incorrect structure") \ No newline at end of file