Commit c564e1ca by Riccardo Albertazzi Committed by GitHub

feat: add --lock option to remove command (#7917)

parent ee567a72
...@@ -471,6 +471,7 @@ about dependency groups. ...@@ -471,6 +471,7 @@ about dependency groups.
* `--group (-G)`: The group to remove the dependency from. * `--group (-G)`: The group to remove the dependency from.
* `--dev (-D)`: Removes a package from the development dependencies. (**Deprecated**, use `-G dev` instead) * `--dev (-D)`: Removes a package from the development dependencies. (**Deprecated**, use `-G dev` instead)
* `--dry-run` : Outputs the operations but will not execute anything (implicitly enables --verbose). * `--dry-run` : Outputs the operations but will not execute anything (implicitly enables --verbose).
* `--lock`: Do not perform operations (only update the lockfile).
## show ## show
......
...@@ -35,6 +35,7 @@ class RemoveCommand(InstallerCommand): ...@@ -35,6 +35,7 @@ class RemoveCommand(InstallerCommand):
"(implicitly enables --verbose)." "(implicitly enables --verbose)."
), ),
), ),
option("lock", None, "Do not perform operations (only update the lockfile)."),
] ]
help = """The <info>remove</info> command removes a package from the current help = """The <info>remove</info> command removes a package from the current
...@@ -108,15 +109,13 @@ list of installed packages ...@@ -108,15 +109,13 @@ list of installed packages
) )
# Refresh the locker # Refresh the locker
self.poetry.set_locker( self.poetry.locker.set_local_config(poetry_content)
self.poetry.locker.__class__(self.poetry.locker.lock, poetry_content)
)
self.installer.set_locker(self.poetry.locker) self.installer.set_locker(self.poetry.locker)
self.installer.set_package(self.poetry.package) self.installer.set_package(self.poetry.package)
self.installer.dry_run(self.option("dry-run", False)) self.installer.dry_run(self.option("dry-run", False))
self.installer.verbose(self.io.is_verbose()) self.installer.verbose(self.io.is_verbose())
self.installer.update(True) self.installer.update(True)
self.installer.execute_operations(not self.option("lock"))
self.installer.whitelist(removed_set) self.installer.whitelist(removed_set)
status = self.installer.run() status = self.installer.run()
......
...@@ -90,6 +90,10 @@ class Locker: ...@@ -90,6 +90,10 @@ class Locker:
return False return False
def set_local_config(self, local_config: dict[str, Any]) -> None:
self._local_config = local_config
self._content_hash = self._get_content_hash()
def locked_repository(self) -> LockfileRepository: def locked_repository(self) -> LockfileRepository:
""" """
Searches and returns a repository of locked packages. Searches and returns a repository of locked packages.
......
...@@ -10,6 +10,7 @@ import tomlkit ...@@ -10,6 +10,7 @@ import tomlkit
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.factory import Factory from poetry.factory import Factory
from tests.helpers import TestLocker
from tests.helpers import get_package from tests.helpers import get_package
...@@ -33,12 +34,16 @@ def poetry_with_up_to_date_lockfile( ...@@ -33,12 +34,16 @@ def poetry_with_up_to_date_lockfile(
) -> Poetry: ) -> Poetry:
source = fixture_dir("up_to_date_lock") source = fixture_dir("up_to_date_lock")
return project_factory( poetry = project_factory(
name="foobar", name="foobar",
pyproject_content=(source / "pyproject.toml").read_text(encoding="utf-8"), pyproject_content=(source / "pyproject.toml").read_text(encoding="utf-8"),
poetry_lock_content=(source / "poetry.lock").read_text(encoding="utf-8"), poetry_lock_content=(source / "poetry.lock").read_text(encoding="utf-8"),
) )
assert isinstance(poetry.locker, TestLocker)
poetry.locker.locked(True)
return poetry
@pytest.fixture() @pytest.fixture()
def tester(command_tester_factory: CommandTesterFactory) -> CommandTester: def tester(command_tester_factory: CommandTesterFactory) -> CommandTester:
...@@ -49,7 +54,6 @@ def test_remove_without_specific_group_removes_from_all_groups( ...@@ -49,7 +54,6 @@ def test_remove_without_specific_group_removes_from_all_groups(
tester: CommandTester, tester: CommandTester,
app: PoetryTestApplication, app: PoetryTestApplication,
repo: TestRepository, repo: TestRepository,
command_tester_factory: CommandTesterFactory,
installed: Repository, installed: Repository,
) -> None: ) -> None:
""" """
...@@ -108,7 +112,6 @@ def test_remove_without_specific_group_removes_from_specific_groups( ...@@ -108,7 +112,6 @@ def test_remove_without_specific_group_removes_from_specific_groups(
tester: CommandTester, tester: CommandTester,
app: PoetryTestApplication, app: PoetryTestApplication,
repo: TestRepository, repo: TestRepository,
command_tester_factory: CommandTesterFactory,
installed: Repository, installed: Repository,
) -> None: ) -> None:
""" """
...@@ -166,7 +169,6 @@ def test_remove_does_not_live_empty_groups( ...@@ -166,7 +169,6 @@ def test_remove_does_not_live_empty_groups(
tester: CommandTester, tester: CommandTester,
app: PoetryTestApplication, app: PoetryTestApplication,
repo: TestRepository, repo: TestRepository,
command_tester_factory: CommandTesterFactory,
installed: Repository, installed: Repository,
) -> None: ) -> None:
""" """
...@@ -213,7 +215,6 @@ def test_remove_canonicalized_named_removes_dependency_correctly( ...@@ -213,7 +215,6 @@ def test_remove_canonicalized_named_removes_dependency_correctly(
tester: CommandTester, tester: CommandTester,
app: PoetryTestApplication, app: PoetryTestApplication,
repo: TestRepository, repo: TestRepository,
command_tester_factory: CommandTesterFactory,
installed: Repository, installed: Repository,
) -> None: ) -> None:
""" """
...@@ -308,3 +309,47 @@ def test_remove_with_dry_run_keep_files_intact( ...@@ -308,3 +309,47 @@ def test_remove_with_dry_run_keep_files_intact(
assert ( assert (
poetry_with_up_to_date_lockfile._locker.lock_data == original_lockfile_content poetry_with_up_to_date_lockfile._locker.lock_data == original_lockfile_content
) )
def test_remove_performs_uninstall_op(
poetry_with_up_to_date_lockfile: Poetry,
command_tester_factory: CommandTesterFactory,
installed: Repository,
) -> None:
installed.add_package(get_package("docker", "4.3.1"))
tester = command_tester_factory("remove", poetry=poetry_with_up_to_date_lockfile)
tester.execute("docker")
expected = """\
Updating dependencies
Resolving dependencies...
Package operations: 0 installs, 0 updates, 1 removal
• Removing docker (4.3.1)
Writing lock file
"""
assert tester.io.fetch_output() == expected
def test_remove_with_lock_does_not_perform_uninstall_op(
poetry_with_up_to_date_lockfile: Poetry,
command_tester_factory: CommandTesterFactory,
installed: Repository,
) -> None:
installed.add_package(get_package("docker", "4.3.1"))
tester = command_tester_factory("remove", poetry=poetry_with_up_to_date_lockfile)
tester.execute("docker --lock")
expected = """\
Updating dependencies
Resolving dependencies...
Writing lock file
"""
assert tester.io.fetch_output() == expected
...@@ -187,12 +187,8 @@ class TestLocker(Locker): ...@@ -187,12 +187,8 @@ class TestLocker(Locker):
__test__ = False __test__ = False
def __init__(self, lock: Path, local_config: dict[str, Any]) -> None: def __init__(self, lock: Path, local_config: dict[str, Any]) -> None:
self._lock = lock super().__init__(lock, local_config)
self._local_config = local_config
self._lock_data = None
self._content_hash = self._get_content_hash()
self._locked = False self._locked = False
self._lock_data = None
self._write = False self._write = False
def write(self, write: bool = True) -> None: def write(self, write: bool = True) -> None:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment