@@ -9,6 +9,7 @@ import testscommon
99from nimblepkg/ common import cd, cdNewDir
1010from nimblepkg/ tools import tryDoCmdEx
1111from nimblepkg/ packageinfotypes import DownloadMethod
12+ from nimblepkg/ options import defaultLockFileName
1213
1314suite " nimble refresh" :
1415 test " can refresh with default urls" :
@@ -142,34 +143,41 @@ license = "MIT"
142143 tryDoCmdEx (" git add ." )
143144 tryDoCmdEx (" git commit -am " & msg.quoteShell)
144145
145- proc writeDepVersion (version: string ) =
146- # # Writes dep1 .nimble at `version` in the cwd and tags it.
147- writeFile (" dep1 .nimble" , nimbleFileTemplate % version)
146+ proc writeDepVersion (version: string , name = " dep1 " ) =
147+ # # Writes <name> .nimble at `version` in the cwd and tags it.
148+ writeFile (& " { name } .nimble" , nimbleFileTemplate % version)
148149 commitAll (version)
149150 tryDoCmdEx (& " git tag v{ version} " )
150151
151- proc initDepOrigin (versions: seq [string ]) =
152- cdNewDir depOriginPath :
152+ proc initDepOrigin (versions: seq [string ], name = " dep1 " ) =
153+ cdNewDir originsDirPath / name :
153154 initRepo ()
154155 for v in versions:
155- writeDepVersion (v)
156+ writeDepVersion (v, name )
156157
157- proc addDepVersion (version: string ) =
158- cd depOriginPath :
159- writeDepVersion (version)
158+ proc addDepVersion (version: string , name = " dep1 " ) =
159+ cd originsDirPath / name :
160+ writeDepVersion (version, name )
160161
161- proc initMainPkg (requirement: string ) =
162+ proc initMainPkg (requirement: string , underVcs = false ) =
162163 createDir mainPkgPath
163164 cd mainPkgPath:
164165 writeFile (" main.nimble" ,
165166 (nimbleFileTemplate % " 0.1.0" ) & & " requires \" { requirement} \"\n " )
167+ if underVcs:
168+ # Rewriting an existing lock file requires the project dir to be under
169+ # version control (creating one does not).
170+ initRepo ()
171+ commitAll (" main" )
166172
167- proc writePkgListFile () =
173+ proc writePkgListFile (names = @ [ " dep1 " ] ) =
168174 createDir tempDir
169- let record = PackagesListFileRecord (
170- name: " dep1" , url: depOriginPath, `method`: DownloadMethod .git,
171- tags: @ [" test" ], description: " A test package." , license: " MIT" )
172- writeFile (pkgListFilePath, (% (@ [record])).pretty)
175+ var records: seq [PackagesListFileRecord ]
176+ for name in names:
177+ records.add PackagesListFileRecord (
178+ name: name, url: originsDirPath / name, `method`: DownloadMethod .git,
179+ tags: @ [" test" ], description: " A test package." , license: " MIT" )
180+ writeFile (pkgListFilePath, (% records).pretty)
173181
174182 template withCleanDirs (body: untyped ) =
175183 removeDir tempDir
@@ -182,15 +190,46 @@ license = "MIT"
182190 template withDepProject (requirement: string , body: untyped ) =
183191 # # dep1 origin at 0.1.0, a main package requiring it, and a warm cache
184192 # # (`nimble install` resolved dep1 once, so tagged_versions.json knows 0.1.0).
193+ withDepProject (requirement, false , body)
194+
195+ template withDepProject (requirement: string , underVcs, body: untyped ) =
196+ # # As the 2-arg overload, but with the main package's directory under git
197+ # # control so the lock file can be rewritten in place.
185198 withCleanDirs:
186199 writePkgListFile ()
187200 usePackageListFile pkgListFilePath:
188201 initDepOrigin (@ [" 0.1.0" ])
189- initMainPkg (requirement)
202+ initMainPkg (requirement, underVcs)
203+ cd mainPkgPath:
204+ check execNimbleYes (" install" ).exitCode == QuitSuccess
205+ body
206+
207+ template withTwoDepProject (body: untyped ) =
208+ # # dep1 and dep2 origins at 0.1.0 and a main package requiring both, under
209+ # # git so its lock file can be rewritten. Two deps are what make "only the
210+ # # named package moved" observable.
211+ withCleanDirs:
212+ writePkgListFile (@ [" dep1" , " dep2" ])
213+ usePackageListFile pkgListFilePath:
214+ initDepOrigin (@ [" 0.1.0" ], " dep1" )
215+ initDepOrigin (@ [" 0.1.0" ], " dep2" )
216+ createDir mainPkgPath
190217 cd mainPkgPath:
218+ writeFile (" main.nimble" , (nimbleFileTemplate % " 0.1.0" ) &
219+ " requires \" dep1 >= 0.1.0\"\n requires \" dep2 >= 0.1.0\"\n " )
220+ initRepo ()
221+ commitAll (" main" )
191222 check execNimbleYes (" install" ).exitCode == QuitSuccess
192223 body
193224
225+ proc lockedVersion (pkg: string ): string =
226+ # # The version `pkg` is pinned to in the main package's lock file.
227+ let lock = parseJson (readFile (mainPkgPath / defaultLockFileName))
228+ for name, dep in lock[" packages" ].pairs:
229+ if name.cmpIgnoreCase (pkg) == 0 :
230+ return dep[" version" ].getStr
231+ return " "
232+
194233 test " refresh makes a newly published tag visible" :
195234 withDepProject (" dep1 >= 0.1.0" ):
196235 addDepVersion (" 0.2.0" ) # published after the cache was warmed
@@ -300,3 +339,70 @@ license = "MIT"
300339 cd depClonePath:
301340 let tag = tryDoCmdEx (" git describe --tags" ).strip
302341 check tag == " v0.1.0"
342+
343+ test " lock --refresh relocks to a newly published version" :
344+ withDepProject (" dep1 >= 0.1.0" , true ):
345+ cd mainPkgPath:
346+ # Lock first so the next publish has an existing pin to keep or move.
347+ check execNimbleYes (" lock" ).exitCode == QuitSuccess
348+ check (defaultLockFileName.readFile).contains (" 0.1.0" )
349+ addDepVersion (" 0.2.0" ) # published after the lock was written
350+ cd mainPkgPath:
351+ # A plain `lock` keeps its pins; the newly published version is not used.
352+ check execNimbleYes (" lock" ).exitCode == QuitSuccess
353+ check not (defaultLockFileName.readFile).contains (" 0.2.0" )
354+ check (defaultLockFileName.readFile).contains (" 0.1.0" )
355+
356+ # `lock --refresh` ignores the pins and relocks to the newest.
357+ check execNimbleYes (" lock" , " --refresh" ).exitCode == QuitSuccess
358+ check (defaultLockFileName.readFile).contains (" 0.2.0" )
359+ check not (defaultLockFileName.readFile).contains (" 0.1.0" )
360+
361+ test " upgrade still works and says it is deprecated" :
362+ withDepProject (" dep1 >= 0.1.0" , true ):
363+ cd mainPkgPath:
364+ # Lock first so `upgrade` relocks an existing pin rather than creating one.
365+ check execNimbleYes (" lock" ).exitCode == QuitSuccess
366+ check (defaultLockFileName.readFile).contains (" 0.1.0" )
367+ addDepVersion (" 0.2.0" ) # published after the lock was written
368+ cd mainPkgPath:
369+ let (output, exitCode) = execNimbleYes (" upgrade" )
370+ check exitCode == QuitSuccess
371+ # `upgrade` is an alias of `lock --refresh`, so it fetches the remotes
372+ # and finds 0.2.0 the same way `lock --refresh` does.
373+ check output.contains (" `nimble upgrade` is deprecated" )
374+ check output.contains (" nimble lock --refresh" )
375+ check (defaultLockFileName.readFile).contains (" 0.2.0" )
376+ check not (defaultLockFileName.readFile).contains (" 0.1.0" )
377+
378+ test " lock --refresh pkg relocks only that package" :
379+ withTwoDepProject:
380+ cd mainPkgPath:
381+ check execNimbleYes (" lock" ).exitCode == QuitSuccess
382+ check lockedVersion (" dep1" ) == " 0.1.0"
383+ check lockedVersion (" dep2" ) == " 0.1.0"
384+ addDepVersion (" 0.2.0" , " dep1" )
385+ addDepVersion (" 0.2.0" , " dep2" )
386+ cd mainPkgPath:
387+ check execNimbleYes (" lock" , " --refresh" , " dep1" ).exitCode == QuitSuccess
388+ # Naming a package scopes the relock to it; dep2 keeps its pin even
389+ # though 0.2.0 is available for it too.
390+ check lockedVersion (" dep1" ) == " 0.2.0"
391+ check lockedVersion (" dep2" ) == " 0.1.0"
392+
393+ test " lock pkg relocks from the cache without fetching" :
394+ withTwoDepProject:
395+ cd mainPkgPath:
396+ check execNimbleYes (" lock" ).exitCode == QuitSuccess
397+ addDepVersion (" 0.2.0" , " dep1" )
398+ cd mainPkgPath:
399+ # Without --refresh nothing is fetched, so the newly published 0.2.0 is
400+ # not visible yet and the pin stays put.
401+ check execNimbleYes (" lock" , " dep1" ).exitCode == QuitSuccess
402+ check lockedVersion (" dep1" ) == " 0.1.0"
403+
404+ # Once discovery has seen it, naming the package moves it - and only it.
405+ check execNimbleYes (" refresh" ).exitCode == QuitSuccess
406+ check execNimbleYes (" lock" , " dep1" ).exitCode == QuitSuccess
407+ check lockedVersion (" dep1" ) == " 0.2.0"
408+ check lockedVersion (" dep2" ) == " 0.1.0"
0 commit comments