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

View file

@ -107,6 +107,10 @@ proc copyFileD(fro, to: string) =
echo(fro, " -> ", to) echo(fro, " -> ", to)
copyFile(fro, to) copyFile(fro, to)
proc copyDirD(fro, to: string) =
echo(fro, " -> ", to)
copyDir(fro, to)
proc doCmd(cmd: string) = proc doCmd(cmd: string) =
let exitCode = execCmd(cmd) let exitCode = execCmd(cmd)
if exitCode != QuitSuccess: if exitCode != QuitSuccess:
@ -122,20 +126,70 @@ template cd(dir: string, body: stmt) =
body body
setCurrentDir(lastDir) 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) = proc copyFilesRec(origDir, currentDir, dest: string, pkgInfo: TPackageInfo) =
## Copies all the required files, skips files specified in the .babel file ## Copies all the required files, skips files specified in the .babel file
## (TPackageInfo). ## (TPackageInfo).
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): for kind, file in walkDir(currentDir):
if kind == pcDir: if kind == pcDir:
var skip = false let skip = pkgInfo.checkInstallDir(origDir, file)
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 if skip: continue
# Create the dir. # Create the dir.
@ -143,21 +197,10 @@ proc copyFilesRec(origDir, currentDir, dest: string, pkgInfo: TPackageInfo) =
copyFilesRec(origDir, file, dest, pkgInfo) copyFilesRec(origDir, file, dest, pkgInfo)
else: else:
var skip = false let skip = pkgInfo.checkInstallFile(origDir, file)
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 skip: continue
if file.splitFile.ext == ('.' & ignoreExt):
skip = true
break
if not skip:
copyFileD(file, changeRoot(origDir, dest, file)) copyFileD(file, changeRoot(origDir, dest, file))
proc install(packages: seq[String], verRange: PVersionRange): string {.discardable.} proc install(packages: seq[String], verRange: PVersionRange): string {.discardable.}
@ -220,12 +263,13 @@ proc installFromDir(dir: string, latest: bool): string =
buildFromDir(dir, paths) buildFromDir(dir, paths)
createDir(binDir) createDir(binDir)
# Copy all binaries and files that are not skipped # Copy all binaries and files that are not skipped
var nPkgInfo = pkgInfo copyFilesRec(dir, dir, pkgDestDir, pkgInfo)
nPkgInfo.skipExt.add("nim") # Implicitly skip .nim files
copyFilesRec(dir, dir, pkgDestDir, nPkgInfo)
# Set file permissions to +x for all binaries built, # Set file permissions to +x for all binaries built,
# and symlink them on *nix OS' to $babelDir/bin/ # and symlink them on *nix OS' to $babelDir/bin/
for bin in pkgInfo.bin: for bin in pkgInfo.bin:
if not existsFile(pkgDestDir / bin):
copyFileD(dir / bin, pkgDestDir / bin)
let currentPerms = getFilePermissions(pkgDestDir / bin) let currentPerms = getFilePermissions(pkgDestDir / bin)
setFilePermissions(pkgDestDir / bin, currentPerms + {fpUserExec}) setFilePermissions(pkgDestDir / bin, currentPerms + {fpUserExec})
when defined(unix): when defined(unix):

View file

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

View file

@ -13,6 +13,9 @@ type
skipDirs*: seq[string] skipDirs*: seq[string]
skipFiles*: seq[string] skipFiles*: seq[string]
skipExt*: seq[string] skipExt*: seq[string]
installDirs*: seq[string]
installFiles*: seq[string]
installExt*: seq[string]
requires*: seq[tuple[name: string, ver: PVersionRange]] requires*: seq[tuple[name: string, ver: PVersionRange]]
bin*: seq[string] bin*: seq[string]
@ -36,6 +39,9 @@ proc initPackageInfo(): TPackageInfo =
result.skipDirs = @[] result.skipDirs = @[]
result.skipFiles = @[] result.skipFiles = @[]
result.skipExt = @[] result.skipExt = @[]
result.installDirs = @[]
result.installFiles = @[]
result.installExt = @[]
result.requires = @[] result.requires = @[]
result.bin = @[] result.bin = @[]
@ -93,6 +99,12 @@ proc readPackageInfo*(path: string): TPackageInfo =
result.skipFiles.add(ev.value.split(',')) result.skipFiles.add(ev.value.split(','))
of "skipext": of "skipext":
result.skipExt.add(ev.value.split(',')) 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": of "bin":
for i in ev.value.split(','): for i in ev.value.split(','):
result.bin.add(i.addFileExt(ExeExt)) 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 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 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 #### 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 symlink to the binary in ``$babelDir/bin/``. On Windows a stub .bat file is
created instead. created instead.
Other files will be copied in the same way as they are for library packages.
Dependencies are automatically installed before building. Dependencies are automatically installed before building.
## Dependencies ## Dependencies

View file

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