install() now copies files to ~/.babel/lib/, fixed code as per Araq's critique.

This commit is contained in:
Dominik Picheta 2011-01-27 21:44:02 +00:00
commit bcc94d7e76
4 changed files with 77 additions and 38 deletions

View file

@ -1,4 +1,4 @@
import parser, version, osproc, strutils, re, os
import parser, version, osproc, strutils, re, os, parseutils
type
EInstall = object of EBase
@ -7,18 +7,18 @@ type
proc getNimVersion(cmd: string = "nimrod"): String =
var output = execProcess(cmd & " -v")
# TODO: Fix this. Don't know why it doesn't work.
##echo(splitlines(output)[0])
# :\
if splitlines(output)[0] =~ re"(Version\s.+?\s)":
echo(matches[0])
for i in items(matches):
echo(i)
else:
nil
#echo(":(")
return "0.8.10"
var line = splitLines(output)[0]
# Thanks Araq :)
var i = 0
var nimrodVersion = ""
i = skipIgnoreCase(line, "Nimrod Compiler Version ")
if i <= 0: raise newException(EInstall, "Cannot detect Nimrod's version")
i = parseToken(line, nimrodVersion, {'.', '0'..'9'}, i)
if nimrodVersion.len == 0:
raise newException(EInstall, "Cannot detect Nimrod's version")
return nimrodVersion
proc dependExists(name: string, verRange: PVersionRange): Bool =
if name == "nimrod":
@ -33,7 +33,7 @@ proc dependExists(name: string, verRange: PVersionRange): Bool =
# ... or just look for the package in PATH + $nimrod/lib/babel/packageName
assert(False)
proc verifyDepends*(proj: TProject): seq[TDepend] =
proc verifyDepends(proj: TProject): seq[TDepend] =
result = @[]
for i in items(proj.depends):
var spl = i.split()
@ -58,12 +58,45 @@ proc verifyDepends*(proj: TProject): seq[TDepend] =
if not dependExists(nameStr, verRange):
result.add((nameStr, verRange))
proc createDirs(dirs: seq[string]) =
for i in items(dirs):
if not existsDir(i):
createDir(i)
proc copyFiles(proj: TProject) =
# This will create a $home/.babel and lib/ or bin/. It will also copy all the
# files listed in proj.modules and proj.files.
when defined(windows):
var babelDir = getHomeDir() / "babel"
else:
var babelDir = getHomeDir() / ".babel"
var dirs = @[babelDir, babelDir / "lib", babelDir / "bin"]
if proj.library:
var projDir = babelDir / "lib" / (proj.name & "-" & proj.version)
dirs.add(projDir)
createDirs(dirs)
# Copy the files
for i in items(proj.modules):
stdout.write("Copying " & i.addFileExt("nim") & "...")
copyFile(i.addFileExt("nim"), projDir / i.addFileExt("nim"))
echo(" Done!")
if proj.files.len > 0:
for i in items(proj.files):
copyFile(i, projDir / i)
elif proj.executable:
# TODO: Copy files for executable.
assert(false)
proc install*(name: string, filename: string = "") =
## Install package by the name of ``name``, filename specifies where to look for it
## if left as "", the current working directory will be assumed.
# TODO: Add a `debug` variable? If true the status messages get echo-ed,
# vice-versa if false?
var babelFile: TProject = initProj()
var babelFile: TProject
var path = ""
if filename == "":
path = name.addFileExt("babel")
@ -74,8 +107,8 @@ proc install*(name: string, filename: string = "") =
babelFile = parseBabel(path)
var ret = babelFile.verify()
if not ret.b:
raise newException(EInstall, "Verifying the .babel file failed: " & ret.reason)
if ret != "":
raise newException(EInstall, "Verifying the .babel file failed: " & ret)
if babelFile.depends.len == 1:
echo("Verifying 1 dependency...")
@ -87,8 +120,10 @@ proc install*(name: string, filename: string = "") =
else:
echo("All dependencies verified!")
echo("Installing " & name)
# TODO: Install.
echo("Installing " & name & "...")
babelFile.copyFiles()
echo("Package " & name & " successfully installed.")
when isMainModule:
install("babel")

