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

View file

@ -19,9 +19,9 @@ type
unknownFields*: seq[string] # TODO: unknownFields*: seq[string] # TODO:
EParseErr* = object of EIO EParseErr* = object of EBase
proc initProj*(): TProject = proc initProj(): TProject =
result.name = "" result.name = ""
result.version = "" result.version = ""
result.author = "" result.author = ""
@ -37,7 +37,6 @@ proc initProj*(): TProject =
result.files = @[] result.files = @[]
result.unknownFields = @[] result.unknownFields = @[]
proc parseList(s: string): seq[string] = proc parseList(s: string): seq[string] =
result = @[] result = @[]
@ -50,6 +49,7 @@ proc parseErr(p: TCfgParser, msg: string) =
$p.getColumn() & ") " & msg) $p.getColumn() & ") " & msg)
proc parseBabel*(file: string): TProject = proc parseBabel*(file: string): TProject =
result = initProj()
var f = newFileStream(file, fmRead) var f = newFileStream(file, fmRead)
if f != nil: if f != nil:
var p: TCfgParser var p: TCfgParser
@ -123,20 +123,20 @@ proc parseBabel*(file: string): TProject =
else: else:
raise newException(EIO, "Cannot open " & file) 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. ## Checks whether the required fields have been specified.
if isEmpty(proj.name) or isEmpty(proj.version) or isEmpty(proj.author) or if isEmpty(proj.name) or isEmpty(proj.version) or isEmpty(proj.author) or
isEmpty(proj.category) or isEmpty(proj.desc): isEmpty(proj.category) or isEmpty(proj.desc):
return (False, "Missing required fields.") return "Missing required fields."
elif proj.library == false and proj.executable == false: 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: 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. # TODO: Rules for Bin.
return (True, "") return ""
when isMainModule: when isMainModule:
for i in items(parseList("test, asdasd >sda; jsj, kk >>, sd")): for i in items(parseList("test, asdasd >sda; jsj, kk >>, sd")):

View file

@ -1,6 +1,12 @@
# Babel # Babel
Babel is a work in progress package manager for Nimrod. 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 ## Contribution
If you would like to help, feel free to fork and make any additions you see If you would like to help, feel free to fork and make any additions you see
fit and then send a pull request. fit and then send a pull request.

View file

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