Skip to content

Commit 5da6164

Browse files
authored
Merge branch 'master' into feature/run-package-executable
2 parents 5833669 + bc68d48 commit 5da6164

File tree

8 files changed

+170
-68
lines changed

8 files changed

+170
-68
lines changed

readme.markdown

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,11 @@ query parameter. For example:
228228
### nimble develop
229229

230230
The develop command is used for putting packages in a development mode. When
231-
executed with a list of packages it clones their repository. If it is
232-
executed in a package directory it adds cloned packages to the special
233-
`nimble.develop` file. This is a special file which is used for holding the
234-
paths to development mode dependencies of the current directory package. It has
235-
the following structure:
231+
executed with a list of packages it clones their repository. If it is executed
232+
in a package directory it adds cloned packages to the special `nimble.develop`
233+
file. This is a special file which is used for holding the paths to development
234+
mode dependencies of the current directory package. It has the following
235+
structure:
236236

237237
```json
238238
{
@@ -247,17 +247,15 @@ the following structure:
247247
* `dependencies` - JSON array of paths to Nimble packages directories.
248248

249249
The format for included develop files is the same as the project's develop
250-
file, but their validation works slightly different.
250+
file.
251251

252-
Validation rules:
252+
Develop files validation rules:
253253

254254
* The included develop files must be valid.
255-
* The packages listed in `dependencies` section must be dependencies required
256-
by the package's `.nimble` file and to be in the required by its version range.
257-
Transitive dependencies are not allowed, but this may be changed in the future.
258-
* The packages listed in the included develop files are required to be valid
259-
**Nimble** packages, but they are not required to be valid dependencies of the
260-
current project. In the latter case, they are simply ignored.
255+
* The packages listed in the `dependencies` section and in the included develop
256+
files are required to be valid **Nimble** packages, but they are not required
257+
to be valid dependencies of the current project. In the latter case, they are
258+
simply ignored.
261259
* The develop files of the develop mode dependencies of a package are being
262260
followed and processed recursively. Finally, only one common set of develop
263261
mode dependencies is created.
@@ -292,6 +290,9 @@ packages for which the develop command is executed.
292290
* `--develop-file` - Changes the name of the develop file which to be
293291
manipulated. It is useful for creating a free develop file which is not
294292
associated with any project intended for inclusion in some other develop file.
293+
* `-g, --global` - Creates an old style link file in the special `links`
294+
directory. It is read by Nim to be able to use global develop mode packages.
295+
Nimble uses it as a global develop file if a local one does not exist.
295296

296297
The options for manipulation of the develop files could be given only when
297298
executing `develop` command from some package's directory unless
@@ -300,16 +301,6 @@ executing `develop` command from some package's directory unless
300301
Because the develop files are user-specific and they contain local file system
301302
paths they **MUST NOT** be committed.
302303

303-
**Current limitations:**
304-
305-
* Currently transitive dependencies in the `dependencies` section of the
306-
develop file are not allowed. In the future, they should be allowed because
307-
this will allow using in develop mode some transitive package dependencies
308-
without having in develop mode the full dependency tree path to them. It was a
309-
design mistake that was not allowed at the beginning. The current workaround is
310-
to add the transitive dependency as a dependency in the project's `.nimble`
311-
file.
312-
313304
### nimble lock
314305

315306
The `nimble lock` command will generate or update a package lock file named

src/nimble.nim

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,21 @@ proc listTasks(options: Options) =
11701170

11711171
proc developAllDependencies(pkgInfo: PackageInfo, options: var Options)
11721172

1173+
proc saveLinkFile(pkgInfo: PackageInfo, options: Options) =
1174+
let
1175+
pkgName = pkgInfo.basicInfo.name
1176+
pkgLinkDir = options.getPkgsLinksDir / pkgName.getLinkFileDir
1177+
pkgLinkFilePath = pkgLinkDir / pkgName.getLinkFileName
1178+
pkgLinkFileContent = pkgInfo.myPath & "\n" & pkgInfo.getNimbleFileDir
1179+
1180+
if pkgLinkDir.dirExists and not options.prompt(
1181+
&"The link file for {pkgName} already exists. Overwrite?"):
1182+
return
1183+
1184+
pkgLinkDir.createDir
1185+
writeFile(pkgLinkFilePath, pkgLinkFileContent)
1186+
displaySuccess(pkgLinkFileSavedMsg(pkgLinkFilePath))
1187+
11731188
proc developFromDir(pkgInfo: PackageInfo, options: var Options) =
11741189
assert options.action.typ == actionDevelop,
11751190
"This procedure should be called only when executing develop sub-command."
@@ -1205,6 +1220,9 @@ proc developFromDir(pkgInfo: PackageInfo, options: var Options) =
12051220
# Dependencies need to be processed before the creation of the pkg dir.
12061221
discard processAllDependencies(pkgInfo, options)
12071222

1223+
if options.action.global:
1224+
saveLinkFile(pkgInfo, options)
1225+
12081226
displaySuccess(pkgSetupInDevModeMsg(pkgInfo.basicInfo.name, dir))
12091227

12101228
# Execute the post-develop hook.
@@ -1306,7 +1324,7 @@ proc updateSyncFile(dependentPkg: PackageInfo, options: Options)
13061324

13071325
proc updatePathsFile(pkgInfo: PackageInfo, options: Options) =
13081326
let paths = pkgInfo.getDependenciesPaths(options)
1309-
var pathsFileContent: string
1327+
var pathsFileContent = "--noNimblePath\n"
13101328
for path in paths:
13111329
pathsFileContent &= &"--path:{path.escape}\n"
13121330
var action = if fileExists(nimblePathsFileName): "updated" else: "generated"
@@ -1463,10 +1481,9 @@ proc check(options: Options) =
14631481
try:
14641482
let currentDir = getCurrentDir()
14651483
let pkgInfo = getPkgInfo(currentDir, options, true)
1466-
if currentDir.developFileExists:
1467-
validateDevelopFile(pkgInfo, options)
1468-
let dependencies = pkgInfo.processAllDependencies(options).toSeq
1469-
validateDevelopDependenciesVersionRanges(pkgInfo, dependencies, options)
1484+
validateDevelopFile(pkgInfo, options)
1485+
let dependencies = pkgInfo.processAllDependencies(options).toSeq
1486+
validateDevelopDependenciesVersionRanges(pkgInfo, dependencies, options)
14701487
displaySuccess(&"The package \"{pkgInfo.basicInfo.name}\" is valid.")
14711488
except CatchableError as error:
14721489
displayError(error)

src/nimblepkg/common.nim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type
2424
const
2525
nimbleVersion* = "0.14.0"
2626
nimblePackagesDirName* = "pkgs2"
27+
nimblePackagesLinksDirName* ="links"
2728
nimbleBinariesDirName* = "bin"
2829

2930
proc newNimbleError*[ErrorType](msg: string, hint = "",
@@ -77,3 +78,9 @@ template cdNewDir*(dir: string, body: untyped) =
7778
createNewDir dir
7879
cd dir:
7980
body
81+
82+
proc getLinkFileDir*(pkgName: string): string =
83+
pkgName & "-#head"
84+
85+
proc getLinkFileName*(pkgName: string): string =
86+
pkgName & ".nimble-link"

src/nimblepkg/developfile.nim

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ proc mergeFollowedDevFileData(lhs: var DevelopFileData, rhs: DevelopFileData,
307307
errors.collidingNames)
308308
309309
proc load(path: Path, dependentPkg: PackageInfo, options: Options,
310-
silentIfFileNotExists, raiseOnValidationErrors: bool):
310+
silentIfFileNotExists, raiseOnValidationErrors, loadGlobalDeps: bool):
311311
DevelopFileData
312312
313313
template load(dependentPkg: PackageInfo, args: varargs[untyped]):
@@ -318,8 +318,37 @@ template load(dependentPkg: PackageInfo, args: varargs[untyped]):
318318
dependentPkg.assertIsLoaded
319319
load(dependentPkg.getPkgDevFilePath, dependentPkg, args)
320320
321+
proc loadGlobalDependencies(result: var DevelopFileData,
322+
collidingNames: var CollidingNames,
323+
options: Options) =
324+
## Loads data from the `links` subdirectory in the Nimble cache. The links
325+
## in the cache are treated as paths in a global develop file used when a
326+
## local one does not exist.
327+
328+
for (kind, path) in walkDir(options.getPkgsLinksDir):
329+
if kind != pcDir:
330+
continue
331+
let (pkgName, _, _) = getNameVersionChecksum(path)
332+
let linkFilePath = path / pkgName.getLinkFileName
333+
if not linkFilePath.fileExists:
334+
displayWarning(&"Not found link file in \"{path}\".")
335+
continue
336+
let lines = linkFilePath.readFile.split("\n")
337+
if lines.len != 2:
338+
displayWarning(&"Invalid link file \"{linkFilePath}\".")
339+
continue
340+
let pkgPath = lines[1]
341+
let (pkgInfo, error) = validatePackage(pkgPath, options)
342+
if error == nil:
343+
let path = path.Path
344+
result.addPackage(pkgInfo, path, [path].toHashSet, collidingNames)
345+
else:
346+
displayWarning(
347+
&"Package \"{pkgName}\" at path \"{pkgPath}\" is invalid. Skipping it.")
348+
displayDetails(error.msg)
349+
321350
proc load(path: Path, dependentPkg: PackageInfo, options: Options,
322-
silentIfFileNotExists, raiseOnValidationErrors: bool):
351+
silentIfFileNotExists, raiseOnValidationErrors, loadGlobalDeps: bool):
323352
DevelopFileData =
324353
## Loads data from a develop file at path `path`.
325354
##
@@ -328,6 +357,10 @@ proc load(path: Path, dependentPkg: PackageInfo, options: Options,
328357
##
329358
## If `raiseOnValidationErrors` raises a `NimbleError` in the case some of the
330359
## contents of the develop file are invalid.
360+
##
361+
## If `loadGlobalDeps` then load the packages pointed by the link files in the
362+
## `links` directory in the Nimble cache instead of the once pointed by the
363+
## local develop file.
331364
##
332365
## Raises if the develop file or some of the included develop files:
333366
## - cannot be read.
@@ -343,9 +376,6 @@ proc load(path: Path, dependentPkg: PackageInfo, options: Options,
343376
result.path = path
344377
result.dependentPkg = dependentPkg
345378

346-
if silentIfFileNotExists and not path.fileExists:
347-
return
348-
349379
var
350380
errors {.global.}: ErrorsCollection
351381
visitedFiles {.global.}: HashSet[Path]
@@ -355,31 +385,38 @@ proc load(path: Path, dependentPkg: PackageInfo, options: Options,
355385
if dependentPkg.isLoaded:
356386
visitedPkgs.incl dependentPkg.getNimbleFileDir
357387

358-
try:
359-
fromJson(result.jsonData, parseFile(path), Joptions(allowExtraKeys: true))
360-
except ValueError as error:
361-
raise nimbleError(notAValidDevFileJsonMsg($path), details = error)
362-
363-
for depPath in result.jsonData.dependencies:
364-
let depPath = if depPath.isAbsolute:
365-
depPath.normalizedPath else: (path.splitFile.dir / depPath).normalizedPath
366-
let (pkgInfo, error) = validatePackage(depPath, options)
367-
if error == nil:
368-
result.addPackage(pkgInfo, path, [path].toHashSet, errors.collidingNames)
369-
else:
370-
errors.invalidPackages[depPath] = error
388+
if loadGlobalDeps:
389+
loadGlobalDependencies(result, errors.collidingNames, options)
390+
else:
391+
if silentIfFileNotExists and not path.fileExists:
392+
return
371393

372-
for inclPath in result.jsonData.includes:
373-
let inclPath = inclPath.normalizedPath
374-
if visitedFiles.contains(inclPath):
375-
continue
376-
var inclDevFileData = initDevelopFileData()
377394
try:
378-
inclDevFileData = load(inclPath, initPackageInfo(), options, false, false)
379-
except CatchableError as error:
380-
errors.invalidIncludeFiles[path] = error
381-
continue
382-
result.mergeIncludedDevFileData(inclDevFileData, errors)
395+
fromJson(result.jsonData, parseFile(path), Joptions(allowExtraKeys: true))
396+
except ValueError as error:
397+
raise nimbleError(notAValidDevFileJsonMsg($path), details = error)
398+
399+
for depPath in result.jsonData.dependencies:
400+
let depPath = if depPath.isAbsolute:
401+
depPath.normalizedPath else: (path.splitFile.dir / depPath).normalizedPath
402+
let (pkgInfo, error) = validatePackage(depPath, options)
403+
if error == nil:
404+
result.addPackage(pkgInfo, path, [path].toHashSet, errors.collidingNames)
405+
else:
406+
errors.invalidPackages[depPath] = error
407+
408+
for inclPath in result.jsonData.includes:
409+
let inclPath = inclPath.normalizedPath
410+
if visitedFiles.contains(inclPath):
411+
continue
412+
var inclDevFileData = initDevelopFileData()
413+
try:
414+
inclDevFileData = load(
415+
inclPath, initPackageInfo(), options, false, false, false)
416+
except CatchableError as error:
417+
errors.invalidIncludeFiles[path] = error
418+
continue
419+
result.mergeIncludedDevFileData(inclDevFileData, errors)
383420

384421
if result.dependentPkg.isLoaded and path.splitPath.tail == developFileName:
385422
# If this is a package develop file, but not a free one, for each of the
@@ -390,7 +427,7 @@ proc load(path: Path, dependentPkg: PackageInfo, options: Options,
390427
continue
391428
var followedPkgDevFileData = initDevelopFileData()
392429
try:
393-
followedPkgDevFileData = load(pkg[], options, true, false)
430+
followedPkgDevFileData = load(pkg[], options, true, false, false)
394431
except:
395432
# The errors will be accumulated in `errors` global variable and
396433
# reported by the `load` call which initiated the recursive process.
@@ -580,7 +617,7 @@ proc includeDevelopFile(data: var DevelopFileData, path: Path,
580617
581618
var inclFileData = initDevelopFileData()
582619
try:
583-
inclFileData = load(path, initPackageInfo(), options, false, true)
620+
inclFileData = load(path, initPackageInfo(), options, false, true, false)
584621
except CatchableError as error:
585622
displayError(failedToLoadFileMsg($path))
586623
displayDetails(error)
@@ -660,7 +697,7 @@ proc updateDevelopFile*(dependentPkg: PackageInfo, options: Options): bool =
660697
var
661698
hasError = false
662699
hasSuccessfulRemoves = false
663-
data = load(developFile, dependentPkg, options, true, true)
700+
data = load(developFile, dependentPkg, options, true, true, false)
664701
665702
defer:
666703
let writeEmpty = hasSuccessfulRemoves or
@@ -691,7 +728,8 @@ proc processDevelopDependencies*(dependentPkg: PackageInfo, options: Options):
691728
## Returns a sequence with the develop mode dependencies of the `dependentPkg`
692729
## and recursively all of their develop mode dependencies.
693730
694-
let data = load(dependentPkg, options, true, true)
731+
let loadGlobalDeps = not dependentPkg.getPkgDevFilePath.fileExists
732+
let data = load(dependentPkg, options, true, true, loadGlobalDeps)
695733
result = newSeqOfCap[PackageInfo](data.nameToPkg.len)
696734
for _, pkg in data.nameToPkg:
697735
result.add pkg[]
@@ -702,7 +740,8 @@ proc getDevelopDependencies*(dependentPkg: PackageInfo, options: Options):
702740
## mode dependencies of package `dependentPkg` and recursively all of their
703741
## develop mode dependencies.
704742
705-
let data = load(dependentPkg, options, true, true)
743+
let loadGlobalDeps = not dependentPkg.getPkgDevFilePath.fileExists
744+
let data = load(dependentPkg, options, true, true, loadGlobalDeps)
706745
return data.nameToPkg
707746
708747
type
@@ -908,6 +947,7 @@ proc validateDevelopFile*(dependentPkg: PackageInfo, options: Options) =
908947
## The procedure is used in the Nimble's `check` command to transitively
909948
## validate the contents of the develop files.
910949
911-
discard load(dependentPkg, options, true, true)
950+
let loadGlobalDeps = not dependentPkg.getPkgDevFilePath.fileExists
951+
discard load(dependentPkg, options, true, true, loadGlobalDeps)
912952
if dependentPkg.areLockedDepsLoaded:
913953
validateDevelopFileAgainstLockFile(dependentPkg, options)

src/nimblepkg/displaymessages.nim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,6 @@ proc binaryNotDefinedInPkgMsg*(binaryName, pkgName: string): string =
167167
proc notFoundPkgWithNameInPkgDepTree*(pkgName: string): string =
168168
&"Not found package with name '{pkgName}' in the current package's " &
169169
"dependency tree."
170+
171+
proc pkgLinkFileSavedMsg*(path: string): string =
172+
&"Package link file \"{path}\" is saved."

src/nimblepkg/download.nim

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@ type
1515
version: Version
1616
vcsRevision: Sha1Hash
1717

18+
proc updateSubmodules(dir: string) =
19+
discard tryDoCmdEx(
20+
&"git -C {dir} submodule update --init --recursive --depth 1")
21+
1822
proc doCheckout(meth: DownloadMethod, downloadDir, branch: string) =
1923
case meth
2024
of DownloadMethod.git:
2125
# Force is used here because local changes may appear straight after a clone
2226
# has happened. Like in the case of git on Windows where it messes up the
2327
# damn line endings.
24-
discard tryDoCmdEx(&"git -C {downloadDir} checkout --force {branch}")
25-
discard tryDoCmdEx(
26-
&"git -C {downloadDir} submodule update --recursive --depth 1")
28+
discard tryDoCmdEx(&"git -C {downloadDir} checkout --force {branch}")
29+
downloadDir.updateSubmodules
2730
of DownloadMethod.hg:
2831
discard tryDoCmdEx(&"hg --cwd {downloadDir} checkout {branch}")
2932

@@ -35,7 +38,8 @@ proc doClone(meth: DownloadMethod, url, downloadDir: string, branch = "",
3538
depthArg = if onlyTip: "--depth 1" else: ""
3639
branchArg = if branch == "": "" else: &"-b {branch}"
3740
discard tryDoCmdEx(
38-
&"git clone --recursive {depthArg} {branchArg} {url} {downloadDir}")
41+
"git clone --config core.autocrlf=false --recursive " &
42+
&"{depthArg} {branchArg} {url} {downloadDir}")
3943
of DownloadMethod.hg:
4044
let
4145
tipArg = if onlyTip: "-r tip " else: ""
@@ -143,10 +147,12 @@ proc cloneSpecificRevision(downloadMethod: DownloadMethod,
143147
let downloadDir = downloadDir.quoteShell
144148
createDir(downloadDir)
145149
discard tryDoCmdEx(&"git -C {downloadDir} init")
150+
discard tryDoCmdEx(&"git -C {downloadDir} config core.autocrlf false")
146151
discard tryDoCmdEx(&"git -C {downloadDir} remote add origin {url}")
147152
discard tryDoCmdEx(
148153
&"git -C {downloadDir} fetch --depth 1 origin {vcsRevision}")
149154
discard tryDoCmdEx(&"git -C {downloadDir} reset --hard FETCH_HEAD")
155+
downloadDir.updateSubmodules
150156
of DownloadMethod.hg:
151157
discard tryDoCmdEx(&"hg clone {url} -r {vcsRevision}")
152158

0 commit comments

Comments
 (0)