Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9dd966d
Refactor display procs to be thread safe
jmgomez Nov 20, 2025
ab3f407
Green: doCmdExAsync executes command
jmgomez Nov 20, 2025
3e7817b
[OK] doCloneAsync clones a repo
jmgomez Nov 20, 2025
4ea1d96
[OK] gitFetchTagsAsync fetches tags
jmgomez Nov 20, 2025
cd0c204
[OK] getTagsListRemoteAsync queries remote tags
jmgomez Nov 20, 2025
281c478
[OK] cloneSpecificRevisionAsync clones specific commit
jmgomez Nov 20, 2025
09aadb6
[OK] doDownloadTarballAsync downloads and extracts tarball
jmgomez Nov 20, 2025
0cc76b7
[OK] downloadPkgAsync downloads package
jmgomez Nov 20, 2025
c55ae68
Refactors declarative parser to be gcsafe
jmgomez Nov 20, 2025
7b72215
[OK] getTagsListAsync lists tags from local repo
jmgomez Nov 20, 2025
cc2d05c
[OK] doCheckoutAsync
jmgomez Nov 20, 2025
7a47298
[OK] getPackageMinimalVersionsFromRepoAsync gets package versions
jmgomez Nov 20, 2025
38fab27
[OK] downloadMinimalPackageAsync downloads package with versions
jmgomez Nov 20, 2025
f738e0a
Refactor a bunch of procs to be thread safe
jmgomez Nov 20, 2025
fb951d1
[OK] getMinimalFromPreferredAsync returns preferred package
jmgomez Nov 20, 2025
5c4deb1
uses collectAllVersionsAsync in solvePackages
jmgomez Nov 21, 2025
ad2e1a8
[OK] gitShowFileAsync reads file from git commit
jmgomez Nov 21, 2025
006554d
[OK] gitListNimbleFilesInCommitAsync lists nimble files
jmgomez Nov 21, 2025
b72dd94
[OK] getPackageMinimalVersionsFromRepoAsyncFast gets versions witho…
jmgomez Nov 21, 2025
ce076b9
Deduplicates cache dirs
jmgomez Nov 21, 2025
79fd5fe
Fix subdirectory packages in fast version enumeration
jmgomez Nov 24, 2025
c8ab53e
Opt-in async downloads
jmgomez Nov 25, 2025
6a0bdb1
Put cache deduplication behind useAsyncDownloads flag
jmgomez Nov 26, 2025
930e0b1
Opts-in the new cache format
jmgomez Nov 26, 2025
647209d
Removes unused var
jmgomez Nov 26, 2025
ed339eb
Fix async/sync path selection logic
jmgomez Nov 26, 2025
0642531
Adds the tasynctools suite
jmgomez Nov 26, 2025
caf923f
Fixes unused warn
jmgomez Nov 27, 2025
9b9f1a5
Disable async unittest
jmgomez Nov 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions src/nimblepkg/cli.nim
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ proc newCLI(): CLI =
showColor: true,
)

var globalCLI = newCLI()
var globalCLI {.threadvar.}: CLI

proc getGlobalCLI*(): CLI =
if globalCLI.isNil:
globalCLI = newCLI()
result = globalCLI

proc calculateCategoryOffset(category: string): int =
assert category.len <= longestCategory
Expand All @@ -57,14 +62,14 @@ proc calculateCategoryOffset(category: string): int =
proc isSuppressed(displayType: DisplayType): bool =
# Don't print any Warning, Message or Success messages when suppression of
# warnings is enabled. That is, unless the user asked for --verbose output.
if globalCLI.suppressMessages and displayType >= Warning and
globalCLI.level == HighPriority:
if getGlobalCLI().suppressMessages and displayType >= Warning and
getGlobalCLI().level == HighPriority:
return true

proc displayFormatted*(displayType: DisplayType, msgs: varargs[string]) =
## for styling outputs lines using the DisplayTypes
for msg in msgs:
if globalCLI.showColor:
if getGlobalCLI().showColor:
stdout.styledWrite(foregrounds[displayType], msg)
else:
stdout.write(msg)
Expand All @@ -85,7 +90,7 @@ proc displayCategory(category: string, displayType: DisplayType,

# Display the category.
let text = "$1$2 " % [spaces(offset), category]
if globalCLI.showColor:
if getGlobalCLI().showColor:
if priority != DebugPriority:
setForegroundColor(stdout, foregrounds[displayType])
writeStyled(text, styles[priority])
Expand All @@ -109,16 +114,16 @@ proc display*(category, msg: string, displayType = Message,
# Multiple warnings containing the same messages should not be shown.
let warningPair = (category, msg)
if displayType == Warning:
if warningPair in globalCLI.warnings:
if warningPair in getGlobalCLI().warnings:
return
else:
globalCLI.warnings.incl(warningPair)
getGlobalCLI().warnings.incl(warningPair)

# Suppress this message if its priority isn't high enough.
# TODO: Per-priority suppression counts?
if priority < globalCLI.level:
if priority < getGlobalCLI().level:
if priority != DebugPriority:
globalCLI.suppressionCount.inc
getGlobalCLI().suppressionCount.inc
return

# Display each line in the message.
Expand Down Expand Up @@ -173,9 +178,9 @@ proc displayDebug*(msg: string) =
proc displayTip*() =
## Called just before Nimble exits. Shows some tips for the user, for example
## the amount of messages that were suppressed and how to show them.
if globalCLI.suppressionCount > 0:
if getGlobalCLI().suppressionCount > 0:
let msg = "$1 messages have been suppressed, use --verbose to show them." %
$globalCLI.suppressionCount
$getGlobalCLI().suppressionCount
display("Tip:", msg, Warning, HighPriority)

proc prompt*(forcePrompts: ForcePrompt, question: string): bool =
Expand All @@ -187,7 +192,7 @@ proc prompt*(forcePrompts: ForcePrompt, question: string): bool =
display("Prompt:", question & " -> [forced no]", Warning, HighPriority)
return false
of dontForcePrompt:
if globalCLI.level > SilentPriority:
if getGlobalCLI().level > SilentPriority:
display("Prompt:", question & " [y/N]", Warning, HighPriority)
displayCategory("Answer:", Warning, HighPriority)
let yn = stdin.readLine()
Expand Down Expand Up @@ -321,10 +326,10 @@ proc promptList*(forcePrompts: ForcePrompt, question: string, args: openarray[st
return promptListFallback(question, args)

proc setVerbosity*(level: Priority) =
globalCLI.level = level
getGlobalCLI().level = level

proc setShowColor*(val: bool) =
globalCLI.showColor = val
getGlobalCLI().showColor = val

proc setSuppressMessages*(val: bool) =
globalCLI.suppressMessages = val
getGlobalCLI().suppressMessages = val
149 changes: 76 additions & 73 deletions src/nimblepkg/declarativeparser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -210,24 +210,25 @@ proc getNimCompilationPath*(nimbleFile: string): string =
let fileIdx = fileInfoIdx(conf, AbsoluteFile nimbleFile)
var parser: Parser
var includePath = ""
if setupParser(parser, fileIdx, newIdentCache(), conf):
let ast = parseAll(parser)
proc findIncludePath(n: PNode) =
case n.kind
of nkStmtList, nkStmtListExpr:
for child in n:
findIncludePath(child)
of nkIncludeStmt:
# Found an include statement
if n.len > 0 and n[0].kind in {nkStrLit..nkTripleStrLit}:
includePath = n[0].strVal
# echo "Found include: ", includePath
else:
for i in 0..<n.safeLen:
findIncludePath(n[i])

findIncludePath(ast)
closeParser(parser)
{.cast(gcSafe).}:
if setupParser(parser, fileIdx, newIdentCache(), conf):
let ast = parseAll(parser)
proc findIncludePath(n: PNode) =
case n.kind
of nkStmtList, nkStmtListExpr:
for child in n:
findIncludePath(child)
of nkIncludeStmt:
# Found an include statement
if n.len > 0 and n[0].kind in {nkStrLit..nkTripleStrLit}:
includePath = n[0].strVal
# echo "Found include: ", includePath
else:
for i in 0..<n.safeLen:
findIncludePath(n[i])

findIncludePath(ast)
closeParser(parser)

if includePath.len > 0:
if includePath.contains("compilation.nim"):
Expand All @@ -251,51 +252,51 @@ proc extractNimVersion*(nimbleFile: string): string =

let compFileIdx = fileInfoIdx(conf, AbsoluteFile compilationPath)
var parser: Parser

if setupParser(parser, compFileIdx, newIdentCache(), conf):
let ast = parseAll(parser)

# Process AST to find NimMajor, NimMinor, NimPatch definitions
proc processNode(n: PNode) =
case n.kind
of nkStmtList, nkStmtListExpr:
for child in n:
processNode(child)
of nkConstSection:
for child in n:
if child.kind == nkConstDef:
var identName = ""
case child[0].kind
of nkPostfix:
if child[0][1].kind == nkIdent:
identName = child[0][1].ident.s
of nkIdent:
identName = child[0].ident.s
of nkPragmaExpr:
# Handle pragma expression (like NimMajor* {.intdefine.})
if child[0][0].kind == nkIdent:
identName = child[0][0].ident.s
elif child[0][0].kind == nkPostfix and child[0][0][1].kind == nkIdent:
identName = child[0][0][1].ident.s
else: discard
# echo "Unhandled node kind for const name: ", child[0].kind
# Extract value
if child.len > 2:
case child[2].kind
of nkIntLit:
let value = child[2].intVal.int
case identName
of "NimMajor": major = value
of "NimMinor": minor = value
of "NimPatch": patch = value
else: discard
else:
discard
else:
discard

processNode(ast)
closeParser(parser)
{.cast(gcSafe).}:
if setupParser(parser, compFileIdx, newIdentCache(), conf):
let ast = parseAll(parser)
# Process AST to find NimMajor, NimMinor, NimPatch definitions
proc processNode(n: PNode) =
case n.kind
of nkStmtList, nkStmtListExpr:
for child in n:
processNode(child)
of nkConstSection:
for child in n:
if child.kind == nkConstDef:
var identName = ""
case child[0].kind
of nkPostfix:
if child[0][1].kind == nkIdent:
identName = child[0][1].ident.s
of nkIdent:
identName = child[0].ident.s
of nkPragmaExpr:
# Handle pragma expression (like NimMajor* {.intdefine.})
if child[0][0].kind == nkIdent:
identName = child[0][0].ident.s
elif child[0][0].kind == nkPostfix and child[0][0][1].kind == nkIdent:
identName = child[0][0][1].ident.s
else: discard
# echo "Unhandled node kind for const name: ", child[0].kind
# Extract value
if child.len > 2:
case child[2].kind
of nkIntLit:
let value = child[2].intVal.int
case identName
of "NimMajor": major = value
of "NimMinor": minor = value
of "NimPatch": patch = value
else: discard
else:
discard
else:
discard
processNode(ast)
closeParser(parser)
# echo "Extracted version: ", major, ".", minor, ".", patch
return &"{major}.{minor}.{patch}"

Expand Down Expand Up @@ -340,12 +341,13 @@ proc extractRequiresInfo*(nimbleFile: string, options: Options): NimbleFileInfo
localError(config, info, warnUser, msg)

let fileIdx = fileInfoIdx(conf, AbsoluteFile nimbleFile)
var parser: Parser
if setupParser(parser, fileIdx, newIdentCache(), conf):
let ast = parseAll(parser)
extract(ast, conf, result, options)
closeParser(parser)
result.hasErrors = result.hasErrors or conf.errorCounter > 0
{.cast(gcSafe).}:
var parser: Parser
if setupParser(parser, fileIdx, newIdentCache(), conf):
let ast = parseAll(parser)
extract(ast, conf, result, options)
closeParser(parser)
result.hasErrors = result.hasErrors or conf.errorCounter > 0

# Add requires from external requires file
let nimbleDir = nimbleFile.splitFile.dir
Expand Down Expand Up @@ -380,10 +382,11 @@ proc extractPluginInfo*(nimscriptFile: string, info: var PluginInfo) =
conf.mainPackageNotes = {}

let fileIdx = fileInfoIdx(conf, AbsoluteFile nimscriptFile)
var parser: Parser
if setupParser(parser, fileIdx, newIdentCache(), conf):
extractPlugin(nimscriptFile, parseAll(parser), conf, info)
closeParser(parser)
{.cast(gcSafe).}:
var parser: Parser
if setupParser(parser, fileIdx, newIdentCache(), conf):
extractPlugin(nimscriptFile, parseAll(parser), conf, info)
closeParser(parser)

const Operators* = {'<', '>', '=', '&', '@', '!', '^'}

Expand Down
Loading