https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/172123
>From 4b0b1ee150ea820f00564667e734ddd225665d53 Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Fri, 12 Dec 2025 22:39:40 +0800 Subject: [PATCH 01/12] [Github][CI] Introduce `doc8` to `code-lint-helper.py` --- .../github-action-ci-tooling/Dockerfile | 5 +- .github/workflows/pr-code-lint.yml | 6 +- llvm/utils/git/code-lint-helper.py | 61 ++++++++++++++++++- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/.github/workflows/containers/github-action-ci-tooling/Dockerfile b/.github/workflows/containers/github-action-ci-tooling/Dockerfile index b78c99efb9be3..47dedba5194e2 100644 --- a/.github/workflows/containers/github-action-ci-tooling/Dockerfile +++ b/.github/workflows/containers/github-action-ci-tooling/Dockerfile @@ -94,6 +94,10 @@ COPY --from=llvm-downloader /llvm-extract/LLVM-${LLVM_VERSION}-Linux-X64/bin/cla COPY clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py ${LLVM_SYSROOT}/bin/clang-tidy-diff.py # Install dependencies for 'pr-code-lint.yml' job +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y python3-doc8 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* COPY llvm/utils/git/requirements_linting.txt requirements_linting.txt RUN pip install -r requirements_linting.txt --break-system-packages && \ rm requirements_linting.txt @@ -119,4 +123,3 @@ RUN git clone https://github.com/universal-ctags/ctags.git && \ ./configure && \ sudo make install && \ rm -Rf ../ctags - diff --git a/.github/workflows/pr-code-lint.yml b/.github/workflows/pr-code-lint.yml index ea4f8217cd003..ed0b371064b80 100644 --- a/.github/workflows/pr-code-lint.yml +++ b/.github/workflows/pr-code-lint.yml @@ -20,7 +20,7 @@ jobs: run: shell: bash container: - image: 'ghcr.io/llvm/ci-ubuntu-24.04-lint' + image: 'ghcr.io/llvm/ci-ubuntu-24.04-lint-doc8' timeout-minutes: 60 concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -71,12 +71,12 @@ jobs: -DLLVM_INCLUDE_TESTS=OFF \ -DCLANG_INCLUDE_TESTS=OFF \ -DCMAKE_BUILD_TYPE=Release - + ninja -C build \ clang-tablegen-targets \ genconfusable # for "ConfusableIdentifierCheck.h" - - name: Run code linter + - name: Run code linters env: GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py index a53549fb69a77..aca88e2be5a8c 100644 --- a/llvm/utils/git/code-lint-helper.py +++ b/llvm/utils/git/code-lint-helper.py @@ -36,6 +36,7 @@ class LintArgs: issue_number: int = 0 build_path: str = "build" clang_tidy_binary: str = "clang-tidy" + doc8_binary: str = "doc8" def __init__(self, args: argparse.Namespace) -> None: if args is not None: @@ -50,6 +51,7 @@ def __init__(self, args: argparse.Namespace) -> None: self.verbose = args.verbose self.build_path = args.build_path self.clang_tidy_binary = args.clang_tidy_binary + self.doc8_binary = args.doc8_binary class LintHelper: @@ -289,8 +291,59 @@ def _clean_clang_tidy_output(self, output: str) -> str: return "" +class Doc8LintHelper(LintHelper): + name: Final = "doc8" + friendly_name: Final = "documentation linter" -ALL_LINTERS = (ClangTidyLintHelper(),) + def instructions(self, files_to_lint: Sequence[str], args: LintArgs) -> str: + files_str = " ".join(files_to_lint) + return f"doc8 -q {files_str}" + + def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]: + filtered_files = [] + for filepath in changed_files: + _, ext = os.path.splitext(filepath) + if ext != ".rst": + continue + if not filepath.startswith("clang-tools-extra/docs/clang-tidy/"): + continue + if os.path.exists(filepath): + filtered_files.append(filepath) + return filtered_files + + def run_linter_tool(self, files_to_lint: Sequence[str], args: LintArgs) -> str: + if not files_to_lint: + return "" + + doc8_cmd = [args.doc8_binary, "-q"] + doc8_cmd.extend(files_to_lint) + + if args.verbose: + print(f"Running doc8: {' '.join(doc8_cmd)}") + + proc = subprocess.run( + doc8_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + check=False, + ) + + if proc.returncode == 0: + return "" + + output = proc.stdout.strip() + if output: + return output + + error_output = proc.stderr.strip() + if error_output: + return error_output + + return f"doc8 exited with return code {proc.returncode} but no output." + + +ALL_LINTERS = (ClangTidyLintHelper(), Doc8LintHelper()) if __name__ == "__main__": @@ -331,6 +384,12 @@ def _clean_clang_tidy_output(self, output: str) -> str: default="clang-tidy", help="Path to clang-tidy binary", ) + parser.add_argument( + "--doc8-binary", + type=str, + default="doc8", + help="Path to doc8 binary", + ) parser.add_argument( "--verbose", action="store_true", default=True, help="Verbose output" ) >From d5f45bb1c2d7deed3eb3ed23f0a18cba6e008706 Mon Sep 17 00:00:00 2001 From: mitchell <[email protected]> Date: Sat, 13 Dec 2025 20:39:00 +0800 Subject: [PATCH 02/12] Apply suggestions from code review Co-authored-by: EugeneZelenko <[email protected]> --- llvm/utils/git/code-lint-helper.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py index aca88e2be5a8c..aabc78f2de033 100644 --- a/llvm/utils/git/code-lint-helper.py +++ b/llvm/utils/git/code-lint-helper.py @@ -295,11 +295,10 @@ class Doc8LintHelper(LintHelper): name: Final = "doc8" friendly_name: Final = "documentation linter" - def instructions(self, files_to_lint: Sequence[str], args: LintArgs) -> str: - files_str = " ".join(files_to_lint) - return f"doc8 -q {files_str}" + def instructions(self, files_to_lint: Iterable[str], args: LintArgs) -> str: + return f"doc8 -q {' '.join(files_to_lint)}" - def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]: + def filter_changed_files(self, changed_files: Iterable[str]) -> Sequence[str]: filtered_files = [] for filepath in changed_files: _, ext = os.path.splitext(filepath) @@ -311,7 +310,7 @@ def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]: filtered_files.append(filepath) return filtered_files - def run_linter_tool(self, files_to_lint: Sequence[str], args: LintArgs) -> str: + def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str: if not files_to_lint: return "" @@ -332,12 +331,10 @@ def run_linter_tool(self, files_to_lint: Sequence[str], args: LintArgs) -> str: if proc.returncode == 0: return "" - output = proc.stdout.strip() - if output: + if output := proc.stdout.strip(): return output - error_output = proc.stderr.strip() - if error_output: + if error_output := proc.stderr.strip(): return error_output return f"doc8 exited with return code {proc.returncode} but no output." >From e014eb29350befe49cd99d131f414661d88e3539 Mon Sep 17 00:00:00 2001 From: mitchell <[email protected]> Date: Sat, 13 Dec 2025 20:48:40 +0800 Subject: [PATCH 03/12] Update llvm/utils/git/code-lint-helper.py Co-authored-by: Baranov Victor <[email protected]> --- llvm/utils/git/code-lint-helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py index aabc78f2de033..db551204f0c1a 100644 --- a/llvm/utils/git/code-lint-helper.py +++ b/llvm/utils/git/code-lint-helper.py @@ -293,7 +293,7 @@ def _clean_clang_tidy_output(self, output: str) -> str: class Doc8LintHelper(LintHelper): name: Final = "doc8" - friendly_name: Final = "documentation linter" + friendly_name: Final = "RST documentation linter" def instructions(self, files_to_lint: Iterable[str], args: LintArgs) -> str: return f"doc8 -q {' '.join(files_to_lint)}" >From 1188b8dbe36b8cfada478cfa3f3f9e25c3b6c18f Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sat, 13 Dec 2025 20:45:35 +0800 Subject: [PATCH 04/12] Fix --- llvm/utils/git/code-lint-helper.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py index db551204f0c1a..3947bcac7f3b9 100644 --- a/llvm/utils/git/code-lint-helper.py +++ b/llvm/utils/git/code-lint-helper.py @@ -23,7 +23,7 @@ import os import subprocess import sys -from typing import Any, Dict, Final, List, Sequence +from typing import Any, Dict, Final, Iterable, List, Sequence class LintArgs: @@ -194,7 +194,7 @@ def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]: arg for arg in changed_files if "third-party" not in arg ] - filtered_files = [] + filtered_files: List[str] = [] for filepath in clang_tidy_changed_files: _, ext = os.path.splitext(filepath) if ext not in (".c", ".cpp", ".cxx", ".h", ".hpp", ".hxx"): @@ -298,8 +298,8 @@ class Doc8LintHelper(LintHelper): def instructions(self, files_to_lint: Iterable[str], args: LintArgs) -> str: return f"doc8 -q {' '.join(files_to_lint)}" - def filter_changed_files(self, changed_files: Iterable[str]) -> Sequence[str]: - filtered_files = [] + def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]: + filtered_files: List[str] = [] for filepath in changed_files: _, ext = os.path.splitext(filepath) if ext != ".rst": >From 03ae3744662c985472aedc387407f7ff5a11194d Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sat, 13 Dec 2025 20:58:15 +0800 Subject: [PATCH 05/12] Split filter function and refactor error handling --- llvm/utils/git/code-lint-helper.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py index 3947bcac7f3b9..d89a1e259ed3a 100644 --- a/llvm/utils/git/code-lint-helper.py +++ b/llvm/utils/git/code-lint-helper.py @@ -304,12 +304,15 @@ def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]: _, ext = os.path.splitext(filepath) if ext != ".rst": continue - if not filepath.startswith("clang-tools-extra/docs/clang-tidy/"): + if not self._should_lint_file(filepath): continue if os.path.exists(filepath): filtered_files.append(filepath) return filtered_files + def _should_lint_file(self, filepath: str) -> bool: + return filepath.startswith("clang-tools-extra/docs/clang-tidy/") + def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str: if not files_to_lint: return "" @@ -331,13 +334,19 @@ def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str: if proc.returncode == 0: return "" - if output := proc.stdout.strip(): - return output + output = proc.stdout.strip() + error_output = proc.stderr.strip() - if error_output := proc.stderr.strip(): - return error_output + parts: List[str] = [] + if output: + parts.append(output) + if error_output: + parts.append(f"stderr:\n{error_output}") - return f"doc8 exited with return code {proc.returncode} but no output." + if parts: + return "\n\n".join(parts) + else: + return f"doc8 exited with return code {proc.returncode} but no output." ALL_LINTERS = (ClangTidyLintHelper(), Doc8LintHelper()) >From 5661fef3bc4a93986c3cd64b40547a864300afa6 Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sun, 14 Dec 2025 13:39:14 +0800 Subject: [PATCH 06/12] Fix EOF --- .../workflows/containers/github-action-ci-tooling/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/containers/github-action-ci-tooling/Dockerfile b/.github/workflows/containers/github-action-ci-tooling/Dockerfile index ba49c1cbfa245..6ac090e9a3385 100644 --- a/.github/workflows/containers/github-action-ci-tooling/Dockerfile +++ b/.github/workflows/containers/github-action-ci-tooling/Dockerfile @@ -116,4 +116,4 @@ RUN apt-get update && \ pkg-config \ universal-ctags && \ apt-get clean && \ - rm -rf /var/lib/apt/lists/* \ No newline at end of file + rm -rf /var/lib/apt/lists/* >From 89bf56774b92fde5ef78c3b7cb032487236b9d0f Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sun, 14 Dec 2025 13:44:43 +0800 Subject: [PATCH 07/12] test `doc8` linting --- .../docs/clang-tidy/checks/bugprone/unsafe-functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst index cb7ea415c54b2..4ecae979831a6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst @@ -23,7 +23,7 @@ The following functions are reported if :option:`ReportDefaultFunctions` is enabled. If *Annex K.* is available, a replacement from *Annex K.* is suggested for the -following functions: +following functions ``asctime``, ``asctime_r``, ``bsearch``, ``ctime``, ``fopen``, ``fprintf``, ``freopen``, ``fscanf``, ``fwprintf``, ``fwscanf``, ``getenv``, ``gets``, >From 472af3792b7b5e0c58f5eb98d0c1809a2f56f6c4 Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sun, 14 Dec 2025 13:56:14 +0800 Subject: [PATCH 08/12] Test doc update --- .../checks/bugprone/unsafe-functions.rst | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst index 4ecae979831a6..27909ca329df8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst @@ -23,7 +23,7 @@ The following functions are reported if :option:`ReportDefaultFunctions` is enabled. If *Annex K.* is available, a replacement from *Annex K.* is suggested for the -following functions +following functions: ``asctime``, ``asctime_r``, ``bsearch``, ``ctime``, ``fopen``, ``fprintf``, ``freopen``, ``fscanf``, ``fwprintf``, ``fwscanf``, ``getenv``, ``gets``, @@ -96,21 +96,22 @@ to be checked. The format is the following, without newlines: The functions are matched using POSIX extended regular expressions. *(Note: The regular expressions do not support negative* ``(?!)`` *matches.)* -The ``reason`` is optional and is used to provide additional information about the -reasoning behind the replacement. The default reason is ``is marked as unsafe``. +The ``reason`` is optional and is used to provide additional information about +the reasoning behind the replacement. The default reason is +``is marked as unsafe``. If ``replacement`` is empty, the default text ``it should not be used`` will be shown instead of the suggestion for a replacement. -If the ``reason`` starts with the character ``>``, the reason becomes fully custom. -The default suffix is disabled even if a ``replacement`` is present, and only the -reason message is shown after the matched function, to allow better control over -the suggestions. (The starting ``>`` and whitespace directly after it are -trimmed from the message.) +If the ``reason`` starts with the character ``>``, the reason becomes fully +custom. The default suffix is disabled even if a ``replacement`` is present, +and only the reason message is shown after the matched function, to allow +better control over the suggestions. (The starting ``>`` and whitespace +directly after it are trimmed from the message.) -As an example, the following configuration matches only the function ``original`` -in the default namespace. A similar diagnostic can also be printed using a fully -custom reason. +As an example, the following configuration matches only the function +``original`` in the default namespace. A similar diagnostic can also be +printed using a fully custom reason. .. code:: c @@ -123,10 +124,10 @@ custom reason. ::std::original(); // no-warning original_function(); // no-warning -If the regular expression contains the character ``:``, it is matched against the -qualified name (i.e. ``std::original``), otherwise the regex is matched against -the unqualified name (``original``). If the regular expression starts with ``::`` -(or ``^::``), it is matched against the fully qualified name +If the regular expression contains the character ``:``, it is matched against +the qualified name (i.e. ``std::original``), otherwise the regex is matched +against the unqualified name (``original``). If the regular expression starts +with ``::`` (or ``^::``), it is matched against the fully qualified name (``::std::original``). One of the use cases for fully custom messages is suggesting compiler options >From 702005aa818993050aae4e9fafde561d18152a13 Mon Sep 17 00:00:00 2001 From: mitchell <[email protected]> Date: Sun, 14 Dec 2025 14:05:08 +0800 Subject: [PATCH 09/12] Apply suggestions from code review Co-authored-by: EugeneZelenko <[email protected]> --- llvm/utils/git/code-lint-helper.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py index d89a1e259ed3a..8d97f99dc8f4a 100644 --- a/llvm/utils/git/code-lint-helper.py +++ b/llvm/utils/git/code-lint-helper.py @@ -298,7 +298,7 @@ class Doc8LintHelper(LintHelper): def instructions(self, files_to_lint: Iterable[str], args: LintArgs) -> str: return f"doc8 -q {' '.join(files_to_lint)}" - def filter_changed_files(self, changed_files: Sequence[str]) -> Sequence[str]: + def filter_changed_files(self, changed_files: Iterable[str]) -> Sequence[str]: filtered_files: List[str] = [] for filepath in changed_files: _, ext = os.path.splitext(filepath) @@ -345,8 +345,7 @@ def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str: if parts: return "\n\n".join(parts) - else: - return f"doc8 exited with return code {proc.returncode} but no output." + return f"doc8 exited with return code {proc.returncode} but no output." ALL_LINTERS = (ClangTidyLintHelper(), Doc8LintHelper()) >From 242834036ca2cb5321f3f29aafc10a1467fd847d Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sun, 14 Dec 2025 14:13:53 +0800 Subject: [PATCH 10/12] Fix style issues --- llvm/utils/git/code-lint-helper.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/llvm/utils/git/code-lint-helper.py b/llvm/utils/git/code-lint-helper.py index 8d97f99dc8f4a..b2ab101e6d1b9 100644 --- a/llvm/utils/git/code-lint-helper.py +++ b/llvm/utils/git/code-lint-helper.py @@ -299,19 +299,14 @@ def instructions(self, files_to_lint: Iterable[str], args: LintArgs) -> str: return f"doc8 -q {' '.join(files_to_lint)}" def filter_changed_files(self, changed_files: Iterable[str]) -> Sequence[str]: - filtered_files: List[str] = [] - for filepath in changed_files: - _, ext = os.path.splitext(filepath) - if ext != ".rst": - continue - if not self._should_lint_file(filepath): - continue - if os.path.exists(filepath): - filtered_files.append(filepath) - return filtered_files + return list(filter(self._should_lint_file, changed_files)) def _should_lint_file(self, filepath: str) -> bool: - return filepath.startswith("clang-tools-extra/docs/clang-tidy/") + return ( + os.path.splitext(filepath)[1] == ".rst" + and filepath.startswith("clang-tools-extra/docs/clang-tidy/") + and os.path.exists(filepath) + ) def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str: if not files_to_lint: @@ -334,13 +329,10 @@ def run_linter_tool(self, files_to_lint: Iterable[str], args: LintArgs) -> str: if proc.returncode == 0: return "" - output = proc.stdout.strip() - error_output = proc.stderr.strip() - parts: List[str] = [] - if output: + if output := proc.stdout.strip(): parts.append(output) - if error_output: + if error_output := proc.stderr.strip(): parts.append(f"stderr:\n{error_output}") if parts: >From af21767e1cb748412d595d6374aa1db82fc2924b Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sun, 14 Dec 2025 14:16:21 +0800 Subject: [PATCH 11/12] Test again --- .../docs/clang-tidy/checks/bugprone/unsafe-functions.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst index 27909ca329df8..864a9d1931332 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst @@ -3,8 +3,7 @@ bugprone-unsafe-functions ========================= -Checks for functions that have safer, more secure replacements available, or -are considered deprecated due to design flaws. +Checks for functions that have safer, more secure replacements available, or are considered deprecated due to design flaws. The check heavily relies on the functions from the **Annex K.** "Bounds-checking interfaces" of C11. >From d3bdea8d506c17a0fc3b37feed580f9209a18b48 Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sun, 14 Dec 2025 14:52:40 +0800 Subject: [PATCH 12/12] Revert "Test again" This reverts commit af21767e1cb748412d595d6374aa1db82fc2924b. --- .../docs/clang-tidy/checks/bugprone/unsafe-functions.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst index 864a9d1931332..27909ca329df8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst @@ -3,7 +3,8 @@ bugprone-unsafe-functions ========================= -Checks for functions that have safer, more secure replacements available, or are considered deprecated due to design flaws. +Checks for functions that have safer, more secure replacements available, or +are considered deprecated due to design flaws. The check heavily relies on the functions from the **Annex K.** "Bounds-checking interfaces" of C11. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