View file

@ -19,9 +19,9 @@ type
unknownFields*: seq[string] # TODO:
EParseErr* = object of EIO
EParseErr* = object of EBase
proc initProj*(): TProject =
proc initProj(): TProject =
result.name = ""
result.version = ""
result.author = ""
@ -37,7 +37,6 @@ proc initProj*(): TProject =
result.files = @[]
result.unknownFields = @[]
proc parseList(s: string): seq[string] =
result = @[]
@ -50,6 +49,7 @@ proc parseErr(p: TCfgParser, msg: string) =
$p.getColumn() & ") " & msg)
proc parseBabel*(file: string): TProject =
result = initProj()
var f = newFileStream(file, fmRead)
if f != nil:
var p: TCfgParser
@ -123,20 +123,20 @@ proc parseBabel*(file: string): TProject =
else:
raise newException(EIO, "Cannot open " & file)
proc isEmpty*(s: string): Bool = return s == ""
proc isEmpty(s: string): Bool = return s == ""
proc verify*(proj: TProject): tuple[b: Bool, reason: string] =
proc verify*(proj: TProject): string =
## Checks whether the required fields have been specified.
if isEmpty(proj.name) or isEmpty(proj.version) or isEmpty(proj.author) or
isEmpty(proj.category) or isEmpty(proj.desc):
return (False, "Missing required fields.")
return "Missing required fields."
elif proj.library == false and proj.executable == false:
return (False, "Either a valid Library needs to be specified or a valid Bin.")
return "Either a valid Library needs to be specified or a valid Bin."
elif proj.library == true and proj.modules.len() == 0:
return (False, "A valid library needs at least one ExposedModule listed.")
return "A valid library needs at least one ExposedModule listed."
# TODO: Rules for Bin.
return (True, "")
return ""
when isMainModule:
for i in items(parseList("test, asdasd >sda; jsj, kk >>, sd")):

View file

@ -1,6 +1,12 @@
# Babel
Babel is a work in progress package manager for Nimrod.
##Babel's folder structure
Babel stores everything that has been installed in ~/.babel on Unix systems and
in your $home/babel on Windows. Libraries are installed in lib/ in folders
which names contain both the name and version of the package, the folders
contain the modules and any other files that the package wished to install.
## Contribution
If you would like to help, feel free to fork and make any additions you see
fit and then send a pull request.

View file

@ -17,11 +17,11 @@ type
of verLater, verEarlier, verEqLater, verEqEarlier:
ver*: TVersion
of verIntersect:
verI*: tuple[left: PVersionRange, right: PVersionRange]
verILeft, verIRight: PVersionRange
of verAny:
nil
EParseVersion = object of EBase
EParseVersion = object of EInvalidValue
proc newVersion*(ver: string): TVersion = return TVersion(ver)
@ -61,11 +61,10 @@ proc withinRange*(ver: TVersion, ran: PVersionRange): Bool =
of verEqEarlier:
return ver <= ran.ver
of verIntersect:
return withinRange(ver, ran.verI.left) and withinRange(ver, ran.verI.right)
return withinRange(ver, ran.verILeft) and withinRange(ver, ran.verIRight)
of verAny:
return True
proc makeRange*(version: string, op: string): PVersionRange =
new(result)
case op
@ -93,20 +92,19 @@ proc parseVersionRange*(s: string): PVersionRange =
of '>', '<', '=':
op.add(s[i])
of '&':
var left = makeRange(version, op)
result.kind = verIntersect
result.verILeft = makeRange(version, op)
# Parse everything after &
# Recursion <3
var right = parseVersionRange(copy(s, i + 1))
result.verIRight = parseVersionRange(copy(s, i + 1))
# Disallow more than one verIntersect. It's pointless and could lead to
# major unknown mistakes.
if right.kind == verIntersect:
if result.verIRight.kind == verIntersect:
raise newException(EParseVersion,
"Having more than one `&` in a version range is pointless")
result.kind = verIntersect
result.verI = (left, right)
break
of '0'..'9', '.':