Various optimisations to PackageInfo reading and bug fixes.
* PackageInfo objects are now cached because NimScript evaluation is expensive. * before/after hooks now return `true` by default. * Bugfix: when hooks weren't found Nimble would still think that a hook told it to skip an action. * PackageInfo now includes info about which hooks are defined to prevent unnecessary execution of those hooks. * Probably more.
This commit is contained in:
parent
5d55a5f7a2
commit
42ef358459
8 changed files with 47 additions and 20 deletions
|
|
@ -12,13 +12,6 @@ srcDir = "src"
|
||||||
|
|
||||||
requires "nim >= 0.11.2"
|
requires "nim >= 0.11.2"
|
||||||
|
|
||||||
before tasks:
|
|
||||||
echo("About to list tasks!")
|
|
||||||
return true
|
|
||||||
|
|
||||||
after tasks:
|
|
||||||
echo("Listed tasks!")
|
|
||||||
|
|
||||||
task tests, "Run the Nimble tester!":
|
task tests, "Run the Nimble tester!":
|
||||||
withDir "tests":
|
withDir "tests":
|
||||||
exec "nim c -r tester"
|
exec "nim c -r tester"
|
||||||
|
|
@ -860,11 +860,16 @@ proc execHook(options: Options, before: bool): bool =
|
||||||
## Returns whether to continue.
|
## Returns whether to continue.
|
||||||
result = true
|
result = true
|
||||||
let nimbleFile = findNimbleFile(getCurrentDir(), true)
|
let nimbleFile = findNimbleFile(getCurrentDir(), true)
|
||||||
# TODO: Optimise this, there are two (three?) calls to readPackageInfo.
|
# PackageInfos are cached so we can read them as many times as we want.
|
||||||
if nimbleFile.isNimScript(options):
|
let pkgInfo = readPackageInfo(nimbleFile, options)
|
||||||
let actionName = ($options.action.typ)[6 .. ^1]
|
let actionName = ($options.action.typ)[6 .. ^1]
|
||||||
|
let hookExists =
|
||||||
|
if before: actionName.normalize in pkgInfo.preHooks
|
||||||
|
else: actionName.normalize in pkgInfo.postHooks
|
||||||
|
if pkgInfo.isNimScript and hookExists:
|
||||||
let res = execHook(nimbleFile, actionName, before, options)
|
let res = execHook(nimbleFile, actionName, before, options)
|
||||||
result = res.retVal
|
if res.success:
|
||||||
|
result = res.retVal
|
||||||
|
|
||||||
proc doAction(options: Options) =
|
proc doAction(options: Options) =
|
||||||
if not existsDir(options.getNimbleDir()):
|
if not existsDir(options.getNimbleDir()):
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
# Various miscellaneous common types reside here, to avoid problems with
|
# Various miscellaneous common types reside here, to avoid problems with
|
||||||
# recursive imports
|
# recursive imports
|
||||||
|
|
||||||
|
import sets
|
||||||
|
|
||||||
import version
|
import version
|
||||||
export version.NimbleError
|
export version.NimbleError
|
||||||
|
|
||||||
|
|
@ -14,6 +16,8 @@ type
|
||||||
isNimScript*: bool ## Determines if this pkg info was read from a nims file
|
isNimScript*: bool ## Determines if this pkg info was read from a nims file
|
||||||
isMinimal*: bool
|
isMinimal*: bool
|
||||||
isInstalled*: bool ## Determines if the pkg this info belongs to is installed
|
isInstalled*: bool ## Determines if the pkg this info belongs to is installed
|
||||||
|
postHooks*: HashSet[string] ## Useful to know so that Nimble doesn't execHook unnecessarily
|
||||||
|
preHooks*: HashSet[string]
|
||||||
name*: string
|
name*: string
|
||||||
version*: string
|
version*: string
|
||||||
author*: string
|
author*: string
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,13 @@ proc requires*(deps: varargs[string]) =
|
||||||
template before*(action: untyped, body: untyped): untyped =
|
template before*(action: untyped, body: untyped): untyped =
|
||||||
## Defines a block of code which is evaluated before ``action`` is executed.
|
## Defines a block of code which is evaluated before ``action`` is executed.
|
||||||
proc `action Before`*(): bool =
|
proc `action Before`*(): bool =
|
||||||
result = false
|
result = true
|
||||||
body
|
body
|
||||||
|
|
||||||
template after*(action: untyped, body: untyped): untyped =
|
template after*(action: untyped, body: untyped): untyped =
|
||||||
## Defines a block of code which is evaluated after ``action`` is executed.
|
## Defines a block of code which is evaluated after ``action`` is executed.
|
||||||
proc `action After`*(): bool =
|
proc `action After`*(): bool =
|
||||||
|
result = true
|
||||||
body
|
body
|
||||||
|
|
||||||
template builtin = discard
|
template builtin = discard
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,11 @@ import
|
||||||
|
|
||||||
from compiler/scriptconfig import setupVM
|
from compiler/scriptconfig import setupVM
|
||||||
from compiler/idents import getIdent
|
from compiler/idents import getIdent
|
||||||
from compiler/astalgo import strTableGet, `$`
|
from compiler/astalgo import strTableGet
|
||||||
import compiler/options as compiler_options
|
import compiler/options as compiler_options
|
||||||
|
|
||||||
import compiler/renderer
|
|
||||||
|
|
||||||
import nimbletypes, version, options, packageinfo
|
import nimbletypes, version, options, packageinfo
|
||||||
import os, strutils, strtabs, times, osproc
|
import os, strutils, strtabs, times, osproc, sets
|
||||||
|
|
||||||
type
|
type
|
||||||
ExecutionResult*[T] = object
|
ExecutionResult*[T] = object
|
||||||
|
|
@ -277,7 +275,9 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options,
|
||||||
|
|
||||||
# Extract all the necessary fields populated by the nimscript file.
|
# Extract all the necessary fields populated by the nimscript file.
|
||||||
proc getSym(thisModule: PSym, ident: string): PSym =
|
proc getSym(thisModule: PSym, ident: string): PSym =
|
||||||
thisModule.tab.strTableGet(getIdent(ident))
|
result = thisModule.tab.strTableGet(getIdent(ident))
|
||||||
|
if result.isNil:
|
||||||
|
raise newException(NimbleError, "Ident not found: " & ident)
|
||||||
|
|
||||||
template trivialField(field) =
|
template trivialField(field) =
|
||||||
result.field = getGlobal(getSym(thisModule, astToStr field))
|
result.field = getGlobal(getSym(thisModule, astToStr field))
|
||||||
|
|
@ -322,6 +322,15 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options,
|
||||||
else:
|
else:
|
||||||
result.backend = backend.toLower()
|
result.backend = backend.toLower()
|
||||||
|
|
||||||
|
# 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()
|
cleanup()
|
||||||
|
|
||||||
proc execTask*(scriptName, taskName: string,
|
proc execTask*(scriptName, taskName: string,
|
||||||
|
|
@ -377,6 +386,7 @@ proc execHook*(scriptName, actionName: string, before: bool,
|
||||||
if prc.isNil:
|
if prc.isNil:
|
||||||
# Procedure not defined in the NimScript module.
|
# Procedure not defined in the NimScript module.
|
||||||
result.success = false
|
result.success = false
|
||||||
|
cleanup()
|
||||||
return
|
return
|
||||||
let returnVal = vm.globalCtx.execProc(prc, [])
|
let returnVal = vm.globalCtx.execProc(prc, [])
|
||||||
case returnVal.kind
|
case returnVal.kind
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
# 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 json, strutils, os, parseopt, strtabs, uri
|
import json, strutils, os, parseopt, strtabs, uri, tables
|
||||||
from httpclient import Proxy, newProxy
|
from httpclient import Proxy, newProxy
|
||||||
|
|
||||||
import nimblepkg/config, nimblepkg/version,
|
import nimblepkg/config, nimblepkg/version,
|
||||||
nimblepkg/tools
|
nimblepkg/tools, nimblepkg/nimbletypes
|
||||||
|
|
||||||
type
|
type
|
||||||
Options* = object
|
Options* = object
|
||||||
|
|
@ -15,6 +15,7 @@ type
|
||||||
action*: Action
|
action*: Action
|
||||||
config*: Config
|
config*: Config
|
||||||
nimbleData*: JsonNode ## Nimbledata.json
|
nimbleData*: JsonNode ## Nimbledata.json
|
||||||
|
pkgInfoCache*: TableRef[string, PackageInfo]
|
||||||
|
|
||||||
ActionType* = enum
|
ActionType* = enum
|
||||||
actionNil, actionUpdate, actionInit, actionDump, actionPublish,
|
actionNil, actionUpdate, actionInit, actionDump, actionPublish,
|
||||||
|
|
@ -258,6 +259,7 @@ proc parseFlag*(flag, val: string, result: var Options) =
|
||||||
|
|
||||||
proc initOptions*(): Options =
|
proc initOptions*(): Options =
|
||||||
result.action.typ = actionNil
|
result.action.typ = actionNil
|
||||||
|
result.pkgInfoCache = newTable[string, PackageInfo]()
|
||||||
|
|
||||||
proc parseMisc(): Options =
|
proc parseMisc(): Options =
|
||||||
result = initOptions()
|
result = initOptions()
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ type
|
||||||
|
|
||||||
proc initPackageInfo*(path: string): PackageInfo =
|
proc initPackageInfo*(path: string): PackageInfo =
|
||||||
result.mypath = path
|
result.mypath = path
|
||||||
|
result.preHooks.init()
|
||||||
|
result.postHooks.init()
|
||||||
# reasonable default:
|
# reasonable default:
|
||||||
result.name = path.splitFile.name
|
result.name = path.splitFile.name
|
||||||
result.version = ""
|
result.version = ""
|
||||||
|
|
|
||||||
|
|
@ -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, streams, strutils, parseutils, os
|
import parsecfg, json, streams, strutils, parseutils, os, tables
|
||||||
import version, tools, nimbletypes, nimscriptsupport, options, packageinfo
|
import version, tools, nimbletypes, nimscriptsupport, options, packageinfo
|
||||||
|
|
||||||
## Contains procedures for parsing .nimble files. Moved here from ``packageinfo``
|
## Contains procedures for parsing .nimble files. Moved here from ``packageinfo``
|
||||||
|
|
@ -187,6 +187,15 @@ proc readPackageInfo*(nf: NimbleFile, options: Options,
|
||||||
##
|
##
|
||||||
## When ``onlyMinimalInfo`` is true, only the `name` and `version` fields are
|
## When ``onlyMinimalInfo`` is true, only the `name` and `version` fields are
|
||||||
## populated. The isNimScript field can also be relied on.
|
## populated. The isNimScript field can also be relied on.
|
||||||
|
##
|
||||||
|
## This version uses a cache stored in ``options``, so calling it multiple
|
||||||
|
## times on the same ``nf`` shouldn't require re-evaluation of the Nimble
|
||||||
|
## file.
|
||||||
|
|
||||||
|
# Check the cache.
|
||||||
|
if options.pkgInfoCache.hasKey(nf):
|
||||||
|
return options.pkgInfoCache[nf]
|
||||||
|
|
||||||
result = initPackageInfo(nf)
|
result = initPackageInfo(nf)
|
||||||
|
|
||||||
validatePackageName(nf.splitFile.name)
|
validatePackageName(nf.splitFile.name)
|
||||||
|
|
@ -221,6 +230,7 @@ proc readPackageInfo*(nf: NimbleFile, options: Options,
|
||||||
raise newException(NimbleError, msg)
|
raise newException(NimbleError, msg)
|
||||||
|
|
||||||
validatePackageInfo(result, nf)
|
validatePackageInfo(result, nf)
|
||||||
|
options.pkgInfoCache[nf] = result
|
||||||
|
|
||||||
proc getPkgInfo*(dir: string, options: Options): PackageInfo =
|
proc getPkgInfo*(dir: string, options: Options): PackageInfo =
|
||||||
## Find the .nimble file in ``dir`` and parses it, returning a PackageInfo.
|
## Find the .nimble file in ``dir`` and parses it, returning a PackageInfo.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue