Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 18 additions & 4 deletions src/nimble.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,7 @@ proc validateDevelopDependenciesVersionRanges(dependentPkg: PackageInfo,
# and no special versions, so validate the ordinary version directly. The
# `withinRange(PackageInfo, ...)` overload checks `metaData.specialVersions`,
# which the declarative parser does not populate for develop deps (it stays
# empty), making every concrete range fail. See develop_wf_issues.md.
# empty), making every concrete range fail.
if not withinRange(depPkg.basicInfo.version, dep.ver):
errors.add notInRequiredRangeMsg(pkg, depPkg, dep.ver)
if errors.len > 0:
Expand Down Expand Up @@ -1452,7 +1452,7 @@ proc alignDevelopCheckouts(rootPkg: PackageInfo, options: Options,
## When the resolved solution needs a develop dependency at a version
## different from its current checkout, git-checkout the vendor repo to the
## resolved version ("align"). Stops on the first problem (dirty working copy
## or failed checkout); never touches a dirty repo (doCheckout is --force).
## or failed checkout); never touches a dirty repo
var resolved = initTable[string, Version]()
for sp in options.satResult.solvedPkgs:
resolved[sp.pkgName.toLowerAscii] = sp.version
Expand Down Expand Up @@ -1486,6 +1486,16 @@ proc lock(options: var Options, nimBin: Option[string]) =
currentLockFile = options.lockFile(currentDir)
lockExists = displayLockOperationStart(currentLockFile)

# For no-arg `nimble upgrade`, preserve the lock file's nim entry verbatim so
# upgrading the libraries never moves the compiler. Captured here, BEFORE the
# lock is rewritten below; written back in the dependency loop.
var prevNimDep = none(LockFileDep)
if options.action.typ == actionUpgrade and options.action.packages.len == 0 and lockExists:
for name, dep in currentLockFile.getLockedDependencies.lockedDepsFor(options):
if name.isNim:
prevNimDep = some(dep)
break

var baseDeps = options.satResult.pkgs.toSeq

if options.useSystemNim:
Expand Down Expand Up @@ -1517,9 +1527,13 @@ proc lock(options: var Options, nimBin: Option[string]) =
for solvedPkg in options.satResult.solvedPkgs:
if solvedPkg.pkgName.isNim and not shouldAddNim: continue
if solvedPkg.pkgName == rootPkgName: continue


if solvedPkg.pkgName.isNim and prevNimDep.isSome:
lockDeps[noTask][solvedPkg.pkgName] = prevNimDep.get
continue

# Get the PackageInfo for this solved package
let pkgInfo =
let pkgInfo =
if solvedPkg.pkgName.isFileURL:
getPkgInfo(solvedPkg.pkgName.extractFilePathFromURL(), options, nimBin, pikRequires)
else:
Expand Down
5 changes: 5 additions & 0 deletions src/nimblepkg/install.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ proc getPkgInfoFromSolved*(satResult: SATResult, solvedPkg: SolvedPackage, optio
#For the pkg list we need to check the version as there may be multiple versions of the same package
if nameMatches(pkg, solvedPkg.pkgName, options) and pkg.basicInfo.version == solvedPkg.version:
return pkg
if solvedPkg.pkgName.isNim:
result = initPackageInfo()
result.basicInfo.name = solvedPkg.pkgName
result.basicInfo.version = solvedPkg.version
return
writeStackTrace()
raise newNimbleError[NimbleError]("Package not found in solution: " & $solvedPkg.pkgName & " " & $solvedPkg.version)

Expand Down
8 changes: 8 additions & 0 deletions src/nimblepkg/nimblesat.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,14 @@ proc solveLockFileDeps*(satResult: var SATResult, pkgList: seq[PackageInfo], opt
shouldSolve = true
break

# No-arg `nimble upgrade` = upgrade-all: re-solve the whole graph to the newest
# compatible versions. The incremental actionUpgrade branch below only bumps the
# named packages and keeps the rest locked, which is the wrong model here, so force
# the full fresh solve. (The install-preferring local solve in solvePackages is
# already skipped for actionUpgrade, so this resolves to newest.)
if options.action.typ == actionUpgrade and options.action.packages.len == 0:
shouldSolve = true

var pkgListDecl: seq[PackageInfo]
for pkg in pkgList:
try:
Expand Down
119 changes: 119 additions & 0 deletions tests/tlockfile.nim
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,125 @@ requires "nim >= 1.5.1"
check newRevision == getRevision(dep1PkgName)
check res.exitCode == QuitSuccess

test "upgrade with no args does not change nim":
cleanUp()
withPkgListFile:
initNewNimblePackage(mainPkgOriginRepoPath, mainPkgRepoPath, @[dep1PkgName])
initNewNimblePackage(dep1PkgOriginRepoPath, dep1PkgRepoPath)

var nimBefore: string
cd mainPkgRepoPath:
check execNimbleYes("lock").exitCode == QuitSuccess
let j = defaultLockFileName.readFile.parseJson
nimBefore =
if "nim" in j{$lfjkPackages}: j{$lfjkPackages}{"nim"}{$lfjkPkgVcsRevision}.str
else: ""

cd dep1PkgOriginRepoPath:
addAdditionalFileToTheRepo("dep1.nim", "echo 1")
check execNimbleYes("install").exitCode == QuitSuccess
cd mainPkgRepoPath:
check execNimbleYes("upgrade").exitCode == QuitSuccess
let j2 = defaultLockFileName.readFile.parseJson
let nimAfter =
if "nim" in j2{$lfjkPackages}: j2{$lfjkPackages}{"nim"}{$lfjkPkgVcsRevision}.str
else: ""
check nimAfter == nimBefore # nim unchanged

test "upgrade with no args is a no-op when already newest":
cleanUp()
withPkgListFile:
initNewNimblePackage(mainPkgOriginRepoPath, mainPkgRepoPath, @[dep1PkgName])
initNewNimblePackage(dep1PkgOriginRepoPath, dep1PkgRepoPath)
var before: string
cd mainPkgRepoPath:
check execNimbleYes("lock").exitCode == QuitSuccess
before = getRevision(dep1PkgName)
cd mainPkgRepoPath:
let (_, exitCode) = execNimbleYes("upgrade") # nothing newer exists
check exitCode == QuitSuccess
check getRevision(dep1PkgName) == before # lock unchanged

test "upgrade with no args realigns a develop dependency":
cleanUp()
withPkgListFile:
initNewNimblePackage(mainPkgOriginRepoPath, mainPkgRepoPath, @[dep1PkgName])

cdNewDir dep1PkgOriginRepoPath:
initRepo()
discard dep1PkgOriginRepoPath.initNewNimbleFile()
addFiles(dep1PkgNimbleFileName)
commit("v0.1.0"); tryDoCmdEx("git tag v0.1.0")
writeFile(dep1PkgNimbleFileName, readFile(dep1PkgNimbleFileName).replace("0.1.0", "0.2.0"))
commit("v0.2.0"); tryDoCmdEx("git tag v0.2.0")

clone(dep1PkgOriginRepoPath, dep1PkgRepoPath)
var oldRev, newRev: string
cd dep1PkgRepoPath:
checkout("v0.1.0"); oldRev = getRepoRevision()
newRev = tryDoCmdEx("git rev-parse v0.2.0").replace("\n", "")
check oldRev != newRev

cd mainPkgRepoPath:
let nf = mainPkgNimbleFileName.readFile
mainPkgNimbleFileName.writeFile(nf.replace(&"\"{dep1PkgName}\"", &"\"{dep1PkgName} >= 0.2.0\""))
writeDevelopFile(developFileName, @[], @[dep1PkgRepoPath])
let res = execNimbleYes("upgrade")
check res.exitCode == QuitSuccess
var afterRev: string
cd dep1PkgRepoPath: afterRev = getRepoRevision()
check afterRev == newRev # vendor checkout aligned to v0.2.0
check getRevision(dep1PkgName) == newRev

test "upgrade with no args bumps to a newer tagged version":
cleanUp()
withPkgListFile:
initNewNimblePackage(mainPkgOriginRepoPath, mainPkgRepoPath, @[dep1PkgName])

# dep1 origin starts at version 0.1.0 (one tag).
cdNewDir dep1PkgOriginRepoPath:
initRepo()
discard dep1PkgOriginRepoPath.initNewNimbleFile() # version 0.1.0
addFiles(dep1PkgNimbleFileName)
commit("v0.1.0"); tryDoCmdEx("git tag v0.1.0")
clone(dep1PkgOriginRepoPath, dep1PkgRepoPath)

cd mainPkgRepoPath:
check execNimbleYes("lock").exitCode == QuitSuccess # locks dep1 0.1.0

# dep1 0.2.0 appears upstream and is installed (cache populated).
var newRev: string
cd dep1PkgOriginRepoPath:
writeFile(dep1PkgNimbleFileName,
readFile(dep1PkgNimbleFileName).replace("0.1.0", "0.2.0"))
commit("v0.2.0"); tryDoCmdEx("git tag v0.2.0")
newRev = getRepoRevision() # the v0.2.0 commit
check execNimbleYes("install").exitCode == QuitSuccess
cd mainPkgRepoPath:
let (_, exitCode) = execNimbleYes("upgrade")
check exitCode == QuitSuccess
check getRevision(dep1PkgName) == newRev # lock bumped to dep1 0.2.0

test "upgrade with no args does not add nim to a lock that has none":
cleanUp()
withPkgListFile:
initNewNimblePackage(mainPkgOriginRepoPath, mainPkgRepoPath, @[dep1PkgName])
initNewNimblePackage(dep1PkgOriginRepoPath, dep1PkgRepoPath)

cd mainPkgRepoPath:
# Drop the `requires "nim >= 1.5.1"` line so nim is never locked.
let nf = mainPkgNimbleFileName.readFile
mainPkgNimbleFileName.writeFile(nf.replace("requires \"nim >= 1.5.1\"", ""))
check execNimbleYes("lock").exitCode == QuitSuccess
check "nim" notin defaultLockFileName.readFile.parseJson{$lfjkPackages}

cd dep1PkgOriginRepoPath:
addAdditionalFileToTheRepo("dep1.nim", "echo 1")
check execNimbleYes("install").exitCode == QuitSuccess
cd mainPkgRepoPath:
check execNimbleYes("upgrade").exitCode == QuitSuccess
check "nim" notin defaultLockFileName.readFile.parseJson{$lfjkPackages} # still no nim

test "can upgrade: the new version of the package has a new dep":
cleanUp()
withPkgListFile:
Expand Down
Loading