Открыть боковую панель
Минаков Марк Александрович
git-changelog
Коммиты
cdf17c03
Коммит
cdf17c03
создал
Янв 29, 2023
по автору
Timothée Mazzucotelli
Просмотр файлов
feat: Support Git trailers, render them in Keep A Changelog template
владелец
f7517368
Изменения
6
Скрыть пробелы
Построчно
Рядом
src/git_changelog/build.py
Просмотр файла @
cdf17c03
...
...
@@ -159,6 +159,7 @@ class Changelog:
provider
:
ProviderRefParser
|
None
=
None
,
style
:
StyleType
|
None
=
None
,
parse_provider_refs
:
bool
=
True
,
parse_trailers
:
bool
=
False
,
):
"""
Initialization method.
...
...
@@ -168,9 +169,11 @@ class Changelog:
provider: The provider to use (github.com, gitlab.com, etc.).
style: The commit style to use (angular, atom, etc.).
parse_provider_refs: Whether to parse provider-specific references in the commit messages.
parse_trailers: Whether to parse Git trailers in the commit messages.
"""
self
.
repository
:
str
=
repository
self
.
parse_provider_refs
:
bool
=
parse_provider_refs
self
.
parse_trailers
:
bool
=
parse_trailers
# set provider
if
not
provider
:
...
...
@@ -297,6 +300,7 @@ class Changelog:
refs
=
lines
[
pos
+
7
],
subject
=
lines
[
pos
+
8
],
body
=
body
,
parse_trailers
=
self
.
parse_trailers
,
)
# expand commit object with provider parsing
...
...
src/git_changelog/cli.py
Просмотр файла @
cdf17c03
...
...
@@ -100,6 +100,14 @@ def get_parser() -> argparse.ArgumentParser:
help
=
'The Jinja2 template to use. Prefix with "path:" to specify the path '
'to a directory containing a file named "changelog.md".'
,
)
parser
.
add_argument
(
"-T"
,
"--trailers"
,
action
=
"store_true"
,
default
=
False
,
dest
=
"parse_trailers"
,
help
=
"Parse Git trailers in the commit message. See https://git-scm.com/docs/git-interpret-trailers."
,
)
parser
.
add_argument
(
"-v"
,
"--version"
,
...
...
@@ -141,6 +149,7 @@ def main(args: list[str] | None = None) -> int:
opts
.
repository
,
style
=
opts
.
style
,
parse_provider_refs
=
opts
.
parse_refs
,
parse_trailers
=
opts
.
parse_trailers
,
)
# get rendered contents
...
...
src/git_changelog/commit.py
Просмотр файла @
cdf17c03
...
...
@@ -4,6 +4,7 @@ from __future__ import annotations
import
re
from
abc
import
ABC
,
abstractmethod
from
contextlib
import
suppress
from
datetime
import
datetime
from
typing
import
Any
,
Pattern
...
...
@@ -13,7 +14,7 @@ from git_changelog.providers import ProviderRefParser, Ref
class
Commit
:
"""A class to represent a commit."""
def
__init__
(
def
__init__
(
# noqa: WPS231
self
,
commit_hash
:
str
,
author_name
:
str
=
""
,
...
...
@@ -26,6 +27,7 @@ class Commit:
subject
:
str
=
""
,
body
:
list
[
str
]
|
None
=
None
,
url
:
str
=
""
,
parse_trailers
:
bool
=
False
,
):
"""
Initialization method.
...
...
@@ -42,6 +44,7 @@ class Commit:
subject: The commit message subject.
body: The commit message body.
url: The commit URL.
parse_trailers: Whether to parse Git trailers.
"""
if
not
author_date
:
author_date
=
datetime
.
now
()
...
...
@@ -75,6 +78,12 @@ class Commit:
self
.
text_refs
:
dict
[
str
,
list
[
Ref
]]
=
{}
self
.
style
:
dict
[
str
,
Any
]
=
{}
self
.
trailers
:
dict
[
str
,
str
]
=
{}
self
.
body_without_trailers
=
self
.
body
if
parse_trailers
:
self
.
_parse_trailers
()
def
update_with_style
(
self
,
style
:
"CommitStyle"
)
->
None
:
"""
Apply the style-parsed data to this commit.
...
...
@@ -111,6 +120,24 @@ class Commit:
if
issue
.
ref
not
in
self
.
subject
:
self
.
text_refs
[
"issues_not_in_subject"
].
append
(
issue
)
def
_parse_trailers
(
self
)
->
None
:
last_blank_line
=
-
1
for
index
,
line
in
enumerate
(
self
.
body
):
if
not
line
:
last_blank_line
=
index
with
suppress
(
ValueError
):
trailers
=
self
.
_parse_trailers_block
(
self
.
body
[
last_blank_line
+
1
:])
if
trailers
:
self
.
trailers
.
update
(
trailers
)
self
.
body_without_trailers
=
self
.
body
[:
last_blank_line
]
def
_parse_trailers_block
(
self
,
lines
:
list
[
str
])
->
dict
[
str
,
str
]:
trailers
=
{}
for
line
in
lines
:
title
,
value
=
line
.
split
(
": "
,
1
)
trailers
[
title
]
=
value
.
strip
()
return
trailers
# or raise ValueError due to split unpacking
class
CommitStyle
(
ABC
):
"""A base class for a style of commit messages."""
...
...
src/git_changelog/templates/__init__.py
Просмотр файла @
cdf17c03
...
...
@@ -3,10 +3,15 @@
from
__future__
import
annotations
import
os
from
urllib.parse
import
urlparse
from
jinja2
import
Environment
,
FileSystemLoader
,
Template
def
_filter_is_url
(
value
:
str
)
->
bool
:
return
bool
(
urlparse
(
value
).
scheme
)
def
get_path
()
->
str
:
"""Get the path to the templates directory.
...
...
@@ -25,7 +30,9 @@ def get_env(path: str) -> Environment:
Returns:
The Jinja environment.
"""
return
Environment
(
loader
=
FileSystemLoader
(
path
))
# noqa: S701 (we are OK with not auto-escaping)
env
=
Environment
(
loader
=
FileSystemLoader
(
path
))
# noqa: S701 (we are OK with not auto-escaping)
env
.
filters
.
update
({
"is_url"
:
_filter_is_url
})
return
env
def
get_custom_template
(
path
:
str
)
->
Template
:
...
...
src/git_changelog/templates/keepachangelog/commit.md
Просмотр файла @
cdf17c03
...
...
@@ -2,3 +2,8 @@
{%- if commit.text_refs.issues_not_in_subject %} Related issues/PRs: {% for issue in commit.text_refs.issues_not_in_subject -%}
{% if issue.url %}
[
{{ issue.ref }}
](
{{
issue.url }}){% else %}{{ issue.ref }}{% endif %}{% if not loop.last %}, {% endif -%}
{%- endfor -%}{%- endif -%}
{%- for trailer_name, trailer_value in commit.trailers.items() -%}
{%- if trailer_value|is_url %}
[
{{ trailer_name }}
](
{{
trailer_value }})
{%- else %} {{ trailer_name }}: {{ trailer_value }}{% endif %}
{%- if not loop.last %},{% endif %}
{%- endfor -%}
tests/test_commit.py
0 → 100644
Просмотр файла @
cdf17c03
"""Tests for the `commit` module."""
import
pytest
from
git_changelog.commit
import
Commit
@
pytest
.
mark
.
parametrize
(
(
"body"
,
"expected_trailers"
),
[
(
"t1: v1
\n
t2: v2"
,
{
"t1"
:
"v1"
,
"t2"
:
"v2"
}),
# ok
(
"body
\n\n
t1: v1
\n
t2: v2"
,
{
"t1"
:
"v1"
,
"t2"
:
"v2"
}),
# ok
(
"t1: v1
\n
t2:v2"
,
{}),
# missing space after colon
(
"t1: v1
\n
t2: v2
\n\n
f"
,
{}),
# trailers not last
(
"t1: v1
\n
t2 v2"
,
{}),
# not all trailers
(
"something: else
\n\n
t1: v1
\n
t2: v2"
,
{
"t1"
:
"v1"
,
"t2"
:
"v2"
}),
# parse footer only
],
)
def
test_parsing_trailers
(
body
,
expected_trailers
):
"""Assert trailers are parsed correctly.
Parameters:
body: A commit message body.
expected_trailers: The trailers we expect to be parsed.
"""
commit
=
Commit
(
commit_hash
=
"aaaaaaaa"
,
subject
=
"Summary"
,
body
=
body
.
split
(
"
\n
"
),
parse_trailers
=
True
,
)
assert
commit
.
trailers
==
expected_trailers
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать