Implements #41.
Also, building of binary packages now takes place before any old packages are removed. This is to prevent the case where the old package is removed and a new version of the same package fails to build so the user is left with no package at all.
This commit is contained in:
parent
5322268dd7
commit
10de991d3d
5 changed files with 95 additions and 56 deletions
|
|
@ -2,9 +2,9 @@
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
|
|
||||||
import httpclient, parseopt, os, strutils, osproc, pegs, tables, parseutils,
|
import httpclient, parseopt, os, strutils, osproc, pegs, tables, parseutils,
|
||||||
strtabs, json, algorithm
|
strtabs, json, algorithm, sets
|
||||||
|
|
||||||
import babelpkg/packageinfo, babelpkg/version, babelpkg/common, babelpkg/tools, babelpkg/download
|
import babelpkg/packageinfo, babelpkg/version, babelpkg/tools, babelpkg/download
|
||||||
|
|
||||||
type
|
type
|
||||||
TOptions = object
|
TOptions = object
|
||||||
|
|
@ -180,20 +180,26 @@ proc checkInstallDir(pkgInfo: TPackageInfo,
|
||||||
if thisDir[0] == '.': result = true
|
if thisDir[0] == '.': result = true
|
||||||
if thisDir == "nimcache": result = true
|
if thisDir == "nimcache": result = true
|
||||||
|
|
||||||
proc copyWithExt(origDir, currentDir, dest: string, pkgInfo: TPackageInfo) =
|
proc copyWithExt(origDir, currentDir, dest: string,
|
||||||
|
pkgInfo: TPackageInfo): seq[string] =
|
||||||
|
## Returns the filenames of the files that have been copied
|
||||||
|
## (their destination).
|
||||||
|
result = @[]
|
||||||
for kind, path in walkDir(currentDir):
|
for kind, path in walkDir(currentDir):
|
||||||
if kind == pcDir:
|
if kind == pcDir:
|
||||||
copyWithExt(origDir, path, dest, pkgInfo)
|
result.add copyWithExt(origDir, path, dest, pkgInfo)
|
||||||
else:
|
else:
|
||||||
for iExt in pkgInfo.installExt:
|
for iExt in pkgInfo.installExt:
|
||||||
if path.splitFile.ext == ('.' & iExt):
|
if path.splitFile.ext == ('.' & iExt):
|
||||||
createDir(changeRoot(origDir, dest, path).splitFile.dir)
|
createDir(changeRoot(origDir, dest, path).splitFile.dir)
|
||||||
copyFileD(path, changeRoot(origDir, dest, path))
|
result.add copyFileD(path, changeRoot(origDir, dest, path))
|
||||||
|
|
||||||
proc copyFilesRec(origDir, currentDir, dest: string,
|
proc copyFilesRec(origDir, currentDir, dest: string,
|
||||||
options: TOptions, pkgInfo: TPackageInfo) =
|
options: TOptions, pkgInfo: TPackageInfo): TSet[string] =
|
||||||
## 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).
|
||||||
|
## Returns a list of filepaths to files which have been installed.
|
||||||
|
result = initSet[string]()
|
||||||
let whitelistMode =
|
let whitelistMode =
|
||||||
pkgInfo.installDirs.len != 0 or
|
pkgInfo.installDirs.len != 0 or
|
||||||
pkgInfo.installFiles.len != 0 or
|
pkgInfo.installFiles.len != 0 or
|
||||||
|
|
@ -207,7 +213,7 @@ proc copyFilesRec(origDir, currentDir, dest: string,
|
||||||
else:
|
else:
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
createDir(dest / file.splitFile.dir)
|
createDir(dest / file.splitFile.dir)
|
||||||
copyFileD(src, dest / file)
|
result.incl copyFileD(src, dest / file)
|
||||||
|
|
||||||
for dir in pkgInfo.installDirs:
|
for dir in pkgInfo.installDirs:
|
||||||
# TODO: Allow skipping files inside dirs?
|
# TODO: Allow skipping files inside dirs?
|
||||||
|
|
@ -217,9 +223,9 @@ proc copyFilesRec(origDir, currentDir, dest: string,
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
copyDirD(origDir / dir, dest / dir)
|
result.incl copyDirD(origDir / dir, dest / dir)
|
||||||
|
|
||||||
copyWithExt(origDir, currentDir, dest, pkgInfo)
|
result.incl copyWithExt(origDir, currentDir, dest, pkgInfo)
|
||||||
else:
|
else:
|
||||||
for kind, file in walkDir(currentDir):
|
for kind, file in walkDir(currentDir):
|
||||||
if kind == pcDir:
|
if kind == pcDir:
|
||||||
|
|
@ -229,15 +235,15 @@ proc copyFilesRec(origDir, currentDir, dest: string,
|
||||||
# Create the dir.
|
# Create the dir.
|
||||||
createDir(changeRoot(origDir, dest, file))
|
createDir(changeRoot(origDir, dest, file))
|
||||||
|
|
||||||
copyFilesRec(origDir, file, dest, options, pkgInfo)
|
result.incl copyFilesRec(origDir, file, dest, options, pkgInfo)
|
||||||
else:
|
else:
|
||||||
let skip = pkgInfo.checkInstallFile(origDir, file)
|
let skip = pkgInfo.checkInstallFile(origDir, file)
|
||||||
|
|
||||||
if skip: continue
|
if skip: continue
|
||||||
|
|
||||||
copyFileD(file, changeRoot(origDir, dest, file))
|
result.incl copyFileD(file, changeRoot(origDir, dest, file))
|
||||||
|
|
||||||
copyFileD(pkgInfo.mypath,
|
result.incl copyFileD(pkgInfo.mypath,
|
||||||
changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath))
|
changeRoot(pkgInfo.mypath.splitFile.dir, dest, pkgInfo.mypath))
|
||||||
|
|
||||||
proc install(packages: seq[tuple[name: string, verRange: PVersionRange]],
|
proc install(packages: seq[tuple[name: string, verRange: PVersionRange]],
|
||||||
|
|
@ -286,19 +292,52 @@ proc buildFromDir(pkgInfo: TPackageInfo, paths: seq[string]) =
|
||||||
doCmd("nimrod $# -d:release --noBabelPath $# \"$#\"" %
|
doCmd("nimrod $# -d:release --noBabelPath $# \"$#\"" %
|
||||||
[pkgInfo.backend, args, realDir / bin.changeFileExt("nim")])
|
[pkgInfo.backend, args, realDir / bin.changeFileExt("nim")])
|
||||||
|
|
||||||
proc installFromDir(dir: string, latest: bool, options: TOptions, url: string): seq[string] =
|
proc saveBabelMeta(pkgDestDir, url: string, filesInstalled: TSet[string]) =
|
||||||
## Returns where package has been installed to.
|
var babelmeta = %{"url": %url}
|
||||||
|
babelmeta["files"] = newJArray()
|
||||||
|
for file in filesInstalled:
|
||||||
|
babelmeta["files"].add(%changeRoot(pkgDestDir, "", file))
|
||||||
|
writeFile(pkgDestDir / "babelmeta.json", $babelmeta)
|
||||||
|
|
||||||
|
proc removePkgDir(dir: string, options: TOptions) =
|
||||||
|
## Removes files belonging to the package in ``dir``.
|
||||||
|
try:
|
||||||
|
var babelmeta = parseFile(dir / "babelmeta.json")
|
||||||
|
if not babelmeta.hasKey("files"):
|
||||||
|
raise newException(EJsonParsingError,
|
||||||
|
"Meta data does not contain required info.")
|
||||||
|
for file in babelmeta["files"]:
|
||||||
|
removeFile(dir / file.str)
|
||||||
|
except EOS, EJsonParsingError:
|
||||||
|
echo("Error: Unable to read babelmeta.json: ", getCurrentExceptionMsg())
|
||||||
|
if not options.prompt("Would you like to COMPLETELY overwrite ALL files " &
|
||||||
|
"in " & dir & "?"):
|
||||||
|
quit(QuitSuccess)
|
||||||
|
removeDir(dir)
|
||||||
|
|
||||||
|
proc installFromDir(dir: string, latest: bool, options: TOptions,
|
||||||
|
url: string): seq[string] =
|
||||||
|
## Returns where package has been installed to, together with paths
|
||||||
|
## to the packages this package depends on.
|
||||||
## The return value of this function is used by
|
## The return value of this function is used by
|
||||||
## ``processDeps`` to gather a list of paths to pass to the nimrod compiler.
|
## ``processDeps`` to gather a list of paths to pass to the nimrod compiler.
|
||||||
var pkgInfo = getPkgInfo(dir)
|
var pkgInfo = getPkgInfo(dir)
|
||||||
let realDir = pkgInfo.getRealDir()
|
let realDir = pkgInfo.getRealDir()
|
||||||
|
# Dependencies need to be processed before the creation of the pkg dir.
|
||||||
|
let paths = processDeps(pkginfo, options)
|
||||||
|
|
||||||
|
echo("Installing ", pkginfo.name, "-", pkginfo.version)
|
||||||
|
|
||||||
|
# Build before removing an existing package (if one exists). This way
|
||||||
|
# if the build fails then the old package will still be installed.
|
||||||
|
if pkgInfo.bin.len > 0: buildFromDir(pkgInfo, paths)
|
||||||
|
|
||||||
let versionStr = (if latest: "" else: '-' & pkgInfo.version)
|
let versionStr = (if latest: "" else: '-' & pkgInfo.version)
|
||||||
let pkgDestDir = pkgsDir / (pkgInfo.name & versionStr)
|
let pkgDestDir = pkgsDir / (pkgInfo.name & versionStr)
|
||||||
if existsDir(pkgDestDir):
|
if existsDir(pkgDestDir):
|
||||||
if not options.prompt(pkgInfo.name & versionStr & " already exists. Overwrite?"):
|
if not options.prompt(pkgInfo.name & versionStr & " already exists. Overwrite?"):
|
||||||
quit(QuitSuccess)
|
quit(QuitSuccess)
|
||||||
removeDir(pkgDestDir)
|
removePkgDir(pkgDestDir, options)
|
||||||
# Remove any symlinked binaries
|
# Remove any symlinked binaries
|
||||||
for bin in pkgInfo.bin:
|
for bin in pkgInfo.bin:
|
||||||
# TODO: Check that this binary belongs to the package being installed.
|
# TODO: Check that this binary belongs to the package being installed.
|
||||||
|
|
@ -306,24 +345,21 @@ proc installFromDir(dir: string, latest: bool, options: TOptions, url: string):
|
||||||
removeFile(binDir / bin.changeFileExt("bat"))
|
removeFile(binDir / bin.changeFileExt("bat"))
|
||||||
else:
|
else:
|
||||||
removeFile(binDir / bin)
|
removeFile(binDir / bin)
|
||||||
|
|
||||||
echo("Installing ", pkginfo.name, "-", pkginfo.version)
|
## Will contain a list of files which have been installed.
|
||||||
|
var filesInstalled: TSet[string]
|
||||||
# Dependencies need to be processed before the creation of the pkg dir.
|
|
||||||
let paths = processDeps(pkginfo, options)
|
|
||||||
|
|
||||||
if pkgInfo.bin.len > 0: buildFromDir(pkgInfo, paths)
|
|
||||||
|
|
||||||
createDir(pkgDestDir)
|
createDir(pkgDestDir)
|
||||||
if pkgInfo.bin.len > 0:
|
if pkgInfo.bin.len > 0:
|
||||||
createDir(binDir)
|
createDir(binDir)
|
||||||
# Copy all binaries and files that are not skipped
|
# Copy all binaries and files that are not skipped
|
||||||
copyFilesRec(realDir, realDir, pkgDestDir, options, pkgInfo)
|
filesInstalled = copyFilesRec(realDir, realDir, pkgDestDir, options,
|
||||||
|
pkgInfo)
|
||||||
# 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):
|
if not existsFile(pkgDestDir / bin):
|
||||||
copyFileD(realDir / bin, pkgDestDir / bin)
|
filesInstalled.incl copyFileD(realDir / bin, pkgDestDir / bin)
|
||||||
|
|
||||||
let currentPerms = getFilePermissions(pkgDestDir / bin)
|
let currentPerms = getFilePermissions(pkgDestDir / bin)
|
||||||
setFilePermissions(pkgDestDir / bin, currentPerms + {fpUserExec})
|
setFilePermissions(pkgDestDir / bin, currentPerms + {fpUserExec})
|
||||||
|
|
@ -341,11 +377,11 @@ proc installFromDir(dir: string, latest: bool, options: TOptions, url: string):
|
||||||
else:
|
else:
|
||||||
{.error: "Sorry, your platform is not supported.".}
|
{.error: "Sorry, your platform is not supported.".}
|
||||||
else:
|
else:
|
||||||
copyFilesRec(realDir, realDir, pkgDestDir, options, pkgInfo)
|
filesInstalled = copyFilesRec(realDir, realDir, pkgDestDir, options,
|
||||||
|
pkgInfo)
|
||||||
|
|
||||||
# Save a babelmeta.json file.
|
# Save a babelmeta.json file.
|
||||||
var babelmeta = %{"url": %url}
|
saveBabelMeta(pkgDestDir, url, filesInstalled)
|
||||||
writeFile(pkgDestDir / "babelmeta.json", $babelmeta)
|
|
||||||
|
|
||||||
result = paths # Return the paths to the dependencies of this package.
|
result = paths # Return the paths to the dependencies of this package.
|
||||||
result.add pkgDestDir
|
result.add pkgDestDir
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
# Copyright (C) Dominik Picheta. All rights reserved.
|
|
||||||
# BSD License. Look at license.txt for more info.
|
|
||||||
|
|
||||||
import os, osproc
|
|
||||||
|
|
||||||
type
|
|
||||||
EBabel* = object of EBase
|
|
||||||
|
|
||||||
proc copyFileD*(fro, to: string) =
|
|
||||||
echo(fro, " -> ", to)
|
|
||||||
copyFile(fro, to)
|
|
||||||
|
|
||||||
proc copyDirD*(fro, to: string) =
|
|
||||||
echo(fro, " -> ", to)
|
|
||||||
copyDir(fro, to)
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import parseutils, os, osproc, strutils, tables
|
import parseutils, os, osproc, strutils, tables
|
||||||
|
|
||||||
import packageinfo, common, version, tools
|
import packageinfo, version, tools
|
||||||
|
|
||||||
type
|
type
|
||||||
TDownloadMethod* {.pure.} = enum
|
TDownloadMethod* {.pure.} = enum
|
||||||
|
|
@ -210,4 +210,4 @@ proc echoPackageVersions*(pkg: TPackage) =
|
||||||
except EOS:
|
except EOS:
|
||||||
echo(getCurrentExceptionMsg())
|
echo(getCurrentExceptionMsg())
|
||||||
of TDownloadMethod.Hg:
|
of TDownloadMethod.Hg:
|
||||||
echo(" versions: (Remote tag retrieval not supported by " & pkg.downloadMethod & ")")
|
echo(" versions: (Remote tag retrieval not supported by " & pkg.downloadMethod & ")")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright (C) Dominik Picheta. All rights reserved.
|
# Copyright (C) Dominik Picheta. All rights reserved.
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
import parsecfg, json, streams, strutils, parseutils, os
|
import parsecfg, json, streams, strutils, parseutils, os
|
||||||
import version, common
|
import version, tools
|
||||||
type
|
type
|
||||||
TPackageInfo* = object
|
TPackageInfo* = object
|
||||||
mypath*: string ## The path of this .babel file
|
mypath*: string ## The path of this .babel file
|
||||||
|
|
@ -323,6 +323,13 @@ proc echoPackage*(pkg: TPackage) =
|
||||||
if pkg.web.len > 0:
|
if pkg.web.len > 0:
|
||||||
echo(" website: " & pkg.web)
|
echo(" website: " & pkg.web)
|
||||||
|
|
||||||
|
proc getDownloadDirName*(pkg: TPackage, verRange: PVersionRange): string =
|
||||||
|
result = pkg.name
|
||||||
|
let verSimple = getSimpleString(verRange)
|
||||||
|
if verSimple != "":
|
||||||
|
result.add "_"
|
||||||
|
result.add verSimple
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
doAssert getNameVersion("/home/user/.babel/libs/packagea-0.1") == ("packagea", "0.1")
|
doAssert getNameVersion("/home/user/.babel/libs/packagea-0.1") == ("packagea", "0.1")
|
||||||
doAssert getNameVersion("/home/user/.babel/libs/package-a-0.1") == ("package-a", "0.1")
|
doAssert getNameVersion("/home/user/.babel/libs/package-a-0.1") == ("package-a", "0.1")
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
# BSD License. Look at license.txt for more info.
|
# BSD License. Look at license.txt for more info.
|
||||||
#
|
#
|
||||||
# Various miscellaneous utility functions reside here.
|
# Various miscellaneous utility functions reside here.
|
||||||
import osproc, pegs, strutils, os, parseurl
|
import osproc, pegs, strutils, os, parseurl, sets
|
||||||
import version, common, packageinfo
|
import version, packageinfo
|
||||||
|
|
||||||
# TODO: Merge with common.nim?
|
type
|
||||||
|
EBabel* = object of EBase
|
||||||
|
|
||||||
proc doCmd*(cmd: string) =
|
proc doCmd*(cmd: string) =
|
||||||
let exitCode = execCmd(cmd)
|
let exitCode = execCmd(cmd)
|
||||||
|
|
@ -47,6 +48,19 @@ proc changeRoot*(origRoot, newRoot, path: string): string =
|
||||||
raise newException(EInvalidValue,
|
raise newException(EInvalidValue,
|
||||||
"Cannot change root of path: Path does not begin with original root.")
|
"Cannot change root of path: Path does not begin with original root.")
|
||||||
|
|
||||||
|
proc copyFileD*(fro, to: string): string =
|
||||||
|
## Returns the destination (``to``).
|
||||||
|
echo(fro, " -> ", to)
|
||||||
|
copyFile(fro, to)
|
||||||
|
result = to
|
||||||
|
|
||||||
|
proc copyDirD*(fro, to: string): seq[string] =
|
||||||
|
## Returns the filenames of the files in the directory that were copied.
|
||||||
|
result = @[]
|
||||||
|
echo("Copying directory: ", fro, " -> ", to)
|
||||||
|
for path in walkDirRec(fro):
|
||||||
|
result.add copyFileD(path, changeRoot(fro, to, path))
|
||||||
|
|
||||||
proc getDownloadDirName*(url: string, verRange: PVersionRange): string =
|
proc getDownloadDirName*(url: string, verRange: PVersionRange): string =
|
||||||
## Creates a directory name based on the specified ``url``
|
## Creates a directory name based on the specified ``url``
|
||||||
result = ""
|
result = ""
|
||||||
|
|
@ -68,9 +82,6 @@ proc getDownloadDirName*(url: string, verRange: PVersionRange): string =
|
||||||
result.add "_"
|
result.add "_"
|
||||||
result.add verSimple
|
result.add verSimple
|
||||||
|
|
||||||
proc getDownloadDirName*(pkg: TPackage, verRange: PVersionRange): string =
|
proc incl*(s: var TSet[string], v: seq[string] | TSet[string]) =
|
||||||
result = pkg.name
|
for i in v:
|
||||||
let verSimple = getSimpleString(verRange)
|
s.incl i
|
||||||
if verSimple != "":
|
|
||||||
result.add "_"
|
|
||||||
result.add verSimple
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue