Skip to content

Commit 05dfa85

Browse files
committed
Fix VCS revision upgrades to use correct commit hash
1 parent 43beb08 commit 05dfa85

File tree

7 files changed

+91
-16
lines changed

7 files changed

+91
-16
lines changed

src/nimblepkg/download.nim

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,8 @@ proc downloadPkg*(url: string, verRange: VersionRange,
801801
result.dir = pkgDir
802802

803803
#when using a persistent download dir we can skip the download if it's already done
804-
if pkgDirHasNimble(result.dir, options):
804+
# BUT: for specific VCS revisions, we need to ensure the correct revision is checked out
805+
if pkgDirHasNimble(result.dir, options) and vcsRevision == notSetSha1Hash:
805806
return # already downloaded, skipping
806807

807808
if options.offline:
@@ -882,7 +883,8 @@ proc downloadPkgAsync*(url: string, verRange: VersionRange,
882883
result.dir = pkgDir
883884

884885
#when using a persistent download dir we can skip the download if it's already done
885-
if pkgDirHasNimble(result.dir, options):
886+
# BUT: for specific VCS revisions, we need to ensure the correct revision is checked out
887+
if pkgDirHasNimble(result.dir, options) and vcsRevision == notSetSha1Hash:
886888
return # already downloaded, skipping
887889

888890
if options.offline:

src/nimblepkg/nimblesat.nim

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,8 +597,18 @@ proc downloadFromDownloadInfo*(dlInfo: PackageDownloadInfo, options: Options, ni
597597
let downloadRes = (dir: pkgInfo.getNimbleFileDir(), version: pkgInfo.basicInfo.version, vcsRevision: notSetSha1Hash)
598598
(downloadRes, none(DownloadMethod))
599599
else:
600+
# Extract VCS revision from version range if it's a special version (e.g., @#commit-hash)
601+
var vcsRev = notSetSha1Hash
602+
var downloadDir = dlInfo.downloadDir
603+
if dlInfo.pv.ver.kind == verSpecial:
604+
let speStr = $dlInfo.pv.ver.spe
605+
# Remove '#' prefix if present (e.g., "#head" or "#abc123...")
606+
let revStr = if speStr.startsWith("#"): speStr[1..^1] else: speStr
607+
vcsRev = initSha1Hash(revStr)
608+
# Don't use cached download dir for specific revisions - let downloadPkg create unique dir
609+
downloadDir = ""
600610
let downloadRes = downloadPkg(dlInfo.url, dlInfo.pv.ver, dlInfo.meth.get, dlInfo.subdir, options,
601-
dlInfo.downloadDir, vcsRevision = notSetSha1Hash, nimBin = nimBin)
611+
downloadDir, vcsRevision = vcsRev, nimBin = nimBin)
602612
(downloadRes, dlInfo.meth)
603613

604614
proc downloadPkgFromUrl*(pv: PkgTuple, options: Options, doPrompt = false, nimBin: string): (DownloadPkgResult, Option[DownloadMethod]) =
@@ -967,8 +977,18 @@ proc downloadFromDownloadInfoAsync*(dlInfo: PackageDownloadInfo, options: Option
967977
except Exception as e:
968978
raise newException(CatchableError, e.msg)
969979
else:
980+
# Extract VCS revision from version range if it's a special version (e.g., @#commit-hash)
981+
var vcsRev = notSetSha1Hash
982+
var downloadDir = dlInfo.downloadDir
983+
if dlInfo.pv.ver.kind == verSpecial:
984+
let speStr = $dlInfo.pv.ver.spe
985+
# Remove '#' prefix if present (e.g., "#head" or "#abc123...")
986+
let revStr = if speStr.startsWith("#"): speStr[1..^1] else: speStr
987+
vcsRev = initSha1Hash(revStr)
988+
# Don't use cached download dir for specific revisions - let downloadPkgAsync create unique dir
989+
downloadDir = ""
970990
let downloadRes = await downloadPkgAsync(dlInfo.url, dlInfo.pv.ver, dlInfo.meth.get, dlInfo.subdir, options,
971-
dlInfo.downloadDir, vcsRevision = notSetSha1Hash, nimBin = nimBin)
991+
downloadDir, vcsRevision = vcsRev, nimBin = nimBin)
972992
return (downloadRes, dlInfo.meth)
973993

974994
proc downloadPkgFromUrlAsync*(pv: PkgTuple, options: Options, doPrompt = false, nimBin: string): Future[(DownloadPkgResult, Option[DownloadMethod])] {.async.} =
@@ -1034,6 +1054,11 @@ proc downloadMinimalPackageAsync*(pv: PkgTuple, options: Options, nimBin: string
10341054
## Async version of downloadMinimalPackage with deduplication.
10351055
## If multiple calls request the same package concurrently, they share the same download.
10361056
## Cache key uses canonical package URL (not version) since we download all versions anyway.
1057+
## For specific versions (verSpecial, verEq), skip cache to ensure correct revision is downloaded.
1058+
1059+
# Skip cache for specific versions/revisions - they need exact download
1060+
if pv.ver.kind in [verSpecial, verEq]:
1061+
return await downloadMinimalPackageAsyncImpl(pv, options, nimBin)
10371062

10381063
# Get canonical URL to use as cache key (handles both short names and full URLs)
10391064
var cacheKey: string

src/nimblepkg/packagemetadatafile.nim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,6 @@ proc loadMetaData*(dirName: string, raiseIfNotFound: bool, options: Options): Pa
7676
proc fillMetaData*(packageInfo: var PackageInfo, dirName: string,
7777
raiseIfNotFound: bool, options: Options) =
7878
packageInfo.metaData = loadMetaData(dirName, raiseIfNotFound, options)
79+
# Update checksum from metadata if it's set (important for packages downloaded with specific VCS revision)
80+
if packageInfo.metaData.vcsRevision != notSetSha1Hash:
81+
packageInfo.basicInfo.checksum = packageInfo.metaData.vcsRevision

src/nimblepkg/packageparser.nim

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,14 +336,31 @@ proc readPackageInfo(pkgInfo: var PackageInfo, nf: NimbleFile, options: Options,
336336
pkgInfo.metaData.specialVersions.incl pkgInfo.basicInfo.version
337337
# If the `fileDir` is a VCS repository we can get some of the package meta
338338
# data from it.
339+
var currentVcsRevision = notSetSha1Hash
339340
try:
340-
pkgInfo.metaData.vcsRevision = getVcsRevision(fileDir)
341+
currentVcsRevision = getVcsRevision(fileDir)
342+
pkgInfo.metaData.vcsRevision = currentVcsRevision
341343
except CatchableError:
342344
raise nimbleError(
343345
msg = "Failed to get VCS revision of your project!",
344346
hint = "Try making a commit to your project if you haven't made one yet."
345347
)
346348

349+
# Try to load metadata from nimblemeta.json (for packages downloaded with specific VCS revision)
350+
try:
351+
fillMetaData(pkgInfo, fileDir, raiseIfNotFound = false, options)
352+
except CatchableError:
353+
discard # Metadata file doesn't exist or failed to load, use values set above
354+
355+
# Always use the current VCS revision from the git repo, not from cached metadata
356+
# This ensures we get the correct revision even if metadata file is stale
357+
if currentVcsRevision != notSetSha1Hash:
358+
pkgInfo.metaData.vcsRevision = currentVcsRevision
359+
360+
# For VCS packages, use the VCS revision as the checksum (more accurate than directory SHA1)
361+
if pkgInfo.metaData.vcsRevision != notSetSha1Hash:
362+
pkgInfo.basicInfo.checksum = pkgInfo.metaData.vcsRevision
363+
347364
case getVcsType(fileDir)
348365
of vcsTypeGit: pkgInfo.metaData.downloadMethod = DownloadMethod.git
349366
of vcsTypeHg: pkgInfo.metaData.downloadMethod = DownloadMethod.hg

src/nimblepkg/tools.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,9 @@ proc getDownloadDirName*(uri: string, verRange: VersionRange,
169169
if verSimple != "":
170170
result.add "_"
171171
result.add verSimple
172-
173-
if vcsRevision != notSetSha1Hash:
172+
173+
# Only add vcsRevision if it's not already in the version string (verSpecial already includes it)
174+
if vcsRevision != notSetSha1Hash and verRange.kind != verSpecial:
174175
result.add "_"
175176
result.add $vcsRevision
176177

src/nimblepkg/version.nim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ proc getSimpleString*(verRange: VersionRange): string =
353353
case verRange.kind
354354
of verSpecial:
355355
result = $verRange.spe
356+
# Remove '#' prefix for directory names (can cause issues with shell commands)
357+
if result.startsWith("#"):
358+
result = result[1..^1]
356359
of verLater, verEarlier, verEqLater, verEqEarlier, verEq:
357360
result = $verRange.ver
358361
of verIntersect, verTilde, verCaret:

src/nimblepkg/vnext.nim

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ After we resolve nim, we try to resolve the dependencies for a root package. Roo
1515
import std/[sequtils, sets, options, os, strutils, tables, strformat, algorithm]
1616
import nimblesat, packageinfotypes, options, version, declarativeparser, packageinfo, common,
1717
nimenv, lockfile, cli, downloadnim, packageparser, tools, nimscriptexecutor, packagemetadatafile,
18-
displaymessages, packageinstaller, reversedeps, developfile, urls
18+
displaymessages, packageinstaller, reversedeps, developfile, urls, sha1hashes
1919

2020
when defined(windows):
2121
import std/strscans
@@ -658,10 +658,21 @@ proc packageExists(nimBin: string, pkgInfo: PackageInfo, options: Options):
658658
return some(oldPkgInfo)
659659

660660

661-
proc installFromDirDownloadInfo(nimBin: string,downloadDir: string, url: string, pv: PkgTuple, options: Options): PackageInfo {.instrument.} =
661+
proc installFromDirDownloadInfo(nimBin: string,downloadDir: string, url: string, pv: PkgTuple, options: Options): PackageInfo {.instrument.} =
662662

663663
let dir = downloadDir
664664
var pkgInfo = getPkgInfo(dir, options, nimBin = nimBin)
665+
666+
# If we requested a specific VCS revision (verSpecial), ensure we use it as the checksum
667+
# This handles cases where getVcsRevision might have returned a stale value
668+
if pv.ver.kind == verSpecial:
669+
let speStr = $pv.ver.spe
670+
let revStr = if speStr.startsWith("#"): speStr[1..^1] else: speStr
671+
let requestedRevision = initSha1Hash(revStr)
672+
if requestedRevision != notSetSha1Hash:
673+
pkgInfo.metaData.vcsRevision = requestedRevision
674+
pkgInfo.basicInfo.checksum = requestedRevision
675+
665676
var depsOptions = options
666677
depsOptions.depsOnly = false
667678

@@ -671,13 +682,26 @@ proc installFromDirDownloadInfo(nimBin: string,downloadDir: string, url: string,
671682

672683
let oldPkg = packageExists(nimBin, pkgInfo, options)
673684
if oldPkg.isSome:
674-
# In the case we already have the same package in the cache then only merge
675-
# the new package special versions to the old one.
676-
displayWarning(pkgAlreadyExistsInTheCacheMsg(pkgInfo), MediumPriority)
677-
var oldPkg = oldPkg.get
678-
oldPkg.metaData.specialVersions.incl pkgInfo.metaData.specialVersions
679-
saveMetaData(oldPkg.metaData, oldPkg.getNimbleFileDir, changeRoots = false)
680-
return oldPkg
685+
# Check if checksums are different - if so, force reinstall (handles VCS revision upgrades)
686+
let isDifferentPackage = pkgInfo.basicInfo.checksum != oldPkg.get.basicInfo.checksum
687+
688+
if not isDifferentPackage:
689+
# In the case we already have the same package in the cache then only merge
690+
# the new package special versions to the old one.
691+
displayWarning(pkgAlreadyExistsInTheCacheMsg(pkgInfo), MediumPriority)
692+
var oldPkg = oldPkg.get
693+
oldPkg.metaData.specialVersions.incl pkgInfo.metaData.specialVersions
694+
saveMetaData(oldPkg.metaData, oldPkg.getNimbleFileDir, changeRoots = false)
695+
return oldPkg
696+
else:
697+
# Different checksum - reinstall (e.g., different VCS revision)
698+
display("Upgrading", "$1 from checksum $2 to $3" %
699+
[pkgInfo.basicInfo.name, $oldPkg.get.basicInfo.checksum, $pkgInfo.basicInfo.checksum],
700+
priority = MediumPriority)
701+
# Remove the old package directory to force reinstallation
702+
let oldPkgDir = oldPkg.get.getPkgDest(options)
703+
if dirExists(oldPkgDir):
704+
removeDir(oldPkgDir)
681705

682706
let pkgDestDir = pkgInfo.getPkgDest(options)
683707

0 commit comments

Comments
 (0)