Skip to content

Commit 279b8e1

Browse files
authored
Merge pull request #976 from bobeff/feature/run-package-executable
Add possibility to run executables from dependency packages
2 parents 23d3eea + 5da6164 commit 279b8e1

File tree

10 files changed

+152
-12
lines changed

10 files changed

+152
-12
lines changed

changelog.markdown

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This is a major release containing four new features:
1111
- Support for lock files.
1212
- Download tarballs when downloading packages from GitHub.
1313
- A setup command.
14+
- Added a `--package, -p` command line option.
1415

1516
## 0.13.0
1617

readme.markdown

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,12 @@ files.
427427
The `run` command can be used to build and run any binary specified in your
428428
package's `bin` list. The binary needs to be specified after any compilation flags
429429
if there are several binaries defined. Any flags after the binary or `--`
430-
are passed to the binary when it is run.
430+
are passed to the binary when it is run. It is possible to run a binary from some
431+
dependency package. To do this pass the `--package, -p` option to Nimble. For example:
432+
433+
```
434+
nimble --package:foo run <compilation_flags> bar <run_flags>
435+
```
431436

432437
### nimble c
433438

src/nimble.nim

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -703,14 +703,18 @@ proc getDependenciesPaths(pkgInfo: PackageInfo, options: Options):
703703
let deps = pkgInfo.processAllDependencies(options)
704704
return deps.map(dep => dep.getRealDir())
705705

706-
proc build(options: Options) =
707-
let dir = getCurrentDir()
708-
let pkgInfo = getPkgInfo(dir, options)
706+
proc build(pkgInfo: PackageInfo, options: Options) =
707+
## Builds the package `pkgInfo`.
709708
nimScriptHint(pkgInfo)
710709
let paths = pkgInfo.getDependenciesPaths(options)
711710
var args = options.getCompilationFlags()
712711
buildFromDir(pkgInfo, paths, args, options)
713712

713+
proc build(options: Options) =
714+
let dir = getCurrentDir()
715+
let pkgInfo = getPkgInfo(dir, options)
716+
pkgInfo.build(options)
717+
714718
proc clean(options: Options) =
715719
let dir = getCurrentDir()
716720
let pkgInfo = getPkgInfo(dir, options)
@@ -1846,21 +1850,40 @@ proc setup(options: Options) =
18461850
setupNimbleConfig(options)
18471851
setupVcsIgnoreFile()
18481852

1853+
proc getPackageForAction(pkgInfo: PackageInfo, options: Options): PackageInfo =
1854+
## Returns the `PackageInfo` for the package in `pkgInfo`'s dependencies tree
1855+
## with the name specified in `options.package`. If `options.package` is empty
1856+
## or it matches the name of the `pkgInfo` then `pkgInfo` is returned. Raises
1857+
## a `NimbleError` if the package with the provided name is not found.
1858+
1859+
result = initPackageInfo()
1860+
1861+
if options.package.len == 0 or pkgInfo.basicInfo.name == options.package:
1862+
return pkgInfo
1863+
1864+
let deps = pkgInfo.processAllDependencies(options)
1865+
for dep in deps:
1866+
if dep.basicInfo.name == options.package:
1867+
return dep.toFullInfo(options)
1868+
1869+
raise nimbleError(notFoundPkgWithNameInPkgDepTree(options.package))
1870+
18491871
proc run(options: Options) =
1850-
# Verify parameters.
18511872
var pkgInfo = getPkgInfo(getCurrentDir(), options)
1873+
pkgInfo = getPackageForAction(pkgInfo, options)
18521874

18531875
let binary = options.getCompilationBinary(pkgInfo).get("")
18541876
if binary.len == 0:
18551877
raise nimbleError("Please specify a binary to run")
18561878

18571879
if binary notin pkgInfo.bin:
1858-
raise nimbleError(
1859-
"Binary '$#' is not defined in '$#' package." % [binary, pkgInfo.basicInfo.name]
1860-
)
1880+
raise nimbleError(binaryNotDefinedInPkgMsg(binary, pkgInfo.basicInfo.name))
18611881

