Extra checks for unsatisfiable dependencies.
Specifically this refers to the problem with babel-test/packagebin. PackageBin ends up depending on two different versions of PackageA (0.2 and 0.5). This however cannot be built because the Nimrod compiler can only use one of these packages.
This commit is contained in:
parent
e14ffd5628
commit
8585e11a4d
2 changed files with 44 additions and 11 deletions
33
babel.nim
33
babel.nim
|
|
@ -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 httpclient, parseopt, os, strutils, osproc, pegs, tables, parseutils
|
import httpclient, parseopt, os, strutils, osproc, pegs, tables, parseutils, strtabs
|
||||||
|
|
||||||
import packageinfo, version, common, tools, download, algorithm
|
import packageinfo, version, common, tools, download, algorithm
|
||||||
|
|
||||||
|
|
@ -227,7 +227,7 @@ proc copyFilesRec(origDir, currentDir, dest: string, pkgInfo: TPackageInfo) =
|
||||||
changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath))
|
changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath))
|
||||||
|
|
||||||
proc install(packages: seq[tuple[name: string, verRange: PVersionRange]],
|
proc install(packages: seq[tuple[name: string, verRange: PVersionRange]],
|
||||||
options: TOptions, doPrompt = true): string {.discardable.}
|
options: TOptions, doPrompt = true): seq[string] {.discardable.}
|
||||||
proc processDeps(pkginfo: TPackageInfo, options: TOptions): seq[string] =
|
proc processDeps(pkginfo: TPackageInfo, options: TOptions): seq[string] =
|
||||||
## Verifies and installs dependencies.
|
## Verifies and installs dependencies.
|
||||||
##
|
##
|
||||||
|
|
@ -244,12 +244,23 @@ proc processDeps(pkginfo: TPackageInfo, options: TOptions): seq[string] =
|
||||||
var pkg: TPackageInfo
|
var pkg: TPackageInfo
|
||||||
if not findPkg(pkglist, dep, pkg):
|
if not findPkg(pkglist, dep, pkg):
|
||||||
echo("None found, installing...")
|
echo("None found, installing...")
|
||||||
let dest = install(@[(dep.name, dep.ver)], options)
|
let paths = install(@[(dep.name, dep.ver)], options)
|
||||||
result.add(dest)
|
result.add(paths)
|
||||||
else:
|
else:
|
||||||
echo("Dependency already satisfied.")
|
echo("Dependency already satisfied.")
|
||||||
result.add(pkg.mypath.splitFile.dir)
|
result.add(pkg.mypath.splitFile.dir)
|
||||||
|
|
||||||
|
# Check if two packages of the same name (but different version) are listed
|
||||||
|
# in the path.
|
||||||
|
var pkgsInPath: PStringTable = newStringTable(modeCaseSensitive)
|
||||||
|
for p in result:
|
||||||
|
let (name, version) = getNameVersion(p)
|
||||||
|
if pkgsInPath.hasKey(name):
|
||||||
|
raise newException(EBabel,
|
||||||
|
"Cannot satisfy the dependency on $1 $2 and $1 $3" %
|
||||||
|
[name, version, pkgsInPath[name]])
|
||||||
|
pkgsInPath[name] = version
|
||||||
|
|
||||||
proc buildFromDir(pkgInfo: TPackageInfo, paths: seq[string]) =
|
proc buildFromDir(pkgInfo: TPackageInfo, paths: seq[string]) =
|
||||||
## Builds a package as specified by ``pkgInfo``.
|
## Builds a package as specified by ``pkgInfo``.
|
||||||
let realDir = pkgInfo.getRealDir()
|
let realDir = pkgInfo.getRealDir()
|
||||||
|
|
@ -261,17 +272,17 @@ proc buildFromDir(pkgInfo: TPackageInfo, paths: seq[string]) =
|
||||||
doCmd("nimrod $# -d:release $# \"$#\"" %
|
doCmd("nimrod $# -d:release $# \"$#\"" %
|
||||||
[pkgInfo.backend, args, realDir / bin.changeFileExt("nim")])
|
[pkgInfo.backend, args, realDir / bin.changeFileExt("nim")])
|
||||||
|
|
||||||
proc installFromDir(dir: string, latest: bool, options: TOptions): string =
|
proc installFromDir(dir: string, latest: bool, options: TOptions): seq[string] =
|
||||||
## Returns where package has been installed to.
|
## Returns where package has been installed to.
|
||||||
## The return value of this function is used by
|
## The return value of this function is used by
|
||||||
## ``processDeps`` to gather a list of paths to pass to the nimrod compiler.
|
## ``processDeps`` to gather a list of paths to pass to the nimrod compiler.
|
||||||
var pkgInfo = getPkgInfo(dir)
|
var pkgInfo = getPkgInfo(dir)
|
||||||
let realDir = pkgInfo.getRealDir()
|
let realDir = pkgInfo.getRealDir()
|
||||||
|
|
||||||
let pkgDestDir = pkgsDir / (pkgInfo.name &
|
let versionStr = (if latest: "" else: '-' & pkgInfo.version)
|
||||||
(if latest: "" else: '-' & pkgInfo.version))
|
let pkgDestDir = pkgsDir / (pkgInfo.name & versionStr)
|
||||||
if existsDir(pkgDestDir):
|
if existsDir(pkgDestDir):
|
||||||
if not options.prompt(pkgInfo.name & " already exists. Overwrite?"):
|
if not options.prompt(pkgInfo.name & versionStr & " already exists. Overwrite?"):
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
removeDir(pkgDestDir)
|
removeDir(pkgDestDir)
|
||||||
# Remove any symlinked binaries
|
# Remove any symlinked binaries
|
||||||
|
|
@ -317,7 +328,9 @@ proc installFromDir(dir: string, latest: bool, options: TOptions): string =
|
||||||
{.error: "Sorry, your platform is not supported.".}
|
{.error: "Sorry, your platform is not supported.".}
|
||||||
else:
|
else:
|
||||||
copyFilesRec(realDir, realDir, pkgDestDir, pkgInfo)
|
copyFilesRec(realDir, realDir, pkgDestDir, pkgInfo)
|
||||||
result = pkgDestDir
|
|
||||||
|
result = paths # Return the paths to the dependencies of this package.
|
||||||
|
result.add pkgDestDir
|
||||||
|
|
||||||
echo(pkgInfo.name & " installed successfully.")
|
echo(pkgInfo.name & " installed successfully.")
|
||||||
|
|
||||||
|
|
@ -338,7 +351,7 @@ proc downloadPkg(pkg: TPackage, verRange: PVersionRange): string =
|
||||||
result = downloadDir
|
result = downloadDir
|
||||||
|
|
||||||
proc install(packages: seq[tuple[name: string, verRange: PVersionRange]],
|
proc install(packages: seq[tuple[name: string, verRange: PVersionRange]],
|
||||||
options: TOptions, doPrompt = true): string =
|
options: TOptions, doPrompt = true): seq[string] =
|
||||||
if packages == @[]:
|
if packages == @[]:
|
||||||
result = installFromDir(getCurrentDir(), false, options)
|
result = installFromDir(getCurrentDir(), false, options)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -280,6 +280,22 @@ proc getRealDir*(pkgInfo: TPackageInfo): string =
|
||||||
else:
|
else:
|
||||||
result = pkgInfo.mypath.splitFile.dir
|
result = pkgInfo.mypath.splitFile.dir
|
||||||
|
|
||||||
|
proc getNameVersion*(pkgpath: string): tuple[name, version: string] =
|
||||||
|
## Splits ``pkgpath`` in the format ``/home/user/.babel/libs/package-0.1``
|
||||||
|
## into ``(packagea, 0.1)``
|
||||||
|
result.name = ""
|
||||||
|
result.version = ""
|
||||||
|
let tail = pkgpath.splitPath.tail
|
||||||
|
if '-' notin tail:
|
||||||
|
result.name = tail
|
||||||
|
return
|
||||||
|
|
||||||
|
for i in countdown(tail.len-1, 0):
|
||||||
|
if tail[i] == '-':
|
||||||
|
result.name = tail[0 .. i-1]
|
||||||
|
result.version = tail[i+1 .. -1]
|
||||||
|
break
|
||||||
|
|
||||||
proc echoPackage*(pkg: TPackage) =
|
proc echoPackage*(pkg: TPackage) =
|
||||||
echo(pkg.name & ":")
|
echo(pkg.name & ":")
|
||||||
echo(" url: " & pkg.url & " (" & pkg.downloadMethod & ")")
|
echo(" url: " & pkg.url & " (" & pkg.downloadMethod & ")")
|
||||||
|
|
@ -288,3 +304,7 @@ proc echoPackage*(pkg: TPackage) =
|
||||||
echo(" license: " & pkg.license)
|
echo(" license: " & pkg.license)
|
||||||
if pkg.web.len > 0:
|
if pkg.web.len > 0:
|
||||||
echo(" website: " & pkg.web)
|
echo(" website: " & pkg.web)
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
doAssert getNameVersion("/home/user/.babel/libs/packagea-0.1") == ("packagea", "0.1")
|
||||||
|
doAssert getNameVersion("/home/user/.babel/libs/package-a-0.1") == ("package-a", "0.1")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue