Implemented a whitelist mode.

This commit is contained in:
Dominik Picheta 2013-06-26 22:45:13 +01:00
commit 19b5d3072f
5 changed files with 104 additions and 40 deletions

116
babel.nim
View file

@ -107,6 +107,10 @@ proc copyFileD(fro, to: string) =
echo(fro, " -> ", to)
copyFile(fro, to)
proc copyDirD(fro, to: string) =
echo(fro, " -> ", to)
copyDir(fro, to)
proc doCmd(cmd: string) =
let exitCode = execCmd(cmd)
if exitCode != QuitSuccess:
@ -122,42 +126,81 @@ template cd(dir: string, body: stmt) =
body
setCurrentDir(lastDir)
proc checkInstallFile(pkgInfo: TPackageInfo,
origDir, file: string): bool =
## Checks whether ``file`` should be installed.
## ``True`` means file should be skipped.
for ignoreFile in pkgInfo.skipFiles:
if ignoreFile.endswith("babel"):
raise newException(EBabel, ignoreFile & " must be installed.")
if samePaths(file, origDir / ignoreFile):
result = true
break
for ignoreExt in pkgInfo.skipExt:
if file.splitFile.ext == ('.' & ignoreExt):
result = true
break
if file.splitFile().name[0] == '.': result = true
proc checkInstallDir(pkgInfo: TPackageInfo,
origDir, dir: string): bool =
## Determines whether ``dir`` should be installed.
## ``True`` means dir should be skipped.
for ignoreDir in pkgInfo.skipDirs:
if samePaths(dir, origDir / ignoreDir):
result = true
break
let thisDir = splitPath(dir).tail
assert thisDir != ""
if thisDir[0] == '.': result = true
if thisDir == "nimcache": result = true
proc copyWithExt(origDir, currentDir, dest: string, pkgInfo: TPackageInfo) =
for kind, path in walkDir(currentDir):
if kind == pcDir:
copyWithExt(origDir, path, dest, pkgInfo)
else:
for iExt in pkgInfo.installExt:
if path.splitFile.ext == ('.' & iExt):
createDir(changeRoot(origDir, dest, path).splitFile.dir)
copyFileD(path, changeRoot(origDir, dest, path))
proc copyFilesRec(origDir, currentDir, dest: string, pkgInfo: TPackageInfo) =
## Copies all the required files, skips files specified in the .babel file
## (TPackageInfo).
for kind, file in walkDir(currentDir):
if kind == pcDir:
var skip = false
for ignoreDir in pkgInfo.skipDirs:
if samePaths(file, origDir / ignoreDir):
skip = true
break
let thisDir = splitPath(file).tail
assert thisDir != ""
if thisDir[0] == '.': skip = true
if thisDir == "nimcache": skip = true
if skip: continue
# Create the dir.
createDir(changeRoot(origDir, dest, file))
copyFilesRec(origDir, file, dest, pkgInfo)
else:
var skip = false
if file.splitFile().name[0] == '.': skip = true
for ignoreFile in pkgInfo.skipFiles:
if ignoreFile.endswith("babel"):
raise newException(EBabel, ignoreFile & " must be installed.")
if samePaths(file, origDir / ignoreFile):
skip = true
break
for ignoreExt in pkgInfo.skipExt:
if file.splitFile.ext == ('.' & ignoreExt):
skip = true
break
if not skip:
let whitelistMode =
pkgInfo.installDirs.len != 0 or
pkgInfo.installFiles.len != 0 or
pkgInfo.installExt.len != 0
if whitelistMode:
for file in pkgInfo.installFiles:
createDir(dest / file.splitFile.dir)
copyFileD(origDir / file, dest / file)
for dir in pkgInfo.installDirs:
# TODO: Allow skipping files inside dirs?
copyDirD(origDir / dir, dest / dir)
copyWithExt(origDir, currentDir, dest, pkgInfo)
else:
for kind, file in walkDir(currentDir):
if kind == pcDir:
let skip = pkgInfo.checkInstallDir(origDir, file)
if skip: continue
# Create the dir.
createDir(changeRoot(origDir, dest, file))
copyFilesRec(origDir, file, dest, pkgInfo)
else:
let skip = pkgInfo.checkInstallFile(origDir, file)
if skip: continue
copyFileD(file, changeRoot(origDir, dest, file))
proc install(packages: seq[String], verRange: PVersionRange): string {.discardable.}
@ -220,12 +263,13 @@ proc installFromDir(dir: string, latest: bool): string =
buildFromDir(dir, paths)
createDir(binDir)
# Copy all binaries and files that are not skipped
var nPkgInfo = pkgInfo
nPkgInfo.skipExt.add("nim") # Implicitly skip .nim files
copyFilesRec(dir, dir, pkgDestDir, nPkgInfo)
copyFilesRec(dir, dir, pkgDestDir, pkgInfo)
# Set file permissions to +x for all binaries built,
# and symlink them on *nix OS' to $babelDir/bin/
for bin in pkgInfo.bin:
if not existsFile(pkgDestDir / bin):
copyFileD(dir / bin, pkgDestDir / bin)
let currentPerms = getFilePermissions(pkgDestDir / bin)
setFilePermissions(pkgDestDir / bin, currentPerms + {fpUserExec})
when defined(unix):

