diff --git a/docs/cli.md b/docs/cli.md index b8140be51ef..7a10d62d63f 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -548,6 +548,7 @@ Note that, at the moment, only pure python wheels are supported. ### Options * `--format (-f)`: Limit the format to either `wheel` or `sdist`. +* `--clean`: Clean output directory before building. * `--local-version (-l)`: Add or replace a local version label to the build. * `--output (-o)`: Set output directory for build artifacts. Default is `dist`. diff --git a/src/poetry/console/commands/build.py b/src/poetry/console/commands/build.py index 640c68d57e9..41018ef4d67 100644 --- a/src/poetry/console/commands/build.py +++ b/src/poetry/console/commands/build.py @@ -6,6 +6,7 @@ from poetry.console.commands.env_command import EnvCommand from poetry.utils.env import build_environment +from poetry.utils.helpers import remove_directory class BuildCommand(EnvCommand): @@ -14,6 +15,11 @@ class BuildCommand(EnvCommand): options = [ option("format", "f", "Limit the format to either sdist or wheel.", flag=False), + option( + "clean", + "Clean output directory before building.", + flag=True, + ), option( "local-version", "l", @@ -74,6 +80,10 @@ def handle(self) -> int: if not dist_dir.is_absolute(): dist_dir = self.poetry.pyproject_path.parent / dist_dir + + if self.option("clean"): + remove_directory(path=dist_dir, force=True) + self._build(fmt, executable=env.python, target_dir=dist_dir) return 0 diff --git a/tests/console/commands/test_build.py b/tests/console/commands/test_build.py index 1c7a0ede03e..65768a34e4c 100644 --- a/tests/console/commands/test_build.py +++ b/tests/console/commands/test_build.py @@ -8,6 +8,7 @@ import pytest from poetry.factory import Factory +from poetry.utils.helpers import remove_directory if TYPE_CHECKING: @@ -82,6 +83,35 @@ def test_build_with_local_version_label( assert all(archive.exists() for archive in build_artifacts) +@pytest.mark.parametrize("clean", [True, False]) +def test_build_with_clean( + tmp_tester: CommandTester, tmp_project_path: Path, tmp_poetry: Poetry, clean: bool +) -> None: + dist_dir = tmp_project_path.joinpath("dist") + dist_dir.joinpath("hello").touch(exist_ok=True) + + tmp_tester.execute("--clean" if clean else "") + build_artifacts = tuple(dist_dir.glob("*")) + + assert len(build_artifacts) == 2 if clean else 3 + assert all(archive.exists() for archive in build_artifacts) + + +def test_build_with_clean_non_existing_output( + tmp_tester: CommandTester, tmp_project_path: Path, tmp_poetry: Poetry +) -> None: + dist_dir = tmp_project_path.joinpath("dist") + + remove_directory(dist_dir, force=True) + assert not dist_dir.exists() + + tmp_tester.execute("--clean") + build_artifacts = tuple(dist_dir.glob("*")) + + assert len(build_artifacts) == 2 + assert all(archive.exists() for archive in build_artifacts) + + def test_build_not_possible_in_non_package_mode( fixture_dir: FixtureDirGetter, command_tester_factory: CommandTesterFactory,