Implements basic support for building with .nimble-link'ed packages.
This commit is contained in:
parent
5f1de1e4ff
commit
97dc0ffb45
8 changed files with 90 additions and 31 deletions
|
|
@ -4,7 +4,7 @@
|
|||
import system except TResult
|
||||
|
||||
import httpclient, parseopt, os, osproc, pegs, tables, parseutils,
|
||||
strtabs, json, algorithm, sets, uri
|
||||
strtabs, json, algorithm, sets, uri, future, sequtils
|
||||
|
||||
import strutils except toLower
|
||||
from unicode import toLower
|
||||
|
|
@ -198,11 +198,12 @@ proc removeRevDep(options: Options, pkg: PackageInfo) =
|
|||
|
||||
proc install(packages: seq[PkgTuple],
|
||||
options: Options,
|
||||
doPrompt = true): tuple[paths: seq[string], pkg: PackageInfo]
|
||||
proc processDeps(pkginfo: PackageInfo, options: Options): seq[string] =
|
||||
doPrompt = true): tuple[deps: seq[PackageInfo], pkg: PackageInfo]
|
||||
proc processDeps(pkginfo: PackageInfo, options: Options): seq[PackageInfo] =
|
||||
## Verifies and installs dependencies.
|
||||
##
|
||||
## Returns the list of paths to pass to the compiler during build phase.
|
||||
## Returns the list of PackageInfo (for paths) to pass to the compiler
|
||||
## during build phase.
|
||||
result = @[]
|
||||
assert(not pkginfo.isMinimal, "processDeps needs pkginfo.requires")
|
||||
display("Verifying",
|
||||
|
|
@ -233,8 +234,8 @@ proc processDeps(pkginfo: PackageInfo, options: Options): seq[string] =
|
|||
if not found:
|
||||
display("Installing", $resolvedDep, priority = HighPriority)
|
||||
let toInstall = @[(resolvedDep.name, resolvedDep.ver)]
|
||||
let (paths, installedPkg) = install(toInstall, options)
|
||||
result.add(paths)
|
||||
let (pkgs, installedPkg) = install(toInstall, options)
|
||||
result.add(pkgs)
|
||||
|
||||
pkg = installedPkg # For addRevDep
|
||||
|
||||
|
|
@ -243,7 +244,12 @@ proc processDeps(pkginfo: PackageInfo, options: Options): seq[string] =
|
|||
else:
|
||||
display("Info:", "Dependency on $1 already satisfied" % $dep,
|
||||
priority = HighPriority)
|
||||
result.add(pkg.mypath.splitFile.dir)
|
||||
if pkg.isLinked:
|
||||
# TODO (#393): This can be optimised since the .nimble-link files have
|
||||
# a secondary line that specifies the srcDir.
|
||||
pkg = pkg.toFullInfo(options)
|
||||
|
||||
result.add(pkg)
|
||||
# Process the dependencies of this dependency.
|
||||
result.add(processDeps(pkg.toFullInfo(options), options))
|
||||
reverseDeps.add((pkg.name, pkg.specialVersion))
|
||||
|
|
@ -251,8 +257,7 @@ proc processDeps(pkginfo: PackageInfo, options: Options): seq[string] =
|
|||
# Check if two packages of the same name (but different version) are listed
|
||||
# in the path.
|
||||
var pkgsInPath: StringTableRef = newStringTable(modeCaseSensitive)
|
||||
for p in result:
|
||||
let pkgInfo = getPkgInfo(p, options)
|
||||
for pkgInfo in result:
|
||||
if pkgsInPath.hasKey(pkgInfo.name) and
|
||||
pkgsInPath[pkgInfo.name] != pkgInfo.version:
|
||||
raise newException(NimbleError,
|
||||
|
|
@ -267,7 +272,8 @@ proc processDeps(pkginfo: PackageInfo, options: Options): seq[string] =
|
|||
for i in reverseDeps:
|
||||
addRevDep(options, i, pkginfo)
|
||||
|
||||
proc buildFromDir(pkgInfo: PackageInfo, paths: seq[string], args: var seq[string]) =
|
||||
proc buildFromDir(pkgInfo: PackageInfo, paths: seq[string],
|
||||
args: var seq[string]) =
|
||||
## Builds a package as specified by ``pkgInfo``.
|
||||
if pkgInfo.bin.len == 0:
|
||||
raise newException(NimbleError,
|
||||
|
|
@ -369,7 +375,10 @@ proc vcsRevisionInDir(dir: string): string =
|
|||
discard
|
||||
|
||||
proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
||||
url: string): tuple[paths: seq[string], pkg: PackageInfo] =
|
||||
url: string): tuple[
|
||||
deps: seq[PackageInfo],
|
||||
pkg: PackageInfo
|
||||
] =
|
||||
## Returns where package has been installed to, together with paths
|
||||
## to the packages this package depends on.
|
||||
## The return value of this function is used by
|
||||
|
|
@ -385,7 +394,7 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
|||
pkgInfo.specialVersion = $requestedVer.spe
|
||||
|
||||
# Dependencies need to be processed before the creation of the pkg dir.
|
||||
result.paths = processDeps(pkgInfo, depsOptions)
|
||||
result.deps = processDeps(pkgInfo, depsOptions)
|
||||
|
||||
if options.depsOnly:
|
||||
result.pkg = pkgInfo
|
||||
|
|
@ -396,7 +405,9 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
|||
|
||||
# Build before removing an existing package (if one exists). This way
|
||||
# if the build fails then the old package will still be installed.
|
||||
if pkgInfo.bin.len > 0: buildFromDir(pkgInfo, result.paths, true)
|
||||
if pkgInfo.bin.len > 0:
|
||||
let paths = result.deps.map(dep => dep.getRealDir())
|
||||
buildFromDir(pkgInfo, paths, true)
|
||||
|
||||
let pkgDestDir = pkgInfo.getPkgDest(options)
|
||||
if existsDir(pkgDestDir) and existsFile(pkgDestDir / "nimblemeta.json"):
|
||||
|
|
@ -462,8 +473,8 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
|||
# processDeps).
|
||||
saveNimbleData(options)
|
||||
|
||||
# Return the paths to the dependencies of this package.
|
||||
result.paths.add pkgDestDir
|
||||
# Return the dependencies of this package (mainly for paths).
|
||||
result.deps.add pkgInfo
|
||||
result.pkg = pkgInfo
|
||||
result.pkg.isInstalled = true
|
||||
result.pkg.myPath = dest
|
||||
|
|
@ -496,7 +507,7 @@ proc getDownloadInfo*(pv: PkgTuple, options: Options,
|
|||
|
||||
proc install(packages: seq[PkgTuple],
|
||||
options: Options,
|
||||
doPrompt = true): tuple[paths: seq[string], pkg: PackageInfo] =
|
||||
doPrompt = true): tuple[deps: seq[PackageInfo], pkg: PackageInfo] =
|
||||
if packages == @[]:
|
||||
result = installFromDir(getCurrentDir(), newVRAny(), options, "")
|
||||
else:
|
||||
|
|
@ -530,7 +541,8 @@ proc install(packages: seq[PkgTuple],
|
|||
proc build(options: Options) =
|
||||
var pkgInfo = getPkgInfo(getCurrentDir(), options)
|
||||
nimScriptHint(pkgInfo)
|
||||
let paths = processDeps(pkginfo, options)
|
||||
let deps = processDeps(pkginfo, options)
|
||||
let paths = deps.map(dep => dep.getRealDir())
|
||||
var args = options.action.compileOptions
|
||||
buildFromDir(pkgInfo, paths, args)
|
||||
|
||||
|
|
@ -544,10 +556,10 @@ proc execBackend(options: Options) =
|
|||
|
||||
var pkgInfo = getPkgInfo(getCurrentDir(), options)
|
||||
nimScriptHint(pkgInfo)
|
||||
let paths = processDeps(pkginfo, options)
|
||||
let deps = processDeps(pkginfo, options)
|
||||
|
||||
var args = ""
|
||||
for path in paths: args.add("--path:\"" & path & "\" ")
|
||||
for dep in deps: args.add("--path:\"" & dep.getRealDir() & "\" ")
|
||||
for option in options.action.compileOptions:
|
||||
args.add("\"" & option & "\" ")
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ when not defined(nimscript):
|
|||
isNimScript*: bool ## Determines if this pkg info was read from a nims file
|
||||
isMinimal*: bool
|
||||
isInstalled*: bool ## Determines if the pkg this info belongs to is installed
|
||||
isLinked*: bool ## Determines if the pkg this info belongs to has been linked via `develop`
|
||||
postHooks*: HashSet[string] ## Useful to know so that Nimble doesn't execHook unnecessarily
|
||||
preHooks*: HashSet[string]
|
||||
name*: string
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ proc getNameVersion*(pkgpath: string): tuple[name, version: string] =
|
|||
##
|
||||
## Also works for file paths like:
|
||||
## ``/home/user/.nimble/pkgs/package-0.1/package.nimble``
|
||||
if pkgPath.splitFile.ext == ".nimble" or pkgPath.splitFile.ext == ".babel":
|
||||
if pkgPath.splitFile.ext in [".nimble", ".nimble-link", ".babel"]:
|
||||
return getNameVersion(pkgPath.splitPath.head)
|
||||
|
||||
result.name = ""
|
||||
|
|
@ -281,7 +281,7 @@ proc findNimbleFile*(dir: string; error: bool): string =
|
|||
if kind in {pcFile, pcLinkToFile}:
|
||||
let ext = path.splitFile.ext
|
||||
case ext
|
||||
of ".babel", ".nimble":
|
||||
of ".babel", ".nimble", ".nimble-link":
|
||||
result = path
|
||||
inc hits
|
||||
else: discard
|
||||
|
|
@ -293,8 +293,16 @@ proc findNimbleFile*(dir: string; error: bool): string =
|
|||
raise newException(NimbleError,
|
||||
"Specified directory does not contain a .nimble file.")
|
||||
else:
|
||||
display("Warning:", "No .nimble file found for " & dir, Warning,
|
||||
HighPriority)
|
||||
display("Warning:", "No .nimble or .nimble-link file found for " &
|
||||
dir, Warning, HighPriority)
|
||||
|
||||
if result.splitFile.ext == ".nimble-link":
|
||||
# Return the path of the real .nimble file.
|
||||
let lines = readFile(result).splitLines()
|
||||
result = lines[0]
|
||||
if not fileExists(result):
|
||||
raiseNimbleError("The .nimble-link file is pointing to a missing" &
|
||||
" file: " & result)
|
||||
|
||||
proc getInstalledPkgsMin*(libsDir: string, options: Options):
|
||||
seq[tuple[pkginfo: PackageInfo, meta: MetaData]] =
|
||||
|
|
@ -309,13 +317,15 @@ proc getInstalledPkgsMin*(libsDir: string, options: Options):
|
|||
let nimbleFile = findNimbleFile(path, false)
|
||||
if nimbleFile != "":
|
||||
let meta = readMetaData(path)
|
||||
let (name, version) = getNameVersion(nimbleFile)
|
||||
let (name, version) = getNameVersion(path)
|
||||
var pkg = initPackageInfo(nimbleFile)
|
||||
pkg.name = name
|
||||
pkg.version = version
|
||||
pkg.specialVersion = version
|
||||
pkg.isMinimal = true
|
||||
pkg.isInstalled = true
|
||||
pkg.isLinked =
|
||||
cmpPaths(nimbleFile.splitFile().dir, path) != 0
|
||||
result.add((pkg, meta))
|
||||
|
||||
proc withinRange*(pkgInfo: PackageInfo, verRange: VersionRange): bool =
|
||||
|
|
@ -369,7 +379,7 @@ proc findAllPkgs*(pkglist: seq[tuple[pkgInfo: PackageInfo, meta: MetaData]],
|
|||
|
||||
proc getRealDir*(pkgInfo: PackageInfo): string =
|
||||
## Returns the directory containing the package source files.
|
||||
if pkgInfo.srcDir != "" and not pkgInfo.isInstalled:
|
||||
if pkgInfo.srcDir != "" and (not pkgInfo.isInstalled or pkgInfo.isLinked):
|
||||
result = pkgInfo.mypath.splitFile.dir / pkgInfo.srcDir
|
||||
else:
|
||||
result = pkgInfo.mypath.splitFile.dir
|
||||
|
|
@ -515,6 +525,8 @@ when isMainModule:
|
|||
("package", "#head")
|
||||
doAssert getNameVersion("/home/user/.nimble/libs/package-#branch-with-dashes") ==
|
||||
("package", "#branch-with-dashes")
|
||||
# readPackageInfo (and possibly more) depends on this not raising.
|
||||
doAssert getNameVersion("/home/user/.nimble/libs/package") == ("package", "")
|
||||
|
||||
doAssert toValidPackageName("foo__bar") == "foo_bar"
|
||||
doAssert toValidPackageName("jhbasdh!£$@%#^_&*_()qwe") == "jhbasdh_qwe"
|
||||
|
|
|
|||
|
|
@ -292,6 +292,11 @@ proc readPackageInfo(nf: NimbleFile, options: Options,
|
|||
result.version = minimalInfo.version
|
||||
result.isNimScript = true
|
||||
result.isMinimal = true
|
||||
|
||||
# It's possible this proc will receive a .nimble-link file eventually,
|
||||
# I added this assert to hopefully make this error clear for everyone.
|
||||
let msg = "No version detected. Received nimble-link?"
|
||||
assert result.version.len > 0, msg
|
||||
else:
|
||||
try:
|
||||
readPackageInfoFromNims(nf, options, result)
|
||||
|
|
@ -386,6 +391,8 @@ proc getInstalledPkgs*(libsDir: string, options: Options):
|
|||
raise exc
|
||||
|
||||
pkg.isInstalled = true
|
||||
pkg.isLinked =
|
||||
cmpPaths(nimbleFile.splitFile().dir, path) != 0
|
||||
result.add((pkg, meta))
|
||||
|
||||
proc isNimScript*(nf: string, options: Options): bool =
|
||||
|
|
@ -393,7 +400,9 @@ proc isNimScript*(nf: string, options: Options): bool =
|
|||
|
||||
proc toFullInfo*(pkg: PackageInfo, options: Options): PackageInfo =
|
||||
if pkg.isMinimal:
|
||||
return getPkgInfoFromFile(pkg.mypath, options)
|
||||
result = getPkgInfoFromFile(pkg.mypath, options)
|
||||
result.isInstalled = pkg.isInstalled
|
||||
result.isLinked = pkg.isLinked
|
||||
else:
|
||||
return pkg
|
||||
|
||||
|
|
|
|||
12
tests/develop/dependent/dependent.nimble
Normal file
12
tests/develop/dependent/dependent.nimble
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Package
|
||||
|
||||
version = "1.0"
|
||||
author = "Dominik Picheta"
|
||||
description = "dependent"
|
||||
license = "MIT"
|
||||
|
||||
srcDir = "src"
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 0.16.0", "srcdirtest"
|
||||
3
tests/develop/dependent/src/dependent.nim
Normal file
3
tests/develop/dependent/src/dependent.nim
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import srcdirtest
|
||||
|
||||
doAssert foo() == "correct"
|
||||
|
|
@ -1 +1,4 @@
|
|||
proc foo*(): string =
|
||||
return "correct"
|
||||
|
||||
echo("hello")
|
||||
|
|
@ -24,10 +24,11 @@ test "can compile with --os:windows":
|
|||
template cd*(dir: string, body: untyped) =
|
||||
## Sets the current dir to ``dir``, executes ``body`` and restores the
|
||||
## previous working dir.
|
||||
let lastDir = getCurrentDir()
|
||||
setCurrentDir(dir)
|
||||
body
|
||||
setCurrentDir(lastDir)
|
||||
block:
|
||||
let lastDir = getCurrentDir()
|
||||
setCurrentDir(dir)
|
||||
body
|
||||
setCurrentDir(lastDir)
|
||||
|
||||
proc execNimble(args: varargs[string]): tuple[output: string, exitCode: int] =
|
||||
var quotedArgs = @args
|
||||
|
|
@ -500,4 +501,10 @@ suite "develop feature":
|
|||
let split = readFile(path).splitLines()
|
||||
check split.len == 2
|
||||
check split[0].endsWith("develop/srcdirtest/srcdirtest.nimble")
|
||||
check split[1].endsWith("develop/srcdirtest/src")
|
||||
check split[1].endsWith("develop/srcdirtest/src")
|
||||
|
||||
cd "develop/dependent":
|
||||
let (output, exitCode) = execNimble("c", "-r", "src/dependent")
|
||||
checkpoint output
|
||||
check(output.processOutput.inLines("hello"))
|
||||
check exitCode == QuitSuccess
|
||||
Loading…
Add table
Add a link
Reference in a new issue