install() now copies files to ~/.babel/lib/, fixed code as per Araq's critique.
This commit is contained in:
parent
0265915c2c
commit
bcc94d7e76
4 changed files with 77 additions and 38 deletions
|
|
@ -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")
|
||||||
|
|
|
||||||
18
parser.nim
18
parser.nim
|
|
@ -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")):
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
18
version.nim
18
version.nim
|
|
@ -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', '.':
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue