Compare commits

...
Sign in to create a new pull request.

39 commits

Author SHA1 Message Date
Timothee Cour
a10691bdf2
show cmd used with --verbose (even on success); fix #783 (#781)
* show cmd used with --verbose (even on success)

* honor -p:-u:release

* address comment

* remove --showCmds flag

* remove quoteShell

* fix #783

* Revert "fix #783"

This reverts commit af0ac004c00f17e9983c63ab99e40cd38ba6aaa4.

* fix #783 by fixing the gist instead

* Revert "fix #783 by fixing the gist instead" now that upstream gist was updated with my patch

This reverts commit 8bec86039d8335af152acf238ab14d0268e003e5.
2020-03-26 23:14:09 +00:00
Daniel M
68a9c4c955 fix and improve the behavior of nimble run
quote arguments appropriately:
  - whitespace in arguments is preserved;
    previously arguments with whitespace were split
  - quotes are now escaped

the exit code of the command that has been "run"
is re-used when nimble exits

show the output of the "run" command
regardless of whether nimble is debugging
2020-02-23 16:01:14 +00:00
Ganesh Viswanathan
27d56f8e9f Remove ~/.nimble from cache 2020-02-11 21:43:41 +00:00
Ganesh Viswanathan
85e5bc7c37 Use travis gist 2020-02-07 00:12:25 +00:00
inv2004
9391fbc56d Run can work without additional option if only one bin in .nimble (#761)
* nimble run can work if only one binary in config

* usage changed

* runFile is option now

* usage updated

* small refactoring to reduce condition

* setRunOptions fix

* some code optimisation
2020-01-17 22:15:34 +00:00
Taylor Hoff
e9d45ca683 Capitalize the "D" in srcDir to avoid errors when using styleChecks
Fixes #740
2019-11-19 22:00:15 +00:00
Xie Yanbo
16ba5db44e tests' config file should be config.nims
which is created by `nimble init`.
2019-11-10 15:30:38 +00:00
itmuckel
051cfa6cd3 Add '==' as operator for pinning versions. 2019-11-09 12:48:00 +00:00
Dominik Picheta
a8a5bdd863
Fixes #734 2019-10-29 22:43:04 +00:00
yuchunzhou
bbb586dbfc add vcs to the new created project (#729)
* add git vcs and a default .nim.cfg file to the new created project

* remove the gitapi dependency

* add vcs support for new nimble project

* add vcs support for new nimble project

* update pull request #729

* add --git/hg flag instead of --vcs flag for nimble init command
2019-10-28 21:28:46 +00:00
Dominik Picheta
b3abee937d Add tests for #666. 2019-10-24 23:26:21 +01:00
yuchunzhou
703abe3d41 fix #725 2019-10-24 00:20:40 +01:00
Ganesh Viswanathan
5bb795a364 Export initOptions for choosenim 2019-10-23 23:22:00 +01:00
genotrance
a2ec2db8f2
Enable Windows CI (#714)
Also fix #676
2019-10-03 18:38:51 -05:00
Dominik Picheta
4007b2a778 Fixes nimble run on Windows.
Cherry picked from 331a33711d
2019-09-23 00:09:26 +01:00
Dominik Picheta
0ed8e6403c Implicitly disable package validation for run/build/compile. 2019-09-22 22:22:21 +01:00
Dominik Picheta
901afa8c71 Further fix for #432. 2019-09-22 22:13:31 +01:00
Dominik Picheta
3625c1f861 Expand Nimble readme slightly (installation/nimble-run). 2019-09-22 21:36:50 +01:00
Dominik Picheta
b68f7849e6 Add 0.11.0 changelog. 2019-09-22 21:21:26 +01:00
Dominik Picheta
1db54cc736 Fixes some small input validation errors and help text. 2019-09-22 18:11:28 +01:00
Dominik Picheta
10e22fec98 Move issue 432 test to the bottom of tester to fix broken uninstall test. 2019-09-22 17:58:51 +01:00
Dominik Picheta
fe252c6ed6 Fixes #432. Fixes #672. 2019-09-22 16:37:47 +01:00
Dominik Picheta
281a1d129a Fixes #708. Refs #571.
Output from Nimble scripts' top-level statements is now
only visible with --verbose.
2019-09-22 14:39:22 +01:00
Dominik Picheta
a703de5dbd Attempt to reproduce #564. 2019-09-22 13:58:59 +01:00
Dominik Picheta
46dc98bb62 Fixes #710. 2019-09-22 13:34:54 +01:00
Dominik Picheta
c85cdfd814 Fixes #706. No more unused import warnings. 2019-09-22 12:00:15 +01:00
Dominik Picheta
5ea2ac34fe Update CI to test against latest Nim HEAD commit. 2019-09-22 11:53:03 +01:00
Dominik Picheta
da3f70cb98 Fixes #713 and adds test for --depsOnly. 2019-09-22 11:48:00 +01:00
Dominik Picheta
419eba036b Improve error message when there are no packages to uninstall. 2019-09-22 11:48:00 +01:00
Dominik Picheta
137bb1ed07 Fixes #606. Build before/after hook executed every time package is built. 2019-09-22 11:26:57 +01:00
Dominik Picheta
4a2aaa07dc Implements NimblePkgVersion define. Fixes #625. 2019-09-22 10:00:50 +01:00
Dominik Picheta
28ff2e04a7 Fixes tests on 0.19.6. 2019-09-22 00:15:37 +01:00
Dominik Picheta
55dd892aab Fixes #631. Test command now respects backend. 2019-09-22 00:11:28 +01:00
Dominik Picheta
c834faf60e Implements nimble run. Fixes #614. 2019-09-21 23:34:02 +01:00
Dominik Picheta
36c4a39674 Temp files are no longer removed when --debug is present. 2019-09-21 22:54:08 +01:00
Dominik Picheta
445ecfe946 Fixes #649. The dump command now has implicit -y. 2019-09-21 13:02:04 +01:00
Dominik Picheta
3eae8d7d61 Add examples to tag prompt in nimble publish. 2019-09-21 12:46:42 +01:00
Araq
bc8856632a version bump to 0.11.0 2019-09-20 20:10:06 +01:00
Araq
8bdc054817 fixes #703 2019-09-20 20:09:37 +01:00
31 changed files with 751 additions and 165 deletions

View file

@ -1,4 +1,5 @@
os: os:
- windows
- linux - linux
- osx - osx
@ -7,23 +8,17 @@ language: c
env: env:
- BRANCH=0.19.6 - BRANCH=0.19.6
- BRANCH=0.20.2 - BRANCH=0.20.2
- BRANCH=1.0.6
# This is the latest working Nim version against which Nimble is being tested # This is the latest working Nim version against which Nimble is being tested
- BRANCH=#212ae2f1257628bd5d1760593ce0a1bad768831a - BRANCH=#ab525cc48abdbbbed1f772e58e9fe21474f70f07
cache: cache:
directories: directories:
- "$HOME/.choosenim/toolchains/nim-0.19.6" - "$HOME/.choosenim"
- "$HOME/.choosenim/toolchains/nim-0.20.2"
install: install:
- export CHOOSENIM_CHOOSE_VERSION=$BRANCH - curl https://gist.github.com/genotrance/fb53504a4fba88bc5201d3783df5c522/raw/travis.sh -LsSf -o travis.sh
- | - source travis.sh
curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh
sh init.sh -y
before_script:
- export CHOOSENIM_NO_ANALYTICS=1
- export PATH=$HOME/.nimble/bin:$PATH
script: script:
- cd tests - cd tests

View file

@ -3,7 +3,33 @@
# Nimble changelog # Nimble changelog
## 0.11.0 - 22/09/2019
This is a major release containing nearly 60 commits. Most changes are
bug fixes, but this release also includes a couple new features:
- Binaries can now be built and run using the new ``run`` command.
- The ``NimblePkgVersion`` is now defined so you can easily get the package
version in your source code
([example](https://github.com/nim-lang/nimble/blob/4a2aaa07d/tests/nimbleVersionDefine/src/nimbleVersionDefine.nim)).
Some other highlights:
- Temporary files are now kept when the ``--debug`` flag is used.
- Fixed dependency resolution issues with "#head" packages (#432 and #672).
- The `install` command can now take Nim compiler flags via the new
``--passNim`` flag.
- Command line arguments are now passed properly to tasks (#633).
- The ``test`` command now respects the specified backend (#631).
- The ``dump`` command will no longer prompt and now has an implicit ``-y``.
- Fixed bugs with the new nimscript executor (#665).
- Fixed multiple downloads and installs of the same package (#678). - Fixed multiple downloads and installs of the same package (#678).
- Nimble init no longer overwrites existing files (#581).
- Fixed incorrect submodule version being pulled when in a non-master branch (#675).
----
Full changelog: https://github.com/nim-lang/nimble/compare/v0.10.2...v0.11.0
## 0.10.2 - 03/06/2019 ## 0.10.2 - 03/06/2019

View file

@ -1,6 +1,6 @@
# Package # Package
version = "0.10.2" version = "0.11.0"
author = "Dominik Picheta" author = "Dominik Picheta"
description = "Nim package manager." description = "Nim package manager."
license = "BSD" license = "BSD"

View file

@ -15,6 +15,7 @@ Interested in learning **how to create a package**? Skip directly to that sectio
- [nimble install](#nimble-install) - [nimble install](#nimble-install)
- [nimble uninstall](#nimble-uninstall) - [nimble uninstall](#nimble-uninstall)
- [nimble build](#nimble-build) - [nimble build](#nimble-build)
- [nimble run](#nimble-run)
- [nimble c](#nimble-c) - [nimble c](#nimble-c)
- [nimble list](#nimble-list) - [nimble list](#nimble-list)
- [nimble search](#nimble-search) - [nimble search](#nimble-search)
@ -74,10 +75,15 @@ not need to install Nimble manually**.
But in case you still want to install Nimble manually, you can follow the But in case you still want to install Nimble manually, you can follow the
following instructions. following instructions.
There are two ways to install Nimble manually. The first is using the There are two ways to install Nimble manually. Using ``koch`` and using Nimble
``koch`` tool included in the Nim distribution and itself.
### Using koch
The ``koch`` tool is included in the Nim distribution and
[repository](https://github.com/nim-lang/Nim/blob/devel/koch.nim). [repository](https://github.com/nim-lang/Nim/blob/devel/koch.nim).
Simply execute the following command to compile and install Nimble. Simply navigate to the location of your Nim installation and execute the
following command to compile and install Nimble.
``` ```
./koch nimble ./koch nimble
@ -86,6 +92,19 @@ Simply execute the following command to compile and install Nimble.
This will clone the Nimble repository, compile Nimble and copy it into This will clone the Nimble repository, compile Nimble and copy it into
Nim's bin directory. Nim's bin directory.
### Using Nimble
In most cases you will already have Nimble installed, you can install a newer
version of Nimble by simply running the following command:
```
nimble install nimble
```
This will download the latest release of Nimble and install it on your system.
Note that you must have `~/.nimble/bin` in your PATH for this to work, if you're
using choosenim then you likely already have this set up correctly.
## Nimble usage ## Nimble usage
@ -153,12 +172,13 @@ example:
This is of course Git-specific, for Mercurial, use ``tip`` instead of ``head``. A This is of course Git-specific, for Mercurial, use ``tip`` instead of ``head``. A
branch, tag, or commit hash may also be specified in the place of ``head``. branch, tag, or commit hash may also be specified in the place of ``head``.
Instead of specifying a VCS branch, you may also specify a version range, for Instead of specifying a VCS branch, you may also specify a concrete version or a
example: version range, for example:
$ nimble install nimgame@0.5
$ nimble install nimgame@"> 0.5" $ nimble install nimgame@"> 0.5"
In this case a version which is greater than ``0.5`` will be installed. The latter command will install a version which is greater than ``0.5``.
If you don't specify a parameter and there is a ``package.nimble`` file in your If you don't specify a parameter and there is a ``package.nimble`` file in your
current working directory then Nimble will install the package residing in current working directory then Nimble will install the package residing in
@ -219,6 +239,13 @@ flags, i.e. a debug build which includes stack traces but no GDB debug
information. The ``install`` command will build the package in release mode information. The ``install`` command will build the package in release mode
instead. instead.
### nimble run
The ``run`` command can be used to build and run any binary specified in your
package's ``bin`` list. You can pass any compilation flags you wish by specifying
them before the ``run`` command, and you can specify arguments for your binary
by specifying them after the ``run`` command.
### nimble c ### nimble c
The ``c`` (or ``compile``, ``js``, ``cc``, ``cpp``) command can be used by The ``c`` (or ``compile``, ``js``, ``cc``, ``cpp``) command can be used by
@ -478,7 +505,7 @@ For a package named "foobar", the recommended project structure is the following
└── src └── src
└── foobar.nim # Imported via `import foobar` └── foobar.nim # Imported via `import foobar`
└── tests # Contains the tests └── tests # Contains the tests
├── nim.cfg ├── config.nims
├── tfoo1.nim # First test ├── tfoo1.nim # First test
└── tfoo2.nim # Second test └── tfoo2.nim # Second test

View file

@ -3,11 +3,13 @@
import system except TResult import system except TResult
import os, tables, strtabs, json, algorithm, sets, uri, sugar, sequtils import os, tables, strtabs, json, algorithm, sets, uri, sugar, sequtils, osproc
import std/options as std_opt
import strutils except toLower import strutils except toLower
from unicode import toLower from unicode import toLower
from sequtils import toSeq from sequtils import toSeq
from strformat import fmt
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,
@ -199,12 +201,13 @@ proc processDeps(pkginfo: PackageInfo, options: Options): seq[PackageInfo] =
# in the path. # in the path.
var pkgsInPath: StringTableRef = newStringTable(modeCaseSensitive) var pkgsInPath: StringTableRef = newStringTable(modeCaseSensitive)
for pkgInfo in result: for pkgInfo in result:
let currentVer = pkgInfo.getConcreteVersion(options)
if pkgsInPath.hasKey(pkgInfo.name) and if pkgsInPath.hasKey(pkgInfo.name) and
pkgsInPath[pkgInfo.name] != pkgInfo.version: pkgsInPath[pkgInfo.name] != currentVer:
raise newException(NimbleError, raise newException(NimbleError,
"Cannot satisfy the dependency on $1 $2 and $1 $3" % "Cannot satisfy the dependency on $1 $2 and $1 $3" %
[pkgInfo.name, pkgInfo.version, pkgsInPath[pkgInfo.name]]) [pkgInfo.name, currentVer, pkgsInPath[pkgInfo.name]])
pkgsInPath[pkgInfo.name] = pkgInfo.version pkgsInPath[pkgInfo.name] = currentVer
# We add the reverse deps to the JSON file here because we don't want # We add the reverse deps to the JSON file here because we don't want
# them added if the above errorenous condition occurs # them added if the above errorenous condition occurs
@ -213,16 +216,33 @@ proc processDeps(pkginfo: PackageInfo, options: Options): seq[PackageInfo] =
for i in reverseDeps: for i in reverseDeps:
addRevDep(options.nimbleData, i, pkginfo) addRevDep(options.nimbleData, i, pkginfo)
proc buildFromDir(pkgInfo: PackageInfo, paths, args: seq[string]) = proc buildFromDir(
pkgInfo: PackageInfo, paths, args: seq[string],
options: Options
) =
## Builds a package as specified by ``pkgInfo``. ## Builds a package as specified by ``pkgInfo``.
let binToBuild = options.getCompilationBinary(pkgInfo)
# Handle pre-`build` hook.
let realDir = pkgInfo.getRealDir()
cd realDir: # Make sure `execHook` executes the correct .nimble file.
if not execHook(options, actionBuild, true):
raise newException(NimbleError, "Pre-hook prevented further execution.")
if pkgInfo.bin.len == 0: if pkgInfo.bin.len == 0:
raise newException(NimbleError, raise newException(NimbleError,
"Nothing to build. Did you specify a module to build using the" & "Nothing to build. Did you specify a module to build using the" &
" `bin` key in your .nimble file?") " `bin` key in your .nimble file?")
var args = args var args = args
let realDir = pkgInfo.getRealDir() let nimblePkgVersion = "-d:NimblePkgVersion=" & pkgInfo.version
for path in paths: args.add("--path:\"" & path & "\" ") for path in paths: args.add("--path:\"" & path & "\" ")
var binariesBuilt = 0
for bin in pkgInfo.bin: for bin in pkgInfo.bin:
# Check if this is the only binary that we want to build.
if binToBuild.isSome() and binToBuild.get() != bin:
let binToBuild = binToBuild.get()
if bin.extractFilename().changeFileExt("") != binToBuild:
continue
let outputOpt = "-o:\"" & pkgInfo.getOutputDir(bin) & "\"" let outputOpt = "-o:\"" & pkgInfo.getOutputDir(bin) & "\""
display("Building", "$1/$2 using $3 backend" % display("Building", "$1/$2 using $3 backend" %
[pkginfo.name, bin, pkgInfo.backend], priority = HighPriority) [pkginfo.name, bin, pkgInfo.backend], priority = HighPriority)
@ -231,10 +251,15 @@ proc buildFromDir(pkgInfo: PackageInfo, paths, args: seq[string]) =
if not existsDir(outputDir): if not existsDir(outputDir):
createDir(outputDir) createDir(outputDir)
let input = realDir / bin.changeFileExt("nim")
# `quoteShell` would be more robust than `\"` (and avoid quoting when
# un-necessary) but would require changing `extractBin`
let cmd = "\"$#\" $# --noNimblePath $# $# $# \"$#\"" %
[getNimBin(), pkgInfo.backend, nimblePkgVersion,
join(args, " "), outputOpt, input]
try: try:
doCmd("\"" & getNimBin() & "\" $# --noBabelPath $# $# \"$#\"" % doCmd(cmd, showCmd = true)
[pkgInfo.backend, join(args, " "), outputOpt, binariesBuilt.inc()
realDir / bin.changeFileExt("nim")])
except NimbleError: except NimbleError:
let currentExc = (ref NimbleError)(getCurrentException()) let currentExc = (ref NimbleError)(getCurrentException())
let exc = newException(BuildFailed, "Build failed for package: " & let exc = newException(BuildFailed, "Build failed for package: " &
@ -244,6 +269,15 @@ proc buildFromDir(pkgInfo: PackageInfo, paths, args: seq[string]) =
exc.hint = hint exc.hint = hint
raise exc raise exc
if binariesBuilt == 0:
raiseNimbleError(
"No binaries built, did you specify a valid binary name?"
)
# Handle post-`build` hook.
cd realDir: # Make sure `execHook` executes the correct .nimble file.
discard execHook(options, actionBuild, false)
proc removePkgDir(dir: string, options: Options) = proc removePkgDir(dir: string, options: Options) =
## Removes files belonging to the package in ``dir``. ## Removes files belonging to the package in ``dir``.
try: try:
@ -321,7 +355,7 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
# Handle pre-`install` hook. # Handle pre-`install` hook.
if not options.depsOnly: if not options.depsOnly:
cd dir: # Make sure `execHook` executes the correct .nimble file. cd dir: # Make sure `execHook` executes the correct .nimble file.
if not execHook(options, true): if not execHook(options, actionInstall, true):
raise newException(NimbleError, "Pre-hook prevented further execution.") raise newException(NimbleError, "Pre-hook prevented further execution.")
var pkgInfo = getPkgInfo(dir, options) var pkgInfo = getPkgInfo(dir, options)
@ -348,7 +382,11 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
# if the build fails then the old package will still be installed. # if the build fails then the old package will still be installed.
if pkgInfo.bin.len > 0: if pkgInfo.bin.len > 0:
let paths = result.deps.map(dep => dep.getRealDir()) let paths = result.deps.map(dep => dep.getRealDir())
buildFromDir(pkgInfo, paths, options.action.passNimFlags & "-d:release") let flags = if options.action.typ in {actionInstall, actionPath, actionUninstall, actionDevelop}:
options.action.passNimFlags
else:
@[]
buildFromDir(pkgInfo, paths, "-d:release" & flags, options)
let pkgDestDir = pkgInfo.getPkgDest(options) let pkgDestDir = pkgInfo.getPkgDest(options)
if existsDir(pkgDestDir) and existsFile(pkgDestDir / "nimblemeta.json"): if existsDir(pkgDestDir) and existsFile(pkgDestDir / "nimblemeta.json"):
@ -431,7 +469,7 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
# executes the hook defined in the CWD, so we set it to where the package # executes the hook defined in the CWD, so we set it to where the package
# has been installed. # has been installed.
cd dest.splitFile.dir: cd dest.splitFile.dir:
discard execHook(options, false) discard execHook(options, actionInstall, false)
proc getDownloadInfo*(pv: PkgTuple, options: Options, proc getDownloadInfo*(pv: PkgTuple, options: Options,
doPrompt: bool): (DownloadMethod, string, doPrompt: bool): (DownloadMethod, string,
@ -498,12 +536,12 @@ proc build(options: Options) =
nimScriptHint(pkgInfo) nimScriptHint(pkgInfo)
let deps = processDeps(pkginfo, options) let deps = processDeps(pkginfo, options)
let paths = deps.map(dep => dep.getRealDir()) let paths = deps.map(dep => dep.getRealDir())
var args = options.action.compileOptions var args = options.getCompilationFlags()
buildFromDir(pkgInfo, paths, args) buildFromDir(pkgInfo, paths, args, options)
proc execBackend(options: Options) = proc execBackend(pkgInfo: PackageInfo, options: Options) =
let let
bin = options.action.file bin = options.getCompilationBinary(pkgInfo).get()
binDotNim = bin.addFileExt("nim") binDotNim = bin.addFileExt("nim")
if bin == "": if bin == "":
raise newException(NimbleError, "You need to specify a file.") raise newException(NimbleError, "You need to specify a file.")
@ -516,9 +554,10 @@ proc execBackend(options: Options) =
nimScriptHint(pkgInfo) nimScriptHint(pkgInfo)
let deps = processDeps(pkginfo, options) let deps = processDeps(pkginfo, options)
let nimblePkgVersion = "-d:NimblePkgVersion=" & pkgInfo.version
var args = "" var args = ""
for dep in deps: args.add("--path:\"" & dep.getRealDir() & "\" ") for dep in deps: args.add("--path:\"" & dep.getRealDir() & "\" ")
for option in options.action.compileOptions: for option in options.getCompilationFlags():
args.add("\"" & option & "\" ") args.add("\"" & option & "\" ")
let backend = let backend =
@ -533,8 +572,8 @@ proc execBackend(options: Options) =
else: else:
display("Generating", ("documentation for $1 (from package $2) using $3 " & display("Generating", ("documentation for $1 (from package $2) using $3 " &
"backend") % [bin, pkgInfo.name, backend], priority = HighPriority) "backend") % [bin, pkgInfo.name, backend], priority = HighPriority)
doCmd("\"" & getNimBin() & "\" $# --noNimblePath $# \"$#\"" % doCmd("\"" & getNimBin() & "\" $# --noNimblePath $# $# \"$#\"" %
[backend, args, bin], showOutput = true) [backend, nimblePkgVersion, args, bin], showOutput = true)
display("Success:", "Execution finished", Success, HighPriority) display("Success:", "Execution finished", Success, HighPriority)
proc search(options: Options) = proc search(options: Options) =
@ -690,6 +729,11 @@ proc dump(options: Options) =
echo "backend: ", p.backend.escape echo "backend: ", p.backend.escape
proc init(options: Options) = proc init(options: Options) =
# Check whether the vcs is installed.
let vcsBin = options.action.vcsOption
if vcsBin != "" and findExe(vcsBin, true) == "":
raise newException(NimbleError, "Please install git or mercurial first")
# Determine the package name. # Determine the package name.
let pkgName = let pkgName =
if options.action.projName != "": if options.action.projName != "":
@ -824,6 +868,17 @@ js - Compile using JavaScript backend.""",
pkgRoot pkgRoot
) )
# Create a git or hg repo in the new nimble project.
if vcsBin != "":
let cmd = fmt"cd {pkgRoot} && {vcsBin} init"
let ret: tuple[output: string, exitCode: int] = execCmdEx(cmd)
if ret.exitCode != 0: quit ret.output
var ignoreFile = if vcsBin == "git": ".gitignore" else: ".hgignore"
var fd = open(joinPath(pkgRoot, ignoreFile), fmWrite)
fd.write(pkgName & "\n")
fd.close()
display("Success:", "Package $# created successfully" % [pkgName], Success, display("Success:", "Package $# created successfully" % [pkgName], Success,
HighPriority) HighPriority)
@ -866,7 +921,7 @@ proc uninstall(options: Options) =
pkgsToDelete.incl pkg pkgsToDelete.incl pkg
if pkgsToDelete.len == 0: if pkgsToDelete.len == 0:
raise newException(NimbleError, "Failed uninstall - no packages selected") raise newException(NimbleError, "Failed uninstall - no packages to delete")
var pkgNames = "" var pkgNames = ""
for pkg in pkgsToDelete.items: for pkg in pkgsToDelete.items:
@ -901,7 +956,7 @@ proc developFromDir(dir: string, options: Options) =
raiseNimbleError("Cannot develop dependencies only.") raiseNimbleError("Cannot develop dependencies only.")
cd dir: # Make sure `execHook` executes the correct .nimble file. cd dir: # Make sure `execHook` executes the correct .nimble file.
if not execHook(options, true): if not execHook(options, actionDevelop, true):
raise newException(NimbleError, "Pre-hook prevented further execution.") raise newException(NimbleError, "Pre-hook prevented further execution.")
var pkgInfo = getPkgInfo(dir, options) var pkgInfo = getPkgInfo(dir, options)
@ -954,7 +1009,7 @@ proc developFromDir(dir: string, options: Options) =
# Execute the post-develop hook. # Execute the post-develop hook.
cd dir: cd dir:
discard execHook(options, false) discard execHook(options, actionDevelop, false)
proc develop(options: Options) = proc develop(options: Options) =
if options.action.packages == @[]: if options.action.packages == @[]:
@ -990,6 +1045,8 @@ proc develop(options: Options) =
proc test(options: Options) = proc test(options: Options) =
## Executes all tests starting with 't' in the ``tests`` directory. ## Executes all tests starting with 't' in the ``tests`` directory.
## Subdirectories are not walked. ## Subdirectories are not walked.
var pkgInfo = getPkgInfo(getCurrentDir(), options)
var var
files = toSeq(walkDir(getCurrentDir() / "tests")) files = toSeq(walkDir(getCurrentDir() / "tests"))
tests, failures: int tests, failures: int
@ -1006,10 +1063,10 @@ proc test(options: Options) =
var optsCopy = options.briefClone() var optsCopy = options.briefClone()
optsCopy.action = Action(typ: actionCompile) optsCopy.action = Action(typ: actionCompile)
optsCopy.action.file = file.path optsCopy.action.file = file.path
optsCopy.action.backend = "c" optsCopy.action.backend = pkgInfo.backend
optsCopy.action.compileOptions = @[] optsCopy.getCompilationFlags() = @[]
optsCopy.action.compileOptions.add("-r") optsCopy.getCompilationFlags().add("-r")
optsCopy.action.compileOptions.add("--path:.") optsCopy.getCompilationFlags().add("--path:.")
let let
binFileName = file.path.changeFileExt(ExeExt) binFileName = file.path.changeFileExt(ExeExt)
existsBefore = existsFile(binFileName) existsBefore = existsFile(binFileName)
@ -1017,17 +1074,21 @@ proc test(options: Options) =
if options.continueTestsOnFailure: if options.continueTestsOnFailure:
inc tests inc tests
try: try:
execBackend(optsCopy) execBackend(pkgInfo, optsCopy)
except NimbleError: except NimbleError:
inc failures inc failures
else: else:
execBackend(optsCopy) execBackend(pkgInfo, optsCopy)
let let
existsAfter = existsFile(binFileName) existsAfter = existsFile(binFileName)
canRemove = not existsBefore and existsAfter canRemove = not existsBefore and existsAfter
if canRemove: if canRemove:
removeFile(binFileName) try:
removeFile(binFileName)
except OSError as exc:
display("Warning:", "Failed to delete " & binFileName & ": " &
exc.msg, Warning, MediumPriority)
if failures == 0: if failures == 0:
display("Success:", "All tests passed", Success, HighPriority) display("Success:", "All tests passed", Success, HighPriority)
@ -1036,7 +1097,7 @@ proc test(options: Options) =
display("Error:", error, Error, HighPriority) display("Error:", error, Error, HighPriority)
proc check(options: Options) = proc check(options: Options) =
## Validates a package a in the current working directory. ## Validates a package in the current working directory.
let nimbleFile = findNimbleFile(getCurrentDir(), true) let nimbleFile = findNimbleFile(getCurrentDir(), true)
var error: ValidationError var error: ValidationError
var pkgInfo: PackageInfo var pkgInfo: PackageInfo
@ -1054,7 +1115,29 @@ proc check(options: Options) =
display("Failure:", "Validation failed", Error, HighPriority) display("Failure:", "Validation failed", Error, HighPriority)
quit(QuitFailure) quit(QuitFailure)
proc doAction(options: Options) = proc run(options: Options) =
# Verify parameters.
var pkgInfo = getPkgInfo(getCurrentDir(), options)
let binary = options.getCompilationBinary(pkgInfo).get("")
if binary.len == 0:
raiseNimbleError("Please specify a binary to run")
if binary notin pkgInfo.bin:
raiseNimbleError(
"Binary '$#' is not defined in '$#' package." % [binary, pkgInfo.name]
)
# Build the binary.
build(options)
let binaryPath = pkgInfo.getOutputDir(binary)
let cmd = quoteShellCommand(binaryPath & options.action.runFlags)
displayDebug("Executing", cmd)
cmd.execCmd.quit
proc doAction(options: var Options) =
if options.showHelp: if options.showHelp:
writeHelp() writeHelp()
if options.showVersion: if options.showVersion:
@ -1065,6 +1148,10 @@ proc doAction(options: Options) =
if not existsDir(options.getPkgsDir): if not existsDir(options.getPkgsDir):
createDir(options.getPkgsDir) createDir(options.getPkgsDir)
if options.action.typ in {actionTasks, actionRun, actionBuild, actionCompile}:
# Implicitly disable package validation for these commands.
options.disableValidation = true
case options.action.typ case options.action.typ
of actionRefresh: of actionRefresh:
refresh(options) refresh(options)
@ -1090,8 +1177,11 @@ proc doAction(options: Options) =
listPaths(options) listPaths(options)
of actionBuild: of actionBuild:
build(options) build(options)
of actionRun:
run(options)
of actionCompile, actionDoc: of actionCompile, actionDoc:
execBackend(options) var pkgInfo = getPkgInfo(getCurrentDir(), options)
execBackend(pkgInfo, options)
of actionInit: of actionInit:
init(options) init(options)
of actionPublish: of actionPublish:
@ -1108,7 +1198,7 @@ proc doAction(options: Options) =
of actionNil: of actionNil:
assert false assert false
of actionCustom: of actionCustom:
if not execHook(options, true): if not execHook(options, actionCustom, true):
display("Warning", "Pre-hook prevented further execution.", Warning, display("Warning", "Pre-hook prevented further execution.", Warning,
HighPriority) HighPriority)
return return
@ -1117,21 +1207,24 @@ proc doAction(options: Options) =
var execResult: ExecutionResult[bool] var execResult: ExecutionResult[bool]
if execCustom(options, execResult, failFast=not isPreDefined): if execCustom(options, execResult, failFast=not isPreDefined):
if execResult.hasTaskRequestedCommand(): if execResult.hasTaskRequestedCommand():
doAction(execResult.getOptionsForCommand(options)) var options = execResult.getOptionsForCommand(options)
doAction(options)
else: else:
# If there is no task defined for the `test` task, we run the pre-defined # If there is no task defined for the `test` task, we run the pre-defined
# fallback logic. # fallback logic.
if isPreDefined: if isPreDefined:
test(options) test(options)
# Run the post hook for `test` in case it exists. # Run the post hook for `test` in case it exists.
discard execHook(options, false) discard execHook(options, actionCustom, false)
when isMainModule: when isMainModule:
var error = "" var error = ""
var hint = "" var hint = ""
var opt: Options
try: try:
parseCmdLine().doAction() opt = parseCmdLine()
opt.doAction()
except NimbleError: except NimbleError:
let currentExc = (ref NimbleError)(getCurrentException()) let currentExc = (ref NimbleError)(getCurrentException())
(error, hint) = getOutputInfo(currentExc) (error, hint) = getOutputInfo(currentExc)
@ -1139,7 +1232,9 @@ when isMainModule:
discard discard
finally: finally:
try: try:
removeDir(getNimbleTempDir()) let folder = getNimbleTempDir()
if opt.shouldRemoveTmp(folder):
removeDir(folder)
except OSError: except OSError:
let msg = "Couldn't remove Nimble's temp dir" let msg = "Couldn't remove Nimble's temp dir"
display("Warning:", msg, Warning, MediumPriority) display("Warning:", msg, Warning, MediumPriority)

View file

@ -62,8 +62,18 @@ proc calculateCategoryOffset(category: string): int =
assert category.len <= longestCategory assert category.len <= longestCategory
return longestCategory - category.len return longestCategory - category.len
proc isSuppressed(displayType: DisplayType): bool =
# 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
globalCLI.level == HighPriority:
return true
proc displayCategory(category: string, displayType: DisplayType, proc displayCategory(category: string, displayType: DisplayType,
priority: Priority) = priority: Priority) =
if isSuppressed(displayType):
return
# Calculate how much the `category` must be offset to align along a center # Calculate how much the `category` must be offset to align along a center
# line. # line.
let offset = calculateCategoryOffset(category) let offset = calculateCategoryOffset(category)
@ -80,6 +90,9 @@ proc displayCategory(category: string, displayType: DisplayType,
proc displayLine(category, line: string, displayType: DisplayType, proc displayLine(category, line: string, displayType: DisplayType,
priority: Priority) = priority: Priority) =
if isSuppressed(displayType):
return
displayCategory(category, displayType, priority) displayCategory(category, displayType, priority)
# Display the message. # Display the message.
@ -87,12 +100,6 @@ proc displayLine(category, line: string, displayType: DisplayType,
proc display*(category, msg: string, displayType = Message, proc display*(category, msg: string, displayType = Message,
priority = MediumPriority) = 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
globalCLI.level == HighPriority:
return
# Multiple warnings containing the same messages should not be shown. # Multiple warnings containing the same messages should not be shown.
let warningPair = (category, msg) let warningPair = (category, msg)
if displayType == Warning: if displayType == Warning:

View file

@ -22,7 +22,8 @@ when not defined(nimscript):
preHooks*: HashSet[string] preHooks*: HashSet[string]
name*: string name*: string
## The version specified in the .nimble file.Assuming info is non-minimal, ## The version specified in the .nimble file.Assuming info is non-minimal,
## it will always be a non-special version such as '0.1.4' ## it will always be a non-special version such as '0.1.4'.
## If in doubt, use `getConcreteVersion` instead.
version*: string version*: string
specialVersion*: string ## Either `myVersion` or a special version such as #head. specialVersion*: string ## Either `myVersion` or a special version such as #head.
author*: string author*: string
@ -62,7 +63,7 @@ when not defined(nimscript):
return (error, hint) return (error, hint)
const const
nimbleVersion* = "0.10.2" nimbleVersion* = "0.11.0"
when not declared(initHashSet): when not declared(initHashSet):
import sets import sets

View file

@ -300,4 +300,17 @@ when isMainModule:
}) })
doAssert expected == getVersionList(data) doAssert expected == getVersionList(data)
block:
let data2 = @["v0.1.0", "v0.1.1", "v0.2.0",
"0.4.0", "v0.4.2"]
let expected2 = toOrderedTable[Version, string]({
newVersion("0.4.2"): "v0.4.2",
newVersion("0.4.0"): "0.4.0",
newVersion("0.2.0"): "v0.2.0",
newVersion("0.1.1"): "v0.1.1",
newVersion("0.1.0"): "v0.1.0",
})
doAssert expected2 == getVersionList(data2)
echo("Everything works!") echo("Everything works!")

View file

@ -17,7 +17,7 @@ var
author*: string ## The package's author. author*: string ## The package's author.
description*: string ## The package's description. description*: string ## The package's description.
license*: string ## The package's license. license*: string ## The package's license.
srcdir*: string ## The package's source directory. srcDir*: string ## The package's source directory.
binDir*: string ## The package's binary directory. binDir*: string ## The package's binary directory.
backend*: string ## The package's backend. backend*: string ## The package's backend.
@ -101,7 +101,7 @@ proc printPkgInfo(): string =
printIfLen author printIfLen author
printIfLen description printIfLen description
printIfLen license printIfLen license
printIfLen srcdir printIfLen srcDir
printIfLen binDir printIfLen binDir
printIfLen backend printIfLen backend

View file

@ -6,12 +6,12 @@ import os, strutils, sets
import packageparser, common, packageinfo, options, nimscriptwrapper, cli, import packageparser, common, packageinfo, options, nimscriptwrapper, cli,
version version
proc execHook*(options: Options, before: bool): bool = proc execHook*(options: Options, hookAction: ActionType, before: bool): bool =
## Returns whether to continue. ## Returns whether to continue.
result = true result = true
# For certain commands hooks should not be evaluated. # For certain commands hooks should not be evaluated.
if options.action.typ in noHookActions: if hookAction in noHookActions:
return return
var nimbleFile = "" var nimbleFile = ""
@ -21,8 +21,8 @@ proc execHook*(options: Options, before: bool): bool =
# PackageInfos are cached so we can read them as many times as we want. # PackageInfos are cached so we can read them as many times as we want.
let pkgInfo = getPkgInfoFromFile(nimbleFile, options) let pkgInfo = getPkgInfoFromFile(nimbleFile, options)
let actionName = let actionName =
if options.action.typ == actionCustom: options.action.command if hookAction == actionCustom: options.action.command
else: ($options.action.typ)[6 .. ^1] else: ($hookAction)[6 .. ^1]
let hookExists = let hookExists =
if before: actionName.normalize in pkgInfo.preHooks if before: actionName.normalize in pkgInfo.preHooks
else: actionName.normalize in pkgInfo.postHooks else: actionName.normalize in pkgInfo.postHooks
@ -58,7 +58,7 @@ proc execCustom*(options: Options,
HighPriority) HighPriority)
return return
if not execHook(options, false): if not execHook(options, actionCustom, false):
return return
return true return true

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,29 @@ 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 writeExecutionOutput(data: string) =
# TODO: in the future we will likely want this to be live, users will
# undoubtedly be doing loops and other crazy things in their top-level
# Nimble files.
display("Info", data)
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"
@ -36,14 +53,21 @@ proc execNimscript(nimsFile, projectDir, actionName: string, options: Options):
defer: defer:
# Only if copied in this invocation, allows recursive calls of nimble # Only if copied in this invocation, allows recursive calls of nimble
if not isScriptResultCopied: if not isScriptResultCopied and options.shouldRemoveTmp(nimsFileCopied):
nimsFileCopied.removeFile() nimsFileCopied.removeFile()
var var cmd = (
cmd = ("nim e --hints:off --verbosity:0 -p:" & (getTempDir() / "nimblecache").quoteShell & "nim e $# -p:$# $# $# $#" % [
" " & nimsFileCopied.quoteShell & " " & outFile.quoteShell & " " & actionName).strip() "--hints:off --verbosity:0",
(getTempDir() / "nimblecache").quoteShell,
nimsFileCopied.quoteShell,
outFile.quoteShell,
actionName
]
).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():
@ -53,10 +77,16 @@ 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()
discard outFile.tryRemoveFile() if options.shouldRemoveTmp(outFile):
discard outFile.tryRemoveFile()
proc getNimsFile(scriptName: string, options: Options): string = proc getNimsFile(scriptName: string, options: Options): string =
let let
@ -105,27 +135,30 @@ 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)
stdout.writeExecutionOutput()
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)
@ -149,6 +182,8 @@ proc execScript(scriptName, actionName: string, options: Options):
result.flags[flag].add val.getStr() result.flags[flag].add val.getStr()
result.retVal = j{"retVal"}.getBool() result.retVal = j{"retVal"}.getBool()
stdout.writeExecutionOutput()
proc execTask*(scriptName, taskName: string, proc execTask*(scriptName, taskName: string,
options: Options): ExecutionResult[bool] = options: Options): ExecutionResult[bool] =
## Executes the specified task in the specified script. ## Executes the specified task in the specified script.
@ -157,7 +192,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] =
@ -171,11 +206,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

@ -2,6 +2,8 @@
# BSD License. Look at license.txt for more info. # BSD License. Look at license.txt for more info.
import json, strutils, os, parseopt, strtabs, uri, tables, terminal import json, strutils, os, parseopt, strtabs, uri, tables, terminal
import sequtils, sugar
import std/options as std_opt
from httpclient import Proxy, newProxy from httpclient import Proxy, newProxy
import config, version, common, cli import config, version, common, cli
@ -26,12 +28,15 @@ type
continueTestsOnFailure*: bool continueTestsOnFailure*: bool
## Whether packages' repos should always be downloaded with their history. ## Whether packages' repos should always be downloaded with their history.
forceFullClone*: bool forceFullClone*: bool
# Temporary storage of flags that have not been captured by any specific Action.
unknownFlags*: seq[(CmdLineKind, string, string)]
ActionType* = enum ActionType* = enum
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, actionCheck actionDoc, actionCustom, actionTasks, actionDevelop, actionCheck,
actionRun
Action* = object Action* = object
case typ*: ActionType case typ*: ActionType
@ -46,10 +51,15 @@ type
search*: seq[string] # Search string. search*: seq[string] # Search string.
of actionInit, actionDump: of actionInit, actionDump:
projName*: string projName*: string
vcsOption*: string
of actionCompile, actionDoc, actionBuild: of actionCompile, actionDoc, actionBuild:
file*: string file*: string
backend*: string backend*: string
compileOptions*: seq[string] compileOptions: seq[string]
of actionRun:
runFile: Option[string]
compileFlags: seq[string]
runFlags*: seq[string]
of actionCustom: of actionCustom:
command*: string command*: string
arguments*: seq[string] arguments*: seq[string]
@ -71,12 +81,19 @@ Commands:
init [pkgname] Initializes a new Nimble project in the init [pkgname] Initializes a new Nimble project in the
current directory or if a name is provided a current directory or if a name is provided a
new directory of the same name. new directory of the same name.
--git
--hg Create a git or hg repo in the new nimble project.
publish Publishes a package on nim-lang/packages. publish Publishes a package on nim-lang/packages.
The current working directory needs to be the The current working directory needs to be the
toplevel directory of the Nimble package. toplevel directory of the Nimble package.
uninstall [pkgname, ...] Uninstalls a list of packages. uninstall [pkgname, ...] Uninstalls a list of packages.
[-i, --inclDeps] Uninstall package and dependent package(s). [-i, --inclDeps] Uninstall package and dependent package(s).
build Builds a package. build [opts, ...] [bin] Builds a package.
run [opts, ...] [bin] Builds and runs a package.
Binary needs to be specified after any
compilation options if there are several
binaries defined, any flags after the binary
or -- arg are passed to the binary when it is run.
c, cc, js [opts, ...] f.nim Builds a file inside a package. Passes options c, cc, js [opts, ...] f.nim Builds a file inside a package. Passes options
to the Nim compiler. to the Nim compiler.
test Compiles and executes tests test Compiles and executes tests
@ -143,6 +160,8 @@ proc parseActionType*(action: string): ActionType =
result = actionPath result = actionPath
of "build": of "build":
result = actionBuild result = actionBuild
of "run":
result = actionRun
of "c", "compile", "js", "cpp", "cc": of "c", "compile", "js", "cpp", "cc":
result = actionCompile result = actionCompile
of "doc", "doc2": of "doc", "doc2":
@ -185,8 +204,11 @@ proc initAction*(options: var Options, key: string) =
else: options.action.backend = keyNorm else: options.action.backend = keyNorm
of actionInit: of actionInit:
options.action.projName = "" options.action.projName = ""
options.action.vcsOption = ""
of actionDump: of actionDump:
options.action.projName = "" options.action.projName = ""
options.action.vcsOption = ""
options.forcePrompts = forcePromptYes
of actionRefresh: of actionRefresh:
options.action.optionalURL = "" options.action.optionalURL = ""
of actionSearch: of actionSearch:
@ -195,7 +217,7 @@ proc initAction*(options: var Options, key: string) =
options.action.command = key options.action.command = key
options.action.arguments = @[] options.action.arguments = @[]
options.action.flags = newStringTable() options.action.flags = newStringTable()
of actionPublish, actionList, actionTasks, actionCheck, of actionPublish, actionList, actionTasks, actionCheck, actionRun,
actionNil: discard actionNil: discard
proc prompt*(options: Options, question: string): bool = proc prompt*(options: Options, question: string): bool =
@ -244,6 +266,12 @@ proc parseCommand*(key: string, result: var Options) =
result.action = Action(typ: parseActionType(key)) result.action = Action(typ: parseActionType(key))
initAction(result, key) initAction(result, key)
proc setRunOptions(result: var Options, key, val: string, isArg: bool) =
if result.action.runFile.isNone() and (isArg or val == "--"):
result.action.runFile = some(key)
else:
result.action.runFlags.add(val)
proc parseArgument*(key: string, result: var Options) = proc parseArgument*(key: string, result: var Options) =
case result.action.typ case result.action.typ
of actionNil: of actionNil:
@ -264,23 +292,40 @@ proc parseArgument*(key: string, result: var Options) =
result.action.search.add(key) result.action.search.add(key)
of actionInit, actionDump: of actionInit, actionDump:
if result.action.projName != "": if result.action.projName != "":
raise newException(NimbleError, raise newException(
"Can only initialize one package at a time.") NimbleError, "Can only perform this action on one package at a time."
)
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, actionPublish: of actionList, actionPublish:
result.showHelp = true result.showHelp = true
of actionBuild:
result.action.file = key
of actionRun:
result.setRunOptions(key, key, true)
of actionCustom: of actionCustom:
result.action.arguments.add(key) result.action.arguments.add(key)
else: else:
discard discard
proc getFlagString(kind: CmdLineKind, flag, val: string): string =
let prefix =
case kind
of cmdShortOption: "-"
of cmdLongOption: "--"
else: ""
if val == "":
return prefix & flag
else:
return prefix & flag & ":" & val
proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) =
var wasFlagHandled = true
let f = flag.normalize() let f = flag.normalize()
# Global flags. # Global flags.
var isGlobalFlag = true
case f case f
of "help", "h": result.showHelp = true of "help", "h": result.showHelp = true
of "version", "v": result.showVersion = true of "version", "v": result.showVersion = true
@ -291,54 +336,64 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) =
of "debug": result.verbosity = DebugPriority of "debug": result.verbosity = DebugPriority
of "nocolor": result.noColor = true of "nocolor": result.noColor = true
of "disablevalidation": result.disableValidation = true of "disablevalidation": result.disableValidation = true
else: isGlobalFlag = false
var wasFlagHandled = true
# Action-specific flags. # Action-specific flags.
else: case result.action.typ
case result.action.typ of actionSearch, actionList:
of actionSearch, actionList: case f
case f of "installed", "i":
of "installed", "i": result.queryInstalled = true
result.queryInstalled = true of "ver":
of "ver": result.queryVersions = true
result.queryVersions = true
else:
wasFlagHandled = false
of actionInstall:
case f
of "depsonly", "d":
result.depsOnly = true
of "passnim", "p":
result.action.passNimFlags.add(val)
else:
wasFlagHandled = false
of actionUninstall:
case f
of "incldeps", "i":
result.uninstallRevDeps = true
else:
wasFlagHandled = false
of actionCompile, actionDoc, actionBuild:
let prefix = if kind == cmdShortOption: "-" else: "--"
if val == "":
result.action.compileOptions.add(prefix & flag)
else:
result.action.compileOptions.add(prefix & flag & ":" & val)
of actionCustom:
if result.action.command.normalize == "test":
if f == "continue" or f == "c":
result.continueTestsOnFailure = true
result.action.flags[flag] = val
else: else:
wasFlagHandled = false wasFlagHandled = false
of actionInstall:
case f
of "depsonly", "d":
result.depsOnly = true
of "passnim", "p":
result.action.passNimFlags.add(val)
else:
wasFlagHandled = false
of actionInit:
case f
of "git", "hg":
result.action.vcsOption = f
else:
wasFlagHandled = false
of actionUninstall:
case f
of "incldeps", "i":
result.uninstallRevDeps = true
else:
wasFlagHandled = false
of actionCompile, actionDoc, actionBuild:
if not isGlobalFlag:
result.action.compileOptions.add(getFlagString(kind, flag, val))
of actionRun:
result.showHelp = false
result.setRunOptions(flag, getFlagString(kind, flag, val), false)
of actionCustom:
if result.action.command.normalize == "test":
if f == "continue" or f == "c":
result.continueTestsOnFailure = true
result.action.flags[flag] = val
else:
wasFlagHandled = false
if not wasFlagHandled: if not wasFlagHandled and not isGlobalFlag:
raise newException(NimbleError, "Unknown option: --" & flag) result.unknownFlags.add((kind, flag, val))
proc initOptions*(): Options = proc initOptions*(): Options =
result.action = Action(typ: actionNil) # Exported for choosenim
result.pkgInfoCache = newTable[string, PackageInfo]() Options(
result.nimbleDir = "" action: Action(typ: actionNil),
result.verbosity = HighPriority pkgInfoCache: newTable[string, PackageInfo](),
result.noColor = not isatty(stdout) verbosity: HighPriority,
noColor: not isatty(stdout)
)
proc parseMisc(options: var Options) = proc parseMisc(options: var Options) =
# Load nimbledata.json # Load nimbledata.json
@ -353,6 +408,29 @@ proc parseMisc(options: var Options) =
else: else:
options.nimbleData = %{"reverseDeps": newJObject()} options.nimbleData = %{"reverseDeps": newJObject()}
proc handleUnknownFlags(options: var Options) =
if options.action.typ == actionRun:
# ActionRun uses flags that come before the command as compilation flags
# and flags that come after as run flags.
options.action.compileFlags =
map(options.unknownFlags, x => getFlagString(x[0], x[1], x[2]))
options.unknownFlags = @[]
else:
# For everything else, handle the flags that came before the command
# normally.
let unknownFlags = options.unknownFlags
options.unknownFlags = @[]
for flag in unknownFlags:
parseFlag(flag[1], flag[2], options, flag[0])
# Any unhandled flags?
if options.unknownFlags.len > 0:
let flag = options.unknownFlags[0]
raise newException(
NimbleError,
"Unknown option: " & getFlagString(flag[0], flag[1], flag[2])
)
proc parseCmdLine*(): Options = proc parseCmdLine*(): Options =
result = initOptions() result = initOptions()
@ -366,9 +444,11 @@ proc parseCmdLine*(): Options =
else: else:
parseArgument(key, result) parseArgument(key, result)
of cmdLongOption, cmdShortOption: of cmdLongOption, cmdShortOption:
parseFlag(key, val, result, kind) parseFlag(key, val, result, kind)
of cmdEnd: assert(false) # cannot happen of cmdEnd: assert(false) # cannot happen
handleUnknownFlags(result)
# Set verbosity level. # Set verbosity level.
setVerbosity(result.verbosity) setVerbosity(result.verbosity)
@ -384,6 +464,11 @@ proc parseCmdLine*(): Options =
if result.action.typ == actionNil and not result.showVersion: if result.action.typ == actionNil and not result.showVersion:
result.showHelp = true result.showHelp = true
if result.action.typ != actionNil and result.showVersion:
# We've got another command that should be handled. For example:
# nimble run foobar -v
result.showVersion = false
proc getProxy*(options: Options): Proxy = proc getProxy*(options: Options): Proxy =
## Returns ``nil`` if no proxy is specified. ## Returns ``nil`` if no proxy is specified.
var url = "" var url = ""
@ -423,3 +508,44 @@ proc briefClone*(options: Options): Options =
newOptions.forcePrompts = options.forcePrompts newOptions.forcePrompts = options.forcePrompts
newOptions.pkgInfoCache = options.pkgInfoCache newOptions.pkgInfoCache = options.pkgInfoCache
return newOptions return newOptions
proc shouldRemoveTmp*(options: Options, file: string): bool =
result = true
if options.verbosity <= DebugPriority:
let msg = "Not removing temporary path because of debug verbosity: " & file
display("Warning:", msg, Warning, MediumPriority)
return false
proc getCompilationFlags*(options: var Options): var seq[string] =
case options.action.typ
of actionBuild, actionDoc, actionCompile:
return options.action.compileOptions
of actionRun:
return options.action.compileFlags
else:
assert false
proc getCompilationFlags*(options: Options): seq[string] =
var opt = options
return opt.getCompilationFlags()
proc getCompilationBinary*(options: Options, pkgInfo: PackageInfo): Option[string] =
case options.action.typ
of actionBuild, actionDoc, actionCompile:
let file = options.action.file.changeFileExt("")
if file.len > 0:
return some(file)
of actionRun:
let optRunFile = options.action.runFile
let runFile =
if optRunFile.get("").len > 0:
optRunFile.get()
elif pkgInfo.bin.len == 1:
pkgInfo.bin[0]
else:
""
if runFile.len > 0:
return some(runFile.changeFileExt(ExeExt))
else:
discard

View file

@ -487,6 +487,15 @@ proc toFullInfo*(pkg: PackageInfo, options: Options): PackageInfo =
else: else:
return pkg return pkg
proc getConcreteVersion*(pkgInfo: PackageInfo, options: Options): string =
## Returns a non-special version from the specified ``pkgInfo``. If the
## ``pkgInfo`` is minimal it looks it up and retrieves the concrete version.
result = pkgInfo.version
if pkgInfo.isMinimal:
let pkgInfo = pkgInfo.toFullInfo(options)
result = pkgInfo.version
assert(not newVersion(result).isSpecial)
when isMainModule: when isMainModule:
validatePackageName("foo_bar") validatePackageName("foo_bar")
validatePackageName("f_oo_b_a_r") validatePackageName("f_oo_b_a_r")

View file

@ -213,7 +213,10 @@ proc publish*(p: PackageInfo, o: Options) =
url = promptCustom("Github URL of " & p.name & "?", "") url = promptCustom("Github URL of " & p.name & "?", "")
if url.len == 0: userAborted() if url.len == 0: userAborted()
let tags = promptCustom("Whitespace separated list of tags?", "") let tags = promptCustom(
"Whitespace separated list of tags? (For example: web library wrapper)",
""
)
cd pkgsDir: cd pkgsDir:
editJson(p, url, tags, downloadMethod) editJson(p, url, tags, downloadMethod)

View file

@ -11,7 +11,7 @@ proc extractBin(cmd: string): string =
else: else:
return cmd.split(' ')[0] return cmd.split(' ')[0]
proc doCmd*(cmd: string, showOutput = false) = proc doCmd*(cmd: string, showOutput = false, showCmd = false) =
let bin = extractBin(cmd) let bin = extractBin(cmd)
if findExe(bin) == "": if findExe(bin) == "":
raise newException(NimbleError, "'" & bin & "' not in PATH.") raise newException(NimbleError, "'" & bin & "' not in PATH.")
@ -20,7 +20,10 @@ proc doCmd*(cmd: string, showOutput = false) =
stdout.flushFile() stdout.flushFile()
stderr.flushFile() stderr.flushFile()
displayDebug("Executing", cmd) if showCmd:
display("Executing", cmd, priority = MediumPriority)
else:
displayDebug("Executing", cmd)
if showOutput: if showOutput:
let exitCode = execCmd(cmd) let exitCode = execCmd(cmd)
displayDebug("Finished", "with exit code " & $exitCode) displayDebug("Finished", "with exit code " & $exitCode)

View file

@ -147,7 +147,7 @@ proc makeRange*(version: string, op: string): VersionRange =
result = VersionRange(kind: verEqLater) result = VersionRange(kind: verEqLater)
of "<=": of "<=":
result = VersionRange(kind: verEqEarlier) result = VersionRange(kind: verEqEarlier)
of "": of "", "==":
result = VersionRange(kind: verEq) result = VersionRange(kind: verEq)
else: else:
raise newException(ParseVersionError, "Invalid operator: " & op) raise newException(ParseVersionError, "Invalid operator: " & op)
@ -298,9 +298,10 @@ when isMainModule:
doAssert(newVersion("0.1.0") <= newVersion("0.1")) doAssert(newVersion("0.1.0") <= newVersion("0.1"))
var inter1 = parseVersionRange(">= 1.0 & <= 1.5") var inter1 = parseVersionRange(">= 1.0 & <= 1.5")
doAssert inter1.kind == verIntersect doAssert(inter1.kind == verIntersect)
var inter2 = parseVersionRange("1.0") var inter2 = parseVersionRange("1.0")
doAssert(inter2.kind == verEq) doAssert(inter2.kind == verEq)
doAssert(parseVersionRange("== 3.4.2") == parseVersionRange("3.4.2"))
doAssert(not withinRange(newVersion("1.5.1"), inter1)) doAssert(not withinRange(newVersion("1.5.1"), inter1))
doAssert(withinRange(newVersion("1.0.2.3.4.5.6.7.8.9.10.11.12"), inter1)) doAssert(withinRange(newVersion("1.0.2.3.4.5.6.7.8.9.10.11.12"), inter1))

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

@ -0,0 +1,15 @@
# Package
version = "0.1.0"
author = "Dominik Picheta"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"
# Dependencies
requires "nim >= 0.16.0"
requires "https://github.com/nimble-test/packagea#head",
"https://github.com/nimble-test/packagebin2"

View file

@ -0,0 +1,7 @@
# This is just an example to get you started. A typical library package
# exports the main API in this file. Note that you cannot rename this file
# but you can remove it if you wish.
proc add*(x, y: int): int =
## Adds two files together.
return x + y

View file

@ -0,0 +1,14 @@
# Package
version = "0.1.0"
author = "Dominik Picheta"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"
bin = @["issue564/issue564build"]
# Dependencies
requires "nim >= 0.16.0"

View file

@ -0,0 +1,5 @@
# This is just an example to get you started. A typical binary package
# uses this file as the main entry point of the application.
when isMainModule:
echo("Hello, World!")

View file

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

View file

@ -0,0 +1,7 @@
# This is just an example to get you started. A typical library package
# exports the main API in this file. Note that you cannot rename this file
# but you can remove it if you wish.
proc add*(x, y: int): int =
## Adds two files together.
return x + y

View file

@ -0,0 +1,14 @@
# Package
version = "0.1.0"
author = "Dominik Picheta"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"
bin = @["nimbleVersionDefine"]
# Dependencies
requires "nim >= 0.16.0"

Binary file not shown.

View file

@ -0,0 +1,3 @@
when isMainModule:
const NimblePkgVersion {.strdefine.} = "Unknown"
echo(NimblePkgVersion)

View file

@ -54,3 +54,9 @@ before install:
after install: after install:
echo("After PkgDir: ", getPkgDir()) echo("After PkgDir: ", getPkgDir())
before build:
echo("Before build")
after build:
echo("After build")

View file

@ -9,10 +9,9 @@ license = "BSD"
requires "nim >= 0.12.1" requires "nim >= 0.12.1"
when defined(windows): let
let callNimble = "..\\..\\src\\nimble.exe" callNimble = getEnv("NIMBLE_TEST_BINARY_PATH")
else: doAssert callNimble.len != 0, "NIMBLE_TEST_BINARY_PATH not set"
let callNimble = "../../src/nimble"
task recurse, "Level 1": task recurse, "Level 1":
echo 1 echo 1

14
tests/run/run.nimble Normal file
View file

@ -0,0 +1,14 @@
# Package
version = "0.1.0"
author = "Dominik Picheta"
description = "A new awesome nimble package"
license = "MIT"
srcDir = "src"
bin = @["run"]
# Dependencies
requires "nim >= 0.19.0"

4
tests/run/src/run.nim Normal file
View file

@ -0,0 +1,4 @@
import os
when isMainModule:
echo("Testing `nimble run`: ", commandLineParams())

View file

@ -12,6 +12,9 @@ var installDir = rootDir / "tests" / "nimbleDir"
const path = "../src/nimble" const path = "../src/nimble"
const stringNotFound = -1 const stringNotFound = -1
# Set env var to propagate nimble binary path
putEnv("NIMBLE_TEST_BINARY_PATH", nimblePath)
# Clear nimble dir. # Clear nimble dir.
removeDir(installDir) removeDir(installDir)
createDir(installDir) createDir(installDir)
@ -33,9 +36,9 @@ template cd*(dir: string, body: untyped) =
proc execNimble(args: varargs[string]): tuple[output: string, exitCode: int] = proc execNimble(args: varargs[string]): tuple[output: string, exitCode: int] =
var quotedArgs = @args var quotedArgs = @args
quotedArgs.insert("--nimbleDir:" & installDir)
quotedArgs.insert(nimblePath) quotedArgs.insert(nimblePath)
quotedArgs.add("--nimbleDir:" & installDir) quotedArgs = quotedArgs.map((x: string) => x.quoteShell)
quotedArgs = quotedArgs.map((x: string) => ("\"" & x & "\""))
let path {.used.} = getCurrentDir().parentDir() / "src" let path {.used.} = getCurrentDir().parentDir() / "src"
@ -49,6 +52,7 @@ proc execNimble(args: varargs[string]): tuple[output: string, exitCode: int] =
cmd = "DYLD_LIBRARY_PATH=/usr/local/opt/openssl@1.1/lib " & cmd cmd = "DYLD_LIBRARY_PATH=/usr/local/opt/openssl@1.1/lib " & cmd
result = execCmdEx(cmd) result = execCmdEx(cmd)
checkpoint(cmd)
checkpoint(result.output) checkpoint(result.output)
proc execNimbleYes(args: varargs[string]): tuple[output: string, exitCode: int]= proc execNimbleYes(args: varargs[string]): tuple[output: string, exitCode: int]=
@ -78,6 +82,35 @@ proc hasLineStartingWith(lines: seq[string], prefix: string): bool =
return true return true
return false return false
test "issue 708":
cd "issue708":
# TODO: We need a way to filter out compiler messages from the messages
# written by our nimble scripts.
var (output, exitCode) = execNimble("install", "-y", "--verbose")
check exitCode == QuitSuccess
let lines = output.strip.processOutput()
check(inLines(lines, "hello"))
check(inLines(lines, "hello2"))
test "issue 564":
cd "issue564":
var (_, exitCode) = execNimble("build")
check exitCode == QuitSuccess
test "depsOnly + flag order test":
var (output, exitCode) = execNimble(
"--depsOnly", "install", "-y", "https://github.com/nimble-test/packagebin2"
)
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": test "caching of nims and ini detects changes":
cd "caching": cd "caching":
var (output, exitCode) = execNimble("dump") var (output, exitCode) = execNimble("dump")
@ -285,12 +318,21 @@ suite "nimscript":
cd "nimscript": cd "nimscript":
let (output, exitCode) = execNimble(["install", "-y"]) let (output, exitCode) = execNimble(["install", "-y"])
check exitCode == QuitSuccess check exitCode == QuitSuccess
check output.contains("Before build")
check output.contains("After build")
let lines = output.strip.processOutput() let lines = output.strip.processOutput()
check lines[0].startsWith("Before PkgDir:") check lines[0].startsWith("Before PkgDir:")
check lines[0].endsWith("tests" / "nimscript") check lines[0].endsWith("tests" / "nimscript")
check lines[^1].startsWith("After PkgDir:") check lines[^1].startsWith("After PkgDir:")
check lines[^1].endsWith("tests" / "nimbleDir" / "pkgs" / "nimscript-0.1.0") check lines[^1].endsWith("tests" / "nimbleDir" / "pkgs" / "nimscript-0.1.0")
test "before/after on build":
cd "nimscript":
let (output, exitCode) = execNimble(["build"])
check exitCode == QuitSuccess
check output.contains("Before build")
check output.contains("After build")
test "can execute nimscript tasks": test "can execute nimscript tasks":
cd "nimscript": cd "nimscript":
let (output, exitCode) = execNimble("--verbose", "work") let (output, exitCode) = execNimble("--verbose", "work")
@ -441,17 +483,17 @@ test "issue #349":
] ]
proc checkName(name: string) = proc checkName(name: string) =
when defined(windows):
if name.toLowerAscii() in @["con", "nul"]:
return
let (outp, code) = execNimble("init", "-y", name) let (outp, code) = execNimble("init", "-y", name)
let msg = outp.strip.processOutput() let msg = outp.strip.processOutput()
check code == QuitFailure check code == QuitFailure
check inLines(msg, check inLines(msg,
"\"$1\" is an invalid package name: reserved name" % name) "\"$1\" is an invalid package name: reserved name" % name)
removeFile(name.changeFileExt("nimble")) try:
removeDir("src") removeFile(name.changeFileExt("nimble"))
removeDir("tests") removeDir("src")
removeDir("tests")
except OSError:
discard
for reserved in reservedNames: for reserved in reservedNames:
checkName(reserved.toUpperAscii()) checkName(reserved.toUpperAscii())
@ -882,6 +924,91 @@ test "Passing command line arguments to a task (#633)":
check exitCode == QuitSuccess check exitCode == QuitSuccess
check output.contains("Got it") check output.contains("Got it")
suite "nimble run":
test "Invalid binary":
cd "run":
var (output, exitCode) = execNimble(
"--debug", # Flag to enable debug verbosity in Nimble
"run", # Run command invokation
"blahblah", # The command to run
)
check exitCode == QuitFailure
check output.contains("Binary '$1' is not defined in 'run' package." %
"blahblah".changeFileExt(ExeExt))
test "Parameters passed to executable":
cd "run":
var (output, exitCode) = execNimble(
"--debug", # Flag to enable debug verbosity in Nimble
"run", # Run command invokation
"run", # The command to run
"--debug", # First argument passed to the executed command
"check" # Second argument passed to the executed command.
)
check exitCode == QuitSuccess
check output.contains("tests$1run$1$2 --debug check" %
[$DirSep, "run".changeFileExt(ExeExt)])
check output.contains("""Testing `nimble run`: @["--debug", "check"]""")
test "Parameters not passed to single executable":
cd "run":
var (output, exitCode) = execNimble(
"--debug", # Flag to enable debug verbosity in Nimble
"run", # Run command invokation
"--debug" # First argument passed to the executed command
)
check exitCode == QuitSuccess
check output.contains("tests$1run$1$2 --debug" %
[$DirSep, "run".changeFileExt(ExeExt)])
check output.contains("""Testing `nimble run`: @["--debug"]""")
test "Parameters passed to single executable":
cd "run":
var (output, exitCode) = execNimble(
"--debug", # Flag to enable debug verbosity in Nimble
"run", # Run command invokation
"--", # Flag to set run file to "" before next argument
"--debug", # First argument passed to the executed command
"check" # Second argument passed to the executed command.
)
check exitCode == QuitSuccess
check output.contains("tests$1run$1$2 --debug check" %
[$DirSep, "run".changeFileExt(ExeExt)])
check output.contains("""Testing `nimble run`: @["--debug", "check"]""")
test "Executable output is shown even when not debugging":
cd "run":
var (output, exitCode) =
execNimble("run", "run", "--option1", "arg1")
check exitCode == QuitSuccess
check output.contains("""Testing `nimble run`: @["--option1", "arg1"]""")
test "Quotes and whitespace are well handled":
cd "run":
var (output, exitCode) = execNimble(
"run", "run", "\"", "\'", "\t", "arg with spaces"
)
check exitCode == QuitSuccess
check output.contains(
"""Testing `nimble run`: @["\"", "\'", "\t", "arg with spaces"]"""
)
test "NimbleVersion is defined":
cd "nimbleVersionDefine":
var (output, exitCode) = execNimble("c", "-r", "src/nimbleVersionDefine.nim")
check output.contains("0.1.0")
check exitCode == QuitSuccess
var (output2, exitCode2) = execNimble("run", "nimbleVersionDefine")
check output2.contains("0.1.0")
check exitCode2 == QuitSuccess
test "issue 432":
cd "issue432":
check execNimble("install", "-y", "--depsOnly").exitCode == QuitSuccess
check execNimble("install", "-y", "--depsOnly").exitCode == QuitSuccess
test "compilation without warnings": test "compilation without warnings":
const buildDir = "./buildDir/" const buildDir = "./buildDir/"
const filesToBuild = [ const filesToBuild = [