Compare commits
76 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a10691bdf2 |
||
|
|
68a9c4c955 | ||
|
|
27d56f8e9f | ||
|
|
85e5bc7c37 | ||
|
|
9391fbc56d | ||
|
|
e9d45ca683 | ||
|
|
16ba5db44e | ||
|
|
051cfa6cd3 | ||
|
|
a8a5bdd863 |
||
|
|
bbb586dbfc | ||
|
|
b3abee937d | ||
|
|
703abe3d41 | ||
|
|
5bb795a364 | ||
|
|
a2ec2db8f2 |
||
|
|
4007b2a778 | ||
|
|
0ed8e6403c | ||
|
|
901afa8c71 | ||
|
|
3625c1f861 | ||
|
|
b68f7849e6 | ||
|
|
1db54cc736 | ||
|
|
10e22fec98 | ||
|
|
fe252c6ed6 | ||
|
|
281a1d129a | ||
|
|
a703de5dbd | ||
|
|
46dc98bb62 | ||
|
|
c85cdfd814 | ||
|
|
5ea2ac34fe | ||
|
|
da3f70cb98 | ||
|
|
419eba036b | ||
|
|
137bb1ed07 | ||
|
|
4a2aaa07dc | ||
|
|
28ff2e04a7 | ||
|
|
55dd892aab | ||
|
|
c834faf60e | ||
|
|
36c4a39674 | ||
|
|
445ecfe946 | ||
|
|
3eae8d7d61 | ||
|
|
bc8856632a | ||
|
|
8bdc054817 | ||
|
|
d6a6a47dd9 | ||
|
|
46f26e1d4a | ||
|
|
1880730762 | ||
|
|
62699afaa8 | ||
|
|
df11a6f6cf | ||
|
|
9d8cc06724 | ||
|
|
f0c454a399 | ||
|
|
427b412ff9 | ||
|
|
bb1dd21224 | ||
|
|
1eb9f0f01c | ||
|
|
bfc4f25548 | ||
|
|
6e5761b192 | ||
|
|
db018f235b | ||
|
|
2ec470d287 | ||
|
|
38cd55e71a | ||
|
|
1af4505219 |
||
|
|
fb57d47421 | ||
|
|
e39c57482a | ||
|
|
2243e3fbc2 | ||
|
|
da82e3111e | ||
|
|
8e3af03e46 | ||
|
|
f461792686 | ||
|
|
8cf97e0e06 | ||
|
|
871e5c65d1 | ||
|
|
522ef4cf12 | ||
|
|
5b7b061465 | ||
|
|
b5b85489fa | ||
|
|
5ec2ecea77 | ||
|
|
added89acc | ||
|
|
7c2b9f612e | ||
|
|
5e72840336 | ||
|
|
153866252d | ||
|
|
192ea12ab9 | ||
|
|
df8317585f | ||
|
|
98e566adab | ||
|
|
513780a382 | ||
|
|
2c87a7fe5e |
44 changed files with 1149 additions and 1016 deletions
20
.gitignore
vendored
20
.gitignore
vendored
|
|
@ -6,12 +6,15 @@ nimcache/
|
||||||
# Absolute paths
|
# Absolute paths
|
||||||
/src/babel
|
/src/babel
|
||||||
/src/nimble
|
/src/nimble
|
||||||
/tests/tester
|
|
||||||
|
|
||||||
# executables from test and build
|
# executables from test and build
|
||||||
/nimble
|
/nimble
|
||||||
/tests/nimscript/nimscript
|
src/nimblepkg/cli
|
||||||
/tests/issue27/issue27
|
src/nimblepkg/packageinfo
|
||||||
|
src/nimblepkg/packageparser
|
||||||
|
src/nimblepkg/reversedeps
|
||||||
|
src/nimblepkg/version
|
||||||
|
src/nimblepkg/download
|
||||||
|
|
||||||
# Windows executables
|
# Windows executables
|
||||||
*.exe
|
*.exe
|
||||||
|
|
@ -19,4 +22,13 @@ nimcache/
|
||||||
|
|
||||||
# VCC compiler and linker artifacts
|
# VCC compiler and linker artifacts
|
||||||
*.ilk
|
*.ilk
|
||||||
*.pdb
|
*.pdb
|
||||||
|
|
||||||
|
# Editors and IDEs project files and folders
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# VCS artifacts
|
||||||
|
*.orig
|
||||||
|
|
||||||
|
# Test procedure artifacts
|
||||||
|
nimble_*.nims
|
||||||
|
|
|
||||||
18
.travis.yml
18
.travis.yml
|
|
@ -1,4 +1,5 @@
|
||||||
os:
|
os:
|
||||||
|
- windows
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
|
|
||||||
|
|
@ -6,21 +7,18 @@ language: c
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- BRANCH=0.19.6
|
- BRANCH=0.19.6
|
||||||
- BRANCH=#44cc5f6360c7ccc96c296948b2524bd2cdebf1f0
|
- BRANCH=0.20.2
|
||||||
|
- BRANCH=1.0.6
|
||||||
|
# This is the latest working Nim version against which Nimble is being tested
|
||||||
|
- BRANCH=#ab525cc48abdbbbed1f772e58e9fe21474f70f07
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- "$HOME/.choosenim/toolchains/nim-0.19.6"
|
- "$HOME/.choosenim"
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,34 @@
|
||||||
|
|
||||||
# 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).
|
||||||
|
- 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
|
||||||
|
|
||||||
This is a small release which avoids object variant changes that are now
|
This is a small release which avoids object variant changes that are now
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -401,6 +428,7 @@ You can also specify multiple dependencies like so:
|
||||||
|
|
||||||
requires "nim >= 0.10.0", "foobar >= 0.1.0"
|
requires "nim >= 0.10.0", "foobar >= 0.1.0"
|
||||||
requires "fizzbuzz >= 1.0"
|
requires "fizzbuzz >= 1.0"
|
||||||
|
requires "https://github.com/user/pkg#5a54b5e"
|
||||||
```
|
```
|
||||||
|
|
||||||
Nimble currently supports installation of packages from a local directory, a
|
Nimble currently supports installation of packages from a local directory, a
|
||||||
|
|
@ -477,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
|
||||||
|
|
||||||
|
|
@ -785,6 +813,19 @@ To summarise, the steps for release are:
|
||||||
Once the new tag is in the remote repository, Nimble will be able to detect
|
Once the new tag is in the remote repository, Nimble will be able to detect
|
||||||
the new version.
|
the new version.
|
||||||
|
|
||||||
|
##### Git Version Tagging
|
||||||
|
|
||||||
|
Use dot separated numbers to represent the release version in the git
|
||||||
|
tag label. Nimble will parse these git tag labels to know which
|
||||||
|
versions of a package are published.
|
||||||
|
|
||||||
|
``` text
|
||||||
|
v0.2.0 # 0.2.0
|
||||||
|
v1 # 1
|
||||||
|
v1.2.3-zuzu # 1.2.3
|
||||||
|
foo-1.2.3.4 # 1.2.3.4
|
||||||
|
```
|
||||||
|
|
||||||
## Publishing packages
|
## Publishing packages
|
||||||
|
|
||||||
Publishing packages isn't a requirement. But doing so allows people to associate
|
Publishing packages isn't a requirement. But doing so allows people to associate
|
||||||
|
|
|
||||||
248
src/nimble.nim
248
src/nimble.nim
|
|
@ -3,12 +3,13 @@
|
||||||
|
|
||||||
import system except TResult
|
import system except TResult
|
||||||
|
|
||||||
import httpclient, parseopt, os, osproc, pegs, tables, parseutils,
|
import os, tables, strtabs, json, algorithm, sets, uri, sugar, sequtils, osproc
|
||||||
strtabs, json, algorithm, sets, uri, sugar, sequtils
|
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,
|
||||||
|
|
@ -95,7 +96,7 @@ proc copyFilesRec(origDir, currentDir, dest: string,
|
||||||
## Copies all the required files, skips files specified in the .nimble file
|
## Copies all the required files, skips files specified in the .nimble file
|
||||||
## (PackageInfo).
|
## (PackageInfo).
|
||||||
## Returns a list of filepaths to files which have been installed.
|
## Returns a list of filepaths to files which have been installed.
|
||||||
result = initSet[string]()
|
result = initHashSet[string]()
|
||||||
let whitelistMode =
|
let whitelistMode =
|
||||||
pkgInfo.installDirs.len != 0 or
|
pkgInfo.installDirs.len != 0 or
|
||||||
pkgInfo.installFiles.len != 0 or
|
pkgInfo.installFiles.len != 0 or
|
||||||
|
|
@ -156,7 +157,8 @@ proc processDeps(pkginfo: PackageInfo, options: Options): seq[PackageInfo] =
|
||||||
"dependencies for $1@$2" % [pkginfo.name, pkginfo.specialVersion],
|
"dependencies for $1@$2" % [pkginfo.name, pkginfo.specialVersion],
|
||||||
priority = HighPriority)
|
priority = HighPriority)
|
||||||
|
|
||||||
var pkgList = getInstalledPkgsMin(options.getPkgsDir(), options)
|
var pkgList {.global.}: seq[tuple[pkginfo: PackageInfo, meta: MetaData]] = @[]
|
||||||
|
once: pkgList = getInstalledPkgsMin(options.getPkgsDir(), options)
|
||||||
var reverseDeps: seq[tuple[name, version: string]] = @[]
|
var reverseDeps: seq[tuple[name, version: string]] = @[]
|
||||||
for dep in pkginfo.requires:
|
for dep in pkginfo.requires:
|
||||||
if dep.name == "nimrod" or dep.name == "nim":
|
if dep.name == "nimrod" or dep.name == "nim":
|
||||||
|
|
@ -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: seq[string],
|
proc buildFromDir(
|
||||||
args: var seq[string]) =
|
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?")
|
||||||
let realDir = pkgInfo.getRealDir()
|
var args = args
|
||||||
|
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: 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,13 +269,14 @@ proc buildFromDir(pkgInfo: PackageInfo, paths: seq[string],
|
||||||
exc.hint = hint
|
exc.hint = hint
|
||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
proc buildFromDir(pkgInfo: PackageInfo, paths: seq[string], forRelease: bool) =
|
if binariesBuilt == 0:
|
||||||
var args: seq[string]
|
raiseNimbleError(
|
||||||
if forRelease:
|
"No binaries built, did you specify a valid binary name?"
|
||||||
args = @["-d:release"]
|
)
|
||||||
else:
|
|
||||||
args = @[]
|
# Handle post-`build` hook.
|
||||||
buildFromDir(pkgInfo, paths, args)
|
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``.
|
||||||
|
|
@ -329,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)
|
||||||
|
|
@ -356,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, true)
|
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"):
|
||||||
|
|
@ -381,7 +411,7 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
||||||
|
|
||||||
createDir(pkgDestDir)
|
createDir(pkgDestDir)
|
||||||
# Copy this package's files based on the preferences specified in PkgInfo.
|
# Copy this package's files based on the preferences specified in PkgInfo.
|
||||||
var filesInstalled = initSet[string]()
|
var filesInstalled = initHashSet[string]()
|
||||||
iterInstallFiles(realDir, pkgInfo, options,
|
iterInstallFiles(realDir, pkgInfo, options,
|
||||||
proc (file: string) =
|
proc (file: string) =
|
||||||
createDir(changeRoot(realDir, pkgDestDir, file.splitFile.dir))
|
createDir(changeRoot(realDir, pkgDestDir, file.splitFile.dir))
|
||||||
|
|
@ -394,7 +424,7 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
||||||
pkgInfo.myPath)
|
pkgInfo.myPath)
|
||||||
filesInstalled.incl copyFileD(pkgInfo.myPath, dest)
|
filesInstalled.incl copyFileD(pkgInfo.myPath, dest)
|
||||||
|
|
||||||
var binariesInstalled = initSet[string]()
|
var binariesInstalled = initHashSet[string]()
|
||||||
if pkgInfo.bin.len > 0:
|
if pkgInfo.bin.len > 0:
|
||||||
# Make sure ~/.nimble/bin directory is created.
|
# Make sure ~/.nimble/bin directory is created.
|
||||||
createDir(binDir)
|
createDir(binDir)
|
||||||
|
|
@ -439,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,
|
||||||
|
|
@ -506,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.")
|
||||||
|
|
@ -524,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 =
|
||||||
|
|
@ -541,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) =
|
||||||
|
|
@ -558,7 +589,7 @@ proc search(options: Options) =
|
||||||
var found = false
|
var found = false
|
||||||
template onFound {.dirty.} =
|
template onFound {.dirty.} =
|
||||||
echoPackage(pkg)
|
echoPackage(pkg)
|
||||||
if options.queryVersions:
|
if pkg.alias.len == 0 and options.queryVersions:
|
||||||
echoPackageVersions(pkg)
|
echoPackageVersions(pkg)
|
||||||
echo(" ")
|
echo(" ")
|
||||||
found = true
|
found = true
|
||||||
|
|
@ -584,7 +615,7 @@ proc list(options: Options) =
|
||||||
let pkgList = getPackageList(options)
|
let pkgList = getPackageList(options)
|
||||||
for pkg in pkgList:
|
for pkg in pkgList:
|
||||||
echoPackage(pkg)
|
echoPackage(pkg)
|
||||||
if options.queryVersions:
|
if pkg.alias.len == 0 and options.queryVersions:
|
||||||
echoPackageVersions(pkg)
|
echoPackageVersions(pkg)
|
||||||
echo(" ")
|
echo(" ")
|
||||||
|
|
||||||
|
|
@ -698,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 != "":
|
||||||
|
|
@ -732,20 +768,20 @@ proc init(options: Options) =
|
||||||
display("Using", "$# for new package name" % [pkgName.escape()],
|
display("Using", "$# for new package name" % [pkgName.escape()],
|
||||||
priority = HighPriority)
|
priority = HighPriority)
|
||||||
|
|
||||||
# Ask for package author
|
# Determine author by running an external command
|
||||||
|
proc getAuthorWithCmd(cmd: string): string =
|
||||||
|
let (name, exitCode) = doCmdEx(cmd)
|
||||||
|
if exitCode == QuitSuccess and name.len > 0:
|
||||||
|
result = name.strip()
|
||||||
|
display("Using", "$# for new package author" % [result],
|
||||||
|
priority = HighPriority)
|
||||||
|
|
||||||
|
# Determine package author via git/hg or asking
|
||||||
proc getAuthor(): string =
|
proc getAuthor(): string =
|
||||||
if findExe("git") != "":
|
if findExe("git") != "":
|
||||||
let (name, exitCode) = doCmdEx("git config --global user.name")
|
result = getAuthorWithCmd("git config --global user.name")
|
||||||
if exitCode == QuitSuccess and name.len > 0:
|
|
||||||
result = name.strip()
|
|
||||||
display("Using", "$# for new package author" % [result.escape()],
|
|
||||||
priority = HighPriority)
|
|
||||||
elif findExe("hg") != "":
|
elif findExe("hg") != "":
|
||||||
let (name, exitCode) = doCmdEx("hg config ui.username")
|
result = getAuthorWithCmd("hg config ui.username")
|
||||||
if exitCode == QuitSuccess and name.len > 0:
|
|
||||||
result = name.strip()
|
|
||||||
display("Using", "$# for new package author" % [result.escape()],
|
|
||||||
priority = HighPriority)
|
|
||||||
if result.len == 0:
|
if result.len == 0:
|
||||||
result = promptCustom(options, "Your name?", "Anonymous")
|
result = promptCustom(options, "Your name?", "Anonymous")
|
||||||
let pkgAuthor = getAuthor()
|
let pkgAuthor = getAuthor()
|
||||||
|
|
@ -832,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)
|
||||||
|
|
||||||
|
|
@ -840,7 +887,8 @@ proc uninstall(options: Options) =
|
||||||
raise newException(NimbleError,
|
raise newException(NimbleError,
|
||||||
"Please specify the package(s) to uninstall.")
|
"Please specify the package(s) to uninstall.")
|
||||||
|
|
||||||
var pkgsToDelete: seq[PackageInfo] = @[]
|
var pkgsToDelete: HashSet[PackageInfo]
|
||||||
|
pkgsToDelete.init()
|
||||||
# Do some verification.
|
# Do some verification.
|
||||||
for pkgTup in options.action.packages:
|
for pkgTup in options.action.packages:
|
||||||
display("Looking", "for $1 ($2)" % [pkgTup.name, $pkgTup.ver],
|
display("Looking", "for $1 ($2)" % [pkgTup.name, $pkgTup.ver],
|
||||||
|
|
@ -851,37 +899,33 @@ proc uninstall(options: Options) =
|
||||||
raise newException(NimbleError, "Package not found")
|
raise newException(NimbleError, "Package not found")
|
||||||
|
|
||||||
display("Checking", "reverse dependencies", priority = HighPriority)
|
display("Checking", "reverse dependencies", priority = HighPriority)
|
||||||
var errors: seq[string] = @[]
|
|
||||||
for pkg in pkgList:
|
for pkg in pkgList:
|
||||||
# Check whether any packages depend on the ones the user is trying to
|
# Check whether any packages depend on the ones the user is trying to
|
||||||
# uninstall.
|
# uninstall.
|
||||||
if options.uninstallRevDeps:
|
if options.uninstallRevDeps:
|
||||||
getAllRevDeps(options, pkg, pkgsToDelete)
|
getAllRevDeps(options, pkg, pkgsToDelete)
|
||||||
else:
|
else:
|
||||||
let revDeps = getRevDeps(options, pkg)
|
let
|
||||||
|
revDeps = getRevDeps(options, pkg)
|
||||||
var reason = ""
|
var reason = ""
|
||||||
if revDeps.len == 1:
|
for revDep in revDeps:
|
||||||
reason = "$1 ($2) depends on it" % [revDeps[0].name, $revDeps[0].ver]
|
if reason.len != 0: reason.add ", "
|
||||||
else:
|
reason.add("$1 ($2)" % [revDep.name, revDep.version])
|
||||||
for i in 0 ..< revDeps.len:
|
if reason.len != 0:
|
||||||
reason.add("$1 ($2)" % [revDeps[i].name, $revDeps[i].ver])
|
reason &= " depend" & (if revDeps.len == 1: "s" else: "") & " on it"
|
||||||
if i != revDeps.len-1:
|
|
||||||
reason.add ", "
|
|
||||||
reason.add " depend on it"
|
|
||||||
|
|
||||||
if revDeps.len > 0:
|
if len(revDeps - pkgsToDelete) > 0:
|
||||||
errors.add("Cannot uninstall $1 ($2) because $3" %
|
display("Cannot", "uninstall $1 ($2) because $3" %
|
||||||
[pkgTup.name, pkg.specialVersion, reason])
|
[pkgTup.name, pkg.specialVersion, reason], Warning, HighPriority)
|
||||||
else:
|
else:
|
||||||
pkgsToDelete.add pkg
|
pkgsToDelete.incl pkg
|
||||||
|
|
||||||
if pkgsToDelete.len == 0:
|
if pkgsToDelete.len == 0:
|
||||||
raise newException(NimbleError, "\n " & errors.join("\n "))
|
raise newException(NimbleError, "Failed uninstall - no packages to delete")
|
||||||
|
|
||||||
var pkgNames = ""
|
var pkgNames = ""
|
||||||
for i in 0 ..< pkgsToDelete.len:
|
for pkg in pkgsToDelete.items:
|
||||||
if i != 0: pkgNames.add ", "
|
if pkgNames.len != 0: pkgNames.add ", "
|
||||||
let pkg = pkgsToDelete[i]
|
|
||||||
pkgNames.add("$1 ($2)" % [pkg.name, pkg.specialVersion])
|
pkgNames.add("$1 ($2)" % [pkg.name, pkg.specialVersion])
|
||||||
|
|
||||||
# Let's confirm that the user wants these packages removed.
|
# Let's confirm that the user wants these packages removed.
|
||||||
|
|
@ -912,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)
|
||||||
|
|
@ -965,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 == @[]:
|
||||||
|
|
@ -1001,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
|
||||||
|
|
@ -1017,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)
|
||||||
|
|
@ -1028,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)
|
||||||
|
|
@ -1047,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
|
||||||
|
|
@ -1065,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:
|
||||||
|
|
@ -1076,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)
|
||||||
|
|
@ -1101,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:
|
||||||
|
|
@ -1119,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
|
||||||
|
|
@ -1128,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)
|
||||||
|
|
@ -1150,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)
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,11 @@
|
||||||
# - Bright for HighPriority.
|
# - Bright for HighPriority.
|
||||||
# - Normal for MediumPriority.
|
# - Normal for MediumPriority.
|
||||||
|
|
||||||
import logging, terminal, sets, strutils, os
|
import terminal, sets, strutils
|
||||||
import ./common
|
import version
|
||||||
|
|
||||||
when defined(windows):
|
when not declared(initHashSet):
|
||||||
import winlean
|
import common
|
||||||
|
|
||||||
type
|
type
|
||||||
CLI* = ref object
|
CLI* = ref object
|
||||||
|
|
@ -49,7 +49,7 @@ const
|
||||||
proc newCLI(): CLI =
|
proc newCLI(): CLI =
|
||||||
result = CLI(
|
result = CLI(
|
||||||
level: HighPriority,
|
level: HighPriority,
|
||||||
warnings: initSet[(string, string)](),
|
warnings: initHashSet[(string, string)](),
|
||||||
suppressionCount: 0,
|
suppressionCount: 0,
|
||||||
showColor: true,
|
showColor: true,
|
||||||
suppressMessages: false
|
suppressMessages: false
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ when not defined(nimscript):
|
||||||
import sets
|
import sets
|
||||||
|
|
||||||
import version
|
import version
|
||||||
export version.NimbleError # TODO: Surely there is a better way?
|
|
||||||
|
|
||||||
type
|
type
|
||||||
BuildFailed* = object of NimbleError
|
BuildFailed* = object of NimbleError
|
||||||
|
|
@ -23,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
|
||||||
|
|
@ -63,4 +63,16 @@ when not defined(nimscript):
|
||||||
return (error, hint)
|
return (error, hint)
|
||||||
|
|
||||||
const
|
const
|
||||||
nimbleVersion* = "0.10.2"
|
nimbleVersion* = "0.11.0"
|
||||||
|
|
||||||
|
when not declared(initHashSet):
|
||||||
|
import sets
|
||||||
|
|
||||||
|
template initHashSet*[A](initialSize = 64): HashSet[A] =
|
||||||
|
initSet[A](initialSize)
|
||||||
|
|
||||||
|
when not declared(toHashSet):
|
||||||
|
import sets
|
||||||
|
|
||||||
|
template toHashSet*[A](keys: openArray[A]): HashSet[A] =
|
||||||
|
toSet(keys)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Copyright (C) Dominik Picheta. All rights reserved.
|
# Copyright (C) Dominik Picheta. All rights reserved.
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
import parsecfg, streams, strutils, os, tables, Uri
|
import parsecfg, streams, strutils, os, tables, uri
|
||||||
|
|
||||||
import tools, version, common, cli
|
import version, cli
|
||||||
|
|
||||||
type
|
type
|
||||||
Config* = object
|
Config* = object
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,15 @@
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
|
|
||||||
import parseutils, os, osproc, strutils, tables, pegs, uri
|
import parseutils, os, osproc, strutils, tables, pegs, uri
|
||||||
|
|
||||||
import packageinfo, packageparser, version, tools, common, options, cli
|
import packageinfo, packageparser, version, tools, common, options, cli
|
||||||
|
from algorithm import SortOrder, sorted
|
||||||
|
from sequtils import toSeq, filterIt, map
|
||||||
|
|
||||||
type
|
type
|
||||||
DownloadMethod* {.pure.} = enum
|
DownloadMethod* {.pure.} = enum
|
||||||
git = "git", hg = "hg"
|
git = "git", hg = "hg"
|
||||||
|
|
||||||
proc getSpecificDir(meth: DownloadMethod): string =
|
proc getSpecificDir(meth: DownloadMethod): string {.used.} =
|
||||||
case meth
|
case meth
|
||||||
of DownloadMethod.git:
|
of DownloadMethod.git:
|
||||||
".git"
|
".git"
|
||||||
|
|
@ -24,11 +25,12 @@ proc doCheckout(meth: DownloadMethod, downloadDir, branch: string) =
|
||||||
# clone has happened. Like in the case of git on Windows where it
|
# clone has happened. Like in the case of git on Windows where it
|
||||||
# messes up the damn line endings.
|
# messes up the damn line endings.
|
||||||
doCmd("git checkout --force " & branch)
|
doCmd("git checkout --force " & branch)
|
||||||
|
doCmd("git submodule update --recursive")
|
||||||
of DownloadMethod.hg:
|
of DownloadMethod.hg:
|
||||||
cd downloadDir:
|
cd downloadDir:
|
||||||
doCmd("hg checkout " & branch)
|
doCmd("hg checkout " & branch)
|
||||||
|
|
||||||
proc doPull(meth: DownloadMethod, downloadDir: string) =
|
proc doPull(meth: DownloadMethod, downloadDir: string) {.used.} =
|
||||||
case meth
|
case meth
|
||||||
of DownloadMethod.git:
|
of DownloadMethod.git:
|
||||||
doCheckout(meth, downloadDir, "")
|
doCheckout(meth, downloadDir, "")
|
||||||
|
|
@ -102,14 +104,21 @@ proc getTagsListRemote*(url: string, meth: DownloadMethod): seq[string] =
|
||||||
# http://stackoverflow.com/questions/2039150/show-tags-for-remote-hg-repository
|
# http://stackoverflow.com/questions/2039150/show-tags-for-remote-hg-repository
|
||||||
raise newException(ValueError, "Hg doesn't support remote tag querying.")
|
raise newException(ValueError, "Hg doesn't support remote tag querying.")
|
||||||
|
|
||||||
proc getVersionList*(tags: seq[string]): Table[Version, string] =
|
proc getVersionList*(tags: seq[string]): OrderedTable[Version, string] =
|
||||||
# Returns: TTable of version -> git tag name
|
## Return an ordered table of Version -> git tag label. Ordering is
|
||||||
result = initTable[Version, string]()
|
## in descending order with the most recent version first.
|
||||||
for tag in tags:
|
let taggedVers: seq[tuple[ver: Version, tag: string]] =
|
||||||
if tag != "":
|
tags
|
||||||
let i = skipUntil(tag, Digits) # skip any chars before the version
|
.filterIt(it != "")
|
||||||
# TODO: Better checking, tags can have any names. Add warnings and such.
|
.map(proc(s: string): tuple[ver: Version, tag: string] =
|
||||||
result[newVersion(tag[i .. tag.len-1])] = tag
|
# skip any chars before the version
|
||||||
|
let i = skipUntil(s, Digits)
|
||||||
|
# TODO: Better checking, tags can have any
|
||||||
|
# names. Add warnings and such.
|
||||||
|
result = (newVersion(s[i .. s.len-1]), s))
|
||||||
|
.sorted(proc(a, b: (Version, string)): int = cmp(a[0], b[0]),
|
||||||
|
SortOrder.Descending)
|
||||||
|
result = toOrderedTable[Version, string](taggedVers)
|
||||||
|
|
||||||
proc getDownloadMethod*(meth: string): DownloadMethod =
|
proc getDownloadMethod*(meth: string): DownloadMethod =
|
||||||
case meth
|
case meth
|
||||||
|
|
@ -267,14 +276,8 @@ proc echoPackageVersions*(pkg: Package) =
|
||||||
try:
|
try:
|
||||||
let versions = getTagsListRemote(pkg.url, downMethod).getVersionList()
|
let versions = getTagsListRemote(pkg.url, downMethod).getVersionList()
|
||||||
if versions.len > 0:
|
if versions.len > 0:
|
||||||
var vstr = ""
|
let sortedVersions = toSeq(values(versions))
|
||||||
var i = 0
|
echo(" versions: " & join(sortedVersions, ", "))
|
||||||
for v in values(versions):
|
|
||||||
if i != 0:
|
|
||||||
vstr.add(", ")
|
|
||||||
vstr.add(v)
|
|
||||||
i.inc
|
|
||||||
echo(" versions: " & vstr)
|
|
||||||
else:
|
else:
|
||||||
echo(" versions: (No versions tagged in the remote repository)")
|
echo(" versions: (No versions tagged in the remote repository)")
|
||||||
except OSError:
|
except OSError:
|
||||||
|
|
@ -282,3 +285,32 @@ proc echoPackageVersions*(pkg: Package) =
|
||||||
of DownloadMethod.hg:
|
of DownloadMethod.hg:
|
||||||
echo(" versions: (Remote tag retrieval not supported by " &
|
echo(" versions: (Remote tag retrieval not supported by " &
|
||||||
pkg.downloadMethod & ")")
|
pkg.downloadMethod & ")")
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
# Test version sorting
|
||||||
|
block:
|
||||||
|
let data = @["v9.0.0-taeyeon", "v9.0.1-jessica", "v9.2.0-sunny",
|
||||||
|
"v9.4.0-tiffany", "v9.4.2-hyoyeon"]
|
||||||
|
let expected = toOrderedTable[Version, string]({
|
||||||
|
newVersion("9.4.2-hyoyeon"): "v9.4.2-hyoyeon",
|
||||||
|
newVersion("9.4.0-tiffany"): "v9.4.0-tiffany",
|
||||||
|
newVersion("9.2.0-sunny"): "v9.2.0-sunny",
|
||||||
|
newVersion("9.0.1-jessica"): "v9.0.1-jessica",
|
||||||
|
newVersion("9.0.0-taeyeon"): "v9.0.0-taeyeon"
|
||||||
|
})
|
||||||
|
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!")
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,13 @@ type
|
||||||
pkgNimDep: string
|
pkgNimDep: string
|
||||||
pkgType: string
|
pkgType: string
|
||||||
|
|
||||||
|
proc writeExampleIfNonExistent(file: string, content: string) =
|
||||||
|
if not existsFile(file):
|
||||||
|
writeFile(file, content)
|
||||||
|
else:
|
||||||
|
display("Info:", "File " & file & " already exists, did not write " &
|
||||||
|
"example code", priority = HighPriority)
|
||||||
|
|
||||||
proc createPkgStructure*(info: PkgInitInfo, pkgRoot: string) =
|
proc createPkgStructure*(info: PkgInitInfo, pkgRoot: string) =
|
||||||
# Create source directory
|
# Create source directory
|
||||||
createDirD(pkgRoot / info.pkgSrcDir)
|
createDirD(pkgRoot / info.pkgSrcDir)
|
||||||
|
|
@ -23,7 +30,7 @@ proc createPkgStructure*(info: PkgInitInfo, pkgRoot: string) =
|
||||||
case info.pkgType
|
case info.pkgType
|
||||||
of "binary":
|
of "binary":
|
||||||
let mainFile = pkgRoot / info.pkgSrcDir / info.pkgName.changeFileExt("nim")
|
let mainFile = pkgRoot / info.pkgSrcDir / info.pkgName.changeFileExt("nim")
|
||||||
writeFile(mainFile,
|
writeExampleIfNonExistent(mainFile,
|
||||||
"""
|
"""
|
||||||
# This is just an example to get you started. A typical binary package
|
# This is just an example to get you started. A typical binary package
|
||||||
# uses this file as the main entry point of the application.
|
# uses this file as the main entry point of the application.
|
||||||
|
|
@ -35,7 +42,7 @@ when isMainModule:
|
||||||
nimbleFileOptions.add("bin = @[\"$1\"]\n" % info.pkgName)
|
nimbleFileOptions.add("bin = @[\"$1\"]\n" % info.pkgName)
|
||||||
of "library":
|
of "library":
|
||||||
let mainFile = pkgRoot / info.pkgSrcDir / info.pkgName.changeFileExt("nim")
|
let mainFile = pkgRoot / info.pkgSrcDir / info.pkgName.changeFileExt("nim")
|
||||||
writeFile(mainFile,
|
writeExampleIfNonExistent(mainFile,
|
||||||
"""
|
"""
|
||||||
# This is just an example to get you started. A typical library package
|
# 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
|
# exports the main API in this file. Note that you cannot rename this file
|
||||||
|
|
@ -50,7 +57,7 @@ proc add*(x, y: int): int =
|
||||||
createDirD(pkgRoot / info.pkgSrcDir / info.pkgName)
|
createDirD(pkgRoot / info.pkgSrcDir / info.pkgName)
|
||||||
let submodule = pkgRoot / info.pkgSrcDir / info.pkgName /
|
let submodule = pkgRoot / info.pkgSrcDir / info.pkgName /
|
||||||
"submodule".addFileExt("nim")
|
"submodule".addFileExt("nim")
|
||||||
writeFile(submodule,
|
writeExampleIfNonExistent(submodule,
|
||||||
"""
|
"""
|
||||||
# This is just an example to get you started. Users of your library will
|
# This is just an example to get you started. Users of your library will
|
||||||
# import this file by writing ``import $1/submodule``. Feel free to rename or
|
# import this file by writing ``import $1/submodule``. Feel free to rename or
|
||||||
|
|
@ -68,7 +75,7 @@ proc initSubmodule*(): Submodule =
|
||||||
)
|
)
|
||||||
of "hybrid":
|
of "hybrid":
|
||||||
let mainFile = pkgRoot / info.pkgSrcDir / info.pkgName.changeFileExt("nim")
|
let mainFile = pkgRoot / info.pkgSrcDir / info.pkgName.changeFileExt("nim")
|
||||||
writeFile(mainFile,
|
writeExampleIfNonExistent(mainFile,
|
||||||
"""
|
"""
|
||||||
# This is just an example to get you started. A typical hybrid package
|
# This is just an example to get you started. A typical hybrid package
|
||||||
# uses this file as the main entry point of the application.
|
# uses this file as the main entry point of the application.
|
||||||
|
|
@ -83,7 +90,7 @@ when isMainModule:
|
||||||
let pkgSubDir = pkgRoot / info.pkgSrcDir / info.pkgName & "pkg"
|
let pkgSubDir = pkgRoot / info.pkgSrcDir / info.pkgName & "pkg"
|
||||||
createDirD(pkgSubDir)
|
createDirD(pkgSubDir)
|
||||||
let submodule = pkgSubDir / "submodule".addFileExt("nim")
|
let submodule = pkgSubDir / "submodule".addFileExt("nim")
|
||||||
writeFile(submodule,
|
writeExampleIfNonExistent(submodule,
|
||||||
"""
|
"""
|
||||||
# This is just an example to get you started. Users of your hybrid library will
|
# This is just an example to get you started. Users of your hybrid library will
|
||||||
# import this file by writing ``import $1pkg/submodule``. Feel free to rename or
|
# import this file by writing ``import $1pkg/submodule``. Feel free to rename or
|
||||||
|
|
@ -112,7 +119,7 @@ proc getWelcomeMessage*(): string = "Hello, World!"
|
||||||
)
|
)
|
||||||
|
|
||||||
if info.pkgType == "library":
|
if info.pkgType == "library":
|
||||||
writeFile(pkgTestPath / "test1".addFileExt("nim"),
|
writeExampleIfNonExistent(pkgTestPath / "test1".addFileExt("nim"),
|
||||||
"""
|
"""
|
||||||
# This is just an example to get you started. You may wish to put all of your
|
# This is just an example to get you started. You may wish to put all of your
|
||||||
# tests into a single file, or separate them into multiple `test1`, `test2`
|
# tests into a single file, or separate them into multiple `test1`, `test2`
|
||||||
|
|
@ -129,7 +136,7 @@ test "can add":
|
||||||
""" % info.pkgName
|
""" % info.pkgName
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
writeFile(pkgTestPath / "test1".addFileExt("nim"),
|
writeExampleIfNonExistent(pkgTestPath / "test1".addFileExt("nim"),
|
||||||
"""
|
"""
|
||||||
# This is just an example to get you started. You may wish to put all of your
|
# This is just an example to get you started. You may wish to put all of your
|
||||||
# tests into a single file, or separate them into multiple `test1`, `test2`
|
# tests into a single file, or separate them into multiple `test1`, `test2`
|
||||||
|
|
@ -157,8 +164,8 @@ test "correct welcome":
|
||||||
writeFile(nimbleFile, """# Package
|
writeFile(nimbleFile, """# Package
|
||||||
|
|
||||||
version = $#
|
version = $#
|
||||||
author = $#
|
author = "$#"
|
||||||
description = $#
|
description = "$#"
|
||||||
license = $#
|
license = $#
|
||||||
srcDir = $#
|
srcDir = $#
|
||||||
$#
|
$#
|
||||||
|
|
@ -168,7 +175,7 @@ $#
|
||||||
|
|
||||||
requires "nim >= $#"
|
requires "nim >= $#"
|
||||||
""" % [
|
""" % [
|
||||||
info.pkgVersion.escape(), info.pkgAuthor.escape(), info.pkgDesc.escape(),
|
info.pkgVersion.escape(), info.pkgAuthor.replace("\"", "\\\""), info.pkgDesc.replace("\"", "\\\""),
|
||||||
info.pkgLicense.escape(), info.pkgSrcDir.escape(), nimbleFileOptions,
|
info.pkgLicense.escape(), info.pkgSrcDir.escape(), nimbleFileOptions,
|
||||||
pkgBackend, info.pkgNimDep
|
pkgBackend, info.pkgNimDep
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
import system except getCommand, setCommand, switch, `--`
|
import system except getCommand, setCommand, switch, `--`
|
||||||
import strformat, strutils, tables
|
import strformat, strutils, tables
|
||||||
|
|
||||||
|
when not defined(nimscript):
|
||||||
|
import os
|
||||||
|
|
||||||
var
|
var
|
||||||
packageName* = "" ## Set this to the package name. It
|
packageName* = "" ## Set this to the package name. It
|
||||||
## is usually not required to do that, nims' filename is
|
## is usually not required to do that, nims' filename is
|
||||||
|
|
@ -14,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.
|
||||||
|
|
||||||
|
|
@ -81,25 +84,24 @@ template `--`*(key: untyped) =
|
||||||
|
|
||||||
template printIfLen(varName) =
|
template printIfLen(varName) =
|
||||||
if varName.len != 0:
|
if varName.len != 0:
|
||||||
iniOut &= astToStr(varName) & ": \"\"\"" & varName & "\"\"\"\n"
|
result &= astToStr(varName) & ": \"\"\"" & varName & "\"\"\"\n"
|
||||||
|
|
||||||
template printSeqIfLen(varName) =
|
template printSeqIfLen(varName) =
|
||||||
if varName.len != 0:
|
if varName.len != 0:
|
||||||
iniOut &= astToStr(varName) & ": \"" & varName.join(", ") & "\"\n"
|
result &= astToStr(varName) & ": \"" & varName.join(", ") & "\"\n"
|
||||||
|
|
||||||
proc printPkgInfo() =
|
proc printPkgInfo(): string =
|
||||||
if backend.len == 0:
|
if backend.len == 0:
|
||||||
backend = "c"
|
backend = "c"
|
||||||
|
|
||||||
var
|
result = "[Package]\n"
|
||||||
iniOut = "[Package]\n"
|
|
||||||
if packageName.len != 0:
|
if packageName.len != 0:
|
||||||
iniOut &= "name: \"" & packageName & "\"\n"
|
result &= "name: \"" & packageName & "\"\n"
|
||||||
printIfLen version
|
printIfLen version
|
||||||
printIfLen author
|
printIfLen author
|
||||||
printIfLen description
|
printIfLen description
|
||||||
printIfLen license
|
printIfLen license
|
||||||
printIfLen srcdir
|
printIfLen srcDir
|
||||||
printIfLen binDir
|
printIfLen binDir
|
||||||
printIfLen backend
|
printIfLen backend
|
||||||
|
|
||||||
|
|
@ -114,14 +116,13 @@ proc printPkgInfo() =
|
||||||
printSeqIfLen afterHooks
|
printSeqIfLen afterHooks
|
||||||
|
|
||||||
if requiresData.len != 0:
|
if requiresData.len != 0:
|
||||||
iniOut &= "\n[Deps]\n"
|
result &= "\n[Deps]\n"
|
||||||
iniOut &= &"requires: \"{requiresData.join(\", \")}\"\n"
|
result &= &"requires: \"{requiresData.join(\", \")}\"\n"
|
||||||
|
|
||||||
echo iniOut
|
|
||||||
|
|
||||||
proc onExit*() =
|
proc onExit*() =
|
||||||
if "printPkgInfo".normalize in commandLineParams:
|
if "printPkgInfo".normalize in commandLineParams:
|
||||||
printPkgInfo()
|
if outFile.len != 0:
|
||||||
|
writeFile(outFile, printPkgInfo())
|
||||||
else:
|
else:
|
||||||
var
|
var
|
||||||
output = ""
|
output = ""
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
# Copyright (C) Dominik Picheta. All rights reserved.
|
# Copyright (C) Dominik Picheta. All rights reserved.
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
|
|
||||||
import os, tables, strutils, sets
|
import os, strutils, sets
|
||||||
|
|
||||||
import packageparser, common, packageinfo, options, nimscriptwrapper, cli
|
import packageparser, common, packageinfo, options, nimscriptwrapper, cli,
|
||||||
|
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 = ""
|
||||||
|
|
@ -20,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
|
||||||
|
|
@ -57,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
|
||||||
|
|
|
||||||
|
|
@ -1,718 +0,0 @@
|
||||||
# Copyright (C) Andreas Rumpf. All rights reserved.
|
|
||||||
# BSD License. Look at license.txt for more info.
|
|
||||||
|
|
||||||
## Implements the new configuration system for Nimble. Uses Nim as a
|
|
||||||
## scripting language.
|
|
||||||
|
|
||||||
import
|
|
||||||
compiler/ast, compiler/modules, compiler/passes, compiler/passaux,
|
|
||||||
compiler/condsyms, compiler/sem, compiler/semdata,
|
|
||||||
compiler/llstream, compiler/vm, compiler/vmdef, compiler/commands,
|
|
||||||
compiler/msgs, compiler/magicsys, compiler/idents,
|
|
||||||
compiler/nimconf, compiler/nversion
|
|
||||||
|
|
||||||
from compiler/scriptconfig import setupVM
|
|
||||||
from compiler/astalgo import strTableGet
|
|
||||||
import compiler/options as compiler_options
|
|
||||||
|
|
||||||
import common, version, options, packageinfo, cli, tools
|
|
||||||
import os, strutils, strtabs, tables, times, osproc, sets, pegs
|
|
||||||
|
|
||||||
when not declared(resetAllModulesHard):
|
|
||||||
import compiler/modulegraphs
|
|
||||||
|
|
||||||
type
|
|
||||||
Flags = TableRef[string, seq[string]]
|
|
||||||
ExecutionResult*[T] = object
|
|
||||||
success*: bool
|
|
||||||
command*: string
|
|
||||||
arguments*: seq[string]
|
|
||||||
flags*: Flags
|
|
||||||
retVal*: T
|
|
||||||
|
|
||||||
const
|
|
||||||
internalCmd = "NimbleInternal"
|
|
||||||
nimscriptApi = staticRead("nimscriptapi.nim")
|
|
||||||
|
|
||||||
proc raiseVariableError(ident, typ: string) {.noinline.} =
|
|
||||||
raise newException(NimbleError,
|
|
||||||
"NimScript's variable '" & ident & "' needs a value of type '" & typ & "'.")
|
|
||||||
|
|
||||||
proc isStrLit(n: PNode): bool = n.kind in {nkStrLit..nkTripleStrLit}
|
|
||||||
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
const finalApi = NimCompilerApiVersion >= 2
|
|
||||||
|
|
||||||
when NimCompilerApiVersion >= 3:
|
|
||||||
import compiler / pathutils
|
|
||||||
else:
|
|
||||||
const finalApi = false
|
|
||||||
|
|
||||||
proc getGlobal(g: ModuleGraph; ident: PSym): string =
|
|
||||||
when finalApi:
|
|
||||||
let n = vm.getGlobalValue(PCtx g.vm, ident)
|
|
||||||
else:
|
|
||||||
let n = vm.globalCtx.getGlobalValue(ident)
|
|
||||||
if n.isStrLit:
|
|
||||||
result = n.strVal
|
|
||||||
else:
|
|
||||||
raiseVariableError(ident.name.s, "string")
|
|
||||||
|
|
||||||
proc getGlobalAsSeq(g: ModuleGraph; ident: PSym): seq[string] =
|
|
||||||
when finalApi:
|
|
||||||
let n = vm.getGlobalValue(PCtx g.vm, ident)
|
|
||||||
else:
|
|
||||||
let n = vm.globalCtx.getGlobalValue(ident)
|
|
||||||
result = @[]
|
|
||||||
if n.kind == nkBracket:
|
|
||||||
for x in n:
|
|
||||||
if x.isStrLit:
|
|
||||||
result.add x.strVal
|
|
||||||
else:
|
|
||||||
raiseVariableError(ident.name.s, "seq[string]")
|
|
||||||
else:
|
|
||||||
raiseVariableError(ident.name.s, "seq[string]")
|
|
||||||
|
|
||||||
proc extractRequires(g: ModuleGraph; ident: PSym, result: var seq[PkgTuple]) =
|
|
||||||
when finalApi:
|
|
||||||
let n = vm.getGlobalValue(PCtx g.vm, ident)
|
|
||||||
else:
|
|
||||||
let n = vm.globalCtx.getGlobalValue(ident)
|
|
||||||
if n.kind == nkBracket:
|
|
||||||
for x in n:
|
|
||||||
if x.kind == nkPar and x.len == 2 and x[0].isStrLit and x[1].isStrLit:
|
|
||||||
result.add(parseRequires(x[0].strVal & x[1].strVal))
|
|
||||||
elif x.isStrLit:
|
|
||||||
result.add(parseRequires(x.strVal))
|
|
||||||
else:
|
|
||||||
raiseVariableError("requiresData", "seq[(string, VersionReq)]")
|
|
||||||
else:
|
|
||||||
raiseVariableError("requiresData", "seq[(string, VersionReq)]")
|
|
||||||
|
|
||||||
when declared(newIdentCache):
|
|
||||||
var identCache = newIdentCache()
|
|
||||||
|
|
||||||
proc setupVM(graph: ModuleGraph; module: PSym; scriptName: string, flags: Flags): PEvalContext =
|
|
||||||
## This procedure is exported in the compiler sources, but its implementation
|
|
||||||
## is too Nim-specific to be used by Nimble.
|
|
||||||
## Specifically, the implementation of ``switch`` is problematic. Sooo
|
|
||||||
## I simply copied it here and edited it :)
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
result = newCtx(module, identCache, graph)
|
|
||||||
elif declared(newIdentCache):
|
|
||||||
result = newCtx(module, identCache)
|
|
||||||
else:
|
|
||||||
result = newCtx(module)
|
|
||||||
result.mode = emRepl
|
|
||||||
registerAdditionalOps(result)
|
|
||||||
|
|
||||||
# captured vars:
|
|
||||||
let conf = graph.config
|
|
||||||
var errorMsg: string
|
|
||||||
var vthisDir = scriptName.splitFile.dir
|
|
||||||
|
|
||||||
proc listDirs(a: VmArgs, filter: set[PathComponent]) =
|
|
||||||
let dir = getString(a, 0)
|
|
||||||
var res: seq[string] = @[]
|
|
||||||
for kind, path in walkDir(dir):
|
|
||||||
if kind in filter: res.add path
|
|
||||||
setResult(a, res)
|
|
||||||
|
|
||||||
template cbconf(name, body) {.dirty.} =
|
|
||||||
result.registerCallback "stdlib.system." & astToStr(name),
|
|
||||||
proc (a: VmArgs) =
|
|
||||||
body
|
|
||||||
|
|
||||||
template cbos(name, body) {.dirty.} =
|
|
||||||
result.registerCallback "stdlib.system." & astToStr(name),
|
|
||||||
proc (a: VmArgs) =
|
|
||||||
try:
|
|
||||||
body
|
|
||||||
except OSError:
|
|
||||||
errorMsg = getCurrentExceptionMsg()
|
|
||||||
|
|
||||||
# Idea: Treat link to file as a file, but ignore link to directory to prevent
|
|
||||||
# endless recursions out of the box.
|
|
||||||
cbos listFiles:
|
|
||||||
listDirs(a, {pcFile, pcLinkToFile})
|
|
||||||
cbos listDirs:
|
|
||||||
listDirs(a, {pcDir})
|
|
||||||
cbos removeDir:
|
|
||||||
os.removeDir getString(a, 0)
|
|
||||||
cbos removeFile:
|
|
||||||
os.removeFile getString(a, 0)
|
|
||||||
cbos createDir:
|
|
||||||
os.createDir getString(a, 0)
|
|
||||||
cbos getOsError:
|
|
||||||
setResult(a, errorMsg)
|
|
||||||
cbos setCurrentDir:
|
|
||||||
os.setCurrentDir getString(a, 0)
|
|
||||||
cbos getCurrentDir:
|
|
||||||
setResult(a, os.getCurrentDir())
|
|
||||||
cbos moveFile:
|
|
||||||
os.moveFile(getString(a, 0), getString(a, 1))
|
|
||||||
cbos copyFile:
|
|
||||||
os.copyFile(getString(a, 0), getString(a, 1))
|
|
||||||
cbos getLastModificationTime:
|
|
||||||
setResult(a, toUnix(getLastModificationTime(getString(a, 0))))
|
|
||||||
cbos findExe:
|
|
||||||
setResult(a, os.findExe(getString(a, 0)))
|
|
||||||
|
|
||||||
cbos rawExec:
|
|
||||||
setResult(a, osproc.execCmd getString(a, 0))
|
|
||||||
|
|
||||||
cbconf getEnv:
|
|
||||||
setResult(a, os.getEnv(a.getString 0))
|
|
||||||
cbconf existsEnv:
|
|
||||||
setResult(a, os.existsEnv(a.getString 0))
|
|
||||||
cbconf dirExists:
|
|
||||||
setResult(a, os.dirExists(a.getString 0))
|
|
||||||
cbconf fileExists:
|
|
||||||
setResult(a, os.fileExists(a.getString 0))
|
|
||||||
|
|
||||||
cbconf thisDir:
|
|
||||||
setResult(a, vthisDir)
|
|
||||||
cbconf put:
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
compiler_options.setConfigVar(conf, getString(a, 0), getString(a, 1))
|
|
||||||
else:
|
|
||||||
compiler_options.setConfigVar(getString(a, 0), getString(a, 1))
|
|
||||||
cbconf get:
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
setResult(a, compiler_options.getConfigVar(conf, a.getString 0))
|
|
||||||
else:
|
|
||||||
setResult(a, compiler_options.getConfigVar(a.getString 0))
|
|
||||||
cbconf exists:
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
setResult(a, compiler_options.existsConfigVar(conf, a.getString 0))
|
|
||||||
else:
|
|
||||||
setResult(a, compiler_options.existsConfigVar(a.getString 0))
|
|
||||||
cbconf nimcacheDir:
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
setResult(a, compiler_options.getNimcacheDir(conf))
|
|
||||||
else:
|
|
||||||
setResult(a, compiler_options.getNimcacheDir())
|
|
||||||
cbconf paramStr:
|
|
||||||
setResult(a, os.paramStr(int a.getInt 0))
|
|
||||||
cbconf paramCount:
|
|
||||||
setResult(a, os.paramCount())
|
|
||||||
cbconf cmpIgnoreStyle:
|
|
||||||
setResult(a, strutils.cmpIgnoreStyle(a.getString 0, a.getString 1))
|
|
||||||
cbconf cmpIgnoreCase:
|
|
||||||
setResult(a, strutils.cmpIgnoreCase(a.getString 0, a.getString 1))
|
|
||||||
cbconf setCommand:
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
conf.command = a.getString 0
|
|
||||||
let arg = a.getString 1
|
|
||||||
if arg.len > 0:
|
|
||||||
conf.projectName = arg
|
|
||||||
when NimCompilerApiVersion >= 3:
|
|
||||||
try:
|
|
||||||
conf.projectFull = canonicalizePath(conf,
|
|
||||||
conf.projectPath / RelativeFile(conf.projectName))
|
|
||||||
except OSError:
|
|
||||||
conf.projectFull = AbsoluteFile conf.projectName
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
conf.projectFull = canonicalizePath(conf, conf.projectPath / conf.projectName)
|
|
||||||
except OSError:
|
|
||||||
conf.projectFull = conf.projectName
|
|
||||||
else:
|
|
||||||
compiler_options.command = a.getString 0
|
|
||||||
let arg = a.getString 1
|
|
||||||
if arg.len > 0:
|
|
||||||
gProjectName = arg
|
|
||||||
try:
|
|
||||||
gProjectFull = canonicalizePath(gProjectPath / gProjectName)
|
|
||||||
except OSError:
|
|
||||||
gProjectFull = gProjectName
|
|
||||||
cbconf getCommand:
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
setResult(a, conf.command)
|
|
||||||
else:
|
|
||||||
setResult(a, compiler_options.command)
|
|
||||||
cbconf switch:
|
|
||||||
if not flags.isNil:
|
|
||||||
let
|
|
||||||
key = a.getString 0
|
|
||||||
value = a.getString 1
|
|
||||||
if flags.hasKey(key):
|
|
||||||
flags[key].add(value)
|
|
||||||
else:
|
|
||||||
flags[key] = @[value]
|
|
||||||
|
|
||||||
proc isValidLibPath(lib: string): bool =
|
|
||||||
return fileExists(lib / "system.nim")
|
|
||||||
|
|
||||||
proc getNimPrefixDir(options: Options): string =
|
|
||||||
let env = getEnv("NIM_LIB_PREFIX")
|
|
||||||
if env != "":
|
|
||||||
let msg = "Using env var NIM_LIB_PREFIX: " & env
|
|
||||||
display("Warning:", msg, Warning, HighPriority)
|
|
||||||
return env
|
|
||||||
|
|
||||||
if options.config.nimLibPrefix != "":
|
|
||||||
result = options.config.nimLibPrefix
|
|
||||||
let msg = "Using Nim stdlib prefix from Nimble config file: " & result
|
|
||||||
display("Warning:", msg, Warning, HighPriority)
|
|
||||||
return
|
|
||||||
|
|
||||||
result = splitPath(findExe("nim")).head.parentDir
|
|
||||||
# The above heuristic doesn't work for 'choosenim' proxies. Thankfully in
|
|
||||||
# that case the `nimble` binary is beside the `nim` binary so things should
|
|
||||||
# just work.
|
|
||||||
if not dirExists(result / "lib"):
|
|
||||||
# By specifying an empty string we instruct the Nim compiler to use
|
|
||||||
# getAppDir().head as the prefix dir. See compiler/options module for
|
|
||||||
# the code responsible for this.
|
|
||||||
result = ""
|
|
||||||
|
|
||||||
proc getLibVersion(lib: string): Version =
|
|
||||||
## This is quite a hacky procedure, but there is no other way to extract
|
|
||||||
## this out of the ``system`` module. We could evaluate it, but that would
|
|
||||||
## cause an error if the stdlib is out of date. The purpose of this
|
|
||||||
## proc is to give a nice error message to the user instead of a confusing
|
|
||||||
## Nim compile error.
|
|
||||||
let systemPath = lib / "system.nim"
|
|
||||||
if not fileExists(systemPath):
|
|
||||||
raiseNimbleError("system module not found in stdlib path: " & lib)
|
|
||||||
|
|
||||||
let systemFile = readFile(systemPath)
|
|
||||||
let majorPeg = peg"'NimMajor' @ '=' \s* {\d*}"
|
|
||||||
let minorPeg = peg"'NimMinor' @ '=' \s* {\d*}"
|
|
||||||
let patchPeg = peg"'NimPatch' @ '=' \s* {\d*}"
|
|
||||||
|
|
||||||
var majorMatches: array[1, string]
|
|
||||||
let major = find(systemFile, majorPeg, majorMatches)
|
|
||||||
var minorMatches: array[1, string]
|
|
||||||
let minor = find(systemFile, minorPeg, minorMatches)
|
|
||||||
var patchMatches: array[1, string]
|
|
||||||
let patch = find(systemFile, patchPeg, patchMatches)
|
|
||||||
|
|
||||||
if major != -1 and minor != -1 and patch != -1:
|
|
||||||
return newVersion(majorMatches[0] & "." & minorMatches[0] & "." & patchMatches[0])
|
|
||||||
else:
|
|
||||||
return system.NimVersion.newVersion()
|
|
||||||
|
|
||||||
when finalApi:
|
|
||||||
var graph = newModuleGraph(identCache, newConfigRef())
|
|
||||||
|
|
||||||
elif declared(ModuleGraph):
|
|
||||||
var graph = newModuleGraph()
|
|
||||||
|
|
||||||
proc execScript(scriptName: string, flags: Flags, options: Options): PSym =
|
|
||||||
## Executes the specified script. Returns the script's module symbol.
|
|
||||||
##
|
|
||||||
## No clean up is performed and must be done manually!
|
|
||||||
when finalApi:
|
|
||||||
graph = newModuleGraph(graph.cache, graph.config)
|
|
||||||
else:
|
|
||||||
graph = newModuleGraph(graph.config)
|
|
||||||
|
|
||||||
let conf = graph.config
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
if "nimblepkg/nimscriptapi" notin conf.implicitImports:
|
|
||||||
conf.implicitImports.add("nimblepkg/nimscriptapi")
|
|
||||||
elif declared(resetAllModulesHard):
|
|
||||||
# for compatibility with older Nim versions:
|
|
||||||
if "nimblepkg/nimscriptapi" notin compiler_options.implicitIncludes:
|
|
||||||
compiler_options.implicitIncludes.add("nimblepkg/nimscriptapi")
|
|
||||||
else:
|
|
||||||
if "nimblepkg/nimscriptapi" notin compiler_options.implicitImports:
|
|
||||||
compiler_options.implicitImports.add("nimblepkg/nimscriptapi")
|
|
||||||
|
|
||||||
# Ensure the compiler can find its standard library #220.
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
when NimCompilerApiVersion >= 3:
|
|
||||||
conf.prefixDir = AbsoluteDir getNimPrefixDir(options)
|
|
||||||
display("Setting", "Nim stdlib prefix to " & conf.prefixDir.string,
|
|
||||||
priority=LowPriority)
|
|
||||||
|
|
||||||
template myLibPath(): untyped = conf.libpath.string
|
|
||||||
|
|
||||||
else:
|
|
||||||
conf.prefixDir = getNimPrefixDir(options)
|
|
||||||
display("Setting", "Nim stdlib prefix to " & conf.prefixDir,
|
|
||||||
priority=LowPriority)
|
|
||||||
|
|
||||||
template myLibPath(): untyped = conf.libpath
|
|
||||||
|
|
||||||
# Verify that lib path points to existing stdlib.
|
|
||||||
setDefaultLibpath(conf)
|
|
||||||
else:
|
|
||||||
compiler_options.gPrefixDir = getNimPrefixDir(options)
|
|
||||||
display("Setting", "Nim stdlib prefix to " & compiler_options.gPrefixDir,
|
|
||||||
priority=LowPriority)
|
|
||||||
|
|
||||||
template myLibPath(): untyped = compiler_options.libpath
|
|
||||||
|
|
||||||
# Verify that lib path points to existing stdlib.
|
|
||||||
compiler_options.setDefaultLibpath()
|
|
||||||
|
|
||||||
display("Setting", "Nim stdlib path to " & myLibPath(),
|
|
||||||
priority=LowPriority)
|
|
||||||
if not isValidLibPath(myLibPath()):
|
|
||||||
let msg = "Nimble cannot find Nim's standard library.\nLast try in:\n - $1" %
|
|
||||||
myLibPath()
|
|
||||||
let hint = "Nimble does its best to find Nim's standard library, " &
|
|
||||||
"sometimes this fails. You can set the environment variable " &
|
|
||||||
"NIM_LIB_PREFIX to where Nim's `lib` directory is located as " &
|
|
||||||
"a workaround. " &
|
|
||||||
"See https://github.com/nim-lang/nimble#troubleshooting for " &
|
|
||||||
"more info."
|
|
||||||
raiseNimbleError(msg, hint)
|
|
||||||
|
|
||||||
# Verify that the stdlib that was found isn't older than the stdlib that Nimble
|
|
||||||
# was compiled with.
|
|
||||||
let libVersion = getLibVersion(myLibPath())
|
|
||||||
if NimVersion.newVersion() > libVersion:
|
|
||||||
let msg = ("Nimble cannot use an older stdlib than the one it was compiled " &
|
|
||||||
"with.\n Stdlib in '$#' has version: $#.\n Nimble needs at least: $#.") %
|
|
||||||
[myLibPath(), $libVersion, NimVersion]
|
|
||||||
let hint = "You may be running a newer version of Nimble than you intended " &
|
|
||||||
"to. Run an older version of Nimble that is compatible with " &
|
|
||||||
"the stdlib that Nimble is attempting to use or set the environment variable " &
|
|
||||||
"NIM_LIB_PREFIX to where a different stdlib's `lib` directory is located as " &
|
|
||||||
"a workaround." &
|
|
||||||
"See https://github.com/nim-lang/nimble#troubleshooting for " &
|
|
||||||
"more info."
|
|
||||||
raiseNimbleError(msg, hint)
|
|
||||||
|
|
||||||
let pkgName = scriptName.splitFile.name
|
|
||||||
|
|
||||||
# Ensure that "nimblepkg/nimscriptapi" is in the PATH.
|
|
||||||
block:
|
|
||||||
let t = getNimbleUserTempDir() / "nimblecache"
|
|
||||||
let tmpNimscriptApiPath = t / "nimblepkg" / "nimscriptapi.nim"
|
|
||||||
createDir(tmpNimscriptApiPath.splitFile.dir)
|
|
||||||
writeFile(tmpNimscriptApiPath, nimscriptApi)
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
when NimCompilerApiVersion >= 3:
|
|
||||||
conf.searchPaths.add(AbsoluteDir t)
|
|
||||||
else:
|
|
||||||
conf.searchPaths.add(t)
|
|
||||||
else:
|
|
||||||
searchPaths.add(t)
|
|
||||||
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
initDefines(conf.symbols)
|
|
||||||
when NimCompilerApiVersion >= 2:
|
|
||||||
loadConfigs(DefaultConfig, graph.cache, conf)
|
|
||||||
else:
|
|
||||||
loadConfigs(DefaultConfig, conf)
|
|
||||||
passes.gIncludeFile = includeModule
|
|
||||||
passes.gImportModule = importModule
|
|
||||||
|
|
||||||
defineSymbol(conf.symbols, "nimscript")
|
|
||||||
defineSymbol(conf.symbols, "nimconfig")
|
|
||||||
defineSymbol(conf.symbols, "nimble")
|
|
||||||
when NimCompilerApiVersion >= 2:
|
|
||||||
registerPass(graph, semPass)
|
|
||||||
registerPass(graph, evalPass)
|
|
||||||
else:
|
|
||||||
registerPass(semPass)
|
|
||||||
registerPass(evalPass)
|
|
||||||
|
|
||||||
conf.searchPaths.add(conf.libpath)
|
|
||||||
else:
|
|
||||||
initDefines()
|
|
||||||
loadConfigs(DefaultConfig)
|
|
||||||
passes.gIncludeFile = includeModule
|
|
||||||
passes.gImportModule = importModule
|
|
||||||
|
|
||||||
defineSymbol("nimscript")
|
|
||||||
defineSymbol("nimconfig")
|
|
||||||
defineSymbol("nimble")
|
|
||||||
registerPass(semPass)
|
|
||||||
registerPass(evalPass)
|
|
||||||
|
|
||||||
searchPaths.add(compiler_options.libpath)
|
|
||||||
|
|
||||||
when declared(resetAllModulesHard):
|
|
||||||
result = makeModule(scriptName)
|
|
||||||
else:
|
|
||||||
result = graph.makeModule(scriptName)
|
|
||||||
|
|
||||||
incl(result.flags, sfMainModule)
|
|
||||||
when finalApi:
|
|
||||||
graph.vm = setupVM(graph, result, scriptName, flags)
|
|
||||||
|
|
||||||
# Setup builtins defined in nimscriptapi.nim
|
|
||||||
template cbApi(name, body) {.dirty.} =
|
|
||||||
PCtx(graph.vm).registerCallback "nimscriptapi." & astToStr(name),
|
|
||||||
proc (a: VmArgs) =
|
|
||||||
body
|
|
||||||
|
|
||||||
else:
|
|
||||||
vm.globalCtx = setupVM(graph, result, scriptName, flags)
|
|
||||||
|
|
||||||
# Setup builtins defined in nimscriptapi.nim
|
|
||||||
template cbApi(name, body) {.dirty.} =
|
|
||||||
vm.globalCtx.registerCallback "nimscriptapi." & astToStr(name),
|
|
||||||
proc (a: VmArgs) =
|
|
||||||
body
|
|
||||||
|
|
||||||
cbApi getPkgDir:
|
|
||||||
setResult(a, scriptName.splitFile.dir)
|
|
||||||
|
|
||||||
when finalApi:
|
|
||||||
graph.compileSystemModule()
|
|
||||||
when NimCompilerApiVersion >= 3:
|
|
||||||
graph.processModule(result, llStreamOpen(AbsoluteFile scriptName, fmRead))
|
|
||||||
else:
|
|
||||||
graph.processModule(result, llStreamOpen(scriptName, fmRead))
|
|
||||||
elif declared(newIdentCache):
|
|
||||||
graph.compileSystemModule(identCache)
|
|
||||||
graph.processModule(result, llStreamOpen(scriptName, fmRead), nil, identCache)
|
|
||||||
else:
|
|
||||||
compileSystemModule()
|
|
||||||
processModule(result, llStreamOpen(scriptName, fmRead), nil)
|
|
||||||
|
|
||||||
proc cleanup() =
|
|
||||||
# ensure everything can be called again:
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
let conf = graph.config
|
|
||||||
conf.projectName = ""
|
|
||||||
conf.command = ""
|
|
||||||
else:
|
|
||||||
compiler_options.gProjectName = ""
|
|
||||||
compiler_options.command = ""
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
resetSystemArtifacts(graph)
|
|
||||||
elif declared(resetAllModulesHard):
|
|
||||||
resetAllModulesHard()
|
|
||||||
else:
|
|
||||||
resetSystemArtifacts()
|
|
||||||
when finalApi:
|
|
||||||
clearPasses(graph)
|
|
||||||
else:
|
|
||||||
clearPasses()
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
conf.errorMax = 1
|
|
||||||
when NimCompilerApiVersion >= 2:
|
|
||||||
conf.writeLnHook = nil
|
|
||||||
graph.vm = nil
|
|
||||||
else:
|
|
||||||
msgs.writeLnHook = nil
|
|
||||||
vm.globalCtx = nil
|
|
||||||
initDefines(conf.symbols)
|
|
||||||
else:
|
|
||||||
msgs.gErrorMax = 1
|
|
||||||
msgs.writeLnHook = nil
|
|
||||||
vm.globalCtx = nil
|
|
||||||
initDefines()
|
|
||||||
|
|
||||||
proc readPackageInfoFromNims*(scriptName: string, options: Options,
|
|
||||||
result: var PackageInfo) =
|
|
||||||
## Executes the `scriptName` nimscript file. Reads the package information
|
|
||||||
## that it populates.
|
|
||||||
|
|
||||||
# Setup custom error handling.
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
let conf = graph.config
|
|
||||||
conf.errorMax = high(int)
|
|
||||||
else:
|
|
||||||
msgs.gErrorMax = high(int)
|
|
||||||
|
|
||||||
template errCounter(): int =
|
|
||||||
when declared(NimCompilerApiVersion): conf.errorCounter
|
|
||||||
else: msgs.gErrorCounter
|
|
||||||
|
|
||||||
var previousMsg = ""
|
|
||||||
|
|
||||||
proc writelnHook(output: string) =
|
|
||||||
# The error counter is incremented after the writeLnHook is invoked.
|
|
||||||
if errCounter() > 0:
|
|
||||||
raise newException(NimbleError, previousMsg)
|
|
||||||
elif previousMsg.len > 0:
|
|
||||||
display("Info", previousMsg, priority = MediumPriority)
|
|
||||||
if output.normalize.startsWith("error"):
|
|
||||||
raise newException(NimbleError, output)
|
|
||||||
previousMsg = output
|
|
||||||
|
|
||||||
when finalApi:
|
|
||||||
conf.writelnHook = writelnHook
|
|
||||||
else:
|
|
||||||
msgs.writeLnHook = writelnHook
|
|
||||||
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
conf.command = internalCmd
|
|
||||||
else:
|
|
||||||
compiler_options.command = internalCmd
|
|
||||||
|
|
||||||
# Execute the nimscript file.
|
|
||||||
let thisModule = execScript(scriptName, nil, options)
|
|
||||||
|
|
||||||
when declared(resetAllModulesHard):
|
|
||||||
let apiModule = thisModule
|
|
||||||
else:
|
|
||||||
var apiModule: PSym
|
|
||||||
for i in 0..<graph.modules.len:
|
|
||||||
if graph.modules[i] != nil and
|
|
||||||
graph.modules[i].name.s == "nimscriptapi":
|
|
||||||
apiModule = graph.modules[i]
|
|
||||||
break
|
|
||||||
doAssert apiModule != nil
|
|
||||||
|
|
||||||
# Check whether an error has occurred.
|
|
||||||
if errCounter() > 0:
|
|
||||||
raise newException(NimbleError, previousMsg)
|
|
||||||
|
|
||||||
# Extract all the necessary fields populated by the nimscript file.
|
|
||||||
proc getSym(apiModule: PSym, ident: string): PSym =
|
|
||||||
result = apiModule.tab.strTableGet(getIdent(identCache, ident))
|
|
||||||
if result.isNil:
|
|
||||||
raise newException(NimbleError, "Ident not found: " & ident)
|
|
||||||
|
|
||||||
template trivialField(field) =
|
|
||||||
result.field = getGlobal(graph, getSym(apiModule, astToStr field))
|
|
||||||
|
|
||||||
template trivialFieldSeq(field) =
|
|
||||||
result.field.add getGlobalAsSeq(graph, getSym(apiModule, astToStr field))
|
|
||||||
|
|
||||||
# keep reasonable default:
|
|
||||||
let name = getGlobal(graph, apiModule.tab.strTableGet(getIdent(identCache, "packageName")))
|
|
||||||
if name.len > 0: result.name = name
|
|
||||||
|
|
||||||
trivialField version
|
|
||||||
trivialField author
|
|
||||||
trivialField description
|
|
||||||
trivialField license
|
|
||||||
trivialField srcdir
|
|
||||||
trivialField bindir
|
|
||||||
trivialFieldSeq skipDirs
|
|
||||||
trivialFieldSeq skipFiles
|
|
||||||
trivialFieldSeq skipExt
|
|
||||||
trivialFieldSeq installDirs
|
|
||||||
trivialFieldSeq installFiles
|
|
||||||
trivialFieldSeq installExt
|
|
||||||
trivialFieldSeq foreignDeps
|
|
||||||
|
|
||||||
extractRequires(graph, getSym(apiModule, "requiresData"), result.requires)
|
|
||||||
|
|
||||||
let binSeq = getGlobalAsSeq(graph, getSym(apiModule, "bin"))
|
|
||||||
for i in binSeq:
|
|
||||||
result.bin.add(i.addFileExt(ExeExt))
|
|
||||||
|
|
||||||
let backend = getGlobal(graph, getSym(apiModule, "backend"))
|
|
||||||
if backend.len == 0:
|
|
||||||
result.backend = "c"
|
|
||||||
elif cmpIgnoreStyle(backend, "javascript") == 0:
|
|
||||||
result.backend = "js"
|
|
||||||
else:
|
|
||||||
result.backend = backend.toLowerAscii()
|
|
||||||
|
|
||||||
# Grab all the global procs
|
|
||||||
for i in thisModule.tab.data:
|
|
||||||
if not i.isNil():
|
|
||||||
let name = i.name.s.normalize()
|
|
||||||
if name.endsWith("before"):
|
|
||||||
result.preHooks.incl(name[0 .. ^7])
|
|
||||||
if name.endsWith("after"):
|
|
||||||
result.postHooks.incl(name[0 .. ^6])
|
|
||||||
|
|
||||||
cleanup()
|
|
||||||
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
template nimCommand(): untyped = conf.command
|
|
||||||
template nimProjectName(): untyped = conf.projectName
|
|
||||||
else:
|
|
||||||
template nimCommand(): untyped = compiler_options.command
|
|
||||||
template nimProjectName(): untyped = compiler_options.gProjectName
|
|
||||||
|
|
||||||
proc execTask*(scriptName, taskName: string,
|
|
||||||
options: Options): ExecutionResult[void] =
|
|
||||||
## Executes the specified task in the specified script.
|
|
||||||
##
|
|
||||||
## `scriptName` should be a filename pointing to the nimscript file.
|
|
||||||
result.success = true
|
|
||||||
result.flags = newTable[string, seq[string]]()
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
let conf = graph.config
|
|
||||||
nimCommand() = internalCmd
|
|
||||||
display("Executing", "task $# in $#" % [taskName, scriptName],
|
|
||||||
priority = HighPriority)
|
|
||||||
|
|
||||||
let thisModule = execScript(scriptName, result.flags, options)
|
|
||||||
let prc = thisModule.tab.strTableGet(getIdent(identCache, taskName & "Task"))
|
|
||||||
if prc.isNil:
|
|
||||||
# Procedure not defined in the NimScript module.
|
|
||||||
result.success = false
|
|
||||||
cleanup()
|
|
||||||
return
|
|
||||||
when finalApi:
|
|
||||||
discard vm.execProc(PCtx(graph.vm), prc, [])
|
|
||||||
else:
|
|
||||||
discard vm.globalCtx.execProc(prc, [])
|
|
||||||
|
|
||||||
# Read the command, arguments and flags set by the executed task.
|
|
||||||
result.command = nimCommand()
|
|
||||||
result.arguments = @[]
|
|
||||||
for arg in nimProjectName().split():
|
|
||||||
result.arguments.add(arg)
|
|
||||||
|
|
||||||
cleanup()
|
|
||||||
|
|
||||||
proc execHook*(scriptName, actionName: string, before: bool,
|
|
||||||
options: Options): ExecutionResult[bool] =
|
|
||||||
## Executes the specified action's hook. Depending on ``before``, either
|
|
||||||
## the "before" or the "after" hook.
|
|
||||||
##
|
|
||||||
## `scriptName` should be a filename pointing to the nimscript file.
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
let conf = graph.config
|
|
||||||
result.success = true
|
|
||||||
result.flags = newTable[string, seq[string]]()
|
|
||||||
nimCommand() = internalCmd
|
|
||||||
let hookName =
|
|
||||||
if before: actionName.toLowerAscii & "Before"
|
|
||||||
else: actionName.toLowerAscii & "After"
|
|
||||||
display("Attempting", "to execute hook $# in $#" % [hookName, scriptName],
|
|
||||||
priority = MediumPriority)
|
|
||||||
|
|
||||||
let thisModule = execScript(scriptName, result.flags, options)
|
|
||||||
# Explicitly execute the task procedure, instead of relying on hack.
|
|
||||||
let prc = thisModule.tab.strTableGet(getIdent(identCache, hookName))
|
|
||||||
if prc.isNil:
|
|
||||||
# Procedure not defined in the NimScript module.
|
|
||||||
result.success = false
|
|
||||||
cleanup()
|
|
||||||
return
|
|
||||||
when finalApi:
|
|
||||||
let returnVal = vm.execProc(PCtx(graph.vm), prc, [])
|
|
||||||
else:
|
|
||||||
let returnVal = vm.globalCtx.execProc(prc, [])
|
|
||||||
case returnVal.kind
|
|
||||||
of nkCharLit..nkUInt64Lit:
|
|
||||||
result.retVal = returnVal.intVal == 1
|
|
||||||
else: assert false
|
|
||||||
|
|
||||||
# Read the command, arguments and flags set by the executed task.
|
|
||||||
result.command = nimCommand()
|
|
||||||
result.arguments = @[]
|
|
||||||
for arg in nimProjectName().split():
|
|
||||||
result.arguments.add(arg)
|
|
||||||
|
|
||||||
cleanup()
|
|
||||||
|
|
||||||
proc getNimScriptCommand(): string =
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
let conf = graph.config
|
|
||||||
nimCommand()
|
|
||||||
|
|
||||||
proc setNimScriptCommand(command: string) =
|
|
||||||
when declared(NimCompilerApiVersion):
|
|
||||||
let conf = graph.config
|
|
||||||
nimCommand() = command
|
|
||||||
|
|
||||||
proc hasTaskRequestedCommand*(execResult: ExecutionResult): bool =
|
|
||||||
## Determines whether the last executed task used ``setCommand``
|
|
||||||
return execResult.command != internalCmd
|
|
||||||
|
|
||||||
proc listTasks*(scriptName: string, options: Options) =
|
|
||||||
setNimScriptCommand("help")
|
|
||||||
|
|
||||||
discard execScript(scriptName, nil, options)
|
|
||||||
# TODO (#402): Make the 'task' template generate explicit data structure
|
|
||||||
# containing all the task names + descriptions.
|
|
||||||
cleanup()
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
## 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 common, version, options, packageinfo, cli, tools
|
import hashes, json, os, strutils, tables, times, osproc, strtabs
|
||||||
import hashes, json, os, streams, strutils, strtabs,
|
|
||||||
tables, times, osproc, sets, pegs
|
import version, options, cli, tools
|
||||||
|
|
||||||
type
|
type
|
||||||
Flags = TableRef[string, seq[string]]
|
Flags = TableRef[string, seq[string]]
|
||||||
|
|
@ -16,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 =
|
||||||
live = true): 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"
|
||||||
|
|
@ -37,22 +53,40 @@ 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()
|
||||||
|
|
||||||
let
|
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()
|
||||||
|
|
||||||
|
let isCustomTask = isCustomTask(actionName, options)
|
||||||
|
if isCustomTask:
|
||||||
|
for i in options.action.arguments:
|
||||||
|
cmd &= " " & i.quoteShell()
|
||||||
|
for key, val in options.action.flags.pairs():
|
||||||
|
cmd &= " $#$#" % [if key.len == 1: "-" else: "--", key]
|
||||||
|
if val.len != 0:
|
||||||
|
cmd &= ":" & val.quoteShell()
|
||||||
|
|
||||||
displayDebug("Executing " & cmd)
|
displayDebug("Executing " & cmd)
|
||||||
|
|
||||||
if live:
|
if needsLiveOutput(actionName, options, isHook):
|
||||||
result.exitCode = execCmd(cmd)
|
result.exitCode = execCmd(cmd)
|
||||||
if outFile.fileExists():
|
|
||||||
result.output = outFile.readFile()
|
|
||||||
discard outFile.tryRemoveFile()
|
|
||||||
else:
|
else:
|
||||||
result = execCmdEx(cmd, options = {poUsePath, poStdErrToStdOut})
|
# We want to capture any possible errors when parsing a .nimble
|
||||||
|
# file's metadata. See #710.
|
||||||
|
(result.stdout, result.exitCode) = execCmdEx(cmd)
|
||||||
|
if outFile.fileExists():
|
||||||
|
result.output = outFile.readFile()
|
||||||
|
if options.shouldRemoveTmp(outFile):
|
||||||
|
discard outFile.tryRemoveFile()
|
||||||
|
|
||||||
proc getNimsFile(scriptName: string, options: Options): string =
|
proc getNimsFile(scriptName: string, options: Options): string =
|
||||||
let
|
let
|
||||||
|
|
@ -101,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, live=false)
|
)
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -145,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.
|
||||||
|
|
@ -153,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] =
|
||||||
|
|
@ -167,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)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@
|
||||||
# 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, tools, common, cli
|
import config, version, common, cli
|
||||||
|
|
||||||
type
|
type
|
||||||
Options* = object
|
Options* = object
|
||||||
|
|
@ -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
|
||||||
|
|
@ -41,14 +46,20 @@ type
|
||||||
of actionInstall, actionPath, actionUninstall, actionDevelop:
|
of actionInstall, actionPath, actionUninstall, actionDevelop:
|
||||||
packages*: seq[PkgTuple] # Optional only for actionInstall
|
packages*: seq[PkgTuple] # Optional only for actionInstall
|
||||||
# and actionDevelop.
|
# and actionDevelop.
|
||||||
|
passNimFlags*: seq[string]
|
||||||
of actionSearch:
|
of actionSearch:
|
||||||
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]
|
||||||
|
|
@ -61,6 +72,7 @@ Usage: nimble COMMAND [opts]
|
||||||
Commands:
|
Commands:
|
||||||
install [pkgname, ...] Installs a list of packages.
|
install [pkgname, ...] Installs a list of packages.
|
||||||
[-d, --depsOnly] Install only dependencies.
|
[-d, --depsOnly] Install only dependencies.
|
||||||
|
[-p, --passNim] Forward specified flag to compiler.
|
||||||
develop [pkgname, ...] Clones a list of packages for development.
|
develop [pkgname, ...] Clones a list of packages for development.
|
||||||
Symlinks the cloned packages or any package
|
Symlinks the cloned packages or any package
|
||||||
in the current working directory.
|
in the current working directory.
|
||||||
|
|
@ -69,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
|
||||||
|
|
@ -141,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":
|
||||||
|
|
@ -175,6 +196,7 @@ proc initAction*(options: var Options, key: string) =
|
||||||
case options.action.typ
|
case options.action.typ
|
||||||
of actionInstall, actionPath, actionDevelop, actionUninstall:
|
of actionInstall, actionPath, actionDevelop, actionUninstall:
|
||||||
options.action.packages = @[]
|
options.action.packages = @[]
|
||||||
|
options.action.passNimFlags = @[]
|
||||||
of actionCompile, actionDoc, actionBuild:
|
of actionCompile, actionDoc, actionBuild:
|
||||||
options.action.compileOptions = @[]
|
options.action.compileOptions = @[]
|
||||||
options.action.file = ""
|
options.action.file = ""
|
||||||
|
|
@ -182,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:
|
||||||
|
|
@ -192,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 =
|
||||||
|
|
@ -241,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:
|
||||||
|
|
@ -261,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
|
||||||
|
|
@ -288,52 +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
|
|
||||||
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
|
||||||
|
|
@ -348,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()
|
||||||
|
|
||||||
|
|
@ -361,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)
|
||||||
|
|
||||||
|
|
@ -379,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 = ""
|
||||||
|
|
@ -418,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
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
|
|
||||||
# Stdlib imports
|
# Stdlib imports
|
||||||
import system except TResult
|
import system except TResult
|
||||||
import parsecfg, json, streams, strutils, parseutils, os, sets, tables
|
import hashes, json, strutils, os, sets, tables, httpclient
|
||||||
import httpclient
|
|
||||||
|
|
||||||
# Local imports
|
# Local imports
|
||||||
import version, tools, common, options, cli, config
|
import version, tools, common, options, cli, config
|
||||||
|
|
@ -278,7 +277,7 @@ proc getPackage*(pkg: string, options: Options, resPkg: var Package): bool =
|
||||||
proc getPackageList*(options: Options): seq[Package] =
|
proc getPackageList*(options: Options): seq[Package] =
|
||||||
## Returns the list of packages found in the downloaded packages.json files.
|
## Returns the list of packages found in the downloaded packages.json files.
|
||||||
result = @[]
|
result = @[]
|
||||||
var namesAdded = initSet[string]()
|
var namesAdded = initHashSet[string]()
|
||||||
for name, list in options.config.packageLists:
|
for name, list in options.config.packageLists:
|
||||||
let packages = readPackageList(name, options)
|
let packages = readPackageList(name, options)
|
||||||
for p in packages:
|
for p in packages:
|
||||||
|
|
@ -311,7 +310,6 @@ proc findNimbleFile*(dir: string; error: bool): string =
|
||||||
|
|
||||||
if result.splitFile.ext == ".nimble-link":
|
if result.splitFile.ext == ".nimble-link":
|
||||||
# Return the path of the real .nimble file.
|
# Return the path of the real .nimble file.
|
||||||
let nimbleLinkPath = result
|
|
||||||
result = readNimbleLink(result).nimbleFilePath
|
result = readNimbleLink(result).nimbleFilePath
|
||||||
if not fileExists(result):
|
if not fileExists(result):
|
||||||
let msg = "The .nimble-link file is pointing to a missing file: " & result
|
let msg = "The .nimble-link file is pointing to a missing file: " & result
|
||||||
|
|
@ -542,6 +540,11 @@ proc `==`*(pkg1: PackageInfo, pkg2: PackageInfo): bool =
|
||||||
if pkg1.name == pkg2.name and pkg1.myPath == pkg2.myPath:
|
if pkg1.name == pkg2.name and pkg1.myPath == pkg2.myPath:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
proc hash*(x: PackageInfo): Hash =
|
||||||
|
var h: Hash = 0
|
||||||
|
h = h !& hash(x.myPath)
|
||||||
|
result = !$h
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
doAssert getNameVersion("/home/user/.nimble/libs/packagea-0.1") ==
|
doAssert getNameVersion("/home/user/.nimble/libs/packagea-0.1") ==
|
||||||
("packagea", "0.1")
|
("packagea", "0.1")
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,13 @@
|
||||||
import os, strutils, sets, json
|
import os, strutils, sets, json
|
||||||
|
|
||||||
# Local imports
|
# Local imports
|
||||||
import cli, common, options, tools
|
import cli, options, tools
|
||||||
|
|
||||||
|
when defined(windows):
|
||||||
|
import version
|
||||||
|
|
||||||
|
when not declared(initHashSet) or not declared(toHashSet):
|
||||||
|
import common
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
# This is just for Win XP support.
|
# This is just for Win XP support.
|
||||||
|
|
@ -103,4 +109,4 @@ proc saveNimbleMeta*(pkgDestDir, pkgDir, vcsRevision, nimbleLinkPath: string) =
|
||||||
## pkgDir - The directory where the original package files are.
|
## pkgDir - The directory where the original package files are.
|
||||||
## For example: ~/projects/jester/
|
## For example: ~/projects/jester/
|
||||||
saveNimbleMeta(pkgDestDir, "file://" & pkgDir, vcsRevision,
|
saveNimbleMeta(pkgDestDir, "file://" & pkgDir, vcsRevision,
|
||||||
toSet[string]([nimbleLinkPath]), initSet[string](), true)
|
toHashSet[string]([nimbleLinkPath]), initHashSet[string](), true)
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright (C) Dominik Picheta. All rights reserved.
|
# Copyright (C) Dominik Picheta. All rights reserved.
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
import parsecfg, json, sets, streams, strutils, parseutils, os, tables, sugar
|
import parsecfg, sets, streams, strutils, os, tables, sugar
|
||||||
from sequtils import apply, map
|
from sequtils import apply, map
|
||||||
|
|
||||||
import version, tools, common, nimscriptwrapper, options, packageinfo, cli
|
import version, tools, common, nimscriptwrapper, options, packageinfo, cli
|
||||||
|
|
@ -212,7 +212,10 @@ proc multiSplit(s: string): seq[string] =
|
||||||
result.del(i)
|
result.del(i)
|
||||||
# Huh, nothing to return? Return given input.
|
# Huh, nothing to return? Return given input.
|
||||||
if len(result) < 1:
|
if len(result) < 1:
|
||||||
return @[s]
|
if s.strip().len != 0:
|
||||||
|
return @[s]
|
||||||
|
else:
|
||||||
|
return @[]
|
||||||
|
|
||||||
proc readPackageInfoFromNimble(path: string; result: var PackageInfo) =
|
proc readPackageInfoFromNimble(path: string; result: var PackageInfo) =
|
||||||
var fs = newFileStream(path, fmRead)
|
var fs = newFileStream(path, fmRead)
|
||||||
|
|
@ -484,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")
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
## nim-lang/packages automatically.
|
## nim-lang/packages automatically.
|
||||||
|
|
||||||
import system except TResult
|
import system except TResult
|
||||||
import httpclient, base64, strutils, rdstdin, json, os, browsers, times, uri
|
import httpclient, strutils, json, os, browsers, times, uri
|
||||||
import tools, common, cli, config, options
|
import version, tools, common, cli, config, options
|
||||||
|
|
||||||
type
|
type
|
||||||
Auth = object
|
Auth = object
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright (C) Dominik Picheta. All rights reserved.
|
# Copyright (C) Dominik Picheta. All rights reserved.
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
|
|
||||||
import os, json
|
import os, json, sets
|
||||||
|
|
||||||
import options, common, version, download, packageinfo
|
import options, common, version, download, packageinfo
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ proc removeRevDep*(nimbleData: JsonNode, pkg: PackageInfo) =
|
||||||
newData[key] = newVal
|
newData[key] = newVal
|
||||||
nimbleData["reverseDeps"] = newData
|
nimbleData["reverseDeps"] = newData
|
||||||
|
|
||||||
proc getRevDeps*(options: Options, pkg: PackageInfo): seq[PkgTuple] =
|
proc getRevDepTups*(options: Options, pkg: PackageInfo): seq[PkgTuple] =
|
||||||
## Returns a list of *currently installed* reverse dependencies for `pkg`.
|
## Returns a list of *currently installed* reverse dependencies for `pkg`.
|
||||||
result = @[]
|
result = @[]
|
||||||
let thisPkgsDep =
|
let thisPkgsDep =
|
||||||
|
|
@ -76,18 +76,25 @@ proc getRevDeps*(options: Options, pkg: PackageInfo): seq[PkgTuple] =
|
||||||
|
|
||||||
result.add(pkgTup)
|
result.add(pkgTup)
|
||||||
|
|
||||||
proc getAllRevDeps*(options: Options, pkg: PackageInfo, result: var seq[PackageInfo]) =
|
proc getRevDeps*(options: Options, pkg: PackageInfo): HashSet[PackageInfo] =
|
||||||
|
result.init()
|
||||||
|
let installedPkgs = getInstalledPkgsMin(options.getPkgsDir(), options)
|
||||||
|
for rdepTup in getRevDepTups(options, pkg):
|
||||||
|
for rdepInfo in findAllPkgs(installedPkgs, rdepTup):
|
||||||
|
result.incl rdepInfo
|
||||||
|
|
||||||
|
proc getAllRevDeps*(options: Options, pkg: PackageInfo, result: var HashSet[PackageInfo]) =
|
||||||
if pkg in result:
|
if pkg in result:
|
||||||
return
|
return
|
||||||
|
|
||||||
let installedPkgs = getInstalledPkgsMin(options.getPkgsDir(), options)
|
let installedPkgs = getInstalledPkgsMin(options.getPkgsDir(), options)
|
||||||
for rdepTup in getRevDeps(options, pkg):
|
for rdepTup in getRevDepTups(options, pkg):
|
||||||
for rdepInfo in findAllPkgs(installedPkgs, rdepTup):
|
for rdepInfo in findAllPkgs(installedPkgs, rdepTup):
|
||||||
if rdepInfo in result:
|
if rdepInfo in result:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
getAllRevDeps(options, rdepInfo, result)
|
getAllRevDeps(options, rdepInfo, result)
|
||||||
result.add pkg
|
result.incl pkg
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
var nimbleData = %{"reverseDeps": newJObject()}
|
var nimbleData = %{"reverseDeps": newJObject()}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
# Various miscellaneous utility functions reside here.
|
# Various miscellaneous utility functions reside here.
|
||||||
import osproc, pegs, strutils, os, uri, sets, json, parseutils
|
import osproc, pegs, strutils, os, uri, sets, json, parseutils
|
||||||
import version, common, cli
|
import version, cli
|
||||||
|
|
||||||
proc extractBin(cmd: string): string =
|
proc extractBin(cmd: string): string =
|
||||||
if cmd[0] == '"':
|
if cmd[0] == '"':
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,11 @@ proc `==`*(ver: Version, ver2: Version): bool =
|
||||||
else:
|
else:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
proc cmp*(a, b: Version): int =
|
||||||
|
if a < b: -1
|
||||||
|
elif a > b: 1
|
||||||
|
else: 0
|
||||||
|
|
||||||
proc `<=`*(ver: Version, ver2: Version): bool =
|
proc `<=`*(ver: Version, ver2: Version): bool =
|
||||||
return (ver == ver2) or (ver < ver2)
|
return (ver == ver2) or (ver < ver2)
|
||||||
|
|
||||||
|
|
@ -142,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)
|
||||||
|
|
@ -272,7 +277,7 @@ proc newVREq*(ver: string): VersionRange =
|
||||||
result.ver = newVersion(ver)
|
result.ver = newVersion(ver)
|
||||||
|
|
||||||
proc findLatest*(verRange: VersionRange,
|
proc findLatest*(verRange: VersionRange,
|
||||||
versions: Table[Version, string]): tuple[ver: Version, tag: string] =
|
versions: OrderedTable[Version, string]): tuple[ver: Version, tag: string] =
|
||||||
result = (newVersion(""), "")
|
result = (newVersion(""), "")
|
||||||
for ver, tag in versions:
|
for ver, tag in versions:
|
||||||
if not withinRange(ver, verRange): continue
|
if not withinRange(ver, verRange): continue
|
||||||
|
|
@ -293,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))
|
||||||
|
|
@ -309,8 +315,11 @@ when isMainModule:
|
||||||
doAssert(newVersion("") < newVersion("1.0.0"))
|
doAssert(newVersion("") < newVersion("1.0.0"))
|
||||||
doAssert(newVersion("") < newVersion("0.1.0"))
|
doAssert(newVersion("") < newVersion("0.1.0"))
|
||||||
|
|
||||||
var versions = toTable[Version, string]({newVersion("0.1.1"): "v0.1.1",
|
var versions = toOrderedTable[Version, string]({
|
||||||
newVersion("0.2.3"): "v0.2.3", newVersion("0.5"): "v0.5"})
|
newVersion("0.1.1"): "v0.1.1",
|
||||||
|
newVersion("0.2.3"): "v0.2.3",
|
||||||
|
newVersion("0.5"): "v0.5"
|
||||||
|
})
|
||||||
doAssert findLatest(parseVersionRange(">= 0.1 & <= 0.4"), versions) ==
|
doAssert findLatest(parseVersionRange(">= 0.1 & <= 0.4"), versions) ==
|
||||||
(newVersion("0.2.3"), "v0.2.3")
|
(newVersion("0.2.3"), "v0.2.3")
|
||||||
|
|
||||||
|
|
|
||||||
8
tests/.gitignore
vendored
8
tests/.gitignore
vendored
|
|
@ -1,6 +1,10 @@
|
||||||
|
tester
|
||||||
|
/nimble-test
|
||||||
|
/buildDir
|
||||||
/binaryPackage/v1/binaryPackage
|
/binaryPackage/v1/binaryPackage
|
||||||
/binaryPackage/v2/binaryPackage
|
/binaryPackage/v2/binaryPackage
|
||||||
/develop/dependent/src/dependent
|
/develop/dependent/src/dependent
|
||||||
|
/issue27/issue27
|
||||||
/issue206/issue/issue206bin
|
/issue206/issue/issue206bin
|
||||||
/issue289/issue289
|
/issue289/issue289
|
||||||
/issue428/nimbleDir/
|
/issue428/nimbleDir/
|
||||||
|
|
@ -13,3 +17,7 @@
|
||||||
/testCommand/testsPass/tests/one
|
/testCommand/testsPass/tests/one
|
||||||
/testCommand/testsPass/tests/three
|
/testCommand/testsPass/tests/three
|
||||||
/testCommand/testsPass/tests/two
|
/testCommand/testsPass/tests/two
|
||||||
|
/nimscript/nimscript
|
||||||
|
/packageStructure/validBinary/y
|
||||||
|
/testCommand/testsFail/tests/t2
|
||||||
|
/passNimFlags/passNimFlags
|
||||||
|
|
|
||||||
13
tests/invalidPackage/invalidPackage.nimble
Normal file
13
tests/invalidPackage/invalidPackage.nimble
Normal 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"
|
||||||
15
tests/issue432/issue432.nimble
Normal file
15
tests/issue432/issue432.nimble
Normal 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"
|
||||||
7
tests/issue432/src/issue432.nim
Normal file
7
tests/issue432/src/issue432.nim
Normal 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
|
||||||
14
tests/issue564/issue564.nimble
Normal file
14
tests/issue564/issue564.nimble
Normal 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"
|
||||||
5
tests/issue564/src/issue564/issue564build.nim
Normal file
5
tests/issue564/src/issue564/issue564build.nim
Normal 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!")
|
||||||
16
tests/issue633/issue633.nimble
Normal file
16
tests/issue633/issue633.nimble
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "GT"
|
||||||
|
description = "Package for ensuring that issue #633 is resolved."
|
||||||
|
license = "MIT"
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 0.19.6"
|
||||||
|
# to reproduce dependency 2 must be before 1
|
||||||
|
|
||||||
|
task testTask, "Test":
|
||||||
|
for i in 0 .. paramCount():
|
||||||
|
if paramStr(i) == "--testTask":
|
||||||
|
echo "Got it"
|
||||||
12
tests/issue678/issue678.nimble
Normal file
12
tests/issue678/issue678.nimble
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "Ivan Bobev"
|
||||||
|
description = "Package for ensuring that issue #678 is resolved."
|
||||||
|
license = "MIT"
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 0.19.6"
|
||||||
|
# to reproduce dependency 2 must be before 1
|
||||||
|
requires "issue678_dependency_2", "issue678_dependency_1"
|
||||||
19
tests/issue678/packages.json
Normal file
19
tests/issue678/packages.json
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "issue678_dependency_1",
|
||||||
|
"url": "https://github.com/nimble-test/issue678?subdir=dependency_1",
|
||||||
|
"method": "git",
|
||||||
|
"tags": [ "test" ],
|
||||||
|
"description":
|
||||||
|
"Both first and second level dependency of the issue678 package.",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "issue678_dependency_2",
|
||||||
|
"url": "https://github.com/nimble-test/issue678?subdir=dependency_2",
|
||||||
|
"method": "git",
|
||||||
|
"tags": [ "test" ],
|
||||||
|
"description": "First level dependency of the issue678 package.",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
|
]
|
||||||
17
tests/issue708/issue708.nimble
Normal file
17
tests/issue708/issue708.nimble
Normal 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"
|
||||||
7
tests/issue708/src/issue708.nim
Normal file
7
tests/issue708/src/issue708.nim
Normal 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
|
||||||
14
tests/nimbleVersionDefine/nimbleVersionDefine.nimble
Normal file
14
tests/nimbleVersionDefine/nimbleVersionDefine.nimble
Normal 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"
|
||||||
BIN
tests/nimbleVersionDefine/src/nimbleVersionDefine
Executable file
BIN
tests/nimbleVersionDefine/src/nimbleVersionDefine
Executable file
Binary file not shown.
3
tests/nimbleVersionDefine/src/nimbleVersionDefine.nim
Normal file
3
tests/nimbleVersionDefine/src/nimbleVersionDefine.nim
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
when isMainModule:
|
||||||
|
const NimblePkgVersion {.strdefine.} = "Unknown"
|
||||||
|
echo(NimblePkgVersion)
|
||||||
|
|
@ -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")
|
||||||
1
tests/passNimFlags/passNimFlags.nim
Normal file
1
tests/passNimFlags/passNimFlags.nim
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
when not defined(passNimIsWorking): {.error: "-d:passNimIsWorking wasn't passed to the compiler"}
|
||||||
11
tests/passNimFlags/passNimFlags.nimble
Normal file
11
tests/passNimFlags/passNimFlags.nimble
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "SolitudeSF"
|
||||||
|
description = "Test nimble install flag forwarding"
|
||||||
|
license = "BSD"
|
||||||
|
bin = @["passNimFlags"]
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 0.13.0"
|
||||||
|
|
@ -9,13 +9,17 @@ license = "BSD"
|
||||||
|
|
||||||
requires "nim >= 0.12.1"
|
requires "nim >= 0.12.1"
|
||||||
|
|
||||||
|
let
|
||||||
|
callNimble = getEnv("NIMBLE_TEST_BINARY_PATH")
|
||||||
|
doAssert callNimble.len != 0, "NIMBLE_TEST_BINARY_PATH not set"
|
||||||
|
|
||||||
task recurse, "Level 1":
|
task recurse, "Level 1":
|
||||||
echo 1
|
echo 1
|
||||||
exec "../../src/nimble recurse2"
|
exec callNimble & " recurse2"
|
||||||
|
|
||||||
task recurse2, "Level 2":
|
task recurse2, "Level 2":
|
||||||
echo 2
|
echo 2
|
||||||
exec "../../src/nimble recurse3"
|
exec callNimble & " recurse3"
|
||||||
|
|
||||||
task recurse3, "Level 3":
|
task recurse3, "Level 3":
|
||||||
echo 3
|
echo 3
|
||||||
|
|
|
||||||
14
tests/run/run.nimble
Normal file
14
tests/run/run.nimble
Normal 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
4
tests/run/src/run.nim
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
echo("Testing `nimble run`: ", commandLineParams())
|
||||||
271
tests/tester.nim
271
tests/tester.nim
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright (C) Dominik Picheta. All rights reserved.
|
# Copyright (C) Dominik Picheta. All rights reserved.
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
import osproc, streams, unittest, strutils, os, sequtils, sugar
|
import osproc, unittest, strutils, os, sequtils, sugar, strformat
|
||||||
|
|
||||||
# TODO: Each test should start off with a clean slate. Currently installed
|
# TODO: Each test should start off with a clean slate. Currently installed
|
||||||
# packages are shared between each test which causes a multitude of issues
|
# packages are shared between each test which causes a multitude of issues
|
||||||
|
|
@ -10,6 +10,10 @@ var rootDir = getCurrentDir().parentDir()
|
||||||
var nimblePath = rootDir / "src" / addFileExt("nimble", ExeExt)
|
var nimblePath = rootDir / "src" / addFileExt("nimble", ExeExt)
|
||||||
var installDir = rootDir / "tests" / "nimbleDir"
|
var installDir = rootDir / "tests" / "nimbleDir"
|
||||||
const path = "../src/nimble"
|
const path = "../src/nimble"
|
||||||
|
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)
|
||||||
|
|
@ -32,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"
|
||||||
|
|
||||||
|
|
@ -48,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]=
|
||||||
|
|
@ -71,6 +76,41 @@ proc inLines(lines: seq[string], line: string): bool =
|
||||||
for i in lines:
|
for i in lines:
|
||||||
if line.normalize in i.normalize: return true
|
if line.normalize in i.normalize: return true
|
||||||
|
|
||||||
|
proc hasLineStartingWith(lines: seq[string], prefix: string): bool =
|
||||||
|
for line in lines:
|
||||||
|
if line.strip(trailing = false).startsWith(prefix):
|
||||||
|
return true
|
||||||
|
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")
|
||||||
|
|
@ -116,7 +156,7 @@ test "can validate package structure (#144)":
|
||||||
let (output, exitCode) = execNimble(["install", "-y"])
|
let (output, exitCode) = execNimble(["install", "-y"])
|
||||||
check exitCode == QuitSuccess
|
check exitCode == QuitSuccess
|
||||||
let lines = output.strip.processOutput()
|
let lines = output.strip.processOutput()
|
||||||
check(not inLines(lines, "warning"))
|
check(not lines.hasLineStartingWith("Warning:"))
|
||||||
|
|
||||||
# Test that warnings are produced for the incorrectly structured packages.
|
# Test that warnings are produced for the incorrectly structured packages.
|
||||||
for package in ["x", "y", "z"]:
|
for package in ["x", "y", "z"]:
|
||||||
|
|
@ -127,19 +167,22 @@ test "can validate package structure (#144)":
|
||||||
checkpoint(output)
|
checkpoint(output)
|
||||||
case package
|
case package
|
||||||
of "x":
|
of "x":
|
||||||
check inLines(lines, "Package 'x' has an incorrect structure. It should" &
|
check lines.hasLineStartingWith(
|
||||||
" contain a single directory hierarchy for source files," &
|
"Warning: Package 'x' has an incorrect structure. It should" &
|
||||||
" named 'x', but file 'foobar.nim' is in a directory named" &
|
" contain a single directory hierarchy for source files," &
|
||||||
" 'incorrect' instead.")
|
" named 'x', but file 'foobar.nim' is in a directory named" &
|
||||||
|
" 'incorrect' instead.")
|
||||||
of "y":
|
of "y":
|
||||||
check inLines(lines, "Package 'y' has an incorrect structure. It should" &
|
check lines.hasLineStartingWith(
|
||||||
" contain a single directory hierarchy for source files," &
|
"Warning: Package 'y' has an incorrect structure. It should" &
|
||||||
" named 'ypkg', but file 'foobar.nim' is in a directory named" &
|
" contain a single directory hierarchy for source files," &
|
||||||
" 'yWrong' instead.")
|
" named 'ypkg', but file 'foobar.nim' is in a directory named" &
|
||||||
|
" 'yWrong' instead.")
|
||||||
of "z":
|
of "z":
|
||||||
check inLines(lines, "Package 'z' has an incorrect structure. The top level" &
|
check lines.hasLineStartingWith(
|
||||||
" of the package source directory should contain at most one module," &
|
"Warning: Package 'z' has an incorrect structure. The top level" &
|
||||||
" named 'z.nim', but a file named 'incorrect.nim' was found.")
|
" of the package source directory should contain at most one module," &
|
||||||
|
" named 'z.nim', but a file named 'incorrect.nim' was found.")
|
||||||
else:
|
else:
|
||||||
assert false
|
assert false
|
||||||
|
|
||||||
|
|
@ -275,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")
|
||||||
|
|
@ -431,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())
|
||||||
|
|
@ -465,8 +517,7 @@ test "can uninstall":
|
||||||
|
|
||||||
let ls = outp.strip.processOutput()
|
let ls = outp.strip.processOutput()
|
||||||
check exitCode != QuitSuccess
|
check exitCode != QuitSuccess
|
||||||
check "Cannot uninstall issue27b (0.1.0) because issue27a (0.1.0) depends" &
|
check inLines(ls, "Cannot uninstall issue27b (0.1.0) because issue27a (0.1.0) depends")
|
||||||
" on it" in ls[ls.len-1]
|
|
||||||
|
|
||||||
check execNimble("uninstall", "-y", "issue27").exitCode == QuitSuccess
|
check execNimble("uninstall", "-y", "issue27").exitCode == QuitSuccess
|
||||||
check execNimble("uninstall", "-y", "issue27a").exitCode == QuitSuccess
|
check execNimble("uninstall", "-y", "issue27a").exitCode == QuitSuccess
|
||||||
|
|
@ -818,3 +869,177 @@ suite "Module tests":
|
||||||
test "cli":
|
test "cli":
|
||||||
cd "..":
|
cd "..":
|
||||||
check execCmdEx("nim c -r src/nimblepkg/cli").exitCode == QuitSuccess
|
check execCmdEx("nim c -r src/nimblepkg/cli").exitCode == QuitSuccess
|
||||||
|
|
||||||
|
test "download":
|
||||||
|
cd "..":
|
||||||
|
check execCmdEx("nim c -r src/nimblepkg/download").exitCode == QuitSuccess
|
||||||
|
|
||||||
|
test "init does not overwrite existing files (#581)":
|
||||||
|
createDir("issue581/src")
|
||||||
|
cd "issue581":
|
||||||
|
const Src = "echo \"OK\""
|
||||||
|
writeFile("src/issue581.nim", Src)
|
||||||
|
check execNimbleYes("init").exitCode == QuitSuccess
|
||||||
|
check readFile("src/issue581.nim") == Src
|
||||||
|
removeDir("issue581")
|
||||||
|
|
||||||
|
test "remove skips packages with revDeps (#504)":
|
||||||
|
check execNimble("install", "nimboost@0.5.5", "nimfp@0.4.4", "-y").exitCode == QuitSuccess
|
||||||
|
|
||||||
|
var (output, exitCode) = execNimble("uninstall", "nimboost", "nimfp", "-n")
|
||||||
|
var lines = output.strip.processOutput()
|
||||||
|
check inLines(lines, "Cannot uninstall nimboost")
|
||||||
|
|
||||||
|
(output, exitCode) = execNimble("uninstall", "nimfp", "nimboost", "-y")
|
||||||
|
lines = output.strip.processOutput()
|
||||||
|
check (not inLines(lines, "Cannot uninstall nimboost"))
|
||||||
|
|
||||||
|
check execNimble("path", "nimboost").exitCode != QuitSuccess
|
||||||
|
check execNimble("path", "nimfp").exitCode != QuitSuccess
|
||||||
|
|
||||||
|
test "pass options to the compiler with `nimble install`":
|
||||||
|
cd "passNimFlags":
|
||||||
|
check execNimble("install", "--passNim:-d:passNimIsWorking").exitCode == QuitSuccess
|
||||||
|
|
||||||
|
test "do not install single dependency multiple times (#678)":
|
||||||
|
# for the test to be correct, the tested package and its dependencies must not
|
||||||
|
# exist in the local cache
|
||||||
|
removeDir("nimbleDir")
|
||||||
|
cd "issue678":
|
||||||
|
testRefresh():
|
||||||
|
writeFile(configFile, """
|
||||||
|
[PackageList]
|
||||||
|
name = "local"
|
||||||
|
path = "$1"
|
||||||
|
""".unindent % (getCurrentDir() / "packages.json").replace("\\", "\\\\"))
|
||||||
|
check execNimble(["refresh"]).exitCode == QuitSuccess
|
||||||
|
let (output, exitCode) = execNimble("install", "-y")
|
||||||
|
check exitCode == QuitSuccess
|
||||||
|
let index = output.find("issue678_dependency_1@0.1.0 already exists")
|
||||||
|
check index == stringNotFound
|
||||||
|
|
||||||
|
test "Passing command line arguments to a task (#633)":
|
||||||
|
cd "issue633":
|
||||||
|
var (output, exitCode) = execNimble("testTask --testTask")
|
||||||
|
check exitCode == QuitSuccess
|
||||||
|
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":
|
||||||
|
const buildDir = "./buildDir/"
|
||||||
|
const filesToBuild = [
|
||||||
|
"../src/nimble.nim",
|
||||||
|
"../src/nimblepkg/nimscriptapi.nim",
|
||||||
|
"./tester.nim",
|
||||||
|
]
|
||||||
|
|
||||||
|
proc execBuild(fileName: string): tuple[output: string, exitCode: int] =
|
||||||
|
result = execCmdEx(
|
||||||
|
fmt"nim c -o:{buildDir/fileName.splitFile.name} {fileName}")
|
||||||
|
|
||||||
|
proc checkOutput(output: string): uint =
|
||||||
|
const warningsToCheck = [
|
||||||
|
"[UnusedImport]",
|
||||||
|
"[Deprecated]",
|
||||||
|
"[XDeclaredButNotUsed]",
|
||||||
|
]
|
||||||
|
|
||||||
|
for line in output.splitLines():
|
||||||
|
for warning in warningsToCheck:
|
||||||
|
if line.find(warning) != stringNotFound:
|
||||||
|
once: checkpoint("Detected warnings:")
|
||||||
|
checkpoint(line)
|
||||||
|
inc(result)
|
||||||
|
|
||||||
|
removeDir(buildDir)
|
||||||
|
|
||||||
|
var linesWithWarningsCount: uint = 0
|
||||||
|
for file in filesToBuild:
|
||||||
|
let (output, exitCode) = execBuild(file)
|
||||||
|
check exitCode == QuitSuccess
|
||||||
|
linesWithWarningsCount += checkOutput(output)
|
||||||
|
check linesWithWarningsCount == 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue