From f007e0beb6ec2d4793715bb1b608307f1c513d77 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 21:34:14 -0700 Subject: [PATCH 01/21] add ux improvements for deps and other minor changes --- src/nimble.nim | 51 ++++++++++------ src/nimblepkg/deps.nim | 6 +- src/nimblepkg/download.nim | 117 +++++++++++++++++++++---------------- src/nimblepkg/options.nim | 29 ++++++--- src/nimblepkg/publish.nim | 82 +++++++++++++++++++++++++- src/nimblepkg/vcstools.nim | 16 +++++ tests/testscommon.nim | 3 +- tests/tissues.nim | 2 +- 8 files changed, 227 insertions(+), 79 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index 639ccf77..64b19913 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -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]() @@ -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] = @[] @@ -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, @@ -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) @@ -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 @@ -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 @@ -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) @@ -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) = @@ -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: @@ -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: @@ -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 diff --git a/src/nimblepkg/deps.nim b/src/nimblepkg/deps.nim index 99819aca..cb970800 100644 --- a/src/nimblepkg/deps.nim +++ b/src/nimblepkg/deps.nim @@ -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 ## @@ -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") diff --git a/src/nimblepkg/download.nim b/src/nimblepkg/download.nim index 1e4106e8..9a93e4bb 100644 --- a/src/nimblepkg/download.nim +++ b/src/nimblepkg/download.nim @@ -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, @@ -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], @@ -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 diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index 8f913b0e..d9ff28cf 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -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 @@ -115,6 +115,9 @@ type custRunFlags*: seq[string] of actionDeps: format*: string + depsAction*: string + of actionPublish: + publishAction*: string of actionShellEnv, actionShell: discard @@ -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. @@ -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 """ @@ -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 @@ -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: diff --git a/src/nimblepkg/publish.nim b/src/nimblepkg/publish.nim index 8e4c7587..f79d9968 100644 --- a/src/nimblepkg/publish.nim +++ b/src/nimblepkg/publish.nim @@ -6,8 +6,8 @@ import system except TResult import httpclient, strutils, json, os, browsers, times, uri -import common, tools, cli, config, options, packageinfotypes -import strformat +import common, tools, cli, config, options, packageinfotypes, sha1hashes, version, download +import strformat, sequtils, pegs, sets {.warning[UnusedImport]: off.} from net import SslCVerifyMode, newContext @@ -247,3 +247,81 @@ proc publish*(p: PackageInfo, o: Options) = doCmd("git push https://" & auth.token & "@github.com/" & auth.user & "/packages " & branchName) let prUrl = createPullRequest(auth, p, url, branchName) display("Success:", "Pull request successful, check at " & prUrl , Success, HighPriority) + +proc vcsFindCommits*(repoDir, nimbleFile: string, downloadMethod: DownloadMethod): seq[(Sha1Hash, string)] = + var output: string + case downloadMethod: + of DownloadMethod.git: + output = tryDoCmdEx(&"git -C {repoDir} log --format=\"%H %s\" -- $2") + of DownloadMethod.hg: + assert false, "hg not supported" + + for line in output.splitLines(): + let line = line.strip() + if line != "": + result.add((line[0..39].initSha1Hash(), line[40..^1])) + +proc vcsDiff*(commit: Sha1Hash, repoDir, nimbleFile: string, downloadMethod: DownloadMethod): seq[string] = + case downloadMethod: + of DownloadMethod.git: + let (output, exitCode) = doCmdEx(&"git -C {repoDir} diff {commit}~ {commit} {nimbleFile}") + if exitCode != QuitSuccess: + return @[] + else: + return output.splitLines() + of DownloadMethod.hg: + assert false, "hg not supported" + +proc createTag*(tag: string, commit: Sha1Hash, message, repoDir, nimbleFile: string, downloadMethod: DownloadMethod): bool = + case downloadMethod: + of DownloadMethod.git: + let (output, code) = doCmdEx(&"git -C {repoDir} tag -a {tag.quoteShell()} {commit} -m {message.quoteShell()}") + result = code == QuitSuccess + if not result: + displayError(&"Failed to create tag {tag.quoteShell()} with error {output}") + of DownloadMethod.hg: + assert false, "hg not supported" + +proc findVersions(commits: seq[(Sha1Hash, string)], projdir, nimbleFile: string, downloadMethod: DownloadMethod) = + ## parse the versions + var + versions: HashSet[Version] + existingTags: HashSet[Version] + for tag in getTagsList(projdir, downloadMethod): + let tag = tag.strip(leading=true, chars={'v'}) + try: + existingTags.incl(newVersion(tag)) + except ParseVersionError: + discard + + # adapted from @beef331's algorithm https://github.com/beef331/graffiti/blob/master/src/graffiti.nim + for (commit, message) in commits: + # echo "commit: ", commit + let diffs = vcsDiff(commit, projdir, nimbleFile, downloadMethod) + for line in diffs: + var matches: array[0..MaxSubpatterns, string] + if line.find(peg"'+version' \s* '=' \s* {[\34\39]} {@} $1", matches) > -1: + let version = newVersion(matches[1]) + if version notin versions: + versions.incl(version) + if version in existingTags: + displayInfo(&"Found existing tag for version {version}", MediumPriority) + else: + displayInfo(&"Found new version {version} at {commit}", MediumPriority) + let res = createTag(&"v{version}", commit, message, projdir, nimbleFile, downloadMethod) + if not res: + displayError(&"Unable to create tag {version}") + +proc publishTags*(p: PackageInfo, o: Options) = + discard + echo "publishTags:myPath: ", $p.myPath + echo "publishTags:basic: ", $p.basicInfo + # echo "publishTags: ", $p + let (projdir, file, ext) = p.myPath.splitFile() + let nimblefile = file & ext + let dlmethod = p.metadata.downloadMethod + let commits = vcsFindCommits(projdir, nimbleFile, dlmethod) + echo "publishTags:commits: ", $commits.len() + + findVersions(commits, projdir, nimbleFile, dlmethod) + echo "" diff --git a/src/nimblepkg/vcstools.nim b/src/nimblepkg/vcstools.nim index 3defd1f2..e2b921ed 100644 --- a/src/nimblepkg/vcstools.nim +++ b/src/nimblepkg/vcstools.nim @@ -200,6 +200,22 @@ proc getVcsRevision*(dir: Path): Sha1Hash = return initSha1Hash(vcsRevision.strip(chars = Whitespace + {'+'})) +proc getVcsRevisions*(dir: Path): Sha1Hash = + ## Returns current revision number if the directory `dir` is under version + ## control, or an invalid Sha1 checksum otherwise. + ## + ## Raises a `NimbleError` if: + ## - the external command fails. + ## - the directory does not exist. + ## - there is no vcsRevisions in the repository. + + let vcsRevision = tryDoVcsCmd(dir, + gitCmd = "rev-parse HEAD", + hgCmd = "id -i --debug", + noVcsAction = $notSetSha1Hash) + + return initSha1Hash(vcsRevision.strip(chars = Whitespace + {'+'})) + proc getPackageFileListWithoutVcs(dir: Path): seq[string] = ## Recursively walks the directory `dir` and returns a list of files in it and ## its subdirectories. diff --git a/tests/testscommon.nim b/tests/testscommon.nim index b8e3c52c..09ea1d2d 100644 --- a/tests/testscommon.nim +++ b/tests/testscommon.nim @@ -29,9 +29,10 @@ let proc execNimble*(args: varargs[string]): ProcessOutput = var quotedArgs = @args + quotedArgs.insert("--info") + quotedArgs.insert("--noColor") if not args.anyIt("--nimbleDir:" in it or "-l" == it or "--local" == it): quotedArgs.insert("--nimbleDir:" & installDir) - quotedArgs.insert("--noColor") quotedArgs.insert(nimblePath) quotedArgs = quotedArgs.map((x: string) => x.quoteShell) diff --git a/tests/tissues.nim b/tests/tissues.nim index 6514a730..cd445713 100644 --- a/tests/tissues.nim +++ b/tests/tissues.nim @@ -40,7 +40,7 @@ suite "issues": if line.contains("issue799"): let nimbleInstallDir = getPackageDir( pkgsDir, &"nimble-{nimbleVersion}") - let pkgInstalledPath = "--path:'" & nimble_install_dir & "'" + let pkgInstalledPath = "--path:" & nimbleInstallDir.quoteShell & "" check line.contains(pkgInstalledPath) test "issue 793": From 08d786936c1b12cce100e22caf1e6de7751f6065 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 21:37:49 -0700 Subject: [PATCH 02/21] cleanup --- src/nimble.nim | 8 ++++---- src/nimblepkg/urls.nim | 14 +++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index 64b19913..5073a5b6 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1934,13 +1934,13 @@ proc depsTree(options: Options, 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 + echo (%depsRecursive(pkgInfo, dependencies, errors)).pretty elif options.action.depsAction == "inverted": - printDepsHumanReadableInverted(pkgInfo, dependencies, errors, options) + printDepsHumanReadableInverted(pkgInfo, dependencies, errors) elif options.action.depsAction == "tree": - printDepsHumanReadable(pkgInfo, dependencies, errors, options) + printDepsHumanReadable(pkgInfo, dependencies, errors) else: - printDepsHumanReadable(pkgInfo, dependencies, errors, options, true) + printDepsHumanReadable(pkgInfo, dependencies, errors, true) proc deps(options: Options) = ## handles deps actions diff --git a/src/nimblepkg/urls.nim b/src/nimblepkg/urls.nim index 4fca305c..c56d72b7 100644 --- a/src/nimblepkg/urls.nim +++ b/src/nimblepkg/urls.nim @@ -1,4 +1,16 @@ -import std/pegs +import std/pegs, std/strutils proc isURL*(name: string): bool = name.startsWith(peg" @'://' ") or name.startsWith(peg"\ident+'@'@':'.+") + +proc modifyUrl*(url: string, usingHttps: bool): string = + result = + if url.startsWith("git://") and usingHttps: + "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 result.contains("github.com") and result.endswith("/"): + result = result[0 .. ^2] From 152850dbfbc446aa4be78642a9516d7a075f8441 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 22:00:43 -0700 Subject: [PATCH 03/21] cleanup --- src/nimble.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index 5073a5b6..ef536ab8 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1925,7 +1925,7 @@ proc lock(options: Options) = updateSyncFile(pkgInfo, options) displayLockOperationFinish(lockExists) -proc depsTree(options: Options, +proc depsPrint(options: Options, pkgInfo: PackageInfo, dependencies: seq[PackageInfo], errors: ValidationErrors) = @@ -1959,7 +1959,7 @@ proc deps(options: Options) = errors.del name if options.action.depsAction in ["", "tree", "inverted"]: - depsTree(options, pkgInfo, dependencies, errors) + depsPrint(options, pkgInfo, dependencies, errors) else: raise nimbleError("Unknown deps flag: " & options.action.depsAction) From 742761c5bdbe95c1aba137dbabc9c66c1a245e44 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 22:09:49 -0700 Subject: [PATCH 04/21] revert getDownloadInfo --- src/nimblepkg/download.nim | 117 ++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 68 deletions(-) diff --git a/src/nimblepkg/download.nim b/src/nimblepkg/download.nim index 9a93e4bb..1e4106e8 100644 --- a/src/nimblepkg/download.nim +++ b/src/nimblepkg/download.nim @@ -445,31 +445,6 @@ 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, @@ -489,21 +464,38 @@ 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 - let modUrl = modifyUrl(url, options.config.cloneUsingHttps) + # 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 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], @@ -592,46 +584,35 @@ 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]) = - - # 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 +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) elif pv.name.isForgeAlias: let url = newForge(pv.name).expand() return (checkUrlType(url), url, default(Table[string, string])) 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) + var pkg = initPackage() + if getPackage(pv.name, options, pkg, ignorePackageCache): + let (url, metadata) = getUrlData(pkg.url) + return (pkg.downloadMethod, url, metadata) else: - raise nimbleError(pkgNotFoundMsg(pv)) + # 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)) when isMainModule: import unittest From e15bfd72dce197387b4f501d4bbff0356ca8a57d Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 22:41:47 -0700 Subject: [PATCH 05/21] Revert "revert getDownloadInfo" This reverts commit 742761c5bdbe95c1aba137dbabc9c66c1a245e44. --- src/nimblepkg/download.nim | 117 +++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 49 deletions(-) diff --git a/src/nimblepkg/download.nim b/src/nimblepkg/download.nim index 1e4106e8..9a93e4bb 100644 --- a/src/nimblepkg/download.nim +++ b/src/nimblepkg/download.nim @@ -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, @@ -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], @@ -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 From 52a9aba0e17aa328e9edb83441dc245c6066d848 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 22:42:06 -0700 Subject: [PATCH 06/21] cleanup options --- src/nimble.nim | 10 ++++++---- src/nimblepkg/options.nim | 32 +++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index ef536ab8..8768320d 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1023,7 +1023,7 @@ proc search(options: Options) = var found = false template onFound {.dirty.} = echoPackage(pkg) - if pkg.alias.len == 0 and options.queryVersions: + if pkg.alias.len == 0 and options.action.showVersions: echoPackageVersions(pkg) echo(" ") found = true @@ -1049,7 +1049,7 @@ proc list(options: Options) = let pkgList = getPackageList(options) for pkg in pkgList: echoPackage(pkg) - if pkg.alias.len == 0 and options.queryVersions: + if pkg.alias.len == 0 and options.action.listVersions: echoPackageVersions(pkg) echo(" ") @@ -2326,8 +2326,10 @@ proc doAction(options: var Options) = of actionSearch: search(options) of actionList: - if options.queryInstalled: listInstalled(options) - else: list(options) + if options.action.onlyInstalled: + listInstalled(options) + else: + list(options) of actionPath: listPaths(options) of actionBuild: diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index d9ff28cf..57bbe6d8 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -16,13 +16,13 @@ type NimBin* = object path*: string version*: Version + DumpMode* = enum kdumpIni, kdumpJson + Options* = object forcePrompts*: ForcePrompt depsOnly*: bool uninstallRevDeps*: bool - queryVersions*: bool - queryInstalled*: bool nimbleDir*: string verbosity*: cli.Priority action*: Action @@ -79,8 +79,9 @@ type Action* = object case typ*: ActionType - of actionNil, actionList, actionTasks, actionCheck, - actionSetup, actionClean, actionManual: nil + of actionNil, actionTasks, actionCheck, + actionSetup, actionClean, actionManual: + discard of actionSync: listOnly*: bool of actionRefresh: @@ -96,6 +97,11 @@ type global*: bool of actionSearch: search*: seq[string] # Search string. + showVersions*: bool + of actionList: + onlyNimBinaries*: bool + onlyInstalled*: bool + listVersions*: bool of actionInit, actionDump: projName*: string vcsOption*: string @@ -658,12 +664,20 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = var wasFlagHandled = true # Action-specific flags. case result.action.typ - of actionSearch, actionList: + of actionSearch: + case f + of "installed", "i": + result.action.onlyInstalled = true + of "versions", "ver": + result.action.showVersions = true + else: + wasFlagHandled = false + of actionList: case f of "installed", "i": - result.queryInstalled = true - of "ver": - result.queryVersions = true + result.action.onlyInstalled = true + of "versions": + result.action.showVersions = true else: wasFlagHandled = false of actionDump: @@ -674,7 +688,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = wasFlagHandled = false of actionInstall: case f - of "depsonly", "d": + of "depsonly", "deps", "d": result.depsOnly = true of "norebuild": result.action.noRebuild = true From 3b899ae7aa11df9460adcf0e77ba07e9f9660617 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 22:42:38 -0700 Subject: [PATCH 07/21] cleanup options --- src/nimblepkg/options.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index 57bbe6d8..0338d9da 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -676,7 +676,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = case f of "installed", "i": result.action.onlyInstalled = true - of "versions": + of "versions", "ver": result.action.showVersions = true else: wasFlagHandled = false From eb515c5f792da198565d5583e16cc341e2c8fb7e Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 22:44:27 -0700 Subject: [PATCH 08/21] cleanup options --- src/nimble.nim | 4 ++-- src/nimblepkg/options.nim | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index 8768320d..1d96e416 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1023,7 +1023,7 @@ proc search(options: Options) = var found = false template onFound {.dirty.} = echoPackage(pkg) - if pkg.alias.len == 0 and options.action.showVersions: + if pkg.alias.len == 0 and options.action.showSearchVersions: echoPackageVersions(pkg) echo(" ") found = true @@ -1049,7 +1049,7 @@ proc list(options: Options) = let pkgList = getPackageList(options) for pkg in pkgList: echoPackage(pkg) - if pkg.alias.len == 0 and options.action.listVersions: + if pkg.alias.len == 0 and options.action.showListVersions: echoPackageVersions(pkg) echo(" ") diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index 0338d9da..0e1b5d7a 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -97,11 +97,11 @@ type global*: bool of actionSearch: search*: seq[string] # Search string. - showVersions*: bool + showSearchVersions*: bool of actionList: onlyNimBinaries*: bool onlyInstalled*: bool - listVersions*: bool + showListVersions*: bool of actionInit, actionDump: projName*: string vcsOption*: string @@ -669,7 +669,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = of "installed", "i": result.action.onlyInstalled = true of "versions", "ver": - result.action.showVersions = true + result.action.showSearchVersions = true else: wasFlagHandled = false of actionList: @@ -677,7 +677,7 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = of "installed", "i": result.action.onlyInstalled = true of "versions", "ver": - result.action.showVersions = true + result.action.showListVersions = true else: wasFlagHandled = false of actionDump: From 98573473ce6aaf7dc0d6cb5716c12430dbb79deb Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 22:46:38 -0700 Subject: [PATCH 09/21] cleanup options --- src/nimblepkg/options.nim | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index 0e1b5d7a..e153a6e1 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -666,8 +666,6 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = case result.action.typ of actionSearch: case f - of "installed", "i": - result.action.onlyInstalled = true of "versions", "ver": result.action.showSearchVersions = true else: From c490e468ec4ffafcb2c56257a1d961da3909cc5e Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 22:56:14 -0700 Subject: [PATCH 10/21] print verify dependencies --- src/nimble.nim | 2 +- tests/ttaskdeps.nim | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nimble.nim b/src/nimble.nim index 1d96e416..18e56f49 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -182,7 +182,7 @@ proc processFreeDependencies(pkgInfo: PackageInfo, display("Verifying", "dependencies for $1@$2" % [pkgInfo.basicInfo.name, $pkgInfo.basicInfo.version], - priority = LowPriority) + priority = MediumPriority) var reverseDependencies: seq[PackageBasicInfo] = @[] diff --git a/tests/ttaskdeps.nim b/tests/ttaskdeps.nim index 3a1e43f2..a459ebe9 100644 --- a/tests/ttaskdeps.nim +++ b/tests/ttaskdeps.nim @@ -119,6 +119,7 @@ suite "Task level dependencies": test "Dependencies aren't verified twice": inDir: let (output, _) = execNimbleYes("test") + checkpoint("Failed test output: \n>>>" & output.replace("\n", "\n>>> ")) check output.count("dependencies for unittest2@0.0.4") == 1 test "Requirements for tasks in dependencies aren't used": From 5d7b34968454d592072d05d3a421b3c51a9a7cb9 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:17:52 -0700 Subject: [PATCH 11/21] prettify list --- src/nimble.nim | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index 18e56f49..b87e30bc 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1056,22 +1056,36 @@ proc list(options: Options) = proc listInstalled(options: Options) = type VersionChecksumTuple = tuple[version: Version, checksum: Sha1Hash] - var h: OrderedTable[string, seq[VersionChecksumTuple]] + var vers: OrderedTable[string, seq[VersionChecksumTuple]] let pkgs = getInstalledPkgsMin(options.getPkgsDir(), options) for pkg in pkgs: let pName = pkg.basicInfo.name pVersion = pkg.basicInfo.version pChecksum = pkg.basicInfo.checksum - if not h.hasKey(pName): h[pName] = @[] - var s = h[pName] + if not vers.hasKey(pName): vers[pName] = @[] + var s = vers[pName] add(s, (pVersion, pChecksum)) - h[pName] = s + vers[pName] = s - h.sort(proc (a, b: (string, seq[VersionChecksumTuple])): int = + vers.sort(proc (a, b: (string, seq[VersionChecksumTuple])): int = cmpIgnoreCase(a[0], b[0])) - for k in keys(h): - echo k & " [" & h[k].join(", ") & "]" + + displayInfo("Package list format: {PackageName} ") + displayInfo(" {Version} ({CheckSum})") + for k in keys(vers): + displayFormatted(Message, k) + displayFormatted(Hint, "\n") + for idx, item in vers[k]: + if idx == vers[k].len() - 1: + displayFormatted(Hint, "└── ") + else: + displayFormatted(Hint, "├── ") + displayFormatted(Success, "@", $item.version) + displayFormatted(Hint, " ") + displayFormatted(Details, fmt"({item.checksum})") + displayFormatted(Hint, "\n") + # " [" & vers[k].join(", ") & "]" type VersionAndPath = tuple[version: Version, path: string] From 5eaa2d1d0a5a58077744433d5defa93462161c2d Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:23:13 -0700 Subject: [PATCH 12/21] prettify list --- src/nimble.nim | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index b87e30bc..8be174b8 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1076,16 +1076,17 @@ proc listInstalled(options: Options) = for k in keys(vers): displayFormatted(Message, k) displayFormatted(Hint, "\n") - for idx, item in vers[k]: - if idx == vers[k].len() - 1: - displayFormatted(Hint, "└── ") - else: - displayFormatted(Hint, "├── ") - displayFormatted(Success, "@", $item.version) - displayFormatted(Hint, " ") - displayFormatted(Details, fmt"({item.checksum})") - displayFormatted(Hint, "\n") - # " [" & vers[k].join(", ") & "]" + if options.action.showListVersions: + for idx, item in vers[k]: + if idx == vers[k].len() - 1: + displayFormatted(Hint, "└── ") + else: + displayFormatted(Hint, "├── ") + displayFormatted(Success, "@", $item.version) + displayFormatted(Hint, " ") + displayFormatted(Details, fmt"({item.checksum})") + displayFormatted(Hint, "\n") + # " [" & vers[k].join(", ") & "]" type VersionAndPath = tuple[version: Version, path: string] From 2726a82e919681549bda8a6cb76e2faec70b83ca Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:25:10 -0700 Subject: [PATCH 13/21] prettify list --- src/nimblepkg/options.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index e153a6e1..f82c7533 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -202,8 +202,8 @@ Commands: performed by tag and by name. [--ver] Queries remote server for package version. list Lists all packages. - [--ver] Queries remote server for package version. [-i, --installed] Lists all installed packages. + [--ver, --version] Also display versions for packages. tasks Lists the tasks specified in the Nimble package's Nimble file. path pkgname ... Shows absolute path to the installed packages From 2302149c945fdfa765d399d5d1ba294d45fa0aff Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:25:19 -0700 Subject: [PATCH 14/21] prettify list --- src/nimblepkg/options.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index f82c7533..10c6ca6e 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -200,7 +200,7 @@ Commands: can be optionally specified. search pkg/tag Searches for a specified package. Search is performed by tag and by name. - [--ver] Queries remote server for package version. + [--ver, --version] Queries remote server for package version. list Lists all packages. [-i, --installed] Lists all installed packages. [--ver, --version] Also display versions for packages. From cd6f7b055b2eb1466028facd9eb957c0e2861faa Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:33:49 -0700 Subject: [PATCH 15/21] prettify list --- src/nimblepkg/packageinfo.nim | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/nimblepkg/packageinfo.nim b/src/nimblepkg/packageinfo.nim index 0f9ee04d..08e10c83 100644 --- a/src/nimblepkg/packageinfo.nim +++ b/src/nimblepkg/packageinfo.nim @@ -389,16 +389,24 @@ proc getOutputDir*(pkgInfo: PackageInfo, bin: string): string = result &= ".out" proc echoPackage*(pkg: Package) = - echo(pkg.name & ":") + displayFormatted(Message, pkg.name & ":") + displayFormatted(Hint, "\n") + + proc displayInfoLine(field, msg: string) = + displayFormatted(Success, field) + displayFormatted(Details, msg) + displayFormatted(Hint, "\n") + if pkg.alias.len > 0: - echo(" Alias for ", pkg.alias) + displayFormatted(Warning, " Alias for ", pkg.alias) + displayFormatted(Hint, "\n") else: - echo(" url: " & pkg.url & " (" & $pkg.downloadMethod & ")") - echo(" tags: " & pkg.tags.join(", ")) - echo(" description: " & pkg.description) - echo(" license: " & pkg.license) + displayInfoLine(" url: ", pkg.url & " (" & $pkg.downloadMethod & ")") + displayInfoLine(" tags: ", pkg.tags.join(", ")) + displayInfoLine(" description: ", pkg.description) + displayInfoLine(" license: ", pkg.license) if pkg.web.len > 0: - echo(" website: " & pkg.web) + displayInfoLine(" website: ", pkg.web) proc getDownloadDirName*(pkg: Package, verRange: VersionRange): string = result = pkg.name From 0ba360e2e93c72098fd3f78c071b8b7d98381b07 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:40:27 -0700 Subject: [PATCH 16/21] prettify list --- src/nimblepkg/download.nim | 17 ++++++++++++----- src/nimblepkg/options.nim | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/nimblepkg/download.nim b/src/nimblepkg/download.nim index 9a93e4bb..c3ed9285 100644 --- a/src/nimblepkg/download.nim +++ b/src/nimblepkg/download.nim @@ -526,6 +526,11 @@ proc downloadPkg*(url: string, verRange: VersionRange, [$verRange, $pkginfo.basicInfo.version]) proc echoPackageVersions*(pkg: Package) = + proc displayInfoLine(field, msg: string) = + displayFormatted(Success, field) + displayFormatted(Details, msg) + displayFormatted(Hint, "\n") + let downMethod = pkg.downloadMethod case downMethod of DownloadMethod.git: @@ -533,14 +538,16 @@ proc echoPackageVersions*(pkg: Package) = let versions = getTagsListRemote(pkg.url, downMethod).getVersionList() if versions.len > 0: let sortedVersions = toSeq(values(versions)) - echo(" versions: " & join(sortedVersions, ", ")) + displayInfoLine(" versions: ", join(sortedVersions, ", ")) else: - echo(" versions: (No versions tagged in the remote repository)") + displayInfoLine(" versions: ", "(No versions tagged in the remote repository)") except CatchableError: - echo(getCurrentExceptionMsg()) + displayFormatted(Error, " Error: ") + displayFormatted(Error, getCurrentExceptionMsg()) + displayFormatted(Hint, "\n") of DownloadMethod.hg: - echo(" versions: (Remote tag retrieval not supported by " & - $pkg.downloadMethod & ")") + displayInfoLine(" versions: ", "(Remote tag retrieval not supported by " & + $pkg.downloadMethod & ")") proc removeTrailingSlash(s: string): string = s.strip(chars = {'/'}, leading = false) diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index 10c6ca6e..ee5833ed 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -204,6 +204,7 @@ Commands: list Lists all packages. [-i, --installed] Lists all installed packages. [--ver, --version] Also display versions for packages. + [-n, --nimbinaries] Lists all installed packages. tasks Lists the tasks specified in the Nimble package's Nimble file. path pkgname ... Shows absolute path to the installed packages From 40c54b41afacf338253728341a8032110e1fda34 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:41:30 -0700 Subject: [PATCH 17/21] prettify list --- src/nimblepkg/download.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nimblepkg/download.nim b/src/nimblepkg/download.nim index c3ed9285..06ed2b46 100644 --- a/src/nimblepkg/download.nim +++ b/src/nimblepkg/download.nim @@ -528,7 +528,7 @@ proc downloadPkg*(url: string, verRange: VersionRange, proc echoPackageVersions*(pkg: Package) = proc displayInfoLine(field, msg: string) = displayFormatted(Success, field) - displayFormatted(Details, msg) + displayFormatted(Warning, msg) displayFormatted(Hint, "\n") let downMethod = pkg.downloadMethod From 570c875a69fe634abc33dc563df011572266a401 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:58:43 -0700 Subject: [PATCH 18/21] prettify list --- src/nimble.nim | 20 +++++++++++++++++++- src/nimblepkg/cli.nim | 6 ++++++ src/nimblepkg/download.nim | 5 ----- src/nimblepkg/packageinfo.nim | 15 ++++----------- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index 8be174b8..522ed556 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1053,6 +1053,21 @@ proc list(options: Options) = echoPackageVersions(pkg) echo(" ") +proc listNimBinaries(options: Options) = + let nimBininstalledPkgs = getInstalledPkgsMin(options.nimBinariesDir, options) + displayFormatted(Message, "nim") + displayFormatted(Hint, "\n") + for idx, pkg in nimBininstalledPkgs: + assert pkg.basicInfo.name == "nim" + if idx == nimBininstalledPkgs.len() - 1: + displayFormatted(Hint, "└── ") + else: + displayFormatted(Hint, "├── ") + displayFormatted(Success, "version ") + displayFormatted(Details, $pkg.basicInfo.version) + displayFormatted(Hint, "\n") + # echoPackageVersions(pkg) + proc listInstalled(options: Options) = type VersionChecksumTuple = tuple[version: Version, checksum: Sha1Hash] @@ -1072,7 +1087,8 @@ proc listInstalled(options: Options) = cmpIgnoreCase(a[0], b[0])) displayInfo("Package list format: {PackageName} ") - displayInfo(" {Version} ({CheckSum})") + displayInfo(" {PackageName} ") + displayInfo(" {Version} ({CheckSum})") for k in keys(vers): displayFormatted(Message, k) displayFormatted(Hint, "\n") @@ -2343,6 +2359,8 @@ proc doAction(options: var Options) = of actionList: if options.action.onlyInstalled: listInstalled(options) + elif options.action.onlyNimBinaries: + listNimBinaries(options) else: list(options) of actionPath: diff --git a/src/nimblepkg/cli.nim b/src/nimblepkg/cli.nim index 759a6ed7..a09b8e0e 100644 --- a/src/nimblepkg/cli.nim +++ b/src/nimblepkg/cli.nim @@ -62,12 +62,18 @@ proc isSuppressed(displayType: DisplayType): bool = return true proc displayFormatted*(displayType: DisplayType, msgs: varargs[string]) = + ## for styling outputs lines using the DisplayTypes for msg in msgs: if globalCLI.showColor: stdout.styledWrite(foregrounds[displayType], msg) else: stdout.write(msg) +proc displayInfoLine*(field, msg: string) = + displayFormatted(Success, field) + displayFormatted(Details, msg) + displayFormatted(Hint, "\n") + proc displayCategory(category: string, displayType: DisplayType, priority: Priority) = if isSuppressed(displayType): diff --git a/src/nimblepkg/download.nim b/src/nimblepkg/download.nim index 06ed2b46..d2323fef 100644 --- a/src/nimblepkg/download.nim +++ b/src/nimblepkg/download.nim @@ -526,11 +526,6 @@ proc downloadPkg*(url: string, verRange: VersionRange, [$verRange, $pkginfo.basicInfo.version]) proc echoPackageVersions*(pkg: Package) = - proc displayInfoLine(field, msg: string) = - displayFormatted(Success, field) - displayFormatted(Warning, msg) - displayFormatted(Hint, "\n") - let downMethod = pkg.downloadMethod case downMethod of DownloadMethod.git: diff --git a/src/nimblepkg/packageinfo.nim b/src/nimblepkg/packageinfo.nim index 08e10c83..b27e4472 100644 --- a/src/nimblepkg/packageinfo.nim +++ b/src/nimblepkg/packageinfo.nim @@ -392,11 +392,6 @@ proc echoPackage*(pkg: Package) = displayFormatted(Message, pkg.name & ":") displayFormatted(Hint, "\n") - proc displayInfoLine(field, msg: string) = - displayFormatted(Success, field) - displayFormatted(Details, msg) - displayFormatted(Hint, "\n") - if pkg.alias.len > 0: displayFormatted(Warning, " Alias for ", pkg.alias) displayFormatted(Hint, "\n") @@ -408,12 +403,10 @@ proc echoPackage*(pkg: Package) = if pkg.web.len > 0: displayInfoLine(" website: ", pkg.web) -proc getDownloadDirName*(pkg: Package, verRange: VersionRange): string = - result = pkg.name - let verSimple = getSimpleString(verRange) - if verSimple != "": - result.add "_" - result.add verSimple +proc echoPackage*(pkg: PackageInfo) = + displayFormatted(Message, pkg.basicInfo.name & ":") + displayFormatted(Hint, "\n") + proc checkInstallFile(pkgInfo: PackageInfo, origDir, file: string): bool = From 69888df6de45ba8fd423ce5de1b2e7de4113a8cb Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 8 Jan 2025 23:59:24 -0700 Subject: [PATCH 19/21] prettify list --- src/nimblepkg/options.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nimblepkg/options.nim b/src/nimblepkg/options.nim index ee5833ed..ead8d180 100644 --- a/src/nimblepkg/options.nim +++ b/src/nimblepkg/options.nim @@ -675,6 +675,8 @@ proc parseFlag*(flag, val: string, result: var Options, kind = cmdLongOption) = case f of "installed", "i": result.action.onlyInstalled = true + of "nimbinaries", "n": + result.action.onlyNimBinaries = true of "versions", "ver": result.action.showListVersions = true else: From ea533d71ad8a7a6ed69878e8f6d53504d6a6a71f Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Thu, 9 Jan 2025 00:06:23 -0700 Subject: [PATCH 20/21] prettify list --- src/nimble.nim | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/nimble.nim b/src/nimble.nim index 522ed556..f4228bbb 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1063,10 +1063,11 @@ proc listNimBinaries(options: Options) = displayFormatted(Hint, "└── ") else: displayFormatted(Hint, "├── ") - displayFormatted(Success, "version ") - displayFormatted(Details, $pkg.basicInfo.version) + displayFormatted(Success, "@" & $pkg.basicInfo.version) + displayFormatted(Hint, " ") + displayFormatted(Details, fmt"({pkg.myPath})") displayFormatted(Hint, "\n") - # echoPackageVersions(pkg) + displayFormatted(Hint, "\n") proc listInstalled(options: Options) = type From 2bea01f1e0515f1acef4b27d9853f3fa19e48613 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Thu, 9 Jan 2025 00:08:16 -0700 Subject: [PATCH 21/21] prettify list --- src/nimble.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nimble.nim b/src/nimble.nim index f4228bbb..dcdba58d 100644 --- a/src/nimble.nim +++ b/src/nimble.nim @@ -1065,7 +1065,7 @@ proc listNimBinaries(options: Options) = displayFormatted(Hint, "├── ") displayFormatted(Success, "@" & $pkg.basicInfo.version) displayFormatted(Hint, " ") - displayFormatted(Details, fmt"({pkg.myPath})") + displayFormatted(Details, fmt"({pkg.myPath.splitPath().head})") displayFormatted(Hint, "\n") displayFormatted(Hint, "\n")