Compare commits

..

1 commit

Author SHA1 Message Date
Dominik Picheta
822bee893e Add tests for #666. 2019-10-24 23:24:06 +01:00
9 changed files with 68 additions and 141 deletions

View file

@ -8,17 +8,37 @@ language: c
env: env:
- BRANCH=0.19.6 - BRANCH=0.19.6
- BRANCH=0.20.2 - BRANCH=0.20.2
- BRANCH=1.0.6 - BRANCH=1.0.0
# This is the latest working Nim version against which Nimble is being tested # This is the latest working Nim version against which Nimble is being tested
- BRANCH=#ab525cc48abdbbbed1f772e58e9fe21474f70f07 - BRANCH=#16c39f9b2edc963655889cfd33e165bfae91c96d
cache: cache:
directories: directories:
- "$HOME/.nimble/bin"
- "$HOME/.choosenim" - "$HOME/.choosenim"
install: install:
- curl https://gist.github.com/genotrance/fb53504a4fba88bc5201d3783df5c522/raw/travis.sh -LsSf -o travis.sh - export CHOOSENIM_NO_ANALYTICS=1
- source travis.sh - export PATH=$HOME/.nimble/bin:$PATH
- |
if ! type -P choosenim &> /dev/null; then
if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
# Latest choosenim binary doesn't have
# https://github.com/dom96/choosenim/pull/117
# https://github.com/dom96/choosenim/pull/135
#
# Using custom build with these PRs for Windows
curl -L -s "https://bintray.com/genotrance/binaries/download_file?file_path=choosenim.exe" -o choosenim.exe
curl -L -s "https://bintray.com/genotrance/binaries/download_file?file_path=libeay32.dll" -o libeay32.dll
curl -L -s "https://bintray.com/genotrance/binaries/download_file?file_path=ssleay32.dll" -o ssleay32.dll
./choosenim.exe $BRANCH -y
cp ./choosenim.exe $HOME/.nimble/bin/.
else
export CHOOSENIM_CHOOSE_VERSION=$BRANCH
curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh
sh init.sh -y
fi
fi
script: script:
- cd tests - cd tests

View file

@ -172,13 +172,12 @@ 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 concrete version or a Instead of specifying a VCS branch, you may also specify a version range, for
version range, for example: example:
$ nimble install nimgame@0.5
$ nimble install nimgame@"> 0.5" $ nimble install nimgame@"> 0.5"
The latter command will install a version which is greater than ``0.5``. In this case a version which is greater than ``0.5`` will be installed.
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
@ -505,7 +504,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
├── config.nims ├── nim.cfg
├── tfoo1.nim # First test ├── tfoo1.nim # First test
└── tfoo2.nim # Second test └── tfoo2.nim # Second test

View file

@ -3,13 +3,12 @@
import system except TResult import system except TResult
import os, tables, strtabs, json, algorithm, sets, uri, sugar, sequtils, osproc import os, tables, strtabs, json, algorithm, sets, uri, sugar, sequtils
import std/options as std_opt 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,
@ -221,7 +220,7 @@ proc buildFromDir(
options: Options options: Options
) = ) =
## Builds a package as specified by ``pkgInfo``. ## Builds a package as specified by ``pkgInfo``.
let binToBuild = options.getCompilationBinary(pkgInfo) let binToBuild = options.getCompilationBinary()
# Handle pre-`build` hook. # Handle pre-`build` hook.
let realDir = pkgInfo.getRealDir() let realDir = pkgInfo.getRealDir()
cd realDir: # Make sure `execHook` executes the correct .nimble file. cd realDir: # Make sure `execHook` executes the correct .nimble file.
@ -251,14 +250,10 @@ proc buildFromDir(
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(cmd, showCmd = true) doCmd("\"" & getNimBin() & "\" $# --noNimblePath $# $# $# \"$#\"" %
[pkgInfo.backend, nimblePkgVersion, join(args, " "), outputOpt,
realDir / bin.changeFileExt("nim")])
binariesBuilt.inc() binariesBuilt.inc()
except NimbleError: except NimbleError:
let currentExc = (ref NimbleError)(getCurrentException()) let currentExc = (ref NimbleError)(getCurrentException())
@ -386,7 +381,7 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
options.action.passNimFlags options.action.passNimFlags
else: else:
@[] @[]
buildFromDir(pkgInfo, paths, "-d:release" & flags, options) buildFromDir(pkgInfo, paths, flags & "-d:release", 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"):
@ -539,9 +534,9 @@ proc build(options: Options) =
var args = options.getCompilationFlags() var args = options.getCompilationFlags()
buildFromDir(pkgInfo, paths, args, options) buildFromDir(pkgInfo, paths, args, options)
proc execBackend(pkgInfo: PackageInfo, options: Options) = proc execBackend(options: Options) =
let let
bin = options.getCompilationBinary(pkgInfo).get() bin = options.getCompilationBinary().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.")
@ -729,11 +724,6 @@ 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 != "":
@ -868,17 +858,6 @@ 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)
@ -1074,11 +1053,11 @@ proc test(options: Options) =
if options.continueTestsOnFailure: if options.continueTestsOnFailure:
inc tests inc tests
try: try:
execBackend(pkgInfo, optsCopy) execBackend(optsCopy)
except NimbleError: except NimbleError:
inc failures inc failures
else: else:
execBackend(pkgInfo, optsCopy) execBackend(optsCopy)
let let
existsAfter = existsFile(binFileName) existsAfter = existsFile(binFileName)
@ -1117,25 +1096,25 @@ proc check(options: Options) =
proc run(options: Options) = proc run(options: Options) =
# Verify parameters. # Verify parameters.
var pkgInfo = getPkgInfo(getCurrentDir(), options) let binary = options.getCompilationBinary().get("")
let binary = options.getCompilationBinary(pkgInfo).get("")
if binary.len == 0: if binary.len == 0:
raiseNimbleError("Please specify a binary to run") raiseNimbleError("Please specify a binary to run")
var pkgInfo = getPkgInfo(getCurrentDir(), options)
if binary notin pkgInfo.bin: if binary notin pkgInfo.bin:
raiseNimbleError( raiseNimbleError(
"Binary '$#' is not defined in '$#' package." % [binary, pkgInfo.name] "Binary '$#' is not defined in '$#' package." % [binary, pkgInfo.name]
) )
let binaryPath = pkgInfo.getOutputDir(binary)
# Build the binary. # Build the binary.
build(options) build(options)
let binaryPath = pkgInfo.getOutputDir(binary) # Now run it.
let cmd = quoteShellCommand(binaryPath & options.action.runFlags) let args = options.action.runFlags.join(" ")
displayDebug("Executing", cmd)
cmd.execCmd.quit
doCmd("$# $#" % [binaryPath, args], showOutput = true)
proc doAction(options: var Options) = proc doAction(options: var Options) =
if options.showHelp: if options.showHelp:
@ -1180,8 +1159,7 @@ proc doAction(options: var Options) =
of actionRun: of actionRun:
run(options) run(options)
of actionCompile, actionDoc: of actionCompile, actionDoc:
var pkgInfo = getPkgInfo(getCurrentDir(), options) execBackend(options)
execBackend(pkgInfo, options)
of actionInit: of actionInit:
init(options) init(options)
of actionPublish: of actionPublish:

View file

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

View file

@ -51,13 +51,12 @@ type
search*: seq[string] # Search string. search*: seq[string] # Search string.
of actionInit, actionDump: of actionInit, actionDump:
projName*: string projName*: string
vcsOption*: string
of actionCompile, actionDoc, actionBuild: of actionCompile, actionDoc, actionBuild:
file*: string file*: string
backend*: string backend*: string
compileOptions: seq[string] compileOptions: seq[string]
of actionRun: of actionRun:
runFile: Option[string] runFile: string
compileFlags: seq[string] compileFlags: seq[string]
runFlags*: seq[string] runFlags*: seq[string]
of actionCustom: of actionCustom:
@ -81,19 +80,17 @@ 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 [opts, ...] [bin] Builds a package. build [opts, ...] [bin] Builds a package.
run [opts, ...] [bin] Builds and runs a package. run [opts, ...] bin Builds and runs a package.
Binary needs to be specified after any A binary name needs
compilation options if there are several to be specified after any compilation options,
binaries defined, any flags after the binary any flags after the binary name are passed to
or -- arg are passed to the binary when it is run. 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
@ -204,10 +201,8 @@ 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 options.forcePrompts = forcePromptYes
of actionRefresh: of actionRefresh:
options.action.optionalURL = "" options.action.optionalURL = ""
@ -266,12 +261,6 @@ 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:
@ -303,7 +292,10 @@ proc parseArgument*(key: string, result: var Options) =
of actionBuild: of actionBuild:
result.action.file = key result.action.file = key
of actionRun: of actionRun:
result.setRunOptions(key, key, true) if result.action.runFile.len == 0:
result.action.runFile = key
else:
result.action.runFlags.add(key)
of actionCustom: of actionCustom:
result.action.arguments.add(key) result.action.arguments.add(key)
else: else:
@ -357,12 +349,6 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) =
result.action.passNimFlags.add(val) result.action.passNimFlags.add(val)
else: else:
wasFlagHandled = false wasFlagHandled = false
of actionInit:
case f
of "git", "hg":
result.action.vcsOption = f
else:
wasFlagHandled = false
of actionUninstall: of actionUninstall:
case f case f
of "incldeps", "i": of "incldeps", "i":
@ -374,7 +360,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) =
result.action.compileOptions.add(getFlagString(kind, flag, val)) result.action.compileOptions.add(getFlagString(kind, flag, val))
of actionRun: of actionRun:
result.showHelp = false result.showHelp = false
result.setRunOptions(flag, getFlagString(kind, flag, val), false) result.action.runFlags.add(getFlagString(kind, flag, val))
of actionCustom: of actionCustom:
if result.action.command.normalize == "test": if result.action.command.normalize == "test":
if f == "continue" or f == "c": if f == "continue" or f == "c":
@ -444,7 +430,7 @@ 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) handleUnknownFlags(result)
@ -529,23 +515,15 @@ proc getCompilationFlags*(options: Options): seq[string] =
var opt = options var opt = options
return opt.getCompilationFlags() return opt.getCompilationFlags()
proc getCompilationBinary*(options: Options, pkgInfo: PackageInfo): Option[string] = proc getCompilationBinary*(options: Options): Option[string] =
case options.action.typ case options.action.typ
of actionBuild, actionDoc, actionCompile: of actionBuild, actionDoc, actionCompile:
let file = options.action.file.changeFileExt("") let file = options.action.file.changeFileExt("")
if file.len > 0: if file.len > 0:
return some(file) return some(file)
of actionRun: of actionRun:
let optRunFile = options.action.runFile let runFile = options.action.runFile.changeFileExt(ExeExt)
let runFile =
if optRunFile.get("").len > 0:
optRunFile.get()
elif pkgInfo.bin.len == 1:
pkgInfo.bin[0]
else:
""
if runFile.len > 0: if runFile.len > 0:
return some(runFile.changeFileExt(ExeExt)) return some(runFile)
else: else:
discard discard

