87 """Parse a commit message into a :class:`ConventionalCommit`.
89 Returns ``None`` if the first line does not match the Conventional
90 Commits ``type[(scope)][!]: subject`` pattern.
92 if not message
or not message.strip():
95 lines = message.strip().splitlines()
96 header = lines[0].strip()
98 m = _HEADER_RE.match(header)
103 body_lines: list[str] = []
104 footer_lines: list[str] = []
108 while rest
and not rest[0].strip():
114 footer_start = len(rest)
115 for i
in range(len(rest) - 1, -1, -1):
116 if _FOOTER_RE.match(rest[i]):
118 elif rest[i].strip() ==
"":
120 if footer_start < len(rest):
126 body_lines = rest[:footer_start]
127 footer_lines = rest[footer_start:]
130 while body_lines
and not body_lines[-1].strip():
133 breaking = bool(m.group(
"bang"))
135 footer_text =
"\n".join(footer_lines)
136 if "BREAKING CHANGE" in footer_text
or "BREAKING-CHANGE" in footer_text:
140 type=m.group(
"type"),
141 scope=m.group(
"scope"),
142 subject=m.group(
"subject").strip(),
143 body=
"\n".join(body_lines),
259 """Inner implementation of diagnostics impact analysis."""
260 added: dict[str, set[str]] = {}
261 removed: dict[str, set[str]] = {}
263 for line
in diff_text.splitlines():
264 if line.startswith(
"+++")
or line.startswith(
"---"):
267 if line.startswith(
"+")
and "_dbg(" in line:
268 m = _DBG_CALL_RE.search(line)
270 domain = m.group(
"domain")
271 level = m.group(
"level")
or "?"
272 added.setdefault(domain, set()).add(f
"L{level}")
274 elif line.startswith(
"-")
and "_dbg(" in line:
275 m = _DBG_CALL_RE.search(line)
277 domain = m.group(
"domain")
278 level = m.group(
"level")
or "?"
279 removed.setdefault(domain, set()).add(f
"L{level}")
282 impact: list[str] = []
285 for domain
in sorted(added.keys() - removed.keys()):
286 levels =
", ".join(sorted(added[domain]))
287 impact.append(f
"+ Added: {domain} domain ({levels})")
290 for domain
in sorted(removed.keys() - added.keys()):
291 levels =
", ".join(sorted(removed[domain]))
292 impact.append(f
"- Removed: {domain} domain ({levels})")
295 for domain
in sorted(added.keys() & removed.keys()):
296 old_levels =
", ".join(sorted(removed[domain]))
297 new_levels =
", ".join(sorted(added[domain]))
298 impact.append(f
"~ Modified: {domain} ({old_levels} -> {new_levels})")