From bcc94d7e76bf8a2b2680e71c669fadb3edec2a2a Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Thu, 27 Jan 2011 21:44:02 +0000 Subject: [PATCH] install() now copies files to ~/.babel/lib/, fixed code as per Araq's critique. --- installer.nim | 73 ++++++++++++++++++++++++++++++++++++------------- parser.nim | 18 ++++++------ readme.markdown | 6 ++++ version.nim | 18 ++++++------ 4 files changed, 77 insertions(+), 38 deletions(-) diff --git a/installer.nim b/installer.nim index 7d65014..8742c72 100644 --- a/installer.nim +++ b/installer.nim @@ -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") diff --git a/parser.nim b/parser.nim index 35e8a8b..6ed2976 100644 --- a/parser.nim +++ b/parser.nim @@ -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")): diff --git a/readme.markdown b/readme.markdown index 37de51b..971b67c 100644 --- a/readme.markdown +++ b/readme.markdown @@ -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. diff --git a/version.nim b/version.nim index 1e62325..cf13796 100644 --- a/version.nim +++ b/version.nim @@ -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', '.':