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