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 --keep option to allow to generate newsfile, but keep newsfragmen… #453

Merged
merged 9 commits into from
Dec 19, 2022
5 changes: 5 additions & 0 deletions docs/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ Build the combined news file from news fragments.
Do not ask for confirmations.
Useful for automated tasks.

.. option:: --keep

Do not ask for confirmations. But keep newsfiles.
Useful for automated tasks. Where you have to generate several different newsfiles for different parties.


``towncrier create``
--------------------
Expand Down
9 changes: 8 additions & 1 deletion src/towncrier/_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,25 @@
import click


def remove_files(fragment_filenames: list[str], answer_yes: bool) -> None:
def remove_files(
fragment_filenames: list[str], answer_yes: bool, answer_keep: bool
) -> None:
fizyk marked this conversation as resolved.
Show resolved Hide resolved
if not fragment_filenames:
return

if answer_yes:
click.echo("Removing the following files:")
elif answer_keep:
fizyk marked this conversation as resolved.
Show resolved Hide resolved
click.echo("Keeping the following files:")
else:
click.echo("I want to remove the following files:")

for filename in fragment_filenames:
click.echo(filename)

if answer_keep and not answer_yes:
return
fizyk marked this conversation as resolved.
Show resolved Hide resolved

if answer_yes or click.confirm("Is it okay if I remove those files?", default=True):
call(["git", "rm", "--quiet"] + fragment_filenames)

Expand Down
30 changes: 28 additions & 2 deletions src/towncrier/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

import click

from click import Context, Option

from ._builder import find_fragments, render_fragments, split_fragments
from ._git import remove_files, stage_newsfile
from ._project import get_project_name, get_version
Expand All @@ -26,6 +28,18 @@ def _get_date() -> str:
return date.today().isoformat()


def validate_answer(ctx: Context, param: Option, value: bool) -> bool:
fizyk marked this conversation as resolved.
Show resolved Hide resolved
value_check = (
ctx.params.get("answer_yes")
if param.name == "answer_keep"
else ctx.params.get("answer_keep")
)
if value_check and value:
click.echo("You can not choose both --yes and --no at the same time")
ctx.abort()
return value


@click.command(name="build")
@click.option(
"--draft",
Expand Down Expand Up @@ -67,9 +81,18 @@ def _get_date() -> str:
@click.option(
"--yes",
"answer_yes",
default=False,
default=None,
flag_value=True,
help="Do not ask for confirmation to remove news fragments.",
callback=validate_answer,
)
@click.option(
"--keep",
"answer_keep",
default=None,
flag_value=True,
help="Keep the newsfragments.",
fizyk marked this conversation as resolved.
Show resolved Hide resolved
callback=validate_answer,
)
def _main(
draft: bool,
Expand All @@ -79,6 +102,7 @@ def _main(
project_version: str | None,
project_date: str | None,
answer_yes: bool,
answer_keep: bool,
) -> None:
"""
Build a combined news file from news fragment.
Expand All @@ -92,6 +116,7 @@ def _main(
project_version,
project_date,
answer_yes,
answer_keep,
)
except ConfigError as e:
print(e, file=sys.stderr)
Expand All @@ -106,6 +131,7 @@ def __main(
project_version: str | None,
project_date: str | None,
answer_yes: bool,
answer_keep: bool,
) -> None:
"""
The main entry point.
Expand Down Expand Up @@ -237,7 +263,7 @@ def __main(
stage_newsfile(base_directory, news_file)

click.echo("Removing news fragments...", err=to_err)
remove_files(fragment_filenames, answer_yes)
remove_files(fragment_filenames, answer_yes, answer_keep)

click.echo("Done!", err=to_err)

Expand Down
1 change: 1 addition & 0 deletions src/towncrier/newsfragments/129.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added `--keep` option to build command that allows to generate newsfile but keep newsfragments in place. This option can not be used together with `--yes`.
fizyk marked this conversation as resolved.
Show resolved Hide resolved
50 changes: 50 additions & 0 deletions src/towncrier/test/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,56 @@ def test_no_confirmation(self):
self.assertFalse(os.path.isfile(fragment_path1))
self.assertFalse(os.path.isfile(fragment_path2))

def test_keep_fragments(self):
runner = CliRunner()
fizyk marked this conversation as resolved.
Show resolved Hide resolved

with runner.isolated_filesystem():
fizyk marked this conversation as resolved.
Show resolved Hide resolved
setup_simple_project()
fragment_path1 = "foo/newsfragments/123.feature"
fragment_path2 = "foo/newsfragments/124.feature.rst"
with open(fragment_path1, "w") as f:
f.write("Adds levitation")
with open(fragment_path2, "w") as f:
f.write("Extends levitation")

call(["git", "init"])
call(["git", "config", "user.name", "user"])
call(["git", "config", "user.email", "[email protected]"])
call(["git", "add", "."])
call(["git", "commit", "-m", "Initial Commit"])

result = runner.invoke(_main, ["--date", "01-01-2001", "--keep"])

self.assertEqual(0, result.exit_code)
path = "NEWS.rst"
self.assertTrue(os.path.isfile(path))
fizyk marked this conversation as resolved.
Show resolved Hide resolved
self.assertTrue(os.path.isfile(fragment_path1))
self.assertTrue(os.path.isfile(fragment_path2))

def test_yes_keep_error(self):
runner = CliRunner()
fizyk marked this conversation as resolved.
Show resolved Hide resolved

with runner.isolated_filesystem():
fizyk marked this conversation as resolved.
Show resolved Hide resolved
setup_simple_project()
fragment_path1 = "foo/newsfragments/123.feature"
fragment_path2 = "foo/newsfragments/124.feature.rst"
with open(fragment_path1, "w") as f:
f.write("Adds levitation")
with open(fragment_path2, "w") as f:
f.write("Extends levitation")

call(["git", "init"])
call(["git", "config", "user.name", "user"])
call(["git", "config", "user.email", "[email protected]"])
call(["git", "add", "."])
call(["git", "commit", "-m", "Initial Commit"])

result = runner.invoke(_main, ["--date", "01-01-2001", "--yes", "--keep"])
self.assertEqual(1, result.exit_code)

result = runner.invoke(_main, ["--date", "01-01-2001", "--keep", "--yes"])
self.assertEqual(1, result.exit_code)

def test_confirmation_says_no(self):
"""
If the user says "no" to removing the newsfragements, we end up with
Expand Down