diff --git a/src/poetry/console/commands/add.py b/src/poetry/console/commands/add.py index 05bdc21bf77..7b3326ec116 100644 --- a/src/poetry/console/commands/add.py +++ b/src/poetry/console/commands/add.py @@ -243,7 +243,7 @@ def handle(self) -> int: # Refresh the locker self.poetry.set_locker( - self.poetry.locker.__class__(self.poetry.locker.lock, poetry_content) + self.poetry.locker.copy_with(self.poetry.locker.lock, poetry_content) ) self.installer.set_locker(self.poetry.locker) @@ -261,9 +261,29 @@ def handle(self) -> int: status = self.installer.run() - if status == 0 and not self.option("dry-run"): + if self.option("dry-run"): + return status + + if status == 0: assert isinstance(content, TOMLDocument) self.poetry.file.write(content) + else: + # rollback poetry.lock + for r in requirements: + section.remove(r["name"]) + with contextlib.suppress(ValueError): + self.poetry.package.dependency_group(group).remove_dependency( + r["name"] + ) + + self.poetry.set_locker( + self.poetry.locker.copy_with(self.poetry.locker.lock, poetry_content) + ) + self.installer.set_locker(self.poetry.locker) + + self.installer.lock(update=True) + self.installer.whitelist([]) + self.installer.run() return status diff --git a/src/poetry/packages/locker.py b/src/poetry/packages/locker.py index 2f4a2dcfda4..8a7782bbba4 100644 --- a/src/poetry/packages/locker.py +++ b/src/poetry/packages/locker.py @@ -267,6 +267,9 @@ def set_lock_data(self, root: Package, packages: list[Package]) -> bool: self._write_lock_data(lock) return do_write + def copy_with(self, lock: str | Path, local_config: dict[str, Any]) -> Locker: + return self.__class__(lock, local_config) + def _write_lock_data(self, data: TOMLDocument) -> None: lockfile = TOMLFile(self.lock) lockfile.write(data) diff --git a/tests/helpers.py b/tests/helpers.py index feef37728c0..12f042324eb 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -196,6 +196,12 @@ def __init__(self, lock: str | Path, local_config: dict) -> None: self._lock_data = None self._write = False + @property + def lock(self) -> Path: + if isinstance(self._lock, TOMLFile): + return self._lock.path + return self._lock + def write(self, write: bool = True) -> None: self._write = write @@ -215,6 +221,12 @@ def mock_lock_data(self, data: dict) -> None: def is_fresh(self) -> bool: return True + def copy_with(self, lock: str | Path, local_config: dict[str, Any]) -> TestLocker: + new_locker = TestLocker(lock, local_config) + new_locker._locked = self._locked + new_locker._write = self._write + return new_locker + def _write_lock_data(self, data: TOMLDocument) -> None: if self._write: super()._write_lock_data(data)