View file

@ -1,4 +1,4 @@
Copyright (c) 2012, Dominik Picheta
Copyright (c) 2013, Dominik Picheta
All rights reserved.
Redistribution and use in source and binary forms, with or without

View file

@ -13,6 +13,9 @@ type
skipDirs*: seq[string]
skipFiles*: seq[string]
skipExt*: seq[string]
installDirs*: seq[string]
installFiles*: seq[string]
installExt*: seq[string]
requires*: seq[tuple[name: string, ver: PVersionRange]]
bin*: seq[string]
@ -36,6 +39,9 @@ proc initPackageInfo(): TPackageInfo =
result.skipDirs = @[]
result.skipFiles = @[]
result.skipExt = @[]
result.installDirs = @[]
result.installFiles = @[]
result.installExt = @[]
result.requires = @[]
result.bin = @[]
@ -93,6 +99,12 @@ proc readPackageInfo*(path: string): TPackageInfo =
result.skipFiles.add(ev.value.split(','))
of "skipext":
result.skipExt.add(ev.value.split(','))
of "installdirs":
result.installDirs.add(ev.value.split(','))
of "installfiles":
result.installFiles.add(ev.value.split(','))
of "installext":
result.installExt.add(ev.value.split(','))
of "bin":
for i in ev.value.split(','):
result.bin.add(i.addFileExt(ExeExt))

View file

@ -53,7 +53,10 @@ structure may be enforced in the future.
All files and folders in the directory of where the .babel file resides will be
copied as-is, you can however skip some directories or files by setting
the 'SkipDirs' or 'SkipFiles' options in your .babel file.
the ``SkipDirs``, ``SkipFiles`` or ``SkipExt`` options in your .babel file.
Directories and files can also be specified on a *whitelist* basis, if you
specify either of ``InstallDirs``, ``InstallFiles`` or ``InstallExt`` then
babel will **only** install the files specified.
#### Example library .babel file
@ -90,6 +93,8 @@ file, copy it into ``$babelDir/pkgs/pkgname-ver/`` and subsequently create a
symlink to the binary in ``$babelDir/bin/``. On Windows a stub .bat file is
created instead.
Other files will be copied in the same way as they are for library packages.
Dependencies are automatically installed before building.
## Dependencies

View file

@ -14,8 +14,11 @@ proc getNimrodVersion*: TVersion =
proc samePaths*(p1, p2: string): bool =
## Normalizes path (by adding a trailing slash) and compares.
let cp1 = if not p1.endsWith("/"): p1 & "/" else: p1
let cp2 = if not p2.endsWith("/"): p2 & "/" else: p2
var cp1 = if not p1.endsWith("/"): p1 & "/" else: p1
var cp2 = if not p2.endsWith("/"): p2 & "/" else: p2
cp1 = cp1.replace('/', DirSep).replace('\\', DirSep)
cp2 = cp2.replace('/', DirSep).replace('\\', DirSep)
return cmpPaths(cp1, cp2) == 0
proc changeRoot*(origRoot, newRoot, path: string): string =