diff --git a/babel.nim b/babel.nim index 61ac9fd..926ea25 100644 --- a/babel.nim +++ b/babel.nim @@ -1,7 +1,7 @@ # Copyright (C) Dominik Picheta. All rights reserved. # 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 @@ -227,7 +227,7 @@ proc copyFilesRec(origDir, currentDir, dest: string, pkgInfo: TPackageInfo) = changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath)) 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] = ## Verifies and installs dependencies. ## @@ -244,11 +244,22 @@ proc processDeps(pkginfo: TPackageInfo, options: TOptions): seq[string] = var pkg: TPackageInfo if not findPkg(pkglist, dep, pkg): echo("None found, installing...") - let dest = install(@[(dep.name, dep.ver)], options) - result.add(dest) + let paths = install(@[(dep.name, dep.ver)], options) + result.add(paths) else: echo("Dependency already satisfied.") 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]) = ## Builds a package as specified by ``pkgInfo``. @@ -261,17 +272,17 @@ proc buildFromDir(pkgInfo: TPackageInfo, paths: seq[string]) = doCmd("nimrod $# -d:release $# \"$#\"" % [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. ## The return value of this function is used by ## ``processDeps`` to gather a list of paths to pass to the nimrod compiler. var pkgInfo = getPkgInfo(dir) let realDir = pkgInfo.getRealDir() - let pkgDestDir = pkgsDir / (pkgInfo.name & - (if latest: "" else: '-' & pkgInfo.version)) + let versionStr = (if latest: "" else: '-' & pkgInfo.version) + let pkgDestDir = pkgsDir / (pkgInfo.name & versionStr) if existsDir(pkgDestDir): - if not options.prompt(pkgInfo.name & " already exists. Overwrite?"): + if not options.prompt(pkgInfo.name & versionStr & " already exists. Overwrite?"): quit(QuitSuccess) removeDir(pkgDestDir) # Remove any symlinked binaries @@ -317,7 +328,9 @@ proc installFromDir(dir: string, latest: bool, options: TOptions): string = {.error: "Sorry, your platform is not supported.".} else: 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.") @@ -338,7 +351,7 @@ proc downloadPkg(pkg: TPackage, verRange: PVersionRange): string = result = downloadDir proc install(packages: seq[tuple[name: string, verRange: PVersionRange]], - options: TOptions, doPrompt = true): string = + options: TOptions, doPrompt = true): seq[string] = if packages == @[]: result = installFromDir(getCurrentDir(), false, options) else: diff --git a/packageinfo.nim b/packageinfo.nim index d45f179..677f23d 100644 --- a/packageinfo.nim +++ b/packageinfo.nim @@ -280,6 +280,22 @@ proc getRealDir*(pkgInfo: TPackageInfo): string = else: 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) = echo(pkg.name & ":") echo(" url: " & pkg.url & " (" & pkg.downloadMethod & ")") @@ -287,4 +303,8 @@ proc echoPackage*(pkg: TPackage) = echo(" description: " & pkg.description) echo(" license: " & pkg.license) if pkg.web.len > 0: - echo(" website: " & pkg.web) \ No newline at end of file + 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") \ No newline at end of file