This commit is contained in:
Dominik Picheta 2017-08-12 20:48:17 +01:00
commit ee34150d70
4 changed files with 106 additions and 48 deletions

View file

@ -13,7 +13,7 @@ from sequtils import toSeq
import nimblepkg/packageinfo, nimblepkg/version, nimblepkg/tools,
nimblepkg/download, nimblepkg/config, nimblepkg/common,
nimblepkg/publish, nimblepkg/options, nimblepkg/packageparser,
nimblepkg/cli
nimblepkg/cli, nimblepkg/packageinstaller
import nimblepkg/nimscriptsupport
@ -364,10 +364,21 @@ proc removePkgDir(dir: string, options: Options) =
display("Warning:", ("Cannot completely remove $1. Files not installed " &
"by nimble are present.") % dir, Warning, HighPriority)
# Remove binaries.
if nimblemeta.hasKey("binaries"):
# Remove binaries.
for binary in nimblemeta["binaries"]:
removeFile(options.getBinDir() / binary.str)
# Search for an older version of the package we are removing.
let (pkgName, _) = getNameVersion(dir)
let pkgList = getInstalledPkgsMin(options.getPkgsDir(), options)
var pkgInfo: PackageInfo
if pkgList.findPkg((pkgName, newVRAny()), pkgInfo):
pkgInfo = pkgInfo.toFullInfo(options)
for bin in pkgInfo.bin:
let symlinkDest = pkgInfo.getRealDir() / bin
let symlinkFilename = options.getBinDir() / bin.extractFilename
discard setupBinSymlink(symlinkDest, symlinkFilename)
else:
display("Warning:", ("Cannot completely remove $1. Binary symlinks may " &
"have been left over in $2.") %
@ -477,49 +488,11 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
filesInstalled.incl copyFileD(pkgInfo.getOutputDir(bin),
pkgDestDir / bin)
let currentPerms = getFilePermissions(pkgDestDir / bin)
setFilePermissions(pkgDestDir / bin, currentPerms + {fpUserExec})
let cleanBin = bin.extractFilename
when defined(unix):
display("Creating", "symlink: $1 -> $2" %
[pkgDestDir / bin, binDir / cleanBin], priority = MediumPriority)
if existsFile(binDir / cleanBin):
display("Warning:", "Symlink already exists in $1. Replacing." % binDir,
Warning, HighPriority)
removeFile(binDir / cleanBin)
createSymlink(pkgDestDir / bin, binDir / cleanBin)
binariesInstalled.incl(cleanBin)
elif defined(windows):
# There is a bug on XP, described here:
# http://stackoverflow.com/questions/2182568/batch-script-is-not-executed-if-chcp-was-called
# But this workaround brakes code page on newer systems, so we need to detect OS version
var osver = OSVERSIONINFO()
osver.dwOSVersionInfoSize = cast[DWORD](sizeof(OSVERSIONINFO))
if GetVersionExA(osver) == WINBOOL(0):
raise newException(NimbleError,
"Can't detect OS version: GetVersionExA call failed")
let fixChcp = osver.dwMajorVersion <= 5
# Create cmd.exe/powershell stub.
let dest = binDir / cleanBin.changeFileExt("cmd")
display("Creating", "stub: $1 -> $2" % [pkgDestDir / bin, dest],
priority = MediumPriority)
var contents = "@"
if options.config.chcp:
if fixChcp:
contents.add "chcp 65001 > nul && "
else: contents.add "chcp 65001 > nul\n@"
contents.add "\"" & pkgDestDir / bin & "\" %*\n"
writeFile(dest, contents)
binariesInstalled.incl(dest.extractFilename)
# For bash on Windows (Cygwin/Git bash).
let bashDest = dest.changeFileExt("")
display("Creating", "Cygwin stub: $1 -> $2" %
[pkgDestDir / bin, bashDest], priority = MediumPriority)
writeFile(bashDest, "\"" & pkgDestDir / bin & "\" \"$@\"\n")
binariesInstalled.incl(bashDest.extractFilename)
else:
{.error: "Sorry, your platform is not supported.".}
# Set up a symlink.
let symlinkDest = pkgDestDir / bin
let symlinkFilename = binDir / bin.extractFilename
for filename in setupBinSymlink(symlinkDest, symlinkFilename):
binariesInstalled.incl(filename)
let vcsRevision = vcsRevisionInDir(realDir)

View file

@ -300,7 +300,7 @@ proc getInstalledPkgsMin*(libsDir: string, options: Options):
## minimal. This has the advantage that it does not depend on the
## ``packageparser`` module, and so can be used by ``nimscriptsupport``.
##
## ``libsDir`` is in most cases: ~/.nimble/pkgs/
## ``libsDir`` is in most cases: ~/.nimble/pkgs/ (options.getPkgsDir)
result = @[]
for kind, path in walkDir(libsDir):
if kind == pcDir:

View file

@ -0,0 +1,52 @@
# Copyright (C) Dominik Picheta. All rights reserved.
# BSD License. Look at license.txt for more info.
import os, strutils
# Local imports
import cli
proc setupBinSymlink*(symlinkDest, symlinkFilename: string): seq[string] =
result = @[]
let currentPerms = getFilePermissions(symlinkDest)
setFilePermissions(symlinkDest, currentPerms + {fpUserExec})
when defined(unix):
display("Creating", "symlink: $1 -> $2" %
[symlinkDest, symlinkFilename], priority = MediumPriority)
if existsFile(symlinkFilename):
let msg = "Symlink already exists in $1. Replacing." % symlinkFilename
display("Warning:", msg, Warning, HighPriority)
removeFile(symlinkFilename)
createSymlink(symlinkDest, symlinkFilename)
result.add symlinkFilename.extractFilename
elif defined(windows):
# There is a bug on XP, described here:
# http://stackoverflow.com/questions/2182568/batch-script-is-not-executed-if-chcp-was-called
# But this workaround brakes code page on newer systems, so we need to detect OS version
var osver = OSVERSIONINFO()
osver.dwOSVersionInfoSize = cast[DWORD](sizeof(OSVERSIONINFO))
if GetVersionExA(osver) == WINBOOL(0):
raise newException(NimbleError,
"Can't detect OS version: GetVersionExA call failed")
let fixChcp = osver.dwMajorVersion <= 5
# Create cmd.exe/powershell stub.
let dest = symlinkFilename.changeFileExt("cmd")
display("Creating", "stub: $1 -> $2" % [symlinkDest, dest],
priority = MediumPriority)
var contents = "@"
if options.config.chcp:
if fixChcp:
contents.add "chcp 65001 > nul && "
else: contents.add "chcp 65001 > nul\n@"
contents.add "\"" & symlinkDest & "\" %*\n"
writeFile(dest, contents)
result.add dest.extractFilename
# For bash on Windows (Cygwin/Git bash).
let bashDest = dest.changeFileExt("")
display("Creating", "Cygwin stub: $1 -> $2" %
[symlinkDest, bashDest], priority = MediumPriority)
writeFile(bashDest, "\"" & symlinkDest & "\" \"$@\"\n")
result.add bashDest.extractFilename
else:
{.error: "Sorry, your platform is not supported.".}

View file

@ -43,7 +43,9 @@ proc inLines(lines: seq[string], line: string): bool =
test "picks #head when looking for packages":
cd "versionClashes" / "aporiaScenario":
check execNimble("install", "-y", "--verbose").exitCode == QuitSuccess
let (output, exitCode) = execNimble("install", "-y", "--verbose")
checkpoint output
check exitCode == QuitSuccess
check execNimble("remove", "aporiascenario", "-y").exitCode == QuitSuccess
check execNimble("remove", "packagea", "-y").exitCode == QuitSuccess
@ -419,4 +421,35 @@ test "can install diamond deps (#184)":
# reproduce #184.
let (output, exitCode) = execNimble("install", "-y")
checkpoint(output)
check exitCode == 0
check exitCode == 0
suite "can handle two binary versions":
setup:
cd "binaryPackage/v1":
check execNimble("install", "-y").exitCode == QuitSuccess
cd "binaryPackage/v2":
check execNimble("install", "-y").exitCode == QuitSuccess
test "can execute v2":
let (output, exitCode) =
execCmdEx(installDir / "bin" / "binaryPackage".addFileExt(ExeExt))
check exitCode == QuitSuccess
check output.strip() == "v2"
test "can update symlink to earlier version after removal":
check execNimble("remove", "binaryPackage@2.0", "-y").exitCode==QuitSuccess
let (output, exitCode) =
execCmdEx(installDir / "bin" / "binaryPackage".addFileExt(ExeExt))
check exitCode == QuitSuccess
check output.strip() == "v1"
test "can keep symlink version after earlier version removal":
check execNimble("remove", "binaryPackage@1.0", "-y").exitCode==QuitSuccess
let (output, exitCode) =
execCmdEx(installDir / "bin" / "binaryPackage".addFileExt(ExeExt))
check exitCode == QuitSuccess
check output.strip() == "v2"