Refactored code so that it doesn't use a global variable.
This commit is contained in:
parent
3b619f1071
commit
e52087f84d
1 changed files with 56 additions and 53 deletions
109
babel.nim
109
babel.nim
|
|
@ -6,6 +6,10 @@ import httpclient, parseopt, os, strutils, osproc, pegs, tables, parseutils
|
||||||
import packageinfo, version, common, tools, download, algorithm
|
import packageinfo, version, common, tools, download, algorithm
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TOptions = object
|
||||||
|
forcePrompts: TForcePrompt
|
||||||
|
action: TAction
|
||||||
|
|
||||||
TActionType = enum
|
TActionType = enum
|
||||||
ActionNil, ActionUpdate, ActionInstall, ActionSearch, ActionList,
|
ActionNil, ActionUpdate, ActionInstall, ActionSearch, ActionList,
|
||||||
ActionBuild, ActionPath
|
ActionBuild, ActionPath
|
||||||
|
|
@ -24,8 +28,6 @@ type
|
||||||
TForcePrompt = enum
|
TForcePrompt = enum
|
||||||
DontForcePrompt, ForcePromptYes, ForcePromptNo
|
DontForcePrompt, ForcePromptYes, ForcePromptNo
|
||||||
|
|
||||||
var forcePrompts = DontForcePrompt
|
|
||||||
|
|
||||||
const
|
const
|
||||||
help = """
|
help = """
|
||||||
Usage: babel COMMAND [opts]
|
Usage: babel COMMAND [opts]
|
||||||
|
|
@ -55,58 +57,58 @@ proc writeVersion() =
|
||||||
echo("babel v$# compiled at $# $#" % [babelVersion, compileDate, compileTime])
|
echo("babel v$# compiled at $# $#" % [babelVersion, compileDate, compileTime])
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
|
|
||||||
proc parseCmdLine(): TAction =
|
proc parseCmdLine(): TOptions =
|
||||||
result.typ = ActionNil
|
result.action.typ = ActionNil
|
||||||
for kind, key, val in getOpt():
|
for kind, key, val in getOpt():
|
||||||
case kind
|
case kind
|
||||||
of cmdArgument:
|
of cmdArgument:
|
||||||
if result.typ == ActionNil:
|
if result.action.typ == ActionNil:
|
||||||
case key
|
case key
|
||||||
of "install":
|
of "install":
|
||||||
result.typ = ActionInstall
|
result.action.typ = ActionInstall
|
||||||
result.optionalName = @[]
|
result.action.optionalName = @[]
|
||||||
of "build":
|
of "build":
|
||||||
result.typ = ActionBuild
|
result.action.typ = ActionBuild
|
||||||
of "update":
|
of "update":
|
||||||
result.typ = ActionUpdate
|
result.action.typ = ActionUpdate
|
||||||
result.optionalURL = ""
|
result.action.optionalURL = ""
|
||||||
of "search":
|
of "search":
|
||||||
result.typ = ActionSearch
|
result.action.typ = ActionSearch
|
||||||
result.search = @[]
|
result.action.search = @[]
|
||||||
of "list":
|
of "list":
|
||||||
result.typ = ActionList
|
result.action.typ = ActionList
|
||||||
of "path":
|
of "path":
|
||||||
result.typ = ActionPath
|
result.action.typ = ActionPath
|
||||||
result.optionalName = @[]
|
result.action.optionalName = @[]
|
||||||
else: writeHelp()
|
else: writeHelp()
|
||||||
else:
|
else:
|
||||||
case result.typ
|
case result.action.typ
|
||||||
of ActionNil:
|
of ActionNil:
|
||||||
assert false
|
assert false
|
||||||
of ActionInstall, ActionPath:
|
of ActionInstall, ActionPath:
|
||||||
result.optionalName.add(key)
|
result.action.optionalName.add(key)
|
||||||
of ActionUpdate:
|
of ActionUpdate:
|
||||||
result.optionalURL = key
|
result.action.optionalURL = key
|
||||||
of ActionSearch:
|
of ActionSearch:
|
||||||
result.search.add(key)
|
result.action.search.add(key)
|
||||||
of ActionList, ActionBuild:
|
of ActionList, ActionBuild:
|
||||||
writeHelp()
|
writeHelp()
|
||||||
of cmdLongOption, cmdShortOption:
|
of cmdLongOption, cmdShortOption:
|
||||||
case key
|
case key
|
||||||
of "help", "h": writeHelp()
|
of "help", "h": writeHelp()
|
||||||
of "version", "v": writeVersion()
|
of "version", "v": writeVersion()
|
||||||
of "accept", "y": forcePrompts = ForcePromptYes
|
of "accept", "y": result.forcePrompts = ForcePromptYes
|
||||||
of "reject", "n": forcePrompts = ForcePromptNo
|
of "reject", "n": result.forcePrompts = ForcePromptNo
|
||||||
of cmdEnd: assert(false) # cannot happen
|
of cmdEnd: assert(false) # cannot happen
|
||||||
if result.typ == ActionNil:
|
if result.action.typ == ActionNil:
|
||||||
writeHelp()
|
writeHelp()
|
||||||
|
|
||||||
proc prompt(question: string): bool =
|
proc prompt(options: TOptions, question: string): bool =
|
||||||
## Asks an interactive question and returns the result.
|
## Asks an interactive question and returns the result.
|
||||||
##
|
##
|
||||||
## The proc will return immediately without asking the user if the global
|
## The proc will return immediately without asking the user if the global
|
||||||
## forcePrompts has a value different than DontForcePrompt.
|
## forcePrompts has a value different than DontForcePrompt.
|
||||||
case forcePrompts
|
case options.forcePrompts
|
||||||
of ForcePromptYes:
|
of ForcePromptYes:
|
||||||
echo(question & " -> [forced yes]")
|
echo(question & " -> [forced yes]")
|
||||||
return true
|
return true
|
||||||
|
|
@ -128,7 +130,6 @@ let babelDir = getHomeDir() / ".babel"
|
||||||
let pkgsDir = babelDir / "pkgs"
|
let pkgsDir = babelDir / "pkgs"
|
||||||
let binDir = babelDir / "bin"
|
let binDir = babelDir / "bin"
|
||||||
let nimVer = getNimrodVersion()
|
let nimVer = getNimrodVersion()
|
||||||
var didUpdatePackages = false
|
|
||||||
|
|
||||||
proc update(url: string = defaultPackageURL) =
|
proc update(url: string = defaultPackageURL) =
|
||||||
## Downloads the package list from the specified URL.
|
## Downloads the package list from the specified URL.
|
||||||
|
|
@ -137,7 +138,6 @@ proc update(url: string = defaultPackageURL) =
|
||||||
## true. Otherwise an exception is raised on error.
|
## true. Otherwise an exception is raised on error.
|
||||||
echo("Downloading package list from " & url)
|
echo("Downloading package list from " & url)
|
||||||
downloadFile(url, babelDir / "packages.json")
|
downloadFile(url, babelDir / "packages.json")
|
||||||
didUpdatePackages = true
|
|
||||||
echo("Done.")
|
echo("Done.")
|
||||||
|
|
||||||
proc checkInstallFile(pkgInfo: TPackageInfo,
|
proc checkInstallFile(pkgInfo: TPackageInfo,
|
||||||
|
|
@ -220,8 +220,9 @@ proc copyFilesRec(origDir, currentDir, dest: string, pkgInfo: TPackageInfo) =
|
||||||
copyFileD(pkgInfo.mypath,
|
copyFileD(pkgInfo.mypath,
|
||||||
changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath))
|
changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath))
|
||||||
|
|
||||||
proc install(packages: seq[String], verRange: PVersionRange): string {.discardable.}
|
proc install(packages: seq[String], verRange: PVersionRange, options: TOptions,
|
||||||
proc processDeps(pkginfo: TPackageInfo): seq[string] =
|
doPrompt = true): string {.discardable.}
|
||||||
|
proc processDeps(pkginfo: TPackageInfo, options: TOptions): seq[string] =
|
||||||
## Verifies and installs dependencies.
|
## Verifies and installs dependencies.
|
||||||
##
|
##
|
||||||
## Returns the list of paths to pass to the compiler during build phase.
|
## Returns the list of paths to pass to the compiler during build phase.
|
||||||
|
|
@ -236,7 +237,7 @@ proc processDeps(pkginfo: TPackageInfo): 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)
|
let dest = install(@[dep.name], dep.ver, options)
|
||||||
result.add(dest)
|
result.add(dest)
|
||||||
else:
|
else:
|
||||||
echo("Dependency already satisfied.")
|
echo("Dependency already satisfied.")
|
||||||
|
|
@ -253,7 +254,7 @@ 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): string =
|
proc installFromDir(dir: string, latest: bool, options: TOptions): 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.
|
||||||
|
|
@ -263,7 +264,7 @@ proc installFromDir(dir: string, latest: bool): string =
|
||||||
let pkgDestDir = pkgsDir / (pkgInfo.name &
|
let pkgDestDir = pkgsDir / (pkgInfo.name &
|
||||||
(if latest: "" else: '-' & pkgInfo.version))
|
(if latest: "" else: '-' & pkgInfo.version))
|
||||||
if existsDir(pkgDestDir):
|
if existsDir(pkgDestDir):
|
||||||
if not prompt(pkgInfo.name & " already exists. Overwrite?"):
|
if not options.prompt(pkgInfo.name & " already exists. Overwrite?"):
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
removeDir(pkgDestDir)
|
removeDir(pkgDestDir)
|
||||||
# Remove any symlinked binaries
|
# Remove any symlinked binaries
|
||||||
|
|
@ -277,7 +278,7 @@ proc installFromDir(dir: string, latest: bool): string =
|
||||||
echo("Installing ", pkginfo.name, "-", pkginfo.version)
|
echo("Installing ", pkginfo.name, "-", pkginfo.version)
|
||||||
|
|
||||||
# Dependencies need to be processed before the creation of the pkg dir.
|
# Dependencies need to be processed before the creation of the pkg dir.
|
||||||
let paths = processDeps(pkginfo)
|
let paths = processDeps(pkginfo, options)
|
||||||
|
|
||||||
if pkgInfo.bin.len > 0: buildFromDir(pkgInfo, paths)
|
if pkgInfo.bin.len > 0: buildFromDir(pkgInfo, paths)
|
||||||
|
|
||||||
|
|
@ -315,34 +316,36 @@ proc downloadPkg(pkg: TPackage, verRange: PVersionRange): string =
|
||||||
if not existsDir(getTempDir() / "babel"): createDir(getTempDir() / "babel")
|
if not existsDir(getTempDir() / "babel"): createDir(getTempDir() / "babel")
|
||||||
echo("Downloading ", pkg.name, " into ", downloadDir, "...")
|
echo("Downloading ", pkg.name, " into ", downloadDir, "...")
|
||||||
doDownload(pkg, downloadDir, verRange)
|
doDownload(pkg, downloadDir, verRange)
|
||||||
|
|
||||||
result = downloadDir
|
result = downloadDir
|
||||||
|
|
||||||
proc install(packages: seq[String], verRange: PVersionRange): string =
|
proc install(packages: seq[String], verRange: PVersionRange, options: TOptions,
|
||||||
|
doPrompt = true): string =
|
||||||
if packages == @[]:
|
if packages == @[]:
|
||||||
result = installFromDir(getCurrentDir(), false)
|
result = installFromDir(getCurrentDir(), false, options)
|
||||||
else:
|
else:
|
||||||
if not existsFile(babelDir / "packages.json"):
|
if not existsFile(babelDir / "packages.json"):
|
||||||
if prompt("Local packages.json not found, download it from internet?"):
|
if doPrompt and
|
||||||
update()
|
options.prompt("Local packages.json not found, download it from internet?"):
|
||||||
install(packages, verRange)
|
update()
|
||||||
|
install(packages, verRange, options, false)
|
||||||
else:
|
else:
|
||||||
quit("Please run babel update.", QuitFailure)
|
quit("Please run babel update.", QuitFailure)
|
||||||
for p in packages:
|
for p in packages:
|
||||||
var pkg: TPackage
|
var pkg: TPackage
|
||||||
if getPackage(p, babelDir / "packages.json", pkg):
|
if getPackage(p, babelDir / "packages.json", pkg):
|
||||||
let downloadDir = downloadPkg(pkg, verRange)
|
let downloadDir = downloadPkg(pkg, verRange)
|
||||||
result = installFromDir(downloadDir, false)
|
result = installFromDir(downloadDir, false, options)
|
||||||
else:
|
else:
|
||||||
if didUpdatePackages == false and prompt(p & " not found in local packages.json, check internet for updated packages?"):
|
if doPrompt and
|
||||||
|
options.prompt(p & " not found in local packages.json, check internet for updated packages?"):
|
||||||
update()
|
update()
|
||||||
install(@[p], verRange)
|
install(@[p], verRange, options, false)
|
||||||
else:
|
else:
|
||||||
raise newException(EBabel, "Package not found.")
|
raise newException(EBabel, "Package not found.")
|
||||||
|
|
||||||
proc build =
|
proc build(options: TOptions) =
|
||||||
var pkgInfo = getPkgInfo(getCurrentDir())
|
var pkgInfo = getPkgInfo(getCurrentDir())
|
||||||
let paths = processDeps(pkginfo)
|
let paths = processDeps(pkginfo, options)
|
||||||
buildFromDir(pkgInfo, paths)
|
buildFromDir(pkgInfo, paths)
|
||||||
|
|
||||||
proc search(action: TAction) =
|
proc search(action: TAction) =
|
||||||
|
|
@ -385,7 +388,7 @@ type VersionAndPath = tuple[version: TVersion, path: string]
|
||||||
proc listPaths(packages: seq[String]) =
|
proc listPaths(packages: seq[String]) =
|
||||||
## Loops over installing packages displaying their installed paths.
|
## Loops over installing packages displaying their installed paths.
|
||||||
##
|
##
|
||||||
## If there are several pacakges installed, only the last one (the version
|
## If there are several packages installed, only the last one (the version
|
||||||
## listed in the packages.json) will be displayed. If any package name is not
|
## listed in the packages.json) will be displayed. If any package name is not
|
||||||
## found, the proc displays a missing message and continues through the list,
|
## found, the proc displays a missing message and continues through the list,
|
||||||
## but at the end quits with a non zero exit error.
|
## but at the end quits with a non zero exit error.
|
||||||
|
|
@ -411,24 +414,24 @@ proc listPaths(packages: seq[String]) =
|
||||||
if errors > 0:
|
if errors > 0:
|
||||||
quit("FAILURE: At least one specified package was not found", QuitFailure)
|
quit("FAILURE: At least one specified package was not found", QuitFailure)
|
||||||
|
|
||||||
proc doAction(action: TAction) =
|
proc doAction(options: TOptions) =
|
||||||
case action.typ
|
case options.action.typ
|
||||||
of ActionUpdate:
|
of ActionUpdate:
|
||||||
if action.optionalURL != "":
|
if options.action.optionalURL != "":
|
||||||
update(action.optionalURL)
|
update(options.action.optionalURL)
|
||||||
else:
|
else:
|
||||||
update()
|
update()
|
||||||
of ActionInstall:
|
of ActionInstall:
|
||||||
# TODO: Allow user to specify version.
|
# TODO: Allow user to specify version.
|
||||||
install(action.optionalName, PVersionRange(kind: verAny))
|
install(options.action.optionalName, PVersionRange(kind: verAny), options)
|
||||||
of ActionSearch:
|
of ActionSearch:
|
||||||
search(action)
|
search(options.action)
|
||||||
of ActionList:
|
of ActionList:
|
||||||
list()
|
list()
|
||||||
of ActionPath:
|
of ActionPath:
|
||||||
listPaths(action.optionalName)
|
listPaths(options.action.optionalName)
|
||||||
of ActionBuild:
|
of ActionBuild:
|
||||||
build()
|
build(options)
|
||||||
of ActionNil:
|
of ActionNil:
|
||||||
assert false
|
assert false
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue