The .nimble extension is now used for both ini and nims .nimble files.

This is done by parsing the .nimble file using the ini parser first, then if that fails evaluating it using nimscript.
This commit is contained in:
Dominik Picheta 2015-12-23 20:48:05 +00:00
commit dbd478bc20
4 changed files with 61 additions and 20 deletions

View file

@ -892,6 +892,7 @@ proc guessAuthor(): string =
return "Anonymous"
proc join(x: seq[PkgTuple]; y: string): string =
if x.len == 0: return ""
result = x[0][0] & " " & $x[0][1]
for i in 1 ..< x.len:
result.add y
@ -899,7 +900,7 @@ proc join(x: seq[PkgTuple]; y: string): string =
proc dump(options: Options) =
let proj = addFileExt(options.action.projName, NimsExt)
let p = if fileExists(proj): readPackageInfo((true, proj))
let p = if fileExists(proj): readPackageInfo(proj)
else: getPkgInfo(os.getCurrentDir())
echo "name: ", p.name.escape
echo "version: ", p.version.escape
@ -1017,9 +1018,7 @@ proc uninstall(options: Options) =
echo("Removed ", pkg.name, " (", $pkg.version, ")")
proc listTasks(options: Options) =
let (isNimScript, nimbleFile) = findNimbleFile(getCurrentDir(), true)
if not isNimScript:
echo("No tasks defined (Found Nimble file, but no NimScript file)")
let nimbleFile = findNimbleFile(getCurrentDir(), true)
nimscriptsupport.listTasks(nimbleFile)
proc doAction(options: Options) =
@ -1064,8 +1063,8 @@ proc doAction(options: Options) =
assert false
of actionCustom:
# Custom command. Attempt to call a NimScript task.
let (isNimScript, nimbleFile) = findNimbleFile(getCurrentDir(), true)
if not isNimScript:
let nimbleFile = findNimbleFile(getCurrentDir(), true)
if not nimbleFile.isNimScript():
writeHelp()
let oldCmd = getNimScriptCommand()
if not execTask(nimbleFile, oldCmd):

View file

@ -11,6 +11,7 @@ type
PackageInfo* = object
mypath*: string ## The path of this .nimble file
isNimScript*: bool ## Determines if this pkg info was read from a nims file
name*: string
version*: string
author*: string

View file

@ -93,6 +93,16 @@ proc readPackageInfoFromNims*(scriptName: string; result: var PackageInfo) =
## Executes the `scriptName` nimscript file. Reads the package information
## that it populates.
# Setup custom error handling.
msgs.gErrorMax = high(int)
var previousMsg = ""
msgs.writeLnHook =
proc (output: string) =
# The error counter is incremented after the writeLnHook is invoked.
if msgs.gErrorCounter > 0:
raise newException(NimbleError, previousMsg)
previousMsg = output
# Execute the nimscript file.
execScript(scriptName)

View file

@ -26,7 +26,7 @@ type
MetaData* = object
url*: string
NimbleFile* = tuple[isNimScript: bool; file: string]
NimbleFile* = string
proc initPackageInfo(path: string): PackageInfo =
result.mypath = path
@ -73,6 +73,12 @@ proc validatePackageInfo(pkgInfo: PackageInfo, path: string) =
"Version may only consist of numbers and the '.' character " &
"but found '" & c & "'.")
if not pkgInfo.isNimScript:
# TODO: Turn this into a warning.
# TODO: Add a URL explaining more.
echo("NOTE: The .nimble file for this project could make use of " &
"additional features, if converted into the new NimScript format.")
proc multiSplit(s: string): seq[string] =
## Returns ``s`` split by newline and comma characters.
##
@ -169,17 +175,42 @@ proc getNameVersion*(pkgpath: string): tuple[name, version: string] =
break
proc readPackageInfo*(nf: NimbleFile; onlyMinimalInfo=false): PackageInfo =
result = initPackageInfo(nf.file)
if nf.isNimScript:
## Reads package info from the specifed Nimble file.
##
## Attempts to read it using the "old" Nimble ini format first, if that
## fails attempts to evaluate it as a nimscript file.
##
## If both fail then returns an error.
result = initPackageInfo(nf)
var success = false
var iniError: ref NimbleError
# Attempt ini-format first.
try:
readPackageInfoFromNimble(nf, result)
success = true
result.isNimScript = false
except NimbleError:
iniError = (ref NimbleError)(getCurrentException())
if not success:
if onlyMinimalInfo:
let tmp = getNameVersion(nf.file)
let tmp = getNameVersion(nf)
result.name = tmp.name
result.version = tmp.version
else:
readPackageInfoFromNims(nf.file, result)
else:
readPackageInfoFromNimble(nf.file, result)
validatePackageInfo(result, nf.file)
try:
readPackageInfoFromNims(nf, result)
result.isNimScript = true
except NimbleError:
let msg = "Could not read package info file in " & nf & ";\n" &
" Reading as ini file failed with: \n" &
" " & iniError.msg & ".\n" &
" Evaluating as NimScript file failed with: \n" &
" " & getCurrentExceptionMsg() & "."
raise newException(NimbleError, msg)
validatePackageInfo(result, nf)
proc optionalField(obj: JsonNode, name: string, default = ""): string =
## Queries ``obj`` for the optional ``name`` string.
@ -257,17 +288,14 @@ proc getPackageList*(packagesPath: string): seq[Package] =
result.add(pkg)
proc findNimbleFile*(dir: string; error: bool): NimbleFile =
result = (false, "")
result = ""
var hits = 0
for kind, path in walkDir(dir):
if kind == pcFile:
let ext = path.splitFile.ext
case ext
of ".babel", ".nimble":
result = (false, path)
inc hits
of NimsExt:
result = (true, path)
result = path
inc hits
else: discard
if hits >= 2:
@ -295,7 +323,7 @@ proc getInstalledPkgs*(libsDir: string):
for kind, path in walkDir(libsDir):
if kind == pcDir:
let nimbleFile = findNimbleFile(path, false)
if nimbleFile.file != "":
if nimbleFile != "":
let meta = readMetaData(path)
result.add((readPackageInfo(nimbleFile, true), meta))
@ -359,6 +387,9 @@ proc getDownloadDirName*(pkg: Package, verRange: VersionRange): string =
result.add "_"
result.add verSimple
proc isNimScript*(nf: NimbleFile): bool =
readPackageInfo(nf).isNimScript
when isMainModule:
doAssert getNameVersion("/home/user/.nimble/libs/packagea-0.1") ==
("packagea", "0.1")