Skip to content

Commit

Permalink
add ux improvements for deps and other minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
elcritch committed Jan 9, 2025
1 parent 30e7014 commit f007e0b
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 79 deletions.
51 changes: 34 additions & 17 deletions src/nimble.nim
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ proc displaySatisfiedMsg(solvedPkgs: seq[SolvedPackage], pkgToInstall: seq[(stri
for pkg in solvedPkgs:
if pkg.pkgName notin pkgToInstall.mapIt(it[0]):
for req in pkg.requirements:
displayInfo(pkgDepsAlreadySatisfiedMsg(req))
displayInfo(pkgDepsAlreadySatisfiedMsg(req), MediumPriority)

proc displayUsingSpecialVersionWarning(solvedPkgs: seq[SolvedPackage], options: Options) =
var messages = newSeq[string]()
Expand Down Expand Up @@ -182,7 +182,7 @@ proc processFreeDependencies(pkgInfo: PackageInfo,

display("Verifying", "dependencies for $1@$2" %
[pkgInfo.basicInfo.name, $pkgInfo.basicInfo.version],
priority = HighPriority)
priority = LowPriority)

var reverseDependencies: seq[PackageBasicInfo] = @[]

Expand All @@ -208,7 +208,7 @@ proc processFreeDependencies(pkgInfo: PackageInfo,
resolvedDep.name)

if not found:
display("Installing", $resolvedDep, priority = HighPriority)
display("Installing", $resolvedDep, priority = MediumPriority)
let toInstall = @[(resolvedDep.name, resolvedDep.ver)]
let (packages, installedPkg) = install(toInstall, options,
doPrompt = false, first = false, fromLockFile = false,
Expand All @@ -230,7 +230,7 @@ proc processFreeDependencies(pkgInfo: PackageInfo,
# This package has been installed so we add it to our pkgList.
pkgList.add pkg
else:
displayInfo(pkgDepsAlreadySatisfiedMsg(dep))
displayInfo(pkgDepsAlreadySatisfiedMsg(dep), MediumPriority)
result.incl pkg
# Process the dependencies of this dependency.
let fullInfo = pkg.toFullInfo(options)
Expand Down Expand Up @@ -512,13 +512,13 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,

display("Installing", "$1@$2" %
[pkginfo.basicInfo.name, $pkginfo.basicInfo.version],
priority = HighPriority)
priority = MediumPriority)

let oldPkg = pkgInfo.packageExists(options)
if oldPkg.isSome:
# In the case we already have the same package in the cache then only merge
# the new package special versions to the old one.
displayWarning(pkgAlreadyExistsInTheCacheMsg(pkgInfo))
displayWarning(pkgAlreadyExistsInTheCacheMsg(pkgInfo), MediumPriority)
if not options.useSatSolver: #The dep path is not created when using the sat solver as packages are collected upfront
var oldPkg = oldPkg.get
oldPkg.metaData.specialVersions.incl pkgInfo.metaData.specialVersions
Expand Down Expand Up @@ -615,7 +615,7 @@ proc installFromDir(dir: string, requestedVer: VersionRange, options: Options,

pkgInfo.isInstalled = true

displaySuccess(pkgInstalledMsg(pkgInfo.basicInfo.name))
displaySuccess(pkgInstalledMsg(pkgInfo.basicInfo.name), MediumPriority)

result.deps.incl pkgInfo
result.pkg = pkgInfo
Expand Down Expand Up @@ -1925,9 +1925,25 @@ proc lock(options: Options) =
updateSyncFile(pkgInfo, options)
displayLockOperationFinish(lockExists)

proc depsTree(options: Options) =
proc depsTree(options: Options,
pkgInfo: PackageInfo,
dependencies: seq[PackageInfo],
errors: ValidationErrors) =
## Prints the dependency tree

if options.action.format == "json":
if options.action.depsAction == "inverted":
raise nimbleError("Deps JSON format does not support inverted tree")
echo (%depsRecursive(pkgInfo, dependencies, errors, options)).pretty
elif options.action.depsAction == "inverted":
printDepsHumanReadableInverted(pkgInfo, dependencies, errors, options)
elif options.action.depsAction == "tree":
printDepsHumanReadable(pkgInfo, dependencies, errors, options)
else:
printDepsHumanReadable(pkgInfo, dependencies, errors, options, true)

proc deps(options: Options) =
## handles deps actions
let pkgInfo = getPkgInfo(getCurrentDir(), options)

var errors = validateDevModeDepsWorkingCopiesBeforeLock(pkgInfo, options)
Expand All @@ -1942,12 +1958,10 @@ proc depsTree(options: Options) =
if not dependencyGraph.contains name:
errors.del name

if options.action.format == "json":
echo (%depsRecursive(pkgInfo, dependencies, errors)).pretty
elif options.action.format == "inverted":
printDepsHumanReadableInverted(pkgInfo, dependencies, errors)
if options.action.depsAction in ["", "tree", "inverted"]:
depsTree(options, pkgInfo, dependencies, errors)
else:
printDepsHumanReadable(pkgInfo, dependencies, errors)
raise nimbleError("Unknown deps flag: " & options.action.depsAction)

proc syncWorkingCopy(name: string, path: Path, dependentPkg: PackageInfo,
options: Options) =
Expand Down Expand Up @@ -2331,7 +2345,10 @@ proc doAction(options: var Options) =
init(options)
of actionPublish:
var pkgInfo = getPkgInfo(getCurrentDir(), options)
publish(pkgInfo, options)
if options.action.publishAction == "tags":
publishTags(pkgInfo, options)
else:
publish(pkgInfo, options)
of actionDump:
dump(options)
of actionTasks:
Expand All @@ -2343,7 +2360,7 @@ proc doAction(options: var Options) =
of actionLock:
lock(options)
of actionDeps:
depsTree(options)
deps(options)
of actionSync:
sync(options)
of actionSetup:
Expand Down Expand Up @@ -2493,8 +2510,8 @@ when isMainModule:
var opt: Options
try:
opt = parseCmdLine()
opt.setNimbleDir
opt.loadNimbleData
opt.setNimbleDir()
opt.loadNimbleData()
if opt.action.typ in {actionTasks, actionRun, actionBuild, actionCompile, actionDevelop}:
# Implicitly disable package validation for these commands.
opt.disableValidation = true
Expand Down
6 changes: 4 additions & 2 deletions src/nimblepkg/deps.nim
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ proc depsRecursive*(pkgInfo: PackageInfo,
proc printDepsHumanReadable*(pkgInfo: PackageInfo,
dependencies: seq[PackageInfo],
errors: ValidationErrors,
levelInfos: seq[tuple[skip: bool]] = @[]
directOnly = false,
levelInfos: seq[tuple[skip: bool]] = @[],
) =
## print human readable tree deps
##
Expand Down Expand Up @@ -82,7 +83,8 @@ proc printDepsHumanReadable*(pkgInfo: PackageInfo,
displayFormatted(Error, fmt" - error: {errMsg}")
if found:
var levelInfos = levelInfos & @[(skip: isLast)]
printDepsHumanReadable(depPkgInfo, dependencies, errors, levelInfos)
if not directOnly:
printDepsHumanReadable(depPkgInfo, dependencies, errors, directOnly, levelInfos)
if levelInfos.len() == 0:
displayFormatted(Hint, "\n")

Expand Down
117 changes: 68 additions & 49 deletions src/nimblepkg/download.nim
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,31 @@ proc doDownload(url, downloadDir: string, verRange: VersionRange,
result.vcsRevision = downloadDir.getVcsRevision
{.warning[ProveInit]: on.}

proc pkgDirHasNimble*(dir: string, options: Options): bool =
try:
discard findNimbleFile(dir, true, options)
return true
except NimbleError:
#Continue with the download
discard

proc downloadPkgDir*(url: string,
verRange: VersionRange,
subdir: string,
options: Options,
vcsRevision: Sha1Hash = notSetSha1Hash,
downloadPath: string = ""
): (string, string) =
let downloadDir =
if downloadPath == "":
(getNimbleTempDir() / getDownloadDirName(url, verRange, vcsRevision))
else:
downloadPath

createDir(downloadDir)

result = (downloadDir, downloadDir / subdir)

proc downloadPkg*(url: string, verRange: VersionRange,
downMethod: DownloadMethod,
subdir: string,
Expand All @@ -464,38 +489,21 @@ proc downloadPkg*(url: string, verRange: VersionRange,
## If specified this parameter will cause specific VCS revision to be
## checked out.

let (downloadDir, pkgDir) = downloadPkgDir(url, verRange, subdir, options, vcsRevision, downloadPath)
result.dir = pkgDir

#when using a persistent download dir we can skip the download if it's already done
if pkgDirHasNimble(result.dir, options):
return # already downloaded, skipping

if options.offline:
raise nimbleError("Cannot download in offline mode.")
let downloadDir =
if downloadPath == "":
(getNimbleTempDir() / getDownloadDirName(url, verRange, vcsRevision))
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]
let modUrl = modifyUrl(url, options.config.cloneUsingHttps)

let downloadMethod = if downloadTarball(modUrl, options):
"http" else: $downMethod

result.dir = downloadDir / subdir
#when using a persistent download dir we can skip the download if it's already done
try:
discard findNimbleFile(result.dir, true, options)
return
except NimbleError:
#Continue with the download
discard

if subdir.len > 0:
display("Downloading", "$1 using $2 (subdir is '$3')" %
[modUrl, downloadMethod, subdir],
Expand Down Expand Up @@ -584,35 +592,46 @@ proc refresh*(options: Options) =
for name, list in options.config.packageLists:
fetchList(list, options)

proc getDownloadInfo*(pv: PkgTuple, options: Options,
doPrompt: bool, ignorePackageCache = false): (DownloadMethod, string,
Table[string, string]) =
if pv.name.isURL:
let (url, metadata) = getUrlData(pv.name)
return (checkUrlType(url), url, metadata)
proc getDownloadInfo*(
pv: PkgTuple, options: Options,
doPrompt: bool,
ignorePackageCache = false,
): (DownloadMethod, string, Table[string, string]) =

# echo "getDownloadInfo:pv.name: ", $pv.name
var pkg = initPackage()
if getPackage(pv.name, options, pkg, ignorePackageCache):
let (url, metadata) = getUrlData(pkg.url)
result = (pkg.downloadMethod, url, metadata)
# echo "getDownloadInfo:getPackage: ", $result
return
elif pv.name.isURL:
# echo "getDownloadInfo:isURL:name: ", $pv.name
# echo "getDownloadInfo:isURL:options.nimbleData: ", $options.nimbleData
let (url, urlmeta) = getUrlData(pv.name)
var metadata = urlmeta
metadata["urlOnly"] = "true"
result = (checkUrlType(url), url, metadata)
# echo "getDownloadInfo:isURL: ", $result
return
elif pv.name.isForgeAlias:
let url = newForge(pv.name).expand()
return (checkUrlType(url), url, default(Table[string, string]))
else:
var pkg = initPackage()
if getPackage(pv.name, options, pkg, ignorePackageCache):
let (url, metadata) = getUrlData(pkg.url)
return (pkg.downloadMethod, url, metadata)
# If package is not found give the user a chance to refresh
# package.json
if doPrompt and not options.offline and
options.prompt(pv.name & " not found in any local packages.json, " &
"check internet for updated packages?"):
refresh(options)

# Once we've refreshed, try again, but don't prompt if not found
# (as we've already refreshed and a failure means it really
# isn't there)
# Also ignore the package cache so the old info isn't used
return getDownloadInfo(pv, options, false, true)
else:
# If package is not found give the user a chance to refresh
# package.json
if doPrompt and not options.offline and
options.prompt(pv.name & " not found in any local packages.json, " &
"check internet for updated packages?"):
refresh(options)

# Once we've refreshed, try again, but don't prompt if not found
# (as we've already refreshed and a failure means it really
# isn't there)
# Also ignore the package cache so the old info isn't used
return getDownloadInfo(pv, options, false, true)
else:
raise nimbleError(pkgNotFoundMsg(pv))
raise nimbleError(pkgNotFoundMsg(pv))

when isMainModule:
import unittest
Expand Down
29 changes: 22 additions & 7 deletions src/nimblepkg/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ type

Action* = object
case typ*: ActionType
of actionNil, actionList, actionPublish, actionTasks, actionCheck,
of actionNil, actionList, actionTasks, actionCheck,
actionSetup, actionClean, actionManual: nil
of actionSync:
listOnly*: bool
Expand Down Expand Up @@ -115,6 +115,9 @@ type
custRunFlags*: seq[string]
of actionDeps:
format*: string
depsAction*: string
of actionPublish:
publishAction*: string
of actionShellEnv, actionShell:
discard

Expand Down Expand Up @@ -239,9 +242,10 @@ Nimble Options:
--ver Query remote server for package version
information when searching or listing packages.
--nimbleDir:dirname Set the Nimble directory.
--nim:path Use specified path for Nim compiler
--silent Hide all Nimble and Nim output
--verbose Show all non-debug output.
--nim:path Use specified path for Nim compiler.
--silent Hide all Nimble and Nim output.
--info Show some informative output.
--verbose Show extra non-debugging output.
--debug Show all output including debug messages.
--offline Don't use network.
--noColor Don't colorise output.
Expand All @@ -251,11 +255,11 @@ Nimble Options:
--developFile Specifies the name of the develop file which
to be manipulated. If not present creates it.
--useSystemNim Use system nim and ignore nim from the lock
file if any
file if any.
--solver:sat|legacy Use the SAT solver (default) or the legacy for dependency resolution.
--requires Add extra packages to the dependency resolution. Uses the same syntax as the Nimble file. Example: nimble install --requires "pkg1; pkg2 >= 1.2"
--requires Add extra packages to the dependency resolution. Uses the same syntax as the Nimble file. Example: nimble install --requires "pkg1; pkg2 >= 1.2".
--disableNimBinaries Disable the use of nim precompiled binaries. Note in some platforms precompiled binaries are not available but the flag can still be used to avoid compile the Nim version once and reuse it.
--maximumTaggedVersions Maximum number of tags to check for a package when discovering versions for the SAT solver. 0 means all.
--maximumTaggedVersions Maximum number of tags to check for a package when discovering versions for the SAT solver. 0 means all.
For more information read the GitHub readme:
https://github.com/nim-lang/nimble#readme
"""
Expand Down Expand Up @@ -614,6 +618,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) =
of "reject", "n": result.forcePrompts = forcePromptNo
of "nimbledir": result.nimbleDir = val
of "silent": result.verbosity = SilentPriority
of "info": result.verbosity = MediumPriority
of "verbose": result.verbosity = LowPriority
of "debug": result.verbosity = DebugPriority
of "offline": result.offline = true
Expand Down Expand Up @@ -736,10 +741,20 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) =
result.action.listOnly = true
else:
wasFlagHandled = false
of actionPublish:
case f
of "tags":
result.action.publishAction = "tags"
else:
wasFlagHandled = false
of actionDeps:
case f
of "format":
result.action.format = val
of "tree":
result.action.depsAction = "tree"
of "inverted":
result.action.depsAction = "inverted"
else:
wasFlagHandled = false
else:
Expand Down
Loading

0 comments on commit f007e0b

Please sign in to comment.