Implements develop command. Refs #240.
This commit is contained in:
parent
84d63c8988
commit
56dd401831
12 changed files with 234 additions and 57 deletions
137
src/nimble.nim
137
src/nimble.nim
|
|
@ -306,7 +306,8 @@ proc buildFromDir(pkgInfo: PackageInfo, paths: seq[string], forRelease: bool) =
|
|||
buildFromDir(pkgInfo, paths, args)
|
||||
|
||||
proc saveNimbleMeta(pkgDestDir, url, vcsRevision: string,
|
||||
filesInstalled, bins: HashSet[string]) =
|
||||
filesInstalled, bins: HashSet[string],
|
||||
isLink: bool = false) =
|
||||
## Saves the specified data into a ``nimblemeta.json`` file inside
|
||||
## ``pkgDestDir``.
|
||||
##
|
||||
|
|
@ -314,6 +315,9 @@ proc saveNimbleMeta(pkgDestDir, url, vcsRevision: string,
|
|||
## installed.
|
||||
## bins - A list of binary filenames which have been installed for this
|
||||
## package.
|
||||
##
|
||||
## isLink - Determines whether the installed package is a .nimble-link.
|
||||
# TODO: Move to packageinstaller.nim
|
||||
var nimblemeta = %{"url": %url}
|
||||
if not vcsRevision.isNil:
|
||||
nimblemeta["vcsRevision"] = %vcsRevision
|
||||
|
|
@ -325,8 +329,20 @@ proc saveNimbleMeta(pkgDestDir, url, vcsRevision: string,
|
|||
nimblemeta["binaries"] = binaries
|
||||
for bin in bins:
|
||||
binaries.add(%bin)
|
||||
nimblemeta["isLink"] = %isLink
|
||||
writeFile(pkgDestDir / "nimblemeta.json", $nimblemeta)
|
||||
|
||||
proc saveNimbleMeta(pkgDestDir, pkgDir, vcsRevision: string) =
|
||||
## Overload of saveNimbleMeta for linked (.nimble-link) packages.
|
||||
##
|
||||
## pkgDestDir - The directory where the package has been installed.
|
||||
## For example: ~/.nimble/pkgs/jester-#head/
|
||||
##
|
||||
## pkgDir - The directory where the original package files are.
|
||||
## For example: ~/projects/jester/
|
||||
saveNimbleMeta(pkgDestDir, "file://" & pkgDir, vcsRevision,
|
||||
initSet[string](), initSet[string](), true)
|
||||
|
||||
proc removePkgDir(dir: string, options: Options) =
|
||||
## Removes files belonging to the package in ``dir``.
|
||||
try:
|
||||
|
|
@ -399,7 +415,6 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
|||
var pkgInfo = getPkgInfo(dir, options)
|
||||
let realDir = pkgInfo.getRealDir()
|
||||
let binDir = options.getBinDir()
|
||||
let pkgsDir = options.getPkgsDir()
|
||||
var depsOptions = options
|
||||
depsOptions.depsOnly = false
|
||||
|
||||
|
|
@ -421,12 +436,11 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
|||
# if the build fails then the old package will still be installed.
|
||||
if pkgInfo.bin.len > 0: buildFromDir(pkgInfo, result.paths, true)
|
||||
|
||||
let versionStr = '-' & pkgInfo.specialVersion
|
||||
|
||||
let pkgDestDir = pkgsDir / (pkgInfo.name & versionStr)
|
||||
let pkgDestDir = pkgInfo.getPkgDest(options)
|
||||
if existsDir(pkgDestDir) and existsFile(pkgDestDir / "nimblemeta.json"):
|
||||
if not options.prompt(pkgInfo.name & versionStr &
|
||||
" already exists. Overwrite?"):
|
||||
let msg = "$1@$2 already exists. Overwrite?" %
|
||||
[pkgInfo.name, pkgInfo.specialVersion]
|
||||
if not options.prompt(msg):
|
||||
raise NimbleQuit(msg: "")
|
||||
removePkgDir(pkgDestDir, options)
|
||||
# Remove any symlinked binaries
|
||||
|
|
@ -495,49 +509,6 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,
|
|||
display("Success:", pkgInfo.name & " installed successfully.",
|
||||
Success, HighPriority)
|
||||
|
||||
proc getNimbleTempDir(): string =
|
||||
## Returns a path to a temporary directory.
|
||||
##
|
||||
## The returned path will be the same for the duration of the process but
|
||||
## different for different runs of it. You have to make sure to create it
|
||||
## first. In release builds the directory will be removed when nimble finishes
|
||||
## its work.
|
||||
result = getTempDir() / "nimble_"
|
||||
when defined(windows):
|
||||
proc GetCurrentProcessId(): int32 {.stdcall, dynlib: "kernel32",
|
||||
importc: "GetCurrentProcessId".}
|
||||
result.add($GetCurrentProcessId())
|
||||
else:
|
||||
result.add($getpid())
|
||||
|
||||
proc downloadPkg(url: string, verRange: VersionRange,
|
||||
downMethod: DownloadMethod,
|
||||
options: Options): (string, Version) =
|
||||
## 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))
|
||||
createDir(downloadDir)
|
||||
var modUrl =
|
||||
if url.startsWith("git://") and options.config.cloneUsingHttps:
|
||||
"https://" & url[6 .. ^1]
|
||||
else: url
|
||||
|
||||
# Fixes issue #204
|
||||
# github + https + trailing url slash causes a
|
||||
# checkout/ls-remote to fail with Repository not found
|
||||
if modUrl.contains("github.com") and modUrl.endswith("/"):
|
||||
modUrl = modUrl[0 .. ^2]
|
||||
|
||||
display("Downloading", "$1 using $2" % [modUrl, $downMethod],
|
||||
priority = HighPriority)
|
||||
result = (
|
||||
downloadDir,
|
||||
doDownload(modUrl, downloadDir, verRange, downMethod, options)
|
||||
)
|
||||
|
||||
proc getDownloadInfo*(pv: PkgTuple, options: Options,
|
||||
doPrompt: bool): (DownloadMethod, string) =
|
||||
if pv.name.isURL:
|
||||
|
|
@ -931,6 +902,70 @@ proc listTasks(options: Options) =
|
|||
let nimbleFile = findNimbleFile(getCurrentDir(), true)
|
||||
nimscriptsupport.listTasks(nimbleFile, options)
|
||||
|
||||
proc developFromDir(dir: string, options: Options) =
|
||||
if options.depsOnly:
|
||||
raiseNimbleError("Cannot develop dependencies only.")
|
||||
|
||||
var pkgInfo = getPkgInfo(dir, options)
|
||||
if pkgInfo.bin.len > 0:
|
||||
if "nim" in pkgInfo.skipExt:
|
||||
raiseNimbleError("Cannot develop packages that are binaries only.")
|
||||
|
||||
display("Warning:", "This package's binaries will not be compiled " &
|
||||
"nor symlinked for development.", Warning, HighPriority)
|
||||
|
||||
# Overwrite the version to #head always.
|
||||
pkgInfo.specialVersion = "#head"
|
||||
|
||||
# Dependencies need to be processed before the creation of the pkg dir.
|
||||
discard processDeps(pkgInfo, options)
|
||||
|
||||
# This is similar to the code in `installFromDir`, except that we
|
||||
# *consciously* not worry about the package's binaries.
|
||||
let pkgDestDir = pkgInfo.getPkgDest(options)
|
||||
if existsDir(pkgDestDir) and existsFile(pkgDestDir / "nimblemeta.json"):
|
||||
let msg = "$1@$2 already exists. Overwrite?" %
|
||||
[pkgInfo.name, pkgInfo.specialVersion]
|
||||
if not options.prompt(msg):
|
||||
raise NimbleQuit(msg: "")
|
||||
removePkgDir(pkgDestDir, options)
|
||||
|
||||
createDir(pkgDestDir)
|
||||
# The .nimble-link file contains the path to the real .nimble file,
|
||||
# and a secondary path to the source directory of the package.
|
||||
# The secondary path is necessary so that the package's .nimble file doesn't
|
||||
# need to be read. This will mean that users will need to re-run
|
||||
# `nimble develop` if they change their `srcDir` but I think it's a worthy
|
||||
# compromise.
|
||||
let contents = pkgInfo.myPath & "\n" & pkgInfo.getRealDir()
|
||||
writeFile(pkgDestDir / pkgInfo.name.addFileExt("nimble-link"), contents)
|
||||
|
||||
# TODO: Handle dependencies of the package we are developing (they need to be
|
||||
# installed).
|
||||
|
||||
# Save a nimblemeta.json file.
|
||||
saveNimbleMeta(pkgDestDir, "file://" & dir, vcsRevisionInDir(dir))
|
||||
|
||||
# Save the nimble data (which might now contain reverse deps added in
|
||||
# processDeps).
|
||||
saveNimbleData(options)
|
||||
|
||||
proc develop(options: Options) =
|
||||
if options.action.packages == @[]:
|
||||
developFromDir(getCurrentDir(), options)
|
||||
else:
|
||||
# Install each package.
|
||||
for pv in options.action.packages:
|
||||
let downloadDir = getCurrentDir() / pv.name
|
||||
if dirExists(downloadDir):
|
||||
let msg = "Cannot clone into '$1': directory exists." % downloadDir
|
||||
let hint = "Remove the directory, or run this command somewhere else."
|
||||
raiseNimbleError(msg, hint)
|
||||
|
||||
let (meth, url) = getDownloadInfo(pv, options, true)
|
||||
discard downloadPkg(url, pv.ver, meth, options, downloadDir)
|
||||
developFromDir(downloadDir, options)
|
||||
|
||||
proc execHook(options: Options, before: bool): bool =
|
||||
## Returns whether to continue.
|
||||
result = true
|
||||
|
|
@ -1002,6 +1037,8 @@ proc doAction(options: Options) =
|
|||
dump(options)
|
||||
of actionTasks:
|
||||
listTasks(options)
|
||||
of actionDevelop:
|
||||
develop(options)
|
||||
of actionNil:
|
||||
assert false
|
||||
of actionCustom:
|
||||
|
|
|
|||
|
|
@ -212,6 +212,42 @@ proc doDownload*(url: string, downloadDir: string, verRange: VersionRange,
|
|||
|
||||
verifyClone()
|
||||
|
||||
proc downloadPkg*(url: string, verRange: VersionRange,
|
||||
downMethod: DownloadMethod,
|
||||
options: Options,
|
||||
downloadPath = ""): (string, Version) =
|
||||
## Downloads the repository as specified by ``url`` and ``verRange`` using
|
||||
## the download method specified.
|
||||
##
|
||||
## If `downloadPath` isn't specified a location in /tmp/ will be used.
|
||||
##
|
||||
## Returns the directory where it was downloaded and the concrete version
|
||||
## which was downloaded.
|
||||
let downloadDir =
|
||||
if downloadPath == "":
|
||||
(getNimbleTempDir() / getDownloadDirName(url, verRange))
|
||||
else:
|
||||
downloadPath
|
||||
|
||||
createDir(downloadDir)
|
||||
var modUrl =
|
||||
if url.startsWith("git://") and options.config.cloneUsingHttps:
|
||||
"https://" & url[6 .. ^1]
|
||||
else: url
|
||||
|
||||
# Fixes issue #204
|
||||
# github + https + trailing url slash causes a
|
||||
# checkout/ls-remote to fail with Repository not found
|
||||
if modUrl.contains("github.com") and modUrl.endswith("/"):
|
||||
modUrl = modUrl[0 .. ^2]
|
||||
|
||||
display("Downloading", "$1 using $2" % [modUrl, $downMethod],
|
||||
priority = HighPriority)
|
||||
result = (
|
||||
downloadDir,
|
||||
doDownload(modUrl, downloadDir, verRange, downMethod, options)
|
||||
)
|
||||
|
||||
proc echoPackageVersions*(pkg: Package) =
|
||||
let downMethod = pkg.downloadMethod.getDownloadMethod()
|
||||
case downMethod
|
||||
|
|
|
|||
|
|
@ -27,15 +27,16 @@ type
|
|||
actionNil, actionRefresh, actionInit, actionDump, actionPublish,
|
||||
actionInstall, actionSearch,
|
||||
actionList, actionBuild, actionPath, actionUninstall, actionCompile,
|
||||
actionDoc, actionCustom, actionTasks
|
||||
actionDoc, actionCustom, actionTasks, actionDevelop
|
||||
|
||||
Action* = object
|
||||
case typ*: ActionType
|
||||
of actionNil, actionList, actionPublish, actionTasks: nil
|
||||
of actionRefresh:
|
||||
optionalURL*: string # Overrides default package list.
|
||||
of actionInstall, actionPath, actionUninstall:
|
||||
packages*: seq[PkgTuple] # Optional only for actionInstall.
|
||||
of actionInstall, actionPath, actionUninstall, actionDevelop:
|
||||
packages*: seq[PkgTuple] # Optional only for actionInstall
|
||||
# and actionDevelop.
|
||||
of actionSearch:
|
||||
search*: seq[string] # Search string.
|
||||
of actionInit, actionDump:
|
||||
|
|
@ -56,6 +57,9 @@ Usage: nimble COMMAND [opts]
|
|||
Commands:
|
||||
install [pkgname, ...] Installs a list of packages.
|
||||
[-d, --depsOnly] Install only dependencies.
|
||||
develop [pkgname, ...] Clones a list of packages for development.
|
||||
Symlinks the cloned packages or any package
|
||||
in the current working directory.
|
||||
init [pkgname] Initializes a new Nimble project.
|
||||
publish Publishes a package on nim-lang/packages.
|
||||
The current working directory needs to be the
|
||||
|
|
@ -141,6 +145,8 @@ proc parseActionType*(action: string): ActionType =
|
|||
result = actionPublish
|
||||
of "tasks":
|
||||
result = actionTasks
|
||||
of "develop":
|
||||
result = actionDevelop
|
||||
else:
|
||||
result = actionCustom
|
||||
|
||||
|
|
@ -149,7 +155,7 @@ proc initAction*(options: var Options, key: string) =
|
|||
## `key`.
|
||||
let keyNorm = key.normalize()
|
||||
case options.action.typ
|
||||
of actionInstall, actionPath:
|
||||
of actionInstall, actionPath, actionDevelop, actionUninstall:
|
||||
options.action.packages = @[]
|
||||
of actionCompile, actionDoc, actionBuild:
|
||||
options.action.compileOptions = @[]
|
||||
|
|
@ -164,8 +170,6 @@ proc initAction*(options: var Options, key: string) =
|
|||
options.action.optionalURL = ""
|
||||
of actionSearch:
|
||||
options.action.search = @[]
|
||||
of actionUninstall:
|
||||
options.action.packages = @[]
|
||||
of actionCustom:
|
||||
options.action.command = key
|
||||
options.action.arguments = @[]
|
||||
|
|
|
|||
|
|
@ -497,6 +497,11 @@ proc iterInstallFiles*(realDir: string, pkgInfo: PackageInfo,
|
|||
|
||||
action(file)
|
||||
|
||||
proc getPkgDest*(pkgInfo: PackageInfo, options: Options): string =
|
||||
let versionStr = '-' & pkgInfo.specialVersion
|
||||
let pkgDestDir = options.getPkgsDir() / (pkgInfo.name & versionStr)
|
||||
return pkgDestDir
|
||||
|
||||
when isMainModule:
|
||||
doAssert getNameVersion("/home/user/.nimble/libs/packagea-0.1") ==
|
||||
("packagea", "0.1")
|
||||
|
|
|
|||
|
|
@ -141,3 +141,20 @@ proc contains*(j: JsonNode, elem: tuple[key: string, val: JsonNode]): bool =
|
|||
for key, val in pairs(j):
|
||||
if key == elem.key and val == elem.val:
|
||||
return true
|
||||
|
||||
when not defined(windows):
|
||||
from posix import getpid
|
||||
proc getNimbleTempDir*(): string =
|
||||
## Returns a path to a temporary directory.
|
||||
##
|
||||
## The returned path will be the same for the duration of the process but
|
||||
## different for different runs of it. You have to make sure to create it
|
||||
## first. In release builds the directory will be removed when nimble finishes
|
||||
## its work.
|
||||
result = getTempDir() / "nimble_"
|
||||
when defined(windows):
|
||||
proc GetCurrentProcessId(): int32 {.stdcall, dynlib: "kernel32",
|
||||
importc: "GetCurrentProcessId".}
|
||||
result.add($GetCurrentProcessId())
|
||||
else:
|
||||
result.add($getpid())
|
||||
1
tests/develop/binary/binary.nim
Normal file
1
tests/develop/binary/binary.nim
Normal file
|
|
@ -0,0 +1 @@
|
|||
echo("hello")
|
||||
14
tests/develop/binary/binary.nimble
Normal file
14
tests/develop/binary/binary.nimble
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Package
|
||||
|
||||
version = "1.0"
|
||||
author = "Dominik Picheta"
|
||||
description = "binary"
|
||||
license = "MIT"
|
||||
|
||||
bin = @["binary"]
|
||||
|
||||
skipExt = @["nim"]
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 0.16.0"
|
||||
1
tests/develop/hybrid/hybrid.nim
Normal file
1
tests/develop/hybrid/hybrid.nim
Normal file
|
|
@ -0,0 +1 @@
|
|||
echo("hello")
|
||||
12
tests/develop/hybrid/hybrid.nimble
Normal file
12
tests/develop/hybrid/hybrid.nimble
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Package
|
||||
|
||||
version = "1.0"
|
||||
author = "Dominik Picheta"
|
||||
description = "hybrid"
|
||||
license = "MIT"
|
||||
|
||||
bin = @["hybrid"]
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 0.16.0"
|
||||
1
tests/develop/srcdirtest/src/srcdirtest.nim
Normal file
1
tests/develop/srcdirtest/src/srcdirtest.nim
Normal file
|
|
@ -0,0 +1 @@
|
|||
echo("hello")
|
||||
12
tests/develop/srcdirtest/srcdirtest.nimble
Normal file
12
tests/develop/srcdirtest/srcdirtest.nimble
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Package
|
||||
|
||||
version = "1.0"
|
||||
author = "Dominik Picheta"
|
||||
description = "srcdir"
|
||||
license = "MIT"
|
||||
|
||||
srcDir = "src"
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 0.16.0"
|
||||
|
|
@ -460,4 +460,41 @@ test "can pass args with spaces to Nim (#351)":
|
|||
" -d:myVar=\"string with spaces\"" &
|
||||
" binaryPackage")
|
||||
checkpoint output
|
||||
check exitCode == QuitSuccess
|
||||
check exitCode == QuitSuccess
|
||||
|
||||
suite "develop feature":
|
||||
test "can reject binary packages":
|
||||
cd "develop/binary":
|
||||
let (output, exitCode) = execNimble("develop")
|
||||
checkpoint output
|
||||
check output.processOutput.inLines("cannot develop packages")
|
||||
check exitCode == QuitFailure
|
||||
|
||||
test "can develop hybrid":
|
||||
cd "develop/hybrid":
|
||||
let (output, exitCode) = execNimble("develop")
|
||||
checkpoint output
|
||||
check output.processOutput.inLines("will not be compiled")
|
||||
check exitCode == QuitSuccess
|
||||
|
||||
let path = installDir / "pkgs" / "hybrid-#head" / "hybrid.nimble-link"
|
||||
check fileExists(path)
|
||||
let split = readFile(path).splitLines()
|
||||
check split.len == 2
|
||||
check split[0].endsWith("develop/hybrid/hybrid.nimble")
|
||||
check split[1].endsWith("develop/hybrid")
|
||||
|
||||
test "can develop with srcDir":
|
||||
cd "develop/srcdirtest":
|
||||
let (output, exitCode) = execNimble("develop")
|
||||
checkpoint output
|
||||
check(not output.processOutput.inLines("will not be compiled"))
|
||||
check exitCode == QuitSuccess
|
||||
|
||||
let path = installDir / "pkgs" / "srcdirtest-#head" /
|
||||
"srcdirtest.nimble-link"
|
||||
check fileExists(path)
|
||||
let split = readFile(path).splitLines()
|
||||
check split.len == 2
|
||||
check split[0].endsWith("develop/srcdirtest/srcdirtest.nimble")
|
||||
check split[1].endsWith("develop/srcdirtest/src")
|
||||
Loading…
Add table
Add a link
Reference in a new issue