77from packaging .utils import canonicalize_name
88
99from poetry .installation .executor import Executor
10+ from poetry .puzzle .transaction import Transaction
1011from poetry .repositories import Repository
1112from poetry .repositories import RepositoryPool
1213from poetry .repositories .installed_repository import InstalledRepository
@@ -206,6 +207,10 @@ def _do_install(self) -> int:
206207 from poetry .puzzle .solver import Solver
207208
208209 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+
209214 if self ._update :
210215 if not self ._lock and self ._locker .is_locked ():
211216 locked_repository = self ._locker .locked_repository ()
@@ -241,7 +246,6 @@ def _do_install(self) -> int:
241246 self ._write_lock_file (solved_packages )
242247 return 0
243248
244- lockfile_repo = LockfileRepository ()
245249 for package in solved_packages :
246250 if not lockfile_repo .has_package (package ):
247251 lockfile_repo .add_package (package )
@@ -254,6 +258,13 @@ def _do_install(self) -> int:
254258 "pyproject.toml changed significantly since poetry.lock was last"
255259 " generated. Run `poetry lock [--no-update]` to fix the lock file."
256260 )
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
257268
258269 locker_extras = {
259270 canonicalize_name (extra )
@@ -264,41 +275,63 @@ def _do_install(self) -> int:
264275 raise ValueError (f"Extra [{ extra } ] is not specified." )
265276
266277 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 ()
268282
269283 if self ._io .is_verbose ():
270284 self ._io .write_line ("" )
271285 self ._io .write_line (
272286 "<info>Finding the necessary packages for the current system</>"
273287 )
274288
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 ()
279296
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 )
283300
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 (),
301307 )
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+ )
302335
303336 # Validate the dependencies
304337 for op in ops :
0 commit comments