Skip to content

Commit

Permalink
tighten up paths
Browse files Browse the repository at this point in the history
  • Loading branch information
disruptek committed Nov 28, 2019
1 parent 57f906d commit 76555a0
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 70 deletions.
139 changes: 80 additions & 59 deletions src/nimph/config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ proc loadAllCfgs*(dir = ""): ConfigRef =
# maybe we should turn off configuration hints for these reads
when not defined(debug):
result.notes.excl hintConf
when defined(debugPaths):
result.notes.incl hintPath

# stuff the prefixDir so we load the compiler's config/nim.cfg
# just like the compiler would if we were to invoke it directly
Expand Down Expand Up @@ -179,53 +181,37 @@ proc newNimphConfig*(path: string): NimphConfig =
else:
result.toml = parseFile(path)

iterator packagePaths*(config: ConfigRef; exists = true): string =
## yield package paths from the configuration as /-terminated strings;
## if the exists flag is passed, then the path must also exist
if config == nil:
raise newException(Defect, "attempt to load search paths from nil config")
let
lib = config.libpath.string / ""
var
dedupe = newStringTable(modeStyleInsensitive)
for path in config.searchPaths:
let path = path.string / ""
if path.startsWith(lib):
continue
dedupe[path] = ""
for path in config.lazyPaths:
let path = path.string / ""
dedupe[path] = ""
for path in dedupe.keys:
if exists and not path.dirExists:
continue
yield path
template isStdLib*(config: ConfigRef; path: string): bool =
path.startsWith(config.libpath.string / "")

iterator likelySearch*(config: ConfigRef; repo: string): string =
## yield /-terminated directory paths likely added via --path
when defined(debug):
if repo != repo.absolutePath:
error &"repo {repo} wasn't normalized"
template isStdlib*(config: ConfigRef; path: AbsoluteDir): bool =
path.string.isStdLib

iterator likelySearch*(config: ConfigRef; libsToo: bool): string =
## yield /-terminated directory paths likely added via --path
for search in config.searchPaths.items:
let search = search.string / "" # cast from AbsoluteDir
# we don't care about library paths
if search.startsWith(config.libpath.string / ""):
if not libsToo and config.isStdLib(search):
continue
yield search

iterator likelySearch*(config: ConfigRef; repo: string; libsToo: bool): string =
## yield /-terminated directory paths likely added via --path
when defined(debug):
if repo != repo.absolutePath:
error &"repo {repo} wasn't normalized"

for search in config.likelySearch(libsToo = libsToo):
# limit ourselves to the repo?
when WhatHappensInVegas:
if search.startsWith(repo):
yield search
else:
yield search

iterator likelyLazy*(config: ConfigRef; repo: string; least = 0): string =
iterator likelyLazy*(config: ConfigRef; least = 0): string =
## yield /-terminated directory paths likely added via --nimblePath
when defined(debug):
if repo != repo.absolutePath:
error &"repo {repo} wasn't normalized"

# build a table of sightings of directories
var popular = newCountTable[string]()
for search in config.lazyPaths.items:
Expand All @@ -242,22 +228,59 @@ iterator likelyLazy*(config: ConfigRef; repo: string; least = 0): string =

# yield the directories that exist
for search, count in popular.pairs:
when false:
# if the directory doesn't exist, ignore it
if not dirExists(search):
continue

# maybe we can ignore unpopular paths
if least > count:
continue
yield search

iterator likelyLazy*(config: ConfigRef; repo: string; least = 0): string =
## yield /-terminated directory paths likely added via --nimblePath
when defined(debug):
if repo != repo.absolutePath:
error &"repo {repo} wasn't normalized"

for search in config.likelyLazy(least = least):
# limit ourselves to the repo?
when WhatHappensInVegas:
if search.startsWith(repo):
yield search
else:
yield search

