Install #head if version tag does not compile. Fixes #139.

This commit is contained in:
Dominik Picheta 2015-06-04 22:18:35 +01:00
commit 5450dc8213
3 changed files with 73 additions and 42 deletions

View file

@ -467,8 +467,13 @@ proc buildFromDir(pkgInfo: PackageInfo, paths: seq[string], forRelease: bool) =
let outputOpt = "-o:\"" & pkgInfo.getOutputDir(bin) & "\"" let outputOpt = "-o:\"" & pkgInfo.getOutputDir(bin) & "\""
echo("Building ", pkginfo.name, "/", bin, " using ", pkgInfo.backend, echo("Building ", pkginfo.name, "/", bin, " using ", pkgInfo.backend,
" backend...") " backend...")
doCmd(getNimBin() & " $# $# --noBabelPath $# $# \"$#\"" % try:
[pkgInfo.backend, releaseOpt, args, outputOpt, realDir / bin.changeFileExt("nim")]) doCmd(getNimBin() & " $# $# --noBabelPath $# $# \"$#\"" %
[pkgInfo.backend, releaseOpt, args, outputOpt,
realDir / bin.changeFileExt("nim")])
except NimbleError:
raise newException(BuildFailed, "Build failed for package: " &
pkgInfo.name)
proc saveNimbleMeta(pkgDestDir, url: string, filesInstalled: HashSet[string]) = proc saveNimbleMeta(pkgDestDir, url: string, filesInstalled: HashSet[string]) =
var nimblemeta = %{"url": %url} var nimblemeta = %{"url": %url}
@ -608,28 +613,42 @@ proc getNimbleTempDir(): string =
result.add($getpid()) result.add($getpid())
proc downloadPkg(url: string, verRange: VersionRange, proc downloadPkg(url: string, verRange: VersionRange,
downMethod: DownloadMethod): string = downMethod: DownloadMethod): (string, VersionRange) =
## Downloads the repository as specified by ``url`` and ``verRange`` using
## the download method specified.
##
## Returns the directory where it was downloaded and the concrete version
## which was downloaded.
let downloadDir = (getNimbleTempDir() / getDownloadDirName(url, verRange)) let downloadDir = (getNimbleTempDir() / getDownloadDirName(url, verRange))
createDir(downloadDir) createDir(downloadDir)
echo("Downloading ", url, " into ", downloadDir, " using ", downMethod, "...") echo("Downloading ", url, " into ", downloadDir, " using ", downMethod, "...")
doDownload(url, downloadDir, verRange, downMethod) result = (downloadDir, doDownload(url, downloadDir, verRange, downMethod))
result = downloadDir
proc downloadPkg(pkg: Package, verRange: VersionRange): string = proc getDownloadInfo*(pv: PkgTuple, options: Options,
let downloadDir = (getNimbleTempDir() / getDownloadDirName(pkg, verRange)) doPrompt: bool): (DownloadMethod, string) =
let downMethod = pkg.downloadMethod.getDownloadMethod() if pv.name.isURL:
createDir(downloadDir) return (checkUrlType(pv.name), pv.name)
echo("Downloading ", pkg.name, " into ", downloadDir, " using ", downMethod, else:
"...") var pkg: Package
doDownload(pkg.url, downloadDir, verRange, downMethod) if getPackage(pv.name, options.getNimbleDir() / "packages.json", pkg):
result = downloadDir return (pkg.downloadMethod.getDownloadMethod(), pkg.url)
else:
# If package is not found give the user a chance to update
# package.json
if doPrompt and
options.prompt(pv.name & " not found in local packages.json, " &
"check internet for updated packages?"):
update(options)
return getDownloadInfo(pv, options, doPrompt)
else:
raise newException(NimbleError, "Package not found.")
proc install(packages: seq[PkgTuple], proc install(packages: seq[PkgTuple],
options: Options, options: Options,
doPrompt = true): tuple[paths: seq[string], pkg: PackageInfo] = doPrompt = true): tuple[paths: seq[string], pkg: PackageInfo] =
if packages == @[]: if packages == @[]:
result = installFromDir(getCurrentDir(), false, options, "") result = installFromDir(getCurrentDir(), false, options, "")
else: else:
# If packages.json is not present ask the user if they want to download it. # If packages.json is not present ask the user if they want to download it.
if not existsFile(options.getNimbleDir / "packages.json"): if not existsFile(options.getNimbleDir / "packages.json"):
if doPrompt and if doPrompt and
@ -641,25 +660,28 @@ proc install(packages: seq[PkgTuple],
# Install each package. # Install each package.
for pv in packages: for pv in packages:
if pv.name.isURL: let (meth, url) = getDownloadInfo(pv, options, doPrompt)
let meth = checkUrlType(pv.name) let (downloadDir, downloadVersion) = downloadPkg(url, pv.ver, meth)
let downloadDir = downloadPkg(pv.name, pv.ver, meth) try:
result = installFromDir(downloadDir, false, options, pv.name) result = installFromDir(downloadDir, false, options, url)
else: except BuildFailed:
var pkg: Package # The package failed to build.
if getPackage(pv.name, options.getNimbleDir() / "packages.json", pkg): # Check if we tried building a tagged version of the package.
let downloadDir = downloadPkg(pkg, pv.ver) if pv.ver.kind != verSpecial:
result = installFromDir(downloadDir, false, options, pkg.url) # If we tried building a tagged version of the package then
else: # ask the user whether they want to try building #head.
# If package is not found give the user a chance to update let promptResult = doPrompt and
# package.json options.prompt(("Build failed for '$1@$2', would you" &
if doPrompt and " like to try installing '$1@#head' (latest unstable)?") %
options.prompt(pv.name & " not found in local packages.json, " & [pv.name, $downloadVersion])
"check internet for updated packages?"): if promptResult:
update(options) let verRange = parseVersionRange("#" & getHeadName(meth))
result = install(@[pv], options, false) result = install(@[(pv.name, verRange)], options, doPrompt)
else: else:
raise newException(NimbleError, "Package not found.") raise newException(BuildFailed,
"Aborting installation due to build failure")
else:
raise
proc build(options: Options) = proc build(options: Options) =
var pkgInfo = getPkgInfo(getCurrentDir()) var pkgInfo = getPkgInfo(getCurrentDir())

View file

@ -5,7 +5,7 @@ import parseutils, os, osproc, strutils, tables, pegs
import packageinfo, version, tools, nimbletypes import packageinfo, version, tools, nimbletypes
type type
DownloadMethod* {.pure.} = enum DownloadMethod* {.pure.} = enum
git = "git", hg = "hg" git = "git", hg = "hg"
@ -106,11 +106,11 @@ proc getTagsListRemote*(url: string, meth: DownloadMethod): seq[string] =
let start = i.find("refs/tags/")+"refs/tags/".len let start = i.find("refs/tags/")+"refs/tags/".len
let tag = i[start .. i.len-1] let tag = i[start .. i.len-1]
if not tag.endswith("^{}"): result.add(tag) if not tag.endswith("^{}"): result.add(tag)
of DownloadMethod.hg: of DownloadMethod.hg:
# http://stackoverflow.com/questions/2039150/show-tags-for-remote-hg-repository # http://stackoverflow.com/questions/2039150/show-tags-for-remote-hg-repository
raise newException(ValueError, "Hg doesn't support remote tag querying.") raise newException(ValueError, "Hg doesn't support remote tag querying.")
proc getVersionList*(tags: seq[string]): Table[Version, string] = proc getVersionList*(tags: seq[string]): Table[Version, string] =
# Returns: TTable of version -> git tag name # Returns: TTable of version -> git tag name
result = initTable[Version, string]() result = initTable[Version, string]()
@ -147,18 +147,23 @@ proc isURL*(name: string): bool =
name.startsWith(peg" @'://' ") name.startsWith(peg" @'://' ")
proc doDownload*(url: string, downloadDir: string, verRange: VersionRange, proc doDownload*(url: string, downloadDir: string, verRange: VersionRange,
downMethod: DownloadMethod) = downMethod: DownloadMethod): VersionRange =
## Downloads the repository specified by ``url`` using the specified download
## method.
##
## Returns the version of the repository which has been downloaded.
template getLatestByTag(meth: stmt): stmt {.dirty, immediate.} = template getLatestByTag(meth: stmt): stmt {.dirty, immediate.} =
echo("Found tags...") echo("Found tags...")
# Find latest version that fits our ``verRange``. # Find latest version that fits our ``verRange``.
var latest = findLatest(verRange, versions) var latest = findLatest(verRange, versions)
## Note: HEAD is not used when verRange.kind is verAny. This is ## Note: HEAD is not used when verRange.kind is verAny. This is
## intended behaviour, the latest tagged version will be used in this case. ## intended behaviour, the latest tagged version will be used in this case.
# If no tagged versions satisfy our range latest.tag will be "". # If no tagged versions satisfy our range latest.tag will be "".
# We still clone in that scenario because we want to try HEAD in that case. # We still clone in that scenario because we want to try HEAD in that case.
# https://github.com/nimrod-code/nimble/issues/22 # https://github.com/nimrod-code/nimble/issues/22
meth meth
result = parseVersionRange($latest.ver)
proc verifyClone() = proc verifyClone() =
## Makes sure that the downloaded package's version satisfies the requested ## Makes sure that the downloaded package's version satisfies the requested
@ -169,7 +174,7 @@ proc doDownload*(url: string, downloadDir: string, verRange: VersionRange,
"Downloaded package's version does not satisfy requested version " & "Downloaded package's version does not satisfy requested version " &
"range: wanted $1 got $2." % "range: wanted $1 got $2." %
[$verRange, $pkginfo.version]) [$verRange, $pkginfo.version])
removeDir(downloadDir) removeDir(downloadDir)
if verRange.kind == verSpecial: if verRange.kind == verSpecial:
# We want a specific commit/branch/tag here. # We want a specific commit/branch/tag here.
@ -183,6 +188,7 @@ proc doDownload*(url: string, downloadDir: string, verRange: VersionRange,
else: else:
doClone(downMethod, url, downloadDir, tip = false) doClone(downMethod, url, downloadDir, tip = false)
doCheckout(downMethod, downloadDir, $verRange.spe) doCheckout(downMethod, downloadDir, $verRange.spe)
result = verRange
else: else:
case downMethod case downMethod
of DownloadMethod.git: of DownloadMethod.git:
@ -196,17 +202,19 @@ proc doDownload*(url: string, downloadDir: string, verRange: VersionRange,
else: else:
# If no commits have been tagged on the repo we just clone HEAD. # If no commits have been tagged on the repo we just clone HEAD.
doClone(downMethod, url, downloadDir) # Grab HEAD. doClone(downMethod, url, downloadDir) # Grab HEAD.
result = parseVersionRange("#head")
verifyClone() verifyClone()
of DownloadMethod.hg: of DownloadMethod.hg:
doClone(downMethod, url, downloadDir) doClone(downMethod, url, downloadDir)
result = parseVersionRange("#tip")
let versions = getTagsList(downloadDir, downMethod).getVersionList() let versions = getTagsList(downloadDir, downMethod).getVersionList()
if versions.len > 0: if versions.len > 0:
getLatestByTag: getLatestByTag:
echo("Switching to latest tagged version: ", latest.tag) echo("Switching to latest tagged version: ", latest.tag)
doCheckout(downMethod, downloadDir, latest.tag) doCheckout(downMethod, downloadDir, latest.tag)
verifyClone() verifyClone()
proc echoPackageVersions*(pkg: Package) = proc echoPackageVersions*(pkg: Package) =

View file

@ -5,3 +5,4 @@
type type
NimbleError* = object of Exception NimbleError* = object of Exception
BuildFailed* = object of NimbleError