128 """Parse a commit message into a :class:`ConventionalCommit`.
130 Returns ``None`` if the first line does not match the Conventional
131 Commits ``type[(scope)][!]: subject`` pattern.
133 func =
"parse_commit_message"
134 _dbg(
"GIT", func, f
"parsing a {len(message)}-char commit message", 4)
135 if not message
or not message.strip():
138 lines = message.strip().splitlines()
139 header = lines[0].strip()
148 body_lines: list[str] = []
149 footer_lines: list[str] = []
153 while rest
and not rest[0].strip():
159 footer_start = len(rest)
160 for i
in range(len(rest) - 1, -1, -1):
161 if _FOOTER_RE.match(rest[i]):
163 elif rest[i].strip() ==
"":
165 if footer_start < len(rest):
171 body_lines = rest[:footer_start]
172 footer_lines = rest[footer_start:]
175 while body_lines
and not body_lines[-1].strip():
178 breaking = bool(m.group(
"bang"))
180 footer_text =
"\n".join(footer_lines)
181 if "BREAKING CHANGE" in footer_text
or "BREAKING-CHANGE" in footer_text:
185 type=m.group(
"type"),
186 scope=m.group(
"scope"),
187 subject=m.group(
"subject").strip(),
188 body=
"\n".join(body_lines),
349 """Inner implementation of diagnostics impact analysis."""
350 added: dict[str, set[str]] = {}
351 removed: dict[str, set[str]] = {}
353 for line
in diff_text.splitlines():
354 if line.startswith(
"+++")
or line.startswith(
"---"):
357 if line.startswith(
"+")
and "_dbg(" in line:
358 m = _DBG_CALL_RE.search(line)
360 domain = m.group(
"domain")
361 level = m.group(
"level")
or "?"
362 added.setdefault(domain, set()).add(f
"L{level}")
364 elif line.startswith(
"-")
and "_dbg(" in line:
365 m = _DBG_CALL_RE.search(line)
367 domain = m.group(
"domain")
368 level = m.group(
"level")
or "?"
369 removed.setdefault(domain, set()).add(f
"L{level}")
372 impact: list[str] = []
375 for domain
in sorted(added.keys() - removed.keys()):
376 levels =
", ".join(sorted(added[domain]))
377 impact.append(f
"+ Added: {domain} domain ({levels})")
380 for domain
in sorted(removed.keys() - added.keys()):
381 levels =
", ".join(sorted(removed[domain]))
382 impact.append(f
"- Removed: {domain} domain ({levels})")
385 for domain
in sorted(added.keys() & removed.keys()):
386 old_levels =
", ".join(sorted(removed[domain]))
387 new_levels =
", ".join(sorted(added[domain]))
388 impact.append(f
"~ Modified: {domain} ({old_levels} -> {new_levels})")