Implements #421.

This commit is contained in:
Dominik Picheta 2018-02-23 22:27:14 +00:00
commit 25ffe273f7
4 changed files with 54 additions and 31 deletions

View file

@ -434,13 +434,16 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
Success, HighPriority) Success, HighPriority)
proc getDownloadInfo*(pv: PkgTuple, options: Options, proc getDownloadInfo*(pv: PkgTuple, options: Options,
doPrompt: bool): (DownloadMethod, string) = doPrompt: bool): (DownloadMethod, string,
Table[string, string]) =
if pv.name.isURL: if pv.name.isURL:
return (checkUrlType(pv.name), pv.name) let (url, metadata) = getUrlData(pv.name)
return (checkUrlType(url), url, metadata)
else: else:
var pkg: Package var pkg: Package
if getPackage(pv.name, options, pkg): if getPackage(pv.name, options, pkg):
return (pkg.downloadMethod.getDownloadMethod(), pkg.url) let (url, metadata) = getUrlData(pkg.url)
return (pkg.downloadMethod.getDownloadMethod(), url, metadata)
else: else:
# If package is not found give the user a chance to refresh # If package is not found give the user a chance to refresh
# package.json # package.json
@ -464,9 +467,10 @@ proc install(packages: seq[PkgTuple],
else: else:
# Install each package. # Install each package.
for pv in packages: for pv in packages:
let (meth, url) = getDownloadInfo(pv, options, doPrompt) let (meth, url, metadata) = getDownloadInfo(pv, options, doPrompt)
let subdir = metadata.getOrDefault("subdir")
let (downloadDir, downloadVersion) = let (downloadDir, downloadVersion) =
downloadPkg(url, pv.ver, meth, options) downloadPkg(url, pv.ver, meth, subdir, options)
try: try:
# Run pre-install hook in download directory now that package is downloaded # Run pre-install hook in download directory now that package is downloaded
cd downloadDir: cd downloadDir:
@ -1005,8 +1009,9 @@ proc develop(options: Options) =
let hint = "Remove the directory, or run this command somewhere else." let hint = "Remove the directory, or run this command somewhere else."
raiseNimbleError(msg, hint) raiseNimbleError(msg, hint)
let (meth, url) = getDownloadInfo(pv, options, true) let (meth, url, metadata) = getDownloadInfo(pv, options, true)
discard downloadPkg(url, pv.ver, meth, options, downloadDir) let subdir = metadata.getOrDefault("subdir")
discard downloadPkg(url, pv.ver, meth, subdir, options, downloadDir)
developFromDir(downloadDir, options) developFromDir(downloadDir, options)
proc test(options: Options) = proc test(options: Options) =

View file

@ -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 parseutils, os, osproc, strutils, tables, pegs import parseutils, os, osproc, strutils, tables, pegs, uri
import packageinfo, packageparser, version, tools, common, options, cli import packageinfo, packageparser, version, tools, common, options, cli
@ -132,13 +132,24 @@ proc checkUrlType*(url: string): DownloadMethod =
elif doCmdEx("hg identify " & url).exitCode == QuitSuccess: elif doCmdEx("hg identify " & url).exitCode == QuitSuccess:
return DownloadMethod.hg return DownloadMethod.hg
else: else:
raise newException(NimbleError, "Unable to identify url.") raise newException(NimbleError, "Unable to identify url: " & url)
proc getUrlData*(url: string): (string, Table[string, string]) =
var uri = parseUri(url)
# TODO: use uri.parseQuery once it lands... this code is quick and dirty.
var subdir = ""
if uri.query.startsWith("subdir="):
subdir = uri.query[7 .. ^1]
uri.query = ""
return ($uri, {"subdir": subdir}.toTable())
proc isURL*(name: string): bool = 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, options: Options): Version = downMethod: DownloadMethod,
options: Options): Version =
## Downloads the repository specified by ``url`` using the specified download ## Downloads the repository specified by ``url`` using the specified download
## method. ## method.
## ##
@ -159,16 +170,6 @@ proc doDownload*(url: string, downloadDir: string, verRange: VersionRange,
# Result should already be set to #head here. # Result should already be set to #head here.
assert(not result.isNil) assert(not result.isNil)
proc verifyClone() =
## Makes sure that the downloaded package's version satisfies the requested
## version range.
let pkginfo = getPkgInfo(downloadDir, options)
if pkginfo.version.newVersion notin verRange:
raise newException(NimbleError,
"Downloaded package's version does not satisfy requested version " &
"range: wanted $1 got $2." %
[$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.
@ -197,8 +198,6 @@ 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.
verifyClone()
of DownloadMethod.hg: of DownloadMethod.hg:
doClone(downMethod, url, downloadDir) doClone(downMethod, url, downloadDir)
result = getHeadName(downMethod) result = getHeadName(downMethod)
@ -210,10 +209,9 @@ proc doDownload*(url: string, downloadDir: string, verRange: VersionRange,
priority = MediumPriority) priority = MediumPriority)
doCheckout(downMethod, downloadDir, latest.tag) doCheckout(downMethod, downloadDir, latest.tag)
verifyClone()
proc downloadPkg*(url: string, verRange: VersionRange, proc downloadPkg*(url: string, verRange: VersionRange,
downMethod: DownloadMethod, downMethod: DownloadMethod,
subdir: string,
options: Options, options: Options,
downloadPath = ""): (string, Version) = downloadPath = ""): (string, Version) =
## Downloads the repository as specified by ``url`` and ``verRange`` using ## Downloads the repository as specified by ``url`` and ``verRange`` using
@ -221,8 +219,8 @@ proc downloadPkg*(url: string, verRange: VersionRange,
## ##
## If `downloadPath` isn't specified a location in /tmp/ will be used. ## If `downloadPath` isn't specified a location in /tmp/ will be used.
## ##
## Returns the directory where it was downloaded and the concrete version ## Returns the directory where it was downloaded (subdir is appended) and
## which was downloaded. ## the concrete version which was downloaded.
let downloadDir = let downloadDir =
if downloadPath == "": if downloadPath == "":
(getNimbleTempDir() / getDownloadDirName(url, verRange)) (getNimbleTempDir() / getDownloadDirName(url, verRange))
@ -241,13 +239,28 @@ proc downloadPkg*(url: string, verRange: VersionRange,
if modUrl.contains("github.com") and modUrl.endswith("/"): if modUrl.contains("github.com") and modUrl.endswith("/"):
modUrl = modUrl[0 .. ^2] modUrl = modUrl[0 .. ^2]
display("Downloading", "$1 using $2" % [modUrl, $downMethod], if subdir.len > 0:
priority = HighPriority) display("Downloading", "$1 using $2 (subdir is '$3')" %
[modUrl, $downMethod, subdir],
priority = HighPriority)
else:
display("Downloading", "$1 using $2" % [modUrl, $downMethod],
priority = HighPriority)
result = ( result = (
downloadDir, downloadDir / subdir,
doDownload(modUrl, downloadDir, verRange, downMethod, options) doDownload(modUrl, downloadDir, verRange, downMethod, options)
) )
if verRange.kind != verSpecial:
## Makes sure that the downloaded package's version satisfies the requested
## version range.
let pkginfo = getPkgInfo(result[0], options)
if pkginfo.version.newVersion notin verRange:
raise newException(NimbleError,
"Downloaded package's version does not satisfy requested version " &
"range: wanted $1 got $2." %
[$verRange, $pkginfo.version])
proc echoPackageVersions*(pkg: Package) = proc echoPackageVersions*(pkg: Package) =
let downMethod = pkg.downloadMethod.getDownloadMethod() let downMethod = pkg.downloadMethod.getDownloadMethod()
case downMethod case downMethod

View file

@ -304,7 +304,7 @@ proc findNimbleFile*(dir: string; error: bool): string =
elif hits == 0: elif hits == 0:
if error: if error:
raise newException(NimbleError, raise newException(NimbleError,
"Specified directory does not contain a .nimble file.") "Specified directory ($1) does not contain a .nimble file." % dir)
else: else:
display("Warning:", "No .nimble or .nimble-link file found for " & display("Warning:", "No .nimble or .nimble-link file found for " &
dir, Warning, HighPriority) dir, Warning, HighPriority)

View file

@ -675,3 +675,8 @@ suite "check command":
check outp.processOutput.inLines("failure") check outp.processOutput.inLines("failure")
check outp.processOutput.inLines("validation failed") check outp.processOutput.inLines("validation failed")
check outp.processOutput.inLines("package 'x' has an incorrect structure") check outp.processOutput.inLines("package 'x' has an incorrect structure")
suite "multi":
test "can install package from git subdir":
let args = ["install", "-y", "https://github.com/nimble-test/multi?subdir=alpha"]
check execNimble(args).exitCode == QuitSuccess