View file

@ -11,7 +11,7 @@ proc extractBin(cmd: string): string =
else: else:
return cmd.split(' ')[0] return cmd.split(' ')[0]
proc doCmd*(cmd: string, showOutput = false, showCmd = false) = proc doCmd*(cmd: string, showOutput = 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,10 +20,7 @@ proc doCmd*(cmd: string, showOutput = false, showCmd = false) =
stdout.flushFile() stdout.flushFile()
stderr.flushFile() stderr.flushFile()
if showCmd: displayDebug("Executing", cmd)
display("Executing", cmd, priority = MediumPriority)
else:
displayDebug("Executing", cmd)
if showOutput: if showOutput:
let exitCode = execCmd(cmd) let exitCode = execCmd(cmd)
displayDebug("Finished", "with exit code " & $exitCode) displayDebug("Finished", "with exit code " & $exitCode)

View file

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

View file

@ -38,7 +38,7 @@ proc execNimble(args: varargs[string]): tuple[output: string, exitCode: int] =
var quotedArgs = @args var quotedArgs = @args
quotedArgs.insert("--nimbleDir:" & installDir) quotedArgs.insert("--nimbleDir:" & installDir)
quotedArgs.insert(nimblePath) quotedArgs.insert(nimblePath)
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"
@ -950,50 +950,6 @@ suite "nimble run":
[$DirSep, "run".changeFileExt(ExeExt)]) [$DirSep, "run".changeFileExt(ExeExt)])
check output.contains("""Testing `nimble run`: @["--debug", "check"]""") 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": test "NimbleVersion is defined":
cd "nimbleVersionDefine": cd "nimbleVersionDefine":
var (output, exitCode) = execNimble("c", "-r", "src/nimbleVersionDefine.nim") var (output, exitCode) = execNimble("c", "-r", "src/nimbleVersionDefine.nim")