Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 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
43beb08
Fix subdirectory packages in fast version enumeration
jmgomez Nov 24, 2025
05dfa85
Fix VCS revision upgrades to use correct commit hash
jmgomez Nov 24, 2025
080fe8d
Improves copy
jmgomez Nov 25, 2025
6bca548
Disable all suites except lock
jmgomez Nov 25, 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
Loading