7
7
from packaging .utils import canonicalize_name
8
8
9
9
from poetry .installation .executor import Executor
10
+ from poetry .puzzle .transaction import Transaction
10
11
from poetry .repositories import Repository
11
12
from poetry .repositories import RepositoryPool
12
13
from poetry .repositories .installed_repository import InstalledRepository
@@ -206,6 +207,10 @@ def _do_install(self) -> int:
206
207
from poetry .puzzle .solver import Solver
207
208
208
209
locked_repository = Repository ("poetry-locked" )
210
+ reresolve = self ._config .get ("installer.re-resolve" , True )
211
+ solved_packages : dict [Package , TransitivePackageInfo ] = {}
212
+ lockfile_repo = LockfileRepository ()
213
+
209
214
if self ._update :
210
215
if not self ._lock and self ._locker .is_locked ():
211
216
locked_repository = self ._locker .locked_repository ()
@@ -241,7 +246,6 @@ def _do_install(self) -> int:
241
246
self ._write_lock_file (solved_packages )
242
247
return 0
243
248
244
- lockfile_repo = LockfileRepository ()
245
249
for package in solved_packages :
246
250
if not lockfile_repo .has_package (package ):
247
251
lockfile_repo .add_package (package )
@@ -254,6 +258,13 @@ def _do_install(self) -> int:
254
258
"pyproject.toml changed significantly since poetry.lock was last"
255
259
" generated. Run `poetry lock [--no-update]` to fix the lock file."
256
260
)
261
+ if not reresolve and not self ._locker .is_locked_groups_and_markers ():
262
+ if self ._io .is_verbose ():
263
+ self ._io .write_line (
264
+ "<info>Cannot install without re-resolving"
265
+ " because the lock file is not at least version 2.1</>"
266
+ )
267
+ reresolve = True
257
268
258
269
locker_extras = {
259
270
canonicalize_name (extra )
@@ -264,41 +275,63 @@ def _do_install(self) -> int:
264
275
raise ValueError (f"Extra [{ extra } ] is not specified." )
265
276
266
277
locked_repository = self ._locker .locked_repository ()
267
- lockfile_repo = locked_repository
278
+ if reresolve :
279
+ lockfile_repo = locked_repository
280
+ else :
281
+ solved_packages = self ._locker .locked_packages ()
268
282
269
283
if self ._io .is_verbose ():
270
284
self ._io .write_line ("" )
271
285
self ._io .write_line (
272
286
"<info>Finding the necessary packages for the current system</>"
273
287
)
274
288
275
- if self ._groups is not None :
276
- root = self ._package .with_dependency_groups (list (self ._groups ), only = True )
277
- else :
278
- root = self ._package .without_optional_dependency_groups ()
289
+ if reresolve :
290
+ if self ._groups is not None :
291
+ root = self ._package .with_dependency_groups (
292
+ list (self ._groups ), only = True
293
+ )
294
+ else :
295
+ root = self ._package .without_optional_dependency_groups ()
279
296
280
- # We resolve again by only using the lock file
281
- packages = lockfile_repo .packages + locked_repository .packages
282
- pool = RepositoryPool .from_packages (packages , self ._config )
297
+ # We resolve again by only using the lock file
298
+ packages = lockfile_repo .packages + locked_repository .packages
299
+ pool = RepositoryPool .from_packages (packages , self ._config )
283
300
284
- solver = Solver (
285
- root ,
286
- pool ,
287
- self ._installed_repository .packages ,
288
- locked_repository .packages ,
289
- NullIO (),
290
- )
291
- # Everything is resolved at this point, so we no longer need
292
- # to load deferred dependencies (i.e. VCS, URL and path dependencies)
293
- solver .provider .load_deferred (False )
294
-
295
- with solver .use_environment (self ._env ):
296
- ops = solver .solve (use_latest = self ._whitelist ).calculate_operations (
297
- with_uninstalls = self ._requires_synchronization or self ._update ,
298
- synchronize = self ._requires_synchronization ,
299
- skip_directory = self ._skip_directory ,
300
- extras = set (self ._extras ),
301
+ solver = Solver (
302
+ root ,
303
+ pool ,
304
+ self ._installed_repository .packages ,
305
+ locked_repository .packages ,
306
+ NullIO (),
301
307
)
308
+ # Everything is resolved at this point, so we no longer need
309
+ # to load deferred dependencies (i.e. VCS, URL and path dependencies)
310
+ solver .provider .load_deferred (False )
311
+
312
+ with solver .use_environment (self ._env ):
313
+ transaction = solver .solve (use_latest = self ._whitelist )
314
+
315
+ else :
316
+ if self ._groups is None :
317
+ groups = self ._package .dependency_group_names ()
318
+ else :
319
+ groups = set (self ._groups )
320
+ transaction = Transaction (
321
+ locked_repository .packages ,
322
+ solved_packages ,
323
+ self ._installed_repository .packages ,
324
+ self ._package ,
325
+ self ._env .marker_env ,
326
+ groups ,
327
+ )
328
+
329
+ ops = transaction .calculate_operations (
330
+ with_uninstalls = self ._requires_synchronization or self ._update ,
331
+ synchronize = self ._requires_synchronization ,
332
+ skip_directory = self ._skip_directory ,
333
+ extras = set (self ._extras ),
334
+ )
302
335
303
336
# Validate the dependencies
304
337
for op in ops :
0 commit comments