1862-
# Build the binary.
1863-
build(options)
1882+
if pkgInfo.isLink:
1883+
# If this is not installed package then build the binary.
1884+
pkgInfo.build(options)
1885+
elif options.getCompilationFlags.len > 0:
1886+
displayWarning(ignoringCompilationFlagsMsg)
18641887

18651888
let binaryPath = pkgInfo.getOutputDir(binary)
18661889
let cmd = quoteShellCommand(binaryPath & options.action.runFlags)

src/nimblepkg/displaymessages.nim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ const
3434
multipleDevelopFileOptionsGivenMsg* =
3535
"Multiple develop file options are given."
3636

37+
ignoringCompilationFlagsMsg* =
38+
"Ignoring compilation flags for installed package."
39+
3740
updatingTheLockFileMsg* = "Updating the lock file..."
3841
generatingTheLockFileMsg* = "Generating the lock file..."
3942
lockFileIsUpdatedMsg* = "The lock file is updated."
@@ -158,5 +161,12 @@ proc skipDownloadingInAlreadyExistingDirectoryMsg*(dir, name: string): string =
158161
&"The download directory \"{dir}\" already exists.\n" &
159162
&"Skipping the download of \"{name}\"."
160163

164+
proc binaryNotDefinedInPkgMsg*(binaryName, pkgName: string): string =
165+
&"Binary '{binaryName}' is not defined in '{pkgName}' package."
166+
167+
proc notFoundPkgWithNameInPkgDepTree*(pkgName: string): string =
168+
&"Not found package with name '{pkgName}' in the current package's " &
169+
"dependency tree."
170+
161171
proc pkgLinkFileSavedMsg*(path: string): string =
162172
&"Package link file \"{path}\" is saved."

src/nimblepkg/options.nim

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ type
4343
developLocaldeps*: bool # True if local deps + nimble develop pkg1 ...
4444
disableSslCertCheck*: bool
4545
enableTarballs*: bool # Enable downloading of packages as tarballs from GitHub.
46+
package*: string
47+
# For which package in the dependency tree the command should be executed.
48+
# If not provided by default it applies to the current directory package.
49+
# For now, it is used only by the run action and it is ignored by others.
4650

4751
ActionType* = enum
4852
actionNil, actionRefresh, actionInit, actionDump, actionPublish,
@@ -195,7 +199,12 @@ Nimble Options:
195199
-v, --version Print version information.
196200
-y, --accept Accept all interactive prompts.
197201
-n, --reject Reject all interactive prompts.
198-
-l, --localdeps Run in project local dependency mode
202+
-l, --localdeps Run in project local dependency mode.
203+
-p, --package For which package in the dependency tree the
204+
command should be executed. If not provided by
205+
default it applies to the current directory
206+
package. For now, it is used only by the run
207+
action and it is ignored by others.
199208
-t, --tarballs Enable downloading of packages as tarballs
200209
when working with GitHub repositories.
201210
--ver Query remote server for package version
@@ -494,6 +503,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) =
494503
of "localdeps", "l": result.localdeps = true
495504
of "nosslcheck": result.disableSslCertCheck = true
496505
of "tarballs", "t": result.enableTarballs = true
506+
of "package", "p": result.package = val
497507
else: isGlobalFlag = false
498508

499509
var wasFlagHandled = true
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
when isMainModule:
2+
import os
3+
for i in 1 .. paramCount():
4+
echo paramStr(i)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
proc foo* =
2+
echo "Hello from dependency.foo"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version = "0.1.0"
2+
author = "Ivan Bobev"
3+
description = "Test package."
4+
license = "MIT"
5+
6+
bin = @["binary"]
7+
8+
requires "nim >= 1.5.1"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version = "0.1.0"
2+
author = "Ivan Bobev"
3+
description = "Test package."
4+
license = "MIT"
5+
6+
requires "nim >= 1.5.1", "dependency"

tests/truncommand.nim

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
{.used.}
55

6-
import unittest, os, strutils
6+
import unittest, os, strutils, strformat
77
import testscommon
8+
import nimblepkg/displaymessages
89
from nimblepkg/common import cd
10+
from nimblepkg/developfile import developFileName
911

1012
suite "nimble run":
1113
test "Invalid binary":
@@ -162,3 +164,72 @@ suite "nimble run":
162164
[$DirSep, "run".changeFileExt(ExeExt)])
163165
check output.contains("""Testing `nimble run`: @["--test"]""")
164166
check output.contains("""Whee!""")
167+
168+
const
169+
testPkgsPath = "runDependencyBinary"
170+
dependencyPkgPath = testPkgsPath / "dependency"
171+
dependentPkgPath = testPkgsPath / "dependent"
172+
dependencyPkgBinary = dependencyPkgPath / "binary".addFileExt(ExeExt)
173+
dependentPkgDevelopFile = dependentPkgPath / developFileName
174+
packagesFilePath = "develop/packages.json"
175+
176+
test "Run binary from dependency in Nimble cache":
177+
cleanDir installDir
178+
cleanFile dependencyPkgBinary
179+
usePackageListFile(packagesFilePath):
180+
cd dependencyPkgPath:
181+
let (_, exitCode) = execNimble("install")
182+
check exitCode == QuitSuccess
183+
cd dependentPkgPath:
184+
let (output, exitCode) = execNimble("--package:dependency", "run",
185+
"-d:danger", "binary", "--arg1", "--arg2")
186+
check exitCode == QuitSuccess
187+
var lines = output.processOutput
188+
check lines.inLinesOrdered(ignoringCompilationFlagsMsg)
189+
check lines.inLinesOrdered("--arg1")
190+
check lines.inLinesOrdered("--arg2")
191+
192+
test "Run binary from develop mode dependency":
193+
cleanDir installDir
194+
cleanFiles dependencyPkgBinary, dependentPkgDevelopFile
195+
usePackageListFile(packagesFilePath):
196+
cd dependentPkgPath:
197+
var (output, exitCode) = execNimble("develop", "-a:../dependency")
198+
check exitCode == QuitSuccess
199+
(output, exitCode) = execNimble("--package:dependency", "run",
200+
"-d:danger", "binary", "--arg1", "--arg2")
201+
check exitCode == QuitSuccess
202+
var lines = output.processOutput
203+
const binaryName = when defined(windows): "binary.exe" else: "binary"
204+
check lines.inLinesOrdered(
205+
&"Building dependency/{binaryName} using c backend")
206+
check lines.inLinesOrdered("--arg1")
207+
check lines.inLinesOrdered("--arg2")
208+
209+
test "Error when specified package does not exist":
210+
cleanDir installDir
211+
cleanFile dependencyPkgBinary
212+
usePackageListFile(packagesFilePath):
213+
cd dependencyPkgPath:
214+
let (_, exitCode) = execNimble("install")
215+
check exitCode == QuitSuccess
216+
cd dependentPkgPath:
217+
let (output, exitCode) = execNimble("--package:dep", "run",
218+
"-d:danger", "binary", "--arg1", "--arg2")
219+
check exitCode == QuitFailure
220+
check output.contains(notFoundPkgWithNameInPkgDepTree("dep"))
221+
222+
test "Error when specified binary does not exist in specified package":
223+
cleanDir installDir
224+
cleanFile dependencyPkgBinary
225+
usePackageListFile(packagesFilePath):
226+
cd dependencyPkgPath:
227+
let (_, exitCode) = execNimble("install")
228+
check exitCode == QuitSuccess
229+
cd dependentPkgPath:
230+
let (output, exitCode) = execNimble("--package:dependency", "run",
231+
"-d:danger", "bin", "--arg1", "--arg2")
232+
check exitCode == QuitFailure
233+
const binaryName = when defined(windows): "bin.exe" else: "bin"
234+
check output.contains(binaryNotDefinedInPkgMsg(
235+
binaryName, "dependency"))

0 commit comments

Comments
 (0)