Renamed babel to nimble.
This commit is contained in:
parent
7d18e2be1c
commit
adbc30c22e
9 changed files with 216 additions and 190 deletions
232
src/babel.nim
232
src/babel.nim
|
|
@ -6,8 +6,8 @@ import httpclient, parseopt, os, strutils, osproc, pegs, tables, parseutils,
|
||||||
|
|
||||||
from sequtils import toSeq
|
from sequtils import toSeq
|
||||||
|
|
||||||
import babelpkg/packageinfo, babelpkg/version, babelpkg/tools,
|
import nimblepkg/packageinfo, nimblepkg/version, nimblepkg/tools,
|
||||||
babelpkg/download, babelpkg/config, babelpkg/compat
|
nimblepkg/download, nimblepkg/config, nimblepkg/compat
|
||||||
|
|
||||||
when not defined(windows):
|
when not defined(windows):
|
||||||
from posix import getpid
|
from posix import getpid
|
||||||
|
|
@ -18,7 +18,7 @@ type
|
||||||
queryVersions: bool
|
queryVersions: bool
|
||||||
action: TAction
|
action: TAction
|
||||||
config: TConfig
|
config: TConfig
|
||||||
babelData: PJsonNode ## Babeldata.json
|
nimbleData: PJsonNode ## Nimbledata.json
|
||||||
|
|
||||||
TActionType = enum
|
TActionType = enum
|
||||||
ActionNil, ActionUpdate, ActionInit, ActionInstall, ActionSearch,
|
ActionNil, ActionUpdate, ActionInit, ActionInstall, ActionSearch,
|
||||||
|
|
@ -43,11 +43,11 @@ type
|
||||||
|
|
||||||
const
|
const
|
||||||
help = """
|
help = """
|
||||||
Usage: babel COMMAND [opts]
|
Usage: nimble COMMAND [opts]
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
install [pkgname, ...] Installs a list of packages.
|
install [pkgname, ...] Installs a list of packages.
|
||||||
init [pkgname] Initializes a new Babel project.
|
init [pkgname] Initializes a new Nimble project.
|
||||||
uninstall [pkgname, ...] Uninstalls a list of packages.
|
uninstall [pkgname, ...] Uninstalls a list of packages.
|
||||||
build Builds a package.
|
build Builds a package.
|
||||||
update [url] Updates package list. A package list URL can
|
update [url] Updates package list. A package list URL can
|
||||||
|
|
@ -66,7 +66,7 @@ Options:
|
||||||
--ver Query remote server for package version
|
--ver Query remote server for package version
|
||||||
information when searching or listing packages
|
information when searching or listing packages
|
||||||
"""
|
"""
|
||||||
babelVersion = "0.4.0"
|
nimbleVersion = "0.4.0"
|
||||||
defaultPackageURL = "https://github.com/nimrod-code/packages/raw/master/packages.json"
|
defaultPackageURL = "https://github.com/nimrod-code/packages/raw/master/packages.json"
|
||||||
|
|
||||||
proc writeHelp() =
|
proc writeHelp() =
|
||||||
|
|
@ -74,17 +74,51 @@ proc writeHelp() =
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
|
|
||||||
proc writeVersion() =
|
proc writeVersion() =
|
||||||
echo("babel v$# compiled at $# $#" % [babelVersion, CompileDate, CompileTime])
|
echo("nimble v$# compiled at $# $#" % [nimbleVersion, CompileDate, CompileTime])
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
|
|
||||||
proc getBabelDir(options: TOptions): string =
|
proc getNimbleDir(options: TOptions): string =
|
||||||
options.config.babelDir
|
options.config.nimbleDir
|
||||||
|
|
||||||
proc getPkgsDir(options: TOptions): string =
|
proc getPkgsDir(options: TOptions): string =
|
||||||
options.config.babelDir / "pkgs"
|
options.config.nimbleDir / "pkgs"
|
||||||
|
|
||||||
proc getBinDir(options: TOptions): string =
|
proc getBinDir(options: TOptions): string =
|
||||||
options.config.babelDir / "bin"
|
options.config.nimbleDir / "bin"
|
||||||
|
|
||||||
|
proc prompt(options: TOptions, question: string): bool =
|
||||||
|
## Asks an interactive question and returns the result.
|
||||||
|
##
|
||||||
|
## The proc will return immediately without asking the user if the global
|
||||||
|
## forcePrompts has a value different than DontForcePrompt.
|
||||||
|
case options.forcePrompts
|
||||||
|
of ForcePromptYes:
|
||||||
|
echo(question & " -> [forced yes]")
|
||||||
|
return true
|
||||||
|
of ForcePromptNo:
|
||||||
|
echo(question & " -> [forced no]")
|
||||||
|
return false
|
||||||
|
of DontForcePrompt:
|
||||||
|
echo(question & " [y/N]")
|
||||||
|
let yn = stdin.readLine()
|
||||||
|
case yn.normalize
|
||||||
|
of "y", "yes":
|
||||||
|
return true
|
||||||
|
of "n", "no":
|
||||||
|
return false
|
||||||
|
else:
|
||||||
|
return false
|
||||||
|
|
||||||
|
proc renameBabelToNimble(options: TOptions) {.deprecated.} =
|
||||||
|
let babelDir = getHomeDir() / ".babel"
|
||||||
|
let nimbleDir = getHomeDir() / ".nimble"
|
||||||
|
if dirExists(babelDir):
|
||||||
|
if options.prompt("Found deprecated babel package directory, would you like to rename it to nimble?"):
|
||||||
|
copyDir(babelDir, nimbleDir)
|
||||||
|
removeDir(babelDir)
|
||||||
|
|
||||||
|
copyFile(nimbleDir / "babeldata.json", nimbleDir / "nimbledata.json")
|
||||||
|
removeFile(nimbleDir / "babeldata.json")
|
||||||
|
|
||||||
proc parseCmdLine(): TOptions =
|
proc parseCmdLine(): TOptions =
|
||||||
result.action.typ = ActionNil
|
result.action.typ = ActionNil
|
||||||
|
|
@ -136,7 +170,7 @@ proc parseCmdLine(): TOptions =
|
||||||
result.action.search.add(key)
|
result.action.search.add(key)
|
||||||
of ActionInit:
|
of ActionInit:
|
||||||
if result.action.projName != "":
|
if result.action.projName != "":
|
||||||
raise newException(EBabel, "Can only initialize one package at a time.")
|
raise newException(ENimble, "Can only initialize one package at a time.")
|
||||||
result.action.projName = key
|
result.action.projName = key
|
||||||
of ActionList, ActionBuild:
|
of ActionList, ActionBuild:
|
||||||
writeHelp()
|
writeHelp()
|
||||||
|
|
@ -151,35 +185,15 @@ proc parseCmdLine(): TOptions =
|
||||||
if result.action.typ == ActionNil:
|
if result.action.typ == ActionNil:
|
||||||
writeHelp()
|
writeHelp()
|
||||||
|
|
||||||
# Load babeldata.json
|
# Rename deprecated babel dir.
|
||||||
let babeldataFilename = result.getBabelDir() / "babeldata.json"
|
renameBabelToNimble(result)
|
||||||
if fileExists(babeldataFilename):
|
|
||||||
result.babelData = parseFile(babeldataFilename)
|
|
||||||
else:
|
|
||||||
result.babelData = %{"reverseDeps": newJObject()}
|
|
||||||
|
|
||||||
proc prompt(options: TOptions, question: string): bool =
|
# Load nimbledata.json
|
||||||
## Asks an interactive question and returns the result.
|
let nimbledataFilename = result.getNimbleDir() / "nimbledata.json"
|
||||||
##
|
if fileExists(nimbledataFilename):
|
||||||
## The proc will return immediately without asking the user if the global
|
result.nimbleData = parseFile(nimbledataFilename)
|
||||||
## forcePrompts has a value different than DontForcePrompt.
|
|
||||||
case options.forcePrompts
|
|
||||||
of ForcePromptYes:
|
|
||||||
echo(question & " -> [forced yes]")
|
|
||||||
return true
|
|
||||||
of ForcePromptNo:
|
|
||||||
echo(question & " -> [forced no]")
|
|
||||||
return false
|
|
||||||
of DontForcePrompt:
|
|
||||||
echo(question & " [y/N]")
|
|
||||||
let yn = stdin.readLine()
|
|
||||||
case yn.normalize
|
|
||||||
of "y", "yes":
|
|
||||||
return true
|
|
||||||
of "n", "no":
|
|
||||||
return false
|
|
||||||
else:
|
else:
|
||||||
return false
|
result.nimbleData = %{"reverseDeps": newJObject()}
|
||||||
|
|
||||||
proc update(options: TOptions) =
|
proc update(options: TOptions) =
|
||||||
## Downloads the package list from the specified URL.
|
## Downloads the package list from the specified URL.
|
||||||
|
|
@ -192,7 +206,7 @@ proc update(options: TOptions) =
|
||||||
else:
|
else:
|
||||||
defaultPackageURL
|
defaultPackageURL
|
||||||
echo("Downloading package list from " & url)
|
echo("Downloading package list from " & url)
|
||||||
downloadFile(url, options.getBabelDir() / "packages.json")
|
downloadFile(url, options.getNimbleDir() / "packages.json")
|
||||||
echo("Done.")
|
echo("Done.")
|
||||||
|
|
||||||
proc checkInstallFile(pkgInfo: TPackageInfo,
|
proc checkInstallFile(pkgInfo: TPackageInfo,
|
||||||
|
|
@ -201,8 +215,8 @@ proc checkInstallFile(pkgInfo: TPackageInfo,
|
||||||
## ``True`` means file should be skipped.
|
## ``True`` means file should be skipped.
|
||||||
|
|
||||||
for ignoreFile in pkgInfo.skipFiles:
|
for ignoreFile in pkgInfo.skipFiles:
|
||||||
if ignoreFile.endswith("babel"):
|
if ignoreFile.endswith("nimble"):
|
||||||
raise newException(EBabel, ignoreFile & " must be installed.")
|
raise newException(ENimble, ignoreFile & " must be installed.")
|
||||||
if samePaths(file, origDir / ignoreFile):
|
if samePaths(file, origDir / ignoreFile):
|
||||||
result = true
|
result = true
|
||||||
break
|
break
|
||||||
|
|
@ -244,7 +258,7 @@ proc copyWithExt(origDir, currentDir, dest: string,
|
||||||
|
|
||||||
proc copyFilesRec(origDir, currentDir, dest: string,
|
proc copyFilesRec(origDir, currentDir, dest: string,
|
||||||
options: TOptions, pkgInfo: TPackageInfo): TSet[string] =
|
options: TOptions, pkgInfo: TPackageInfo): TSet[string] =
|
||||||
## Copies all the required files, skips files specified in the .babel file
|
## Copies all the required files, skips files specified in the .nimble file
|
||||||
## (TPackageInfo).
|
## (TPackageInfo).
|
||||||
## Returns a list of filepaths to files which have been installed.
|
## Returns a list of filepaths to files which have been installed.
|
||||||
result = initSet[string]()
|
result = initSet[string]()
|
||||||
|
|
@ -294,19 +308,19 @@ proc copyFilesRec(origDir, currentDir, dest: string,
|
||||||
result.incl copyFileD(pkgInfo.mypath,
|
result.incl copyFileD(pkgInfo.mypath,
|
||||||
changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath))
|
changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath))
|
||||||
|
|
||||||
proc saveBabelData(options: TOptions) =
|
proc saveNimbleData(options: TOptions) =
|
||||||
# TODO: This file should probably be locked.
|
# TODO: This file should probably be locked.
|
||||||
writeFile(options.getBabelDir() / "babeldata.json", pretty(options.babelData))
|
writeFile(options.getNimbleDir() / "nimbledata.json", pretty(options.nimbleData))
|
||||||
|
|
||||||
proc addRevDep(options: TOptions, dep: tuple[name, version: string],
|
proc addRevDep(options: TOptions, dep: tuple[name, version: string],
|
||||||
pkg: TPackageInfo) =
|
pkg: TPackageInfo) =
|
||||||
let depNameVer = dep.name & '-' & dep.version
|
let depNameVer = dep.name & '-' & dep.version
|
||||||
if not options.babelData["reverseDeps"].hasKey(dep.name):
|
if not options.nimbleData["reverseDeps"].hasKey(dep.name):
|
||||||
options.babelData["reverseDeps"][dep.name] = newJObject()
|
options.nimbleData["reverseDeps"][dep.name] = newJObject()
|
||||||
if not options.babelData["reverseDeps"][dep.name].hasKey(dep.version):
|
if not options.nimbleData["reverseDeps"][dep.name].hasKey(dep.version):
|
||||||
options.babelData["reverseDeps"][dep.name][dep.version] = newJArray()
|
options.nimbleData["reverseDeps"][dep.name][dep.version] = newJArray()
|
||||||
let revDep = %{ "name": %pkg.name, "version": %pkg.version}
|
let revDep = %{ "name": %pkg.name, "version": %pkg.version}
|
||||||
let thisDep = options.babelData["reverseDeps"][dep.name][dep.version]
|
let thisDep = options.nimbleData["reverseDeps"][dep.name][dep.version]
|
||||||
if revDep notin thisDep:
|
if revDep notin thisDep:
|
||||||
thisDep.add revDep
|
thisDep.add revDep
|
||||||
|
|
||||||
|
|
@ -326,16 +340,16 @@ proc removeRevDep(options: TOptions, pkg: TPackageInfo) =
|
||||||
for depTup in pkg.requires:
|
for depTup in pkg.requires:
|
||||||
if depTup.name.isURL():
|
if depTup.name.isURL():
|
||||||
# We sadly must go through everything in this case...
|
# We sadly must go through everything in this case...
|
||||||
for key, val in options.babelData["reverseDeps"]:
|
for key, val in options.nimbleData["reverseDeps"]:
|
||||||
options.remove(pkg, depTup, val)
|
options.remove(pkg, depTup, val)
|
||||||
else:
|
else:
|
||||||
let thisDep = options.babelData["reverseDeps"][depTup.name]
|
let thisDep = options.nimbleData["reverseDeps"][depTup.name]
|
||||||
if thisDep.isNil: continue
|
if thisDep.isNil: continue
|
||||||
options.remove(pkg, depTup, thisDep)
|
options.remove(pkg, depTup, thisDep)
|
||||||
|
|
||||||
# Clean up empty objects/arrays
|
# Clean up empty objects/arrays
|
||||||
var newData = newJObject()
|
var newData = newJObject()
|
||||||
for key, val in options.babelData["reverseDeps"]:
|
for key, val in options.nimbleData["reverseDeps"]:
|
||||||
if val.len != 0:
|
if val.len != 0:
|
||||||
var newVal = newJObject()
|
var newVal = newJObject()
|
||||||
for ver, elem in val:
|
for ver, elem in val:
|
||||||
|
|
@ -343,9 +357,9 @@ proc removeRevDep(options: TOptions, pkg: TPackageInfo) =
|
||||||
newVal[ver] = elem
|
newVal[ver] = elem
|
||||||
if newVal.len != 0:
|
if newVal.len != 0:
|
||||||
newData[key] = newVal
|
newData[key] = newVal
|
||||||
options.babelData["reverseDeps"] = newData
|
options.nimbleData["reverseDeps"] = newData
|
||||||
|
|
||||||
saveBabelData(options)
|
saveNimbleData(options)
|
||||||
|
|
||||||
proc install(packages: seq[TPkgTuple],
|
proc install(packages: seq[TPkgTuple],
|
||||||
options: TOptions,
|
options: TOptions,
|
||||||
|
|
@ -384,7 +398,7 @@ proc processDeps(pkginfo: TPackageInfo, options: TOptions): seq[string] =
|
||||||
for p in result:
|
for p in result:
|
||||||
let (name, version) = getNameVersion(p)
|
let (name, version) = getNameVersion(p)
|
||||||
if pkgsInPath.hasKey(name) and pkgsInPath[name] != version:
|
if pkgsInPath.hasKey(name) and pkgsInPath[name] != version:
|
||||||
raise newException(EBabel,
|
raise newException(ENimble,
|
||||||
"Cannot satisfy the dependency on $1 $2 and $1 $3" %
|
"Cannot satisfy the dependency on $1 $2 and $1 $3" %
|
||||||
[name, version, pkgsInPath[name]])
|
[name, version, pkgsInPath[name]])
|
||||||
pkgsInPath[name] = version
|
pkgsInPath[name] = version
|
||||||
|
|
@ -394,7 +408,7 @@ proc processDeps(pkginfo: TPackageInfo, options: TOptions): seq[string] =
|
||||||
# (unsatisfiable dependendencies).
|
# (unsatisfiable dependendencies).
|
||||||
for i in reverseDeps:
|
for i in reverseDeps:
|
||||||
addRevDep(options, i, pkginfo)
|
addRevDep(options, i, pkginfo)
|
||||||
saveBabelData(options)
|
saveNimbleData(options)
|
||||||
|
|
||||||
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``.
|
||||||
|
|
@ -404,36 +418,36 @@ proc buildFromDir(pkgInfo: TPackageInfo, paths: seq[string]) =
|
||||||
for bin in pkgInfo.bin:
|
for bin in pkgInfo.bin:
|
||||||
echo("Building ", pkginfo.name, "/", bin, " using ", pkgInfo.backend,
|
echo("Building ", pkginfo.name, "/", bin, " using ", pkgInfo.backend,
|
||||||
" backend...")
|
" backend...")
|
||||||
doCmd(getNimBin() & " $# -d:release --noBabelPath $# \"$#\"" %
|
doCmd(getNimBin() & " $# -d:release --noNimblePath $# \"$#\"" %
|
||||||
[pkgInfo.backend, args, realDir / bin.changeFileExt("nim")])
|
[pkgInfo.backend, args, realDir / bin.changeFileExt("nim")])
|
||||||
|
|
||||||
proc saveBabelMeta(pkgDestDir, url: string, filesInstalled: TSet[string]) =
|
proc saveNimbleMeta(pkgDestDir, url: string, filesInstalled: TSet[string]) =
|
||||||
var babelmeta = %{"url": %url}
|
var nimblemeta = %{"url": %url}
|
||||||
babelmeta["files"] = newJArray()
|
nimblemeta["files"] = newJArray()
|
||||||
for file in filesInstalled:
|
for file in filesInstalled:
|
||||||
babelmeta["files"].add(%changeRoot(pkgDestDir, "", file))
|
nimblemeta["files"].add(%changeRoot(pkgDestDir, "", file))
|
||||||
writeFile(pkgDestDir / "babelmeta.json", $babelmeta)
|
writeFile(pkgDestDir / "nimblemeta.json", $nimblemeta)
|
||||||
|
|
||||||
proc removePkgDir(dir: string, options: TOptions) =
|
proc removePkgDir(dir: string, options: TOptions) =
|
||||||
## Removes files belonging to the package in ``dir``.
|
## Removes files belonging to the package in ``dir``.
|
||||||
try:
|
try:
|
||||||
var babelmeta = parseFile(dir / "babelmeta.json")
|
var nimblemeta = parseFile(dir / "nimblemeta.json")
|
||||||
if not babelmeta.hasKey("files"):
|
if not nimblemeta.hasKey("files"):
|
||||||
raise newException(EJsonParsingError,
|
raise newException(EJsonParsingError,
|
||||||
"Meta data does not contain required info.")
|
"Meta data does not contain required info.")
|
||||||
for file in babelmeta["files"]:
|
for file in nimblemeta["files"]:
|
||||||
removeFile(dir / file.str)
|
removeFile(dir / file.str)
|
||||||
|
|
||||||
removeFile(dir / "babelmeta.json")
|
removeFile(dir / "nimblemeta.json")
|
||||||
|
|
||||||
# If there are no files left in the directory, remove the directory.
|
# If there are no files left in the directory, remove the directory.
|
||||||
if toSeq(walkDirRec(dir)).len == 0:
|
if toSeq(walkDirRec(dir)).len == 0:
|
||||||
removeDir(dir)
|
removeDir(dir)
|
||||||
else:
|
else:
|
||||||
echo("WARNING: Cannot completely remove " & dir &
|
echo("WARNING: Cannot completely remove " & dir &
|
||||||
". Files not installed by babel are present.")
|
". Files not installed by nimble are present.")
|
||||||
except EOS, EJsonParsingError:
|
except EOS, EJsonParsingError:
|
||||||
echo("Error: Unable to read babelmeta.json: ", getCurrentExceptionMsg())
|
echo("Error: Unable to read nimblemeta.json: ", getCurrentExceptionMsg())
|
||||||
if not options.prompt("Would you like to COMPLETELY remove ALL files " &
|
if not options.prompt("Would you like to COMPLETELY remove ALL files " &
|
||||||
"in " & dir & "?"):
|
"in " & dir & "?"):
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
|
|
@ -460,7 +474,7 @@ proc installFromDir(dir: string, latest: bool, options: TOptions,
|
||||||
|
|
||||||
let versionStr = (if latest: "" else: '-' & pkgInfo.version)
|
let versionStr = (if latest: "" else: '-' & pkgInfo.version)
|
||||||
let pkgDestDir = pkgsDir / (pkgInfo.name & versionStr)
|
let pkgDestDir = pkgsDir / (pkgInfo.name & versionStr)
|
||||||
if existsDir(pkgDestDir) and existsFile(pkgDestDir / "babelmeta.json"):
|
if existsDir(pkgDestDir) and existsFile(pkgDestDir / "nimblemeta.json"):
|
||||||
if not options.prompt(pkgInfo.name & versionStr & " already exists. Overwrite?"):
|
if not options.prompt(pkgInfo.name & versionStr & " already exists. Overwrite?"):
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
removePkgDir(pkgDestDir, options)
|
removePkgDir(pkgDestDir, options)
|
||||||
|
|
@ -482,7 +496,7 @@ proc installFromDir(dir: string, latest: bool, options: TOptions,
|
||||||
filesInstalled = copyFilesRec(realDir, realDir, pkgDestDir, options,
|
filesInstalled = copyFilesRec(realDir, realDir, pkgDestDir, options,
|
||||||
pkgInfo)
|
pkgInfo)
|
||||||
# Set file permissions to +x for all binaries built,
|
# Set file permissions to +x for all binaries built,
|
||||||
# and symlink them on *nix OS' to $babelDir/bin/
|
# and symlink them on *nix OS' to $nimbleDir/bin/
|
||||||
for bin in pkgInfo.bin:
|
for bin in pkgInfo.bin:
|
||||||
if not existsFile(pkgDestDir / bin):
|
if not existsFile(pkgDestDir / bin):
|
||||||
filesInstalled.incl copyFileD(realDir / bin, pkgDestDir / bin)
|
filesInstalled.incl copyFileD(realDir / bin, pkgDestDir / bin)
|
||||||
|
|
@ -506,8 +520,8 @@ proc installFromDir(dir: string, latest: bool, options: TOptions,
|
||||||
filesInstalled = copyFilesRec(realDir, realDir, pkgDestDir, options,
|
filesInstalled = copyFilesRec(realDir, realDir, pkgDestDir, options,
|
||||||
pkgInfo)
|
pkgInfo)
|
||||||
|
|
||||||
# Save a babelmeta.json file.
|
# Save a nimblemeta.json file.
|
||||||
saveBabelMeta(pkgDestDir, url, filesInstalled)
|
saveNimbleMeta(pkgDestDir, url, filesInstalled)
|
||||||
|
|
||||||
# Return the paths to the dependencies of this package.
|
# Return the paths to the dependencies of this package.
|
||||||
result.paths.add pkgDestDir
|
result.paths.add pkgDestDir
|
||||||
|
|
@ -515,14 +529,14 @@ proc installFromDir(dir: string, latest: bool, options: TOptions,
|
||||||
|
|
||||||
echo(pkgInfo.name & " installed successfully.")
|
echo(pkgInfo.name & " installed successfully.")
|
||||||
|
|
||||||
proc getBabelTempDir(): string =
|
proc getNimbleTempDir(): string =
|
||||||
## Returns a path to a temporary directory.
|
## Returns a path to a temporary directory.
|
||||||
##
|
##
|
||||||
## The returned path will be the same for the duration of the process but
|
## The returned path will be the same for the duration of the process but
|
||||||
## different for different runs of it. You have to make sure to create it
|
## different for different runs of it. You have to make sure to create it
|
||||||
## first. In release builds the directory will be removed when babel finishes
|
## first. In release builds the directory will be removed when nimble finishes
|
||||||
## its work.
|
## its work.
|
||||||
result = getTempDir() / "babel_"
|
result = getTempDir() / "nimble_"
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
proc GetCurrentProcessId(): int32 {.stdcall, dynlib: "kernel32",
|
proc GetCurrentProcessId(): int32 {.stdcall, dynlib: "kernel32",
|
||||||
importc: "GetCurrentProcessId".}
|
importc: "GetCurrentProcessId".}
|
||||||
|
|
@ -532,14 +546,14 @@ proc getBabelTempDir(): string =
|
||||||
|
|
||||||
proc downloadPkg(url: string, verRange: PVersionRange,
|
proc downloadPkg(url: string, verRange: PVersionRange,
|
||||||
downMethod: TDownloadMethod): string =
|
downMethod: TDownloadMethod): string =
|
||||||
let downloadDir = (getBabelTempDir() / getDownloadDirName(url, verRange))
|
let downloadDir = (getNimbleTempDir() / getDownloadDirName(url, verRange))
|
||||||
createDir(downloadDir)
|
createDir(downloadDir)
|
||||||
echo("Downloading ", url, " into ", downloadDir, " using ", downMethod, "...")
|
echo("Downloading ", url, " into ", downloadDir, " using ", downMethod, "...")
|
||||||
doDownload(url, downloadDir, verRange, downMethod)
|
doDownload(url, downloadDir, verRange, downMethod)
|
||||||
result = downloadDir
|
result = downloadDir
|
||||||
|
|
||||||
proc downloadPkg(pkg: TPackage, verRange: PVersionRange): string =
|
proc downloadPkg(pkg: TPackage, verRange: PVersionRange): string =
|
||||||
let downloadDir = (getBabelTempDir() / getDownloadDirName(pkg, verRange))
|
let downloadDir = (getNimbleTempDir() / getDownloadDirName(pkg, verRange))
|
||||||
let downMethod = pkg.downloadMethod.getDownloadMethod()
|
let downMethod = pkg.downloadMethod.getDownloadMethod()
|
||||||
createDir(downloadDir)
|
createDir(downloadDir)
|
||||||
echo("Downloading ", pkg.name, " into ", downloadDir, " using ", downMethod, "...")
|
echo("Downloading ", pkg.name, " into ", downloadDir, " using ", downMethod, "...")
|
||||||
|
|
@ -553,12 +567,12 @@ proc install(packages: seq[TPkgTuple],
|
||||||
result = installFromDir(getCurrentDir(), false, options, "")
|
result = installFromDir(getCurrentDir(), false, options, "")
|
||||||
else:
|
else:
|
||||||
# If packages.json is not present ask the user if they want to download it.
|
# If packages.json is not present ask the user if they want to download it.
|
||||||
if not existsFile(options.getBabelDir / "packages.json"):
|
if not existsFile(options.getNimbleDir / "packages.json"):
|
||||||
if doPrompt and
|
if doPrompt and
|
||||||
options.prompt("Local packages.json not found, download it from internet?"):
|
options.prompt("Local packages.json not found, download it from internet?"):
|
||||||
update(options)
|
update(options)
|
||||||
else:
|
else:
|
||||||
quit("Please run babel update.", QuitFailure)
|
quit("Please run nimble update.", QuitFailure)
|
||||||
|
|
||||||
# Install each package.
|
# Install each package.
|
||||||
for pv in packages:
|
for pv in packages:
|
||||||
|
|
@ -568,7 +582,7 @@ proc install(packages: seq[TPkgTuple],
|
||||||
result = installFromDir(downloadDir, false, options, pv.name)
|
result = installFromDir(downloadDir, false, options, pv.name)
|
||||||
else:
|
else:
|
||||||
var pkg: TPackage
|
var pkg: TPackage
|
||||||
if getPackage(pv.name, options.getBabelDir() / "packages.json", pkg):
|
if getPackage(pv.name, options.getNimbleDir() / "packages.json", pkg):
|
||||||
let downloadDir = downloadPkg(pkg, pv.ver)
|
let downloadDir = downloadPkg(pkg, pv.ver)
|
||||||
result = installFromDir(downloadDir, false, options, pkg.url)
|
result = installFromDir(downloadDir, false, options, pkg.url)
|
||||||
else:
|
else:
|
||||||
|
|
@ -579,7 +593,7 @@ proc install(packages: seq[TPkgTuple],
|
||||||
update(options)
|
update(options)
|
||||||
result = install(@[pv], options, false)
|
result = install(@[pv], options, false)
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Package not found.")
|
raise newException(ENimble, "Package not found.")
|
||||||
|
|
||||||
proc build(options: TOptions) =
|
proc build(options: TOptions) =
|
||||||
var pkgInfo = getPkgInfo(getCurrentDir())
|
var pkgInfo = getPkgInfo(getCurrentDir())
|
||||||
|
|
@ -592,10 +606,10 @@ proc search(options: TOptions) =
|
||||||
## Searches are done in a case insensitive way making all strings lower case.
|
## Searches are done in a case insensitive way making all strings lower case.
|
||||||
assert options.action.typ == ActionSearch
|
assert options.action.typ == ActionSearch
|
||||||
if options.action.search == @[]:
|
if options.action.search == @[]:
|
||||||
raise newException(EBabel, "Please specify a search string.")
|
raise newException(ENimble, "Please specify a search string.")
|
||||||
if not existsFile(options.getBabelDir() / "packages.json"):
|
if not existsFile(options.getNimbleDir() / "packages.json"):
|
||||||
raise newException(EBabel, "Please run babel update.")
|
raise newException(ENimble, "Please run nimble update.")
|
||||||
let pkgList = getPackageList(options.getBabelDir() / "packages.json")
|
let pkgList = getPackageList(options.getNimbleDir() / "packages.json")
|
||||||
var found = false
|
var found = false
|
||||||
template onFound: stmt =
|
template onFound: stmt =
|
||||||
echoPackage(pkg)
|
echoPackage(pkg)
|
||||||
|
|
@ -619,9 +633,9 @@ proc search(options: TOptions) =
|
||||||
echo("No package found.")
|
echo("No package found.")
|
||||||
|
|
||||||
proc list(options: TOptions) =
|
proc list(options: TOptions) =
|
||||||
if not existsFile(options.getBabelDir() / "packages.json"):
|
if not existsFile(options.getNimbleDir() / "packages.json"):
|
||||||
raise newException(EBabel, "Please run babel update.")
|
raise newException(ENimble, "Please run nimble update.")
|
||||||
let pkgList = getPackageList(options.getBabelDir() / "packages.json")
|
let pkgList = getPackageList(options.getNimbleDir() / "packages.json")
|
||||||
for pkg in pkgList:
|
for pkg in pkgList:
|
||||||
echoPackage(pkg)
|
echoPackage(pkg)
|
||||||
if options.queryVersions:
|
if options.queryVersions:
|
||||||
|
|
@ -647,15 +661,15 @@ proc listPaths(options: TOptions) =
|
||||||
if kind != pcDir or not path.startsWith(options.getPkgsDir / name):
|
if kind != pcDir or not path.startsWith(options.getPkgsDir / name):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
let babelFile = path / name.addFileExt("babel")
|
let nimbleFile = path / name.addFileExt("nimble")
|
||||||
if existsFile(babelFile):
|
if existsFile(nimbleFile):
|
||||||
var pkgInfo = getPkgInfo(path)
|
var pkgInfo = getPkgInfo(path)
|
||||||
var v: VersionAndPath
|
var v: VersionAndPath
|
||||||
v.version = newVersion(pkgInfo.version)
|
v.version = newVersion(pkgInfo.version)
|
||||||
v.path = options.getPkgsDir / (pkgInfo.name & '-' & pkgInfo.version)
|
v.path = options.getPkgsDir / (pkgInfo.name & '-' & pkgInfo.version)
|
||||||
installed.add(v)
|
installed.add(v)
|
||||||
else:
|
else:
|
||||||
echo "Warning: No .babel file found for ", path
|
echo "Warning: No .nimble file found for ", path
|
||||||
|
|
||||||
if installed.len > 0:
|
if installed.len > 0:
|
||||||
sort(installed, system.cmp[VersionAndPath], Descending)
|
sort(installed, system.cmp[VersionAndPath], Descending)
|
||||||
|
|
@ -664,36 +678,36 @@ proc listPaths(options: TOptions) =
|
||||||
echo "Warning: Package '" & name & "' not installed"
|
echo "Warning: Package '" & name & "' not installed"
|
||||||
errors += 1
|
errors += 1
|
||||||
if errors > 0:
|
if errors > 0:
|
||||||
raise newException(EBabel, "At least one of the specified packages was not found")
|
raise newException(ENimble, "At least one of the specified packages was not found")
|
||||||
|
|
||||||
proc init(options: TOptions) =
|
proc init(options: TOptions) =
|
||||||
echo("Initializing new Babel project!")
|
echo("Initializing new Nimble project!")
|
||||||
var
|
var
|
||||||
pkgName, fName: string = ""
|
pkgName, fName: string = ""
|
||||||
outFile: TFile
|
outFile: TFile
|
||||||
|
|
||||||
if (options.action.projName != ""):
|
if (options.action.projName != ""):
|
||||||
pkgName = options.action.projName
|
pkgName = options.action.projName
|
||||||
fName = pkgName & ".babel"
|
fName = pkgName & ".nimble"
|
||||||
if ( existsFile( os.getCurrentDir() / fName ) ):
|
if ( existsFile( os.getCurrentDir() / fName ) ):
|
||||||
raise newException(EBabel, "Already have a babel file.")
|
raise newException(ENimble, "Already have a nimble file.")
|
||||||
else:
|
else:
|
||||||
echo("Enter a project name for this (blank to use working directory), Ctrl-C to abort:")
|
echo("Enter a project name for this (blank to use working directory), Ctrl-C to abort:")
|
||||||
pkgName = readline(stdin)
|
pkgName = readline(stdin)
|
||||||
if (pkgName == ""):
|
if (pkgName == ""):
|
||||||
pkgName = os.getCurrentDir().splitPath.tail
|
pkgName = os.getCurrentDir().splitPath.tail
|
||||||
if (pkgName == ""):
|
if (pkgName == ""):
|
||||||
raise newException(EBabel, "Could not get default file path.")
|
raise newException(ENimble, "Could not get default file path.")
|
||||||
fName = pkgName & ".babel"
|
fName = pkgName & ".nimble"
|
||||||
|
|
||||||
# Now need to write out .babel file with projName and other details
|
# Now need to write out .nimble file with projName and other details
|
||||||
|
|
||||||
if (not existsFile(os.getCurrentDir() / fName) and open(f=outFile, filename = fName, mode = fmWrite)):
|
if (not existsFile(os.getCurrentDir() / fName) and open(f=outFile, filename = fName, mode = fmWrite)):
|
||||||
outFile.writeln("[Package]")
|
outFile.writeln("[Package]")
|
||||||
outFile.writeln("name = \"" & pkgName & "\"")
|
outFile.writeln("name = \"" & pkgName & "\"")
|
||||||
outFile.writeln("version = \"0.01\"")
|
outFile.writeln("version = \"0.01\"")
|
||||||
outFile.writeln("author = \"Anonymous\"")
|
outFile.writeln("author = \"Anonymous\"")
|
||||||
outFile.writeln("description = \"New Babel project for Nimrod\"")
|
outFile.writeln("description = \"New Nimble project for Nimrod\"")
|
||||||
outFile.writeln("license = \"BSD\"")
|
outFile.writeln("license = \"BSD\"")
|
||||||
outFile.writeln("")
|
outFile.writeln("")
|
||||||
outFile.writeln("[Deps]")
|
outFile.writeln("[Deps]")
|
||||||
|
|
@ -701,7 +715,7 @@ proc init(options: TOptions) =
|
||||||
close(outFile)
|
close(outFile)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Unable to open file " & fName & " for writing: " & osErrorMsg())
|
raise newException(ENimble, "Unable to open file " & fName & " for writing: " & osErrorMsg())
|
||||||
|
|
||||||
proc uninstall(options: TOptions) =
|
proc uninstall(options: TOptions) =
|
||||||
var pkgsToDelete: seq[TPackageInfo] = @[]
|
var pkgsToDelete: seq[TPackageInfo] = @[]
|
||||||
|
|
@ -711,14 +725,14 @@ proc uninstall(options: TOptions) =
|
||||||
let installedPkgs = getInstalledPkgs(options.getPkgsDir())
|
let installedPkgs = getInstalledPkgs(options.getPkgsDir())
|
||||||
var pkgList = findAllPkgs(installedPkgs, pkgTup)
|
var pkgList = findAllPkgs(installedPkgs, pkgTup)
|
||||||
if pkgList.len == 0:
|
if pkgList.len == 0:
|
||||||
raise newException(EBabel, "Package not found")
|
raise newException(ENimble, "Package not found")
|
||||||
|
|
||||||
echo("Checking reverse dependencies...")
|
echo("Checking reverse dependencies...")
|
||||||
var errors: seq[string] = @[]
|
var errors: seq[string] = @[]
|
||||||
for pkg in pkgList:
|
for pkg in pkgList:
|
||||||
# Check whether any packages depend on the ones the user is trying to
|
# Check whether any packages depend on the ones the user is trying to
|
||||||
# uninstall.
|
# uninstall.
|
||||||
let thisPkgsDep = options.babelData["reverseDeps"]{pkg.name}{pkg.version}
|
let thisPkgsDep = options.nimbleData["reverseDeps"]{pkg.name}{pkg.version}
|
||||||
if not thisPkgsDep.isNil:
|
if not thisPkgsDep.isNil:
|
||||||
var reason = ""
|
var reason = ""
|
||||||
if thisPkgsDep.len == 1:
|
if thisPkgsDep.len == 1:
|
||||||
|
|
@ -737,7 +751,7 @@ proc uninstall(options: TOptions) =
|
||||||
pkgsToDelete.add pkg
|
pkgsToDelete.add pkg
|
||||||
|
|
||||||
if pkgsToDelete.len == 0:
|
if pkgsToDelete.len == 0:
|
||||||
raise newException(EBabel, "\n " & errors.join("\n "))
|
raise newException(ENimble, "\n " & errors.join("\n "))
|
||||||
|
|
||||||
var pkgNames = ""
|
var pkgNames = ""
|
||||||
for i in 0 .. <pkgsToDelete.len:
|
for i in 0 .. <pkgsToDelete.len:
|
||||||
|
|
@ -757,8 +771,8 @@ proc uninstall(options: TOptions) =
|
||||||
echo("Removed ", pkg.name, " (", $pkg.version, ")")
|
echo("Removed ", pkg.name, " (", $pkg.version, ")")
|
||||||
|
|
||||||
proc doAction(options: TOptions) =
|
proc doAction(options: TOptions) =
|
||||||
if not existsDir(options.getBabelDir()):
|
if not existsDir(options.getNimbleDir()):
|
||||||
createDir(options.getBabelDir())
|
createDir(options.getNimbleDir())
|
||||||
if not existsDir(options.getPkgsDir):
|
if not existsDir(options.getPkgsDir):
|
||||||
createDir(options.getPkgsDir)
|
createDir(options.getPkgsDir)
|
||||||
|
|
||||||
|
|
@ -783,12 +797,14 @@ proc doAction(options: TOptions) =
|
||||||
assert false
|
assert false
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
|
# TODO: Check for .babel dir and rename everything to nimble.
|
||||||
|
|
||||||
when defined(release):
|
when defined(release):
|
||||||
try:
|
try:
|
||||||
parseCmdLine().doAction()
|
parseCmdLine().doAction()
|
||||||
except EBabel:
|
except ENimble:
|
||||||
quit("FAILURE: " & getCurrentExceptionMsg())
|
quit("FAILURE: " & getCurrentExceptionMsg())
|
||||||
finally:
|
finally:
|
||||||
removeDir(getBabelTempDir())
|
removeDir(getNimbleTempDir())
|
||||||
else:
|
else:
|
||||||
parseCmdLine().doAction()
|
parseCmdLine().doAction()
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
# Copyright (C) Dominik Picheta. All rights reserved.
|
|
||||||
# BSD License. Look at license.txt for more info.
|
|
||||||
|
|
||||||
## This module contains additional code from the development version of
|
|
||||||
## Nimrod's standard library. These procs are required to be able to compile
|
|
||||||
## against the last stable release 0.9.4. Once 0.9.6 is release these procs
|
|
||||||
## will disappear.
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
when not (NimrodPatch >= 5):
|
|
||||||
when not defined(`{}`):
|
|
||||||
proc `{}`*(node: PJsonNode, key: string): PJsonNode =
|
|
||||||
## Transverses the node and gets the given value. If any of the
|
|
||||||
## names does not exist, returns nil
|
|
||||||
result = node
|
|
||||||
if isNil(node): return nil
|
|
||||||
result = result[key]
|
|
||||||
|
|
||||||
when not defined(`{}=`):
|
|
||||||
proc `{}=`*(node: PJsonNode, names: varargs[string], value: PJsonNode) =
|
|
||||||
## Transverses the node and tries to set the value at the given location
|
|
||||||
## to `value` If any of the names are missing, they are added
|
|
||||||
var node = node
|
|
||||||
for i in 0..(names.len-2):
|
|
||||||
if isNil(node[names[i]]):
|
|
||||||
node[names[i]] = newJObject()
|
|
||||||
node = node[names[i]]
|
|
||||||
node[names[names.len-1]] = value
|
|
||||||
29
src/nimblepkg/compat.nim
Normal file
29
src/nimblepkg/compat.nim
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright (C) Dominik Picheta. All rights reserved.
|
||||||
|
# BSD License. Look at license.txt for more info.
|
||||||
|
|
||||||
|
## This module contains additional code from the development version of
|
||||||
|
## Nimrod's standard library. These procs are required to be able to compile
|
||||||
|
## against the last stable release 0.9.4. Once 0.9.6 is release these procs
|
||||||
|
## will disappear.
|
||||||
|
|
||||||
|
import json
|
||||||
|
when false:
|
||||||
|
when not (NimrodPatch >= 5):
|
||||||
|
when not defined(`{}`):
|
||||||
|
proc `{}`*(node: PJsonNode, key: string): PJsonNode =
|
||||||
|
## Transverses the node and gets the given value. If any of the
|
||||||
|
## names does not exist, returns nil
|
||||||
|
result = node
|
||||||
|
if isNil(node): return nil
|
||||||
|
result = result[key]
|
||||||
|
|
||||||
|
when not defined(`{}=`):
|
||||||
|
proc `{}=`*(node: PJsonNode, names: varargs[string], value: PJsonNode) =
|
||||||
|
## Transverses the node and tries to set the value at the given location
|
||||||
|
## to `value` If any of the names are missing, they are added
|
||||||
|
var node = node
|
||||||
|
for i in 0..(names.len-2):
|
||||||
|
if isNil(node[names[i]]):
|
||||||
|
node[names[i]] = newJObject()
|
||||||
|
node = node[names[i]]
|
||||||
|
node[names[names.len-1]] = value
|
||||||
|
|
@ -6,16 +6,23 @@ import tools
|
||||||
|
|
||||||
type
|
type
|
||||||
TConfig* = object
|
TConfig* = object
|
||||||
babelDir*: string
|
nimbleDir*: string
|
||||||
|
|
||||||
proc initConfig(): TConfig =
|
proc initConfig(): TConfig =
|
||||||
result.babelDir = getHomeDir() / ".babel"
|
result.nimbleDir = getHomeDir() / ".nimble"
|
||||||
|
|
||||||
proc parseConfig*(): TConfig =
|
proc parseConfig*(): TConfig =
|
||||||
result = initConfig()
|
result = initConfig()
|
||||||
let confFile = getConfigDir() / "babel" / "babel.ini"
|
var confFile = getConfigDir() / "nimble" / "nimble.ini"
|
||||||
|
|
||||||
var f = newFileStream(confFile, fmRead)
|
var f = newFileStream(confFile, fmRead)
|
||||||
|
if f == nil:
|
||||||
|
# Try the old deprecated babel.ini
|
||||||
|
confFile = getConfigDir() / "babel" / "babel.ini"
|
||||||
|
f = newFileStream(confFile, fmRead)
|
||||||
|
if f != nil:
|
||||||
|
echo("[Warning] Using deprecated config file at ", confFile)
|
||||||
|
|
||||||
if f != nil:
|
if f != nil:
|
||||||
echo("Reading from config file at ", confFile)
|
echo("Reading from config file at ", confFile)
|
||||||
var p: TCfgParser
|
var p: TCfgParser
|
||||||
|
|
@ -28,11 +35,11 @@ proc parseConfig*(): TConfig =
|
||||||
of cfgSectionStart: discard
|
of cfgSectionStart: discard
|
||||||
of cfgKeyValuePair, cfgOption:
|
of cfgKeyValuePair, cfgOption:
|
||||||
case e.key.normalize
|
case e.key.normalize
|
||||||
of "babeldir":
|
of "nimbledir":
|
||||||
result.babelDir = e.value
|
result.nimbleDir = e.value
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Unable to parse config file:" &
|
raise newException(ENimble, "Unable to parse config file:" &
|
||||||
" Unknown key: " & e.key)
|
" Unknown key: " & e.key)
|
||||||
of cfgError:
|
of cfgError:
|
||||||
raise newException(EBabel, "Unable to parse config file: " & e.msg)
|
raise newException(ENimble, "Unable to parse config file: " & e.msg)
|
||||||
close(p)
|
close(p)
|
||||||
|
|
@ -111,7 +111,7 @@ proc getDownloadMethod*(meth: string): TDownloadMethod =
|
||||||
of "git": return TDownloadMethod.Git
|
of "git": return TDownloadMethod.Git
|
||||||
of "hg", "mercurial": return TDownloadMethod.Hg
|
of "hg", "mercurial": return TDownloadMethod.Hg
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Invalid download method: " & meth)
|
raise newException(ENimble, "Invalid download method: " & meth)
|
||||||
|
|
||||||
proc getHeadName*(meth: TDownloadMethod): string =
|
proc getHeadName*(meth: TDownloadMethod): string =
|
||||||
## Returns the name of the download method specific head. i.e. for git
|
## Returns the name of the download method specific head. i.e. for git
|
||||||
|
|
@ -127,7 +127,7 @@ proc checkUrlType*(url: string): TDownloadMethod =
|
||||||
elif doCmdEx("hg identify " & url).exitCode == QuitSuccess:
|
elif doCmdEx("hg identify " & url).exitCode == QuitSuccess:
|
||||||
return TDownloadMethod.Hg
|
return TDownloadMethod.Hg
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Unable to identify url.")
|
raise newException(ENimble, "Unable to identify url.")
|
||||||
|
|
||||||
proc isURL*(name: string): bool =
|
proc isURL*(name: string): bool =
|
||||||
name.startsWith(peg" @'://' ")
|
name.startsWith(peg" @'://' ")
|
||||||
|
|
@ -143,7 +143,7 @@ proc doDownload*(url: string, downloadDir: string, verRange: PVersionRange,
|
||||||
|
|
||||||
# If no tagged versions satisfy our range latest.tag will be "".
|
# If no tagged versions satisfy our range latest.tag will be "".
|
||||||
# We still clone in that scenario because we want to try HEAD in that case.
|
# We still clone in that scenario because we want to try HEAD in that case.
|
||||||
# https://github.com/nimrod-code/babel/issues/22
|
# https://github.com/nimrod-code/nimble/issues/22
|
||||||
meth
|
meth
|
||||||
|
|
||||||
proc verifyClone() =
|
proc verifyClone() =
|
||||||
|
|
@ -151,7 +151,7 @@ proc doDownload*(url: string, downloadDir: string, verRange: PVersionRange,
|
||||||
## version range.
|
## version range.
|
||||||
let pkginfo = getPkgInfo(downloadDir)
|
let pkginfo = getPkgInfo(downloadDir)
|
||||||
if pkginfo.version.newVersion notin verRange:
|
if pkginfo.version.newVersion notin verRange:
|
||||||
raise newException(EBabel,
|
raise newException(ENimble,
|
||||||
"Downloaded package's version does not satisfy requested version " &
|
"Downloaded package's version does not satisfy requested version " &
|
||||||
"range: wanted $1 got $2." %
|
"range: wanted $1 got $2." %
|
||||||
[$verRange, $pkginfo.version])
|
[$verRange, $pkginfo.version])
|
||||||
|
|
@ -7,7 +7,7 @@ type
|
||||||
TPkgTuple* = tuple[name: string, ver: PVersionRange]
|
TPkgTuple* = tuple[name: string, ver: PVersionRange]
|
||||||
|
|
||||||
TPackageInfo* = object
|
TPackageInfo* = object
|
||||||
mypath*: string ## The path of this .babel file
|
mypath*: string ## The path of this .nimble file
|
||||||
name*: string
|
name*: string
|
||||||
version*: string
|
version*: string
|
||||||
author*: string
|
author*: string
|
||||||
|
|
@ -60,25 +60,25 @@ proc initPackageInfo(): TPackageInfo =
|
||||||
|
|
||||||
proc validatePackageInfo(pkgInfo: TPackageInfo, path: string) =
|
proc validatePackageInfo(pkgInfo: TPackageInfo, path: string) =
|
||||||
if pkgInfo.name == "":
|
if pkgInfo.name == "":
|
||||||
raise newException(EBabel, "Incorrect .babel file: " & path &
|
raise newException(ENimble, "Incorrect .nimble file: " & path &
|
||||||
" does not contain a name field.")
|
" does not contain a name field.")
|
||||||
if pkgInfo.version == "":
|
if pkgInfo.version == "":
|
||||||
raise newException(EBabel, "Incorrect .babel file: " & path &
|
raise newException(ENimble, "Incorrect .nimble file: " & path &
|
||||||
" does not contain a version field.")
|
" does not contain a version field.")
|
||||||
if pkgInfo.author == "":
|
if pkgInfo.author == "":
|
||||||
raise newException(EBabel, "Incorrect .babel file: " & path &
|
raise newException(ENimble, "Incorrect .nimble file: " & path &
|
||||||
" does not contain an author field.")
|
" does not contain an author field.")
|
||||||
if pkgInfo.description == "":
|
if pkgInfo.description == "":
|
||||||
raise newException(EBabel, "Incorrect .babel file: " & path &
|
raise newException(ENimble, "Incorrect .nimble file: " & path &
|
||||||
" does not contain a description field.")
|
" does not contain a description field.")
|
||||||
if pkgInfo.license == "":
|
if pkgInfo.license == "":
|
||||||
raise newException(EBabel, "Incorrect .babel file: " & path &
|
raise newException(ENimble, "Incorrect .nimble file: " & path &
|
||||||
" does not contain a license field.")
|
" does not contain a license field.")
|
||||||
if pkgInfo.backend notin ["c", "cc", "objc", "cpp", "js"]:
|
if pkgInfo.backend notin ["c", "cc", "objc", "cpp", "js"]:
|
||||||
raise newException(EBabel, "'" & pkgInfo.backend & "' is an invalid backend.")
|
raise newException(ENimble, "'" & pkgInfo.backend & "' is an invalid backend.")
|
||||||
for c in pkgInfo.version:
|
for c in pkgInfo.version:
|
||||||
if c notin ({'.'} + Digits):
|
if c notin ({'.'} + Digits):
|
||||||
raise newException(EBabel,
|
raise newException(ENimble,
|
||||||
"Version may only consist of numbers and the '.' character " &
|
"Version may only consist of numbers and the '.' character " &
|
||||||
"but found '" & c & "'.")
|
"but found '" & c & "'.")
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ proc parseRequires(req: string): TPkgTuple =
|
||||||
result.name = req.strip
|
result.name = req.strip
|
||||||
result.ver = PVersionRange(kind: verAny)
|
result.ver = PVersionRange(kind: verAny)
|
||||||
except EParseVersion:
|
except EParseVersion:
|
||||||
raise newException(EBabel, "Unable to parse dependency version range: " &
|
raise newException(ENimble, "Unable to parse dependency version range: " &
|
||||||
getCurrentExceptionMsg())
|
getCurrentExceptionMsg())
|
||||||
|
|
||||||
proc multiSplit(s: string): seq[string] =
|
proc multiSplit(s: string): seq[string] =
|
||||||
|
|
@ -160,18 +160,18 @@ proc readPackageInfo*(path: string): TPackageInfo =
|
||||||
case result.backend.normalize
|
case result.backend.normalize
|
||||||
of "javascript": result.backend = "js"
|
of "javascript": result.backend = "js"
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Invalid field: " & ev.key)
|
raise newException(ENimble, "Invalid field: " & ev.key)
|
||||||
of "deps", "dependencies":
|
of "deps", "dependencies":
|
||||||
case ev.key.normalize
|
case ev.key.normalize
|
||||||
of "requires":
|
of "requires":
|
||||||
for v in ev.value.multiSplit:
|
for v in ev.value.multiSplit:
|
||||||
result.requires.add(parseRequires(v.strip))
|
result.requires.add(parseRequires(v.strip))
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Invalid field: " & ev.key)
|
raise newException(ENimble, "Invalid field: " & ev.key)
|
||||||
else: raise newException(EBabel, "Invalid section: " & currentSection)
|
else: raise newException(ENimble, "Invalid section: " & currentSection)
|
||||||
of cfgOption: raise newException(EBabel, "Invalid package info, should not contain --" & ev.value)
|
of cfgOption: raise newException(ENimble, "Invalid package info, should not contain --" & ev.value)
|
||||||
of cfgError:
|
of cfgError:
|
||||||
raise newException(EBabel, "Error parsing .babel file: " & ev.msg)
|
raise newException(ENimble, "Error parsing .nimble file: " & ev.msg)
|
||||||
close(p)
|
close(p)
|
||||||
else:
|
else:
|
||||||
raise newException(EInvalidValue, "Cannot open package info: " & path)
|
raise newException(EInvalidValue, "Cannot open package info: " & path)
|
||||||
|
|
@ -187,7 +187,7 @@ proc optionalField(obj: PJsonNode, name: string, default = ""): string =
|
||||||
if obj[name].kind == JString:
|
if obj[name].kind == JString:
|
||||||
return obj[name].str
|
return obj[name].str
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Corrupted packages.json file. " & name & " field is of unexpected type.")
|
raise newException(ENimble, "Corrupted packages.json file. " & name & " field is of unexpected type.")
|
||||||
else: return default
|
else: return default
|
||||||
|
|
||||||
proc requiredField(obj: PJsonNode, name: string): string =
|
proc requiredField(obj: PJsonNode, name: string): string =
|
||||||
|
|
@ -196,7 +196,7 @@ proc requiredField(obj: PJsonNode, name: string): string =
|
||||||
## Aborts execution if the field does not exist or is of invalid json type.
|
## Aborts execution if the field does not exist or is of invalid json type.
|
||||||
result = optionalField(obj, name, nil)
|
result = optionalField(obj, name, nil)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
raise newException(EBabel,
|
raise newException(ENimble,
|
||||||
"Package in packages.json file does not contain a " & name & " field.")
|
"Package in packages.json file does not contain a " & name & " field.")
|
||||||
|
|
||||||
proc fromJson(obj: PJSonNode): TPackage =
|
proc fromJson(obj: PJSonNode): TPackage =
|
||||||
|
|
@ -216,14 +216,18 @@ proc fromJson(obj: PJSonNode): TPackage =
|
||||||
result.web = obj.optionalField("web")
|
result.web = obj.optionalField("web")
|
||||||
|
|
||||||
proc readMetadata*(path: string): TMetadata =
|
proc readMetadata*(path: string): TMetadata =
|
||||||
## Reads the metadata present in ``~/.babel/pkgs/pkg-0.1/babelmeta.json``
|
## Reads the metadata present in ``~/.nimble/pkgs/pkg-0.1/nimblemeta.json``
|
||||||
let bmeta = path / "babelmeta.json"
|
var bmeta = path / "nimblemeta.json"
|
||||||
|
if not existsFile(bmeta):
|
||||||
|
bmeta = path / "babelmeta.json"
|
||||||
|
if existsFile(bmeta):
|
||||||
|
echo("WARNING: using deprecated babelmeta.json file in " & path)
|
||||||
if not existsFile(bmeta):
|
if not existsFile(bmeta):
|
||||||
result.url = ""
|
result.url = ""
|
||||||
echo("WARNING: No babelmeta.json file found in " & path)
|
echo("WARNING: No nimblemeta.json file found in " & path)
|
||||||
return
|
return
|
||||||
# TODO: Make this an error.
|
# TODO: Make this an error.
|
||||||
let cont = readFile(path / "babelmeta.json")
|
let cont = readFile(bmeta)
|
||||||
let jsonmeta = parseJson(cont)
|
let jsonmeta = parseJson(cont)
|
||||||
result.url = jsonmeta["url"].str
|
result.url = jsonmeta["url"].str
|
||||||
|
|
||||||
|
|
@ -247,35 +251,35 @@ proc getPackageList*(packagesPath: string): seq[TPackage] =
|
||||||
let pkg: TPackage = p.fromJson()
|
let pkg: TPackage = p.fromJson()
|
||||||
result.add(pkg)
|
result.add(pkg)
|
||||||
|
|
||||||
proc findBabelFile*(dir: string): string =
|
proc findNimbleFile*(dir: string): string =
|
||||||
result = ""
|
result = ""
|
||||||
for kind, path in walkDir(dir):
|
for kind, path in walkDir(dir):
|
||||||
if kind == pcFile and path.splitFile.ext == ".babel":
|
if kind == pcFile and path.splitFile.ext in [".babel", ".nimble"]:
|
||||||
if result != "":
|
if result != "":
|
||||||
raise newException(EBabel, "Only one .babel file should be present in " & dir)
|
raise newException(ENimble, "Only one .nimble file should be present in " & dir)
|
||||||
result = path
|
result = path
|
||||||
|
|
||||||
proc getPkgInfo*(dir: string): TPackageInfo =
|
proc getPkgInfo*(dir: string): TPackageInfo =
|
||||||
## Find the .babel file in ``dir`` and parses it, returning a TPackageInfo.
|
## Find the .nimble file in ``dir`` and parses it, returning a TPackageInfo.
|
||||||
let babelFile = findBabelFile(dir)
|
let nimbleFile = findNimbleFile(dir)
|
||||||
if babelFile == "":
|
if nimbleFile == "":
|
||||||
raise newException(EBabel, "Specified directory does not contain a .babel file.")
|
raise newException(ENimble, "Specified directory does not contain a .nimble file.")
|
||||||
result = readPackageInfo(babelFile)
|
result = readPackageInfo(nimbleFile)
|
||||||
|
|
||||||
proc getInstalledPkgs*(libsDir: string): seq[tuple[pkginfo: TPackageInfo, meta: TMetaData]] =
|
proc getInstalledPkgs*(libsDir: string): seq[tuple[pkginfo: TPackageInfo, meta: TMetaData]] =
|
||||||
## Gets a list of installed packages.
|
## Gets a list of installed packages.
|
||||||
##
|
##
|
||||||
## ``libsDir`` is in most cases: ~/.babel/pkgs/
|
## ``libsDir`` is in most cases: ~/.nimble/pkgs/
|
||||||
result = @[]
|
result = @[]
|
||||||
for kind, path in walkDir(libsDir):
|
for kind, path in walkDir(libsDir):
|
||||||
if kind == pcDir:
|
if kind == pcDir:
|
||||||
let babelFile = findBabelFile(path)
|
let nimbleFile = findNimbleFile(path)
|
||||||
if babelFile != "":
|
if nimbleFile != "":
|
||||||
let meta = readMetadata(path)
|
let meta = readMetadata(path)
|
||||||
result.add((readPackageInfo(babelFile), meta))
|
result.add((readPackageInfo(nimbleFile), meta))
|
||||||
else:
|
else:
|
||||||
# TODO: Abstract logging.
|
# TODO: Abstract logging.
|
||||||
echo("WARNING: No .babel file found for ", path)
|
echo("WARNING: No .nimble file found for ", path)
|
||||||
|
|
||||||
proc findPkg*(pkglist: seq[tuple[pkginfo: TPackageInfo, meta: TMetaData]],
|
proc findPkg*(pkglist: seq[tuple[pkginfo: TPackageInfo, meta: TMetaData]],
|
||||||
dep: TPkgTuple,
|
dep: TPkgTuple,
|
||||||
|
|
@ -315,7 +319,7 @@ proc getRealDir*(pkgInfo: TPackageInfo): string =
|
||||||
result = pkgInfo.mypath.splitFile.dir
|
result = pkgInfo.mypath.splitFile.dir
|
||||||
|
|
||||||
proc getNameVersion*(pkgpath: string): tuple[name, version: string] =
|
proc getNameVersion*(pkgpath: string): tuple[name, version: string] =
|
||||||
## Splits ``pkgpath`` in the format ``/home/user/.babel/pkgs/package-0.1``
|
## Splits ``pkgpath`` in the format ``/home/user/.nimble/pkgs/package-0.1``
|
||||||
## into ``(packagea, 0.1)``
|
## into ``(packagea, 0.1)``
|
||||||
result.name = ""
|
result.name = ""
|
||||||
result.version = ""
|
result.version = ""
|
||||||
|
|
@ -347,5 +351,5 @@ proc getDownloadDirName*(pkg: TPackage, verRange: PVersionRange): string =
|
||||||
result.add verSimple
|
result.add verSimple
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
doAssert getNameVersion("/home/user/.babel/libs/packagea-0.1") == ("packagea", "0.1")
|
doAssert getNameVersion("/home/user/.nimble/libs/packagea-0.1") == ("packagea", "0.1")
|
||||||
doAssert getNameVersion("/home/user/.babel/libs/package-a-0.1") == ("package-a", "0.1")
|
doAssert getNameVersion("/home/user/.nimble/libs/package-a-0.1") == ("package-a", "0.1")
|
||||||
|
|
@ -6,21 +6,21 @@ import osproc, pegs, strutils, os, parseurl, sets, json
|
||||||
import version, packageinfo
|
import version, packageinfo
|
||||||
|
|
||||||
type
|
type
|
||||||
EBabel* = object of EBase
|
ENimble* = object of EBase
|
||||||
|
|
||||||
proc doCmd*(cmd: string) =
|
proc doCmd*(cmd: string) =
|
||||||
let bin = cmd.split(' ')[0]
|
let bin = cmd.split(' ')[0]
|
||||||
if findExe(bin) == "":
|
if findExe(bin) == "":
|
||||||
raise newException(EBabel, "'" & bin & "' not in PATH.")
|
raise newException(ENimble, "'" & bin & "' not in PATH.")
|
||||||
|
|
||||||
let exitCode = execCmd(cmd)
|
let exitCode = execCmd(cmd)
|
||||||
if exitCode != QuitSuccess:
|
if exitCode != QuitSuccess:
|
||||||
raise newException(EBabel, "Execution failed with exit code " & $exitCode)
|
raise newException(ENimble, "Execution failed with exit code " & $exitCode)
|
||||||
|
|
||||||
proc doCmdEx*(cmd: string): tuple[output: TaintedString, exitCode: int] =
|
proc doCmdEx*(cmd: string): tuple[output: TaintedString, exitCode: int] =
|
||||||
let bin = cmd.split(' ')[0]
|
let bin = cmd.split(' ')[0]
|
||||||
if findExe(bin) == "":
|
if findExe(bin) == "":
|
||||||
raise newException(EBabel, "'" & bin & "' not in PATH.")
|
raise newException(ENimble, "'" & bin & "' not in PATH.")
|
||||||
return execCmdEx(cmd)
|
return execCmdEx(cmd)
|
||||||
|
|
||||||
template cd*(dir: string, body: stmt) =
|
template cd*(dir: string, body: stmt) =
|
||||||
BIN
src/nimblepkg/version
Executable file
BIN
src/nimblepkg/version
Executable file
Binary file not shown.
|
|
@ -280,5 +280,4 @@ when isMainModule:
|
||||||
doAssert newSpecial("ab26sgdt362") in sp
|
doAssert newSpecial("ab26sgdt362") in sp
|
||||||
doAssert newSpecial("ab26saggdt362") notin sp
|
doAssert newSpecial("ab26saggdt362") notin sp
|
||||||
|
|
||||||
|
|
||||||
echo("Everything works!")
|
echo("Everything works!")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue