Skip to content

Commit

Permalink
Make towncrier create increment fragments rather than failing (#475)
Browse files Browse the repository at this point in the history
* Make `towncrier create` increment fragments rather than failing
Fixes #474

* Rename change file

* Add example to tutorial of incrementing via towncrier create

* Remove the counter example from the tutorial, this isn't core functionality

* Better docstring for the new test

---------

Co-authored-by: Glyph <glyph@twistedmatrix.com>
  • Loading branch information
SmileyChris and glyph committed Feb 20, 2023
1 parent 566d315 commit 826beac
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 11 deletions.
3 changes: 3 additions & 0 deletions docs/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ Create a news fragment in the directory that ``towncrier`` is configured to look

``towncrier create`` will enforce that the passed type (e.g. ``bugfix``) is valid.

If the filename exists already, ``towncrier create`` will add (and then increment) a number after the fragment type until it finds a filename that does not exist yet.
In the above example, it will generate ``123.bugfix.1.rst`` if ``123.bugfix.rst`` already exists.

.. option:: --content, -c CONTENT

A string to use for content.
Expand Down
13 changes: 11 additions & 2 deletions src/towncrier/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,17 @@ def __main(
os.makedirs(fragments_directory)

segment_file = os.path.join(fragments_directory, filename)
if os.path.exists(segment_file):
raise click.ClickException(f"{segment_file} already exists")

retry = 0
if filename.split(".")[-1] not in config.types:
filename, extra_ext = os.path.splitext(filename)
else:
extra_ext = ""
while os.path.exists(segment_file):
retry += 1
segment_file = os.path.join(
fragments_directory, f"{filename}.{retry}{extra_ext}"
)

if edit:
edited_content = _get_news_content_from_user(content)
Expand Down
6 changes: 6 additions & 0 deletions src/towncrier/newsfragments/475.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Make ``towncrier create`` use the fragment counter rather than failing
on existing fragment names.

For example, if there is an existing fragment named ``123.feature``,
then ``towncrier create 123.feature`` will now create a fragment
named ``123.feature.1``.
46 changes: 37 additions & 9 deletions src/towncrier/test/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,20 +151,48 @@ def test_invalid_section(self):
"Expected filename '123.foobar.rst' to be of format", result.output
)

def test_file_exists(self):
@with_isolated_runner
def test_file_exists(self, runner: CliRunner):
"""Ensure we don't overwrite existing files."""
runner = CliRunner()
setup_simple_project()
frag_path = Path("foo", "newsfragments")

with runner.isolated_filesystem():
setup_simple_project()
for _ in range(3):
result = runner.invoke(_main, ["123.feature"])
self.assertEqual(result.exit_code, 0, result.output)

fragments = [f.name for f in frag_path.iterdir()]
self.assertEqual(
sorted(fragments),
[
"123.feature",
"123.feature.1",
"123.feature.2",
],
)

self.assertEqual([], os.listdir("foo/newsfragments"))
@with_isolated_runner
def test_file_exists_with_ext(self, runner: CliRunner):
"""
Ensure we don't overwrite existing files when using an extension after the
fragment type.
"""
setup_simple_project()
frag_path = Path("foo", "newsfragments")

runner.invoke(_main, ["123.feature.rst"])
for _ in range(3):
result = runner.invoke(_main, ["123.feature.rst"])

self.assertEqual(type(result.exception), SystemExit)
self.assertIn("123.feature.rst already exists", result.output)
self.assertEqual(result.exit_code, 0, result.output)

fragments = [f.name for f in frag_path.iterdir()]
self.assertEqual(
sorted(fragments),
[
"123.feature.1.rst",
"123.feature.2.rst",
"123.feature.rst",
],
)

@with_isolated_runner
def test_create_orphan_fragment(self, runner: CliRunner):
Expand Down

0 comments on commit 826beac

Please sign in to comment.