Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add force parameter to create #1870

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/1870.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added force flag to create command to overwrite existing scaffolds
7 changes: 6 additions & 1 deletion docs/reference/commands/create.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ to delete and regenerate the app.
Options
=======

There are no additional command line options.
The following options can be provided at the command line.

``--force``
---------------------------------------

Automatically overwrite any existing scaffold for the nominated platform instead of asking for confirmation.
24 changes: 20 additions & 4 deletions src/briefcase/commands/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ def app_template_url(self) -> str:
"""The URL for a cookiecutter repository to use when creating apps."""
return f"https://github.com/beeware/briefcase-{self.platform}-{self.output_format}-template.git"

def add_options(self, parser):
parser.add_argument(
"--force",
action="store_true",
help="Automatically confirm overwriting existing scaffold",
)

def support_package_filename(self, support_revision: str) -> str:
"""The query arguments to use in a support package query request."""
return f"Python-{self.python_version_tag}-{self.platform}-support.b{support_revision}.tar.gz"
Expand Down Expand Up @@ -858,19 +865,27 @@ def cleanup_app_content(self, app: AppConfig):
self.logger.verbose(f"Removing {relative_path}")
path.unlink()

def create_app(self, app: AppConfig, test_mode: bool = False, **options):
def create_app(
self,
app: AppConfig,
test_mode: bool = False,
force: bool = False,
**options,
):
"""Create an application bundle.

:param app: The config object for the app
:param test_mode: Should the app be updated in test mode? (default: False)
:param force: Should any existing scaffold be automatically overwritten?
(default: False)
"""
if not app.supported:
raise UnsupportedPlatform(self.platform)

bundle_path = self.bundle_path(app)
if bundle_path.exists():
self.logger.info()
confirm = self.input.boolean_input(
confirm = force or self.input.boolean_input(
f"Application {app.app_name!r} already exists; overwrite", default=False
)
if not confirm:
Expand Down Expand Up @@ -935,18 +950,19 @@ def verify_app_tools(self, app: AppConfig):
def __call__(
self,
app: AppConfig | None = None,
force: bool = False,
**options,
) -> dict | None:
# Confirm host compatibility, that all required tools are available,
# and that the app configuration is finalized.
self.finalize(app)

if app:
state = self.create_app(app, **options)
state = self.create_app(app, force, **options)
else:
state = None
for app_name, app in sorted(self.apps.items()):
state = self.create_app(app, **full_options(state, options))
state = self.create_app(app, force, **full_options(state, options))

return state

Expand Down
35 changes: 35 additions & 0 deletions tests/commands/create/test_create_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,41 @@ def test_create_app(tracking_create_command, tmp_path):
assert not (tmp_path / "base_path/build/first/tester/dummy/Stub.bin").exists()


def test_create_existing_app_force(tracking_create_command, tmp_path):
"""An existing app is overwritten if --force parameter is added."""

# Generate an app in the location.
bundle_path = tmp_path / "base_path/build/first/tester/dummy"
bundle_path.mkdir(parents=True)
with (bundle_path / "original").open("w", encoding="utf-8") as f:
f.write("original template!")

options, _ = tracking_create_command.parse_options(["--force"])

tracking_create_command.create_app(tracking_create_command.apps["first"], **options)

# Input was not required by the user
assert tracking_create_command.input.prompts == []

# The right sequence of things will be done
assert tracking_create_command.actions == [
("generate", "first"),
("support", "first"),
("verify-app-template", "first"),
("verify-app-tools", "first"),
("code", "first", False),
("requirements", "first", False),
("resources", "first"),
("cleanup", "first"),
]

# Original content has been deleted
assert not (bundle_path / "original").exists()

# New app content has been created
assert (bundle_path / "new").exists()


def test_create_existing_app_overwrite(tracking_create_command, tmp_path):
"""An existing app can be overwritten if requested."""
# Answer yes when asked
Expand Down
4 changes: 2 additions & 2 deletions tests/platforms/linux/appimage/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def test_default_options(create_command):
"""The default options are as expected."""
options, overrides = create_command.parse_options([])

assert options == {}
assert options == {"force": False}
assert overrides == {}

assert create_command.use_docker
Expand All @@ -33,7 +33,7 @@ def test_options(create_command):
"""The extra options can be parsed."""
options, overrides = create_command.parse_options(["--no-docker"])

assert options == {}
assert options == {"force": False}
assert overrides == {}

assert not create_command.use_docker
Expand Down
4 changes: 2 additions & 2 deletions tests/platforms/linux/system/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def test_default_options(create_command):
"""The default options are as expected."""
options, overrides = create_command.parse_options([])

assert options == {}
assert options == {"force": False}
assert overrides == {}

assert create_command.target_image is None
Expand All @@ -26,7 +26,7 @@ def test_options(create_command):
]
)

assert options == {}
assert options == {"force": False}
assert overrides == {}

assert create_command.target_image == "somevendor:surprising"
Expand Down
10 changes: 10 additions & 0 deletions tests/test_cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ def test_upgrade_command(
assert overrides == expected_overrides


# TODO: Find another command to use here since create now has a parameter.
def test_bare_command(monkeypatch, logger, console):
"""``briefcase create`` returns the macOS create app command."""
# Pretend we're on macOS, regardless of where the tests run.
Expand All @@ -369,6 +370,7 @@ def test_bare_command(monkeypatch, logger, console):
assert overrides == {}


# TODO: Find another command to use here since create now has a parameter.
@pytest.mark.skipif(sys.platform != "linux", reason="requires Linux")
def test_linux_default(logger, console):
"""``briefcase create`` returns the linux create system command on Linux."""
Expand Down Expand Up @@ -402,6 +404,7 @@ def test_macOS_default(logger, console):
assert overrides == {}


# TODO: Find another command to use here since create now has a parameter.
@pytest.mark.skipif(sys.platform != "win32", reason="requires Windows")
def test_windows_default(logger, console):
"""``briefcase create`` returns the Windows create app command on Windows."""
Expand All @@ -419,6 +422,7 @@ def test_windows_default(logger, console):
assert overrides == {}


# TODO: Find another command to use here since create now has a parameter.
def test_bare_command_help(monkeypatch, capsys, logger, console):
"""``briefcase create -h`` returns the macOS create app command help."""
# Pretend we're on macOS, regardless of where the tests run.
Expand Down Expand Up @@ -466,6 +470,7 @@ def test_command_unknown_platform(monkeypatch, logger, console):
)


# TODO: Find another command to use here since create now has a parameter.
def test_command_explicit_platform(monkeypatch, logger, console):
"""``briefcase create linux`` returns linux create app command."""
# Pretend we're on macOS, regardless of where the tests run.
Expand All @@ -484,6 +489,7 @@ def test_command_explicit_platform(monkeypatch, logger, console):
assert overrides == {}


# TODO: Find another command to use here since create now has a parameter.
def test_command_explicit_platform_case_handling(monkeypatch, logger, console):
"""``briefcase create macOS`` returns macOS create app command."""
# Pretend we're on macOS, regardless of where the tests run.
Expand All @@ -503,6 +509,7 @@ def test_command_explicit_platform_case_handling(monkeypatch, logger, console):
assert overrides == {}


# TODO: Find another command to use here since create now has a parameter.
def test_command_explicit_platform_help(monkeypatch, capsys, logger, console):
"""``briefcase create macOS -h`` returns the macOS create app command help."""
# Pretend we're on macOS, regardless of where the tests run.
Expand All @@ -523,6 +530,7 @@ def test_command_explicit_platform_help(monkeypatch, capsys, logger, console):
)


# TODO: Find another command to use here since create now has a parameter.
def test_command_explicit_format(monkeypatch, logger, console):
"""``briefcase create macOS app`` returns the macOS create app command."""
# Pretend we're on macOS, regardless of where the tests run.
Expand Down Expand Up @@ -573,6 +581,7 @@ def test_command_explicit_unsupported_format(monkeypatch, logger, console):
do_cmdline_parse("create macOS homebrew".split(), logger, console)


# TODO: Find another command to use here since create now has a parameter.
def test_command_explicit_format_help(monkeypatch, capsys, logger, console):
"""``briefcase create macOS app -h`` returns the macOS create app help."""
# Pretend we're on macOS, regardless of where the tests run.
Expand All @@ -593,6 +602,7 @@ def test_command_explicit_format_help(monkeypatch, capsys, logger, console):
)


# TODO: Find another command to use here since create now has a parameter.
def test_command_disable_input(monkeypatch, logger, console):
"""``briefcase create --no-input`` disables console input."""
# Pretend we're on macOS, regardless of where the tests run.
Expand Down
Loading