iterator packagePaths*(config: ConfigRef; exists = true): string =
## yield package paths from the configuration as /-terminated strings;
## if the exists flag is passed, then the path must also exist.
## this should closely mimic the compiler's search

# the method by which we de-dupe paths
const mode =
when FilesystemCaseSensitive:
modeCaseSensitive
else:
modeCaseInsensitive
var
paths: seq[string]
dedupe = newStringTable(mode)

template addOne(p: AbsoluteDir) =
let path = path.string / ""
if path in dedupe:
continue
dedupe[path] = ""
paths.add path

if config == nil:
raise newException(Defect, "attempt to load search paths from nil config")

for path in config.searchPaths:
addOne(path)
for path in config.lazyPaths:
addOne(path)
for path in paths:
if exists and not path.dirExists:
continue
yield path

proc suggestNimbleDir*(config: ConfigRef; repo: string;
local = ""; global = ""): string =
## come up with a useful nimbleDir based upon what we find in the
Expand All @@ -271,16 +294,15 @@ proc suggestNimbleDir*(config: ConfigRef; repo: string;
# if a local directory is suggested, see if we can confirm its use
if local != "":
assert local.endsWith(DirSep)
for search in config.likelySearch(repo):
{.warning: "look for a nimble packages file here?".}
for search in config.likelySearch(repo, libsToo = false):
if search.startsWith(local):
result = local
break either

# otherwise, try to pick a global .nimble directory based upon lazy paths
for search in config.likelyLazy(repo):
#
# FIXME: maybe we should look for some nimble debris?
#
{.warning: "maybe we should look for some nimble debris?".}
if search.endsWith(PkgDir & DirSep):
result = search.parentDir # ie. the parent of pkgs
else:
Expand All @@ -295,10 +317,12 @@ proc suggestNimbleDir*(config: ConfigRef; repo: string;
break either

iterator pathSubstitutions(config: ConfigRef; path: string;
conf: string): string =
conf: string; write: bool): string =
## compute the possible path substitions, including the original path
const
substitutions = ["nimcache", "config", "projectpath", "lib", "nim", "home"]
readSubs = @["nimcache", "config", "nimbledir", "nimblepath",
"projectdir", "projectpath", "lib", "nim", "home"]
writeSubs = @["nimcache", "config", "projectdir", "lib", "nim", "home"]
var
matchedPath = false
when defined(debug):
Expand All @@ -307,6 +331,8 @@ iterator pathSubstitutions(config: ConfigRef; path: string;
let
path = path / ""
conf = if conf.dirExists: conf else: conf.parentDir
substitutions = if write: writeSubs else: readSubs

for sub in substitutions.items:
let attempt = config.pathSubs(&"${sub}", conf) / ""
# ignore any empty substitutions
Expand All @@ -324,7 +350,7 @@ iterator pathSubstitutions(config: ConfigRef; path: string;
proc bestPathSubstitution(config: ConfigRef; path: string; conf: string): string =
## compute the best path substitution, if any
block found:
for sub in config.pathSubstitutions(path, conf):
for sub in config.pathSubstitutions(path, conf, write = true):
result = sub
break found
result = path
Expand Down Expand Up @@ -355,7 +381,7 @@ proc removeSearchPath*(nimcfg: Target; path: string): bool =
for key, value in parsed.table.pairs:
if key.toLowerAscii notin ["p", "path", "nimblepath"]:
continue
for sub in cfg.get.pathSubstitutions(path, nimcfg.repo):
for sub in cfg.get.pathSubstitutions(path, nimcfg.repo, write = false):
if sub notin [value, value / ""]:
continue
let
Expand All @@ -377,18 +403,13 @@ proc addSearchPath*(config: ConfigRef; nimcfg: Target; path: string): bool =
proc excludeSearchPath*(nimcfg: Target; path: string): bool =
result = appendConfig(nimcfg, &"""--excludePath="{path}"""")

when false:
iterator extantSearchPaths*(config: ConfigRef; repo: string; least = 0): string =
if config == nil:
raise newException(Defect, "attempt to load search paths from nil config")
for path in config.likelySearch(repo):
if dirExists(path):
yield path
for path in config.likelyLazy(repo, least = least):
if dirExists(path):
yield path
else:
iterator extantSearchPaths*(config: ConfigRef;
repo: string; least = 0): string =
for path in config.packagePaths(exists = true):
iterator extantSearchPaths*(config: ConfigRef; least = 0): string =
## yield existing search paths from the configuration as /-terminated strings
if config == nil:
raise newException(Defect, "attempt to load search paths from nil config")
for path in config.likelySearch(libsToo = true):
if dirExists(path):
yield path
for path in config.likelyLazy(least = least):
if dirExists(path):
yield path
9 changes: 6 additions & 3 deletions src/nimph/doctor.nim
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ proc doctor*(project: var Project; dry = true): bool =
# try to parse all nim configuration files
block globalconfig:
when defined(debug):
for path in project.cfg.likelySearch(project.repo):
for path in project.cfg.likelySearch(libsToo = true):
debug &"\tsearch: {path}"
for path in project.cfg.likelyLazy(project.repo):
for path in project.cfg.likelyLazy:
debug &"\t lazy: {path}"
else:
## this space intentionally left blank
Expand Down Expand Up @@ -219,13 +219,16 @@ proc doctor*(project: var Project; dry = true): bool =
for target, linked in imports.pairs:
if group.isUsing(target):
continue
# ignore standard library targets
if project.cfg.isStdLib(target.repo):
continue
let name = linked.importName
warn &"seems like we're not using import `{name}` from {target.repo}"

# remove missing paths from nim.cfg if possible
block missingpaths:
# search paths that are missing should be removed/excluded
for path in likelySearch(project.cfg, project.repo):
for path in likelySearch(project.cfg, libsToo = false):
if dirExists(path):
continue
if dry:
Expand Down
13 changes: 5 additions & 8 deletions src/nimph/project.nim
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ iterator packageDirectories(project: Project): string =
## yield directories according to the project's path configuration
if project.parent != nil or project.cfg == nil:
raise newException(Defect, "nonsensical outside root project")
for directory in project.cfg.packagePaths:
for directory in project.cfg.packagePaths(exists = true):
yield directory

proc len*(group: ProjectGroup): int =
Expand Down Expand Up @@ -605,13 +605,13 @@ proc determineSearchPath(project: Project): string =
result = project.repo

iterator missingSearchPaths*(project: Project; target: Project): string =
## one (or more?) path to the target package which are
## one (or more?) paths to the target package which are
## apparently missing from the project's search paths
let
path = target.determineSearchPath / ""
block found:
for search in project.cfg.packagePaths(exists = false):
if search / "" == path:
if search == path:
break found
yield path

Expand Down Expand Up @@ -706,7 +706,7 @@ proc allImportTargets*(config: ConfigRef; repo: string):
## order that they appear in the parsed configuration? need test for this
result = newOrderedTable[Target, LinkedSearchResult]()

for path in config.extantSearchPaths(repo):
for path in config.extantSearchPaths:
let
target = linkedFindTarget(path, target = path.importName,
nimToo = true, ascend = false)
Expand All @@ -719,13 +719,10 @@ iterator asFoundVia*(group: ProjectGroup; config: ConfigRef;
repo: string): var Project =
## yield projects from the group in the same order that they may be
## resolved by the compiler, if at all, given a particular configuration
##
## FIXME: is it safe to assume that searchPaths are searched in the same
## order that they appear in the parsed configuration? need test for this
var
dedupe = newTable[string, Project](nextPowerOfTwo(group.len))

for path in config.extantSearchPaths(repo):
for path in config.packagePaths(exists = true):
let
target = linkedFindTarget(path, ascend = false)
found = target.search.found
Expand Down

0 comments on commit 76555a0

Please sign in to comment.