From 35c25d66d9e32a3115340b5967b7a72beb8bbdc8 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 26 Jul 2022 15:26:08 -0700 Subject: [PATCH 01/76] integrate mypy type checking into CI --- .github/workflows/run-pylint.yml | 7 +++-- cpp_linter/__init__.py | 27 +++++++++++------ cpp_linter/clang_format_xml.py | 5 ++-- cpp_linter/clang_tidy.py | 22 ++++++++++---- cpp_linter/clang_tidy_yml.py | 9 +++--- cpp_linter/run.py | 51 +++++++++++++++++--------------- cpp_linter/thread_comments.py | 12 ++++---- mypy.ini | 3 ++ requirements-dev.txt | 3 ++ 9 files changed, 85 insertions(+), 54 deletions(-) create mode 100644 mypy.ini create mode 100644 requirements-dev.txt diff --git a/.github/workflows/run-pylint.yml b/.github/workflows/run-pylint.yml index 0d103b95..48e96855 100644 --- a/.github/workflows/run-pylint.yml +++ b/.github/workflows/run-pylint.yml @@ -5,11 +5,13 @@ on: paths: - "**.py" - .pylintrc + - mypy.ini pull_request: types: opened paths: - "**.py" - .pylintrc + - mypy.ini jobs: using-pylint: @@ -20,10 +22,9 @@ jobs: with: python-version: 3.7 - name: Install pylint and action deps - run: | - python3 -m pip install --upgrade pylint - python3 -m pip install -r requirements.txt + run: python3 -m pip install -r requirements.txt -r requierments-dev.txt - name: run pylint run: | pylint cpp_linter/** pylint setup.py + - run: mypy cpp_linter/ diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index db14aa92..503f92ef 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -3,8 +3,17 @@ import io import os import logging +from typing import TYPE_CHECKING, List, Dict, Union, Any from requests import Response +if TYPE_CHECKING: # Used to avoid circular imports + from cpp_linter.clang_format_xml import XMLFixit + from cpp_linter.clang_tidy_yml import YMLFixit + from cpp_linter.clang_tidy import TidyNotification + +# A type alias for custom line filter objects +LINE_FILTER = Dict[str, Union[str, List[List[int]]]] + FOUND_RICH_LIB = False try: from rich.logging import RichHandler @@ -19,7 +28,7 @@ except ImportError: logging.basicConfig() -#: The logging.Logger object used for outputing data. +#: The logging.Logger object used for outputting data. logger = logging.getLogger("CPP Linter") if not FOUND_RICH_LIB: logger.debug("rich module not found") @@ -35,13 +44,13 @@ class Globals: """Global variables for re-use (non-constant).""" - PAYLOAD_TIDY = "" + PAYLOAD_TIDY: str = "" """The accumulated output of clang-tidy (gets appended to OUTPUT)""" - OUTPUT = "" + OUTPUT: str = "" """The accumulated body of the resulting comment that gets posted.""" - FILES = [] + FILES: List[Dict[str, Union[str, int, LINE_FILTER]]] = [] """The responding payload containing info about changed files.""" - EVENT_PAYLOAD = {} + EVENT_PAYLOAD: Dict[str, Any] = {} """The parsed JSON of the event payload.""" response_buffer = Response() """A shared response object for `requests` module.""" @@ -52,13 +61,13 @@ class GlobalParser: following attributes represents a clang-tool's output for 1 source file. """ - tidy_notes = [] + tidy_notes = [] # type: List[TidyNotification] """This can only be a `list` of type [`TidyNotification`][cpp_linter.clang_tidy.TidyNotification]""" - tidy_advice = [] + tidy_advice = [] # type: List[YMLFixit] """This can only be a `list` of type [`YMLFixit`][cpp_linter.clang_tidy_yml.YMLFixit]""" - format_advice = [] + format_advice = [] # type: List[XMLFixit] """This can only be a `list` of type [`XMLFixit`][cpp_linter.clang_format_xml.XMLFixit]""" @@ -97,7 +106,7 @@ def log_response_msg() -> bool: """Output the response buffer's message on a failed request. Returns: - A bool decribing if response's status code was less than 400. + A bool describing if response's status code was less than 400. """ if Globals.response_buffer.status_code >= 400: logger.error( diff --git a/cpp_linter/clang_format_xml.py b/cpp_linter/clang_format_xml.py index 9df31f8d..6626df5a 100644 --- a/cpp_linter/clang_format_xml.py +++ b/cpp_linter/clang_format_xml.py @@ -1,5 +1,6 @@ """Parse output from clang-format's XML suggestions.""" import os +from typing import List import xml.etree.ElementTree as ET from . import GlobalParser, get_line_cnt_from_cols @@ -47,7 +48,7 @@ def __init__(self, line_numb: int): line_numb: The line number of about the replacements """ self.line = line_numb - self.replacements = [] + self.replacements: List[FormatReplacement] = [] def __repr__(self): return ( @@ -74,7 +75,7 @@ def __init__(self, filename: str): file exported by clang-tidy. """ self.filename = filename.replace(os.sep, "/") - self.replaced_lines = [] + self.replaced_lines: List[FormatReplacementLine] = [] def __repr__(self) -> str: return ( diff --git a/cpp_linter/clang_tidy.py b/cpp_linter/clang_tidy.py index 673ba3c0..50582c1d 100644 --- a/cpp_linter/clang_tidy.py +++ b/cpp_linter/clang_tidy.py @@ -1,10 +1,12 @@ """Parse output from clang-tidy's stdout""" import os import re +from typing import Tuple, Union, List, cast from . import GlobalParser, IS_ON_RUNNER # , logger NOTE_HEADER = re.compile("^(.*):(\d+):(\d+):\s(\w+):(.*)\[(.*)\]$") + class TidyNotification: """Create a object that decodes info from the clang-tidy output's initial line that details a specific notification. @@ -20,7 +22,10 @@ class TidyNotification: notification. """ - def __init__(self, notification_line: tuple): + def __init__( + self, + notification_line: Tuple[str, Union[int, str], Union[int, str], str, str, str], + ): """ Args: notification_line: The first line in the notification parsed into a tuple of @@ -37,12 +42,12 @@ def __init__(self, notification_line: tuple): self.diagnostic, ) = notification_line - self.note_info: str = self.note_info.strip() - self.note_type: str = self.note_type.strip() + self.note_info = self.note_info.strip() + self.note_type = self.note_type.strip() self.line = int(self.line) self.cols = int(self.cols) - self.filename: str = self.filename.replace(os.getcwd() + os.sep, "") - self.fixit_lines = [] + self.filename = self.filename.replace(os.getcwd() + os.sep, "") + self.fixit_lines: List[str] = [] def __repr__(self) -> str: return ( @@ -93,7 +98,12 @@ def parse_tidy_output() -> None: for line in tidy_out.readlines(): match = re.match(NOTE_HEADER, line) if match is not None: - notification = TidyNotification(match.groups()) + notification = TidyNotification( + cast( + Tuple[str, Union[int, str], Union[int, str], str, str, str], + match.groups(), + ) + ) GlobalParser.tidy_notes.append(notification) elif notification is not None: notification.fixit_lines.append(line) diff --git a/cpp_linter/clang_tidy_yml.py b/cpp_linter/clang_tidy_yml.py index 5628b602..cb9dcebb 100644 --- a/cpp_linter/clang_tidy_yml.py +++ b/cpp_linter/clang_tidy_yml.py @@ -1,5 +1,6 @@ """Parse output from clang-tidy's YML format""" import os +from typing import List import yaml from . import GlobalParser, get_line_cnt_from_cols @@ -34,7 +35,7 @@ def __init__(self, diagnostic_name: str): self.line = 0 self.cols = 0 self.null_len = 0 - self.replacements = [] + self.replacements: List["TidyReplacement"] = [] def __repr__(self): """a str representation of all attributes.""" @@ -51,7 +52,7 @@ class TidyReplacement: line (int): The replacement content's starting line cols (int): The replacement content's starting columns null_len (int): The number of bytes discarded from `cols` - text (list): The replacement content's text (each `str` item is a line) + text (bytes): The replacement content's text. """ def __init__(self, line_cnt: int, cols: int, length: int): @@ -64,7 +65,7 @@ def __init__(self, line_cnt: int, cols: int, length: int): self.line = line_cnt self.cols = cols self.null_len = length - self.text = [] + self.text: bytes = b"" def __repr__(self) -> str: return ( @@ -88,7 +89,7 @@ def __init__(self, filename: str) -> None: filename: The source file's name (with path) concerning the suggestion. """ self.filename = filename.replace(os.getcwd() + os.sep, "").replace(os.sep, "/") - self.diagnostics = [] + self.diagnostics: List[TidyDiagnostic] = [] def __repr__(self) -> str: return ( diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 9f91d1b6..b3a259f4 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -16,6 +16,7 @@ import argparse import configparser import json +from typing import cast, List import requests from . import ( Globals, @@ -26,6 +27,7 @@ GITHUB_SHA, API_HEADERS, log_response_msg, + LINE_FILTER, ) from .clang_tidy_yml import parse_tidy_suggestions_yml @@ -117,7 +119,7 @@ "--lines-changed-only", default="false", type=lambda input: input.lower() == "true", - help="Set this option to 'true' to only analyse changes in the event's diff. " + help="Set this option to 'true' to only analyze changes in the event's diff. " "Defaults to %(default)s.", ) cli_arg_parser.add_argument( @@ -125,7 +127,7 @@ "--files-changed-only", default="false", type=lambda input: input.lower() == "true", - help="Set this option to 'false' to analyse any source files in the repo. " + help="Set this option to 'false' to analyze any source files in the repo. " "Defaults to %(default)s.", ) cli_arg_parser.add_argument( @@ -171,16 +173,16 @@ def set_exit_code(override: int = None) -> int: def start_log_group(name: str) -> None: - """Begin a callapsable group of log statements. + """Begin a collapsable group of log statements. Args: - name: The name of the callapsable group + name: The name of the collapsable group """ log_commander.fatal("::group::%s", name) def end_log_group() -> None: - """End a callapsable group of log statements.""" + """End a collapsable group of log statements.""" log_commander.fatal("::endgroup::") @@ -247,7 +249,7 @@ def filter_out_non_source_files( """ files = [] for file in ( - Globals.FILES if GITHUB_EVENT_NAME == "pull_request" else Globals.FILES["files"] + Globals.FILES if GITHUB_EVENT_NAME == "pull_request" else Globals.FILES["files"] # type: ignore ): if ( os.path.splitext(file["filename"])[1][1:] in ext_list @@ -259,10 +261,10 @@ def filter_out_non_source_files( ): if lines_changed_only and "patch" in file.keys(): # get diff details for the file's changes - line_filter = { - "name": file["filename"].replace("/", os.sep), - "lines": [], - } + line_filter: LINE_FILTER = dict( + name=file["filename"].replace("/", os.sep), + lines=[], + ) file["diff_line_map"], line_numb_in_diff = ({}, 0) # diff_line_map is a dict for which each # - key is the line number in the file @@ -273,13 +275,15 @@ def filter_out_non_source_files( changed_hunk = changed_hunk.split(",") start_line = int(changed_hunk[0]) hunk_length = int(changed_hunk[1]) - line_filter["lines"].append( + cast(List[List[int]], line_filter["lines"]).append( [start_line, hunk_length + start_line] ) line_numb_in_diff = start_line elif not line.startswith("-"): file["diff_line_map"][line_numb_in_diff] = i - line_filter["lines"][-1][1] = line_numb_in_diff + cast(List[List[int]], line_filter["lines"])[-1][ + 1 + ] = line_numb_in_diff line_numb_in_diff += 1 file["line_filter"] = line_filter elif lines_changed_only: @@ -294,7 +298,7 @@ def filter_out_non_source_files( if GITHUB_EVENT_NAME == "pull_request": Globals.FILES = files else: - Globals.FILES["files"] = files + Globals.FILES["files"] = files # type: ignore if not os.getenv("CI"): # if not executed on a github runner with open(".changed_files.json", "w", encoding="utf-8") as temp: # dump altered json of changed files @@ -314,7 +318,7 @@ def verify_files_are_present() -> None: directory. This is bad for files with the same name from different folders. """ for file in ( - Globals.FILES if GITHUB_EVENT_NAME == "pull_request" else Globals.FILES["files"] + Globals.FILES if GITHUB_EVENT_NAME == "pull_request" else Globals.FILES["files"] # type: ignore ): file_name = file["filename"].replace("/", os.sep) if not os.path.exists(file_name): @@ -373,7 +377,7 @@ def list_source_files(ext_list: list, ignored_paths: list, not_ignored: list) -> if Globals.FILES: logger.info( "Giving attention to the following files:\n\t%s", - "\n\t".join([f["filename"] for f in Globals.FILES]), + "\n\t".join([f["filename"] for f in Globals.FILES]), # type: ignore ) else: logger.info("No source files found.") # this might need to be warning @@ -510,11 +514,11 @@ def capture_clang_tools_output( for file in ( Globals.FILES if GITHUB_EVENT_NAME == "pull_request" or isinstance(Globals.FILES, list) - else Globals.FILES["files"] + else Globals.FILES["files"] # type: ignore ): - filename = file["filename"] - if not os.path.exists(file["filename"]): - filename = os.path.split(file["raw_url"])[1] + filename = cast(str, file["filename"]) + if not os.path.exists(filename): + filename = os.path.split(cast(str, file["raw_url"]))[1] start_log_group(f"Performing checkup on {filename}") run_clang_tidy( filename, file, version, checks, lines_changed_only, database, repo_root @@ -718,11 +722,11 @@ def make_annotations(style: str, file_annotations: bool) -> bool: # log_commander obj's verbosity is hard-coded to show debug statements ret_val = False count = 0 - for note in GlobalParser.format_advice: - if note.replaced_lines: + for advice in GlobalParser.format_advice: + if advice.replaced_lines: ret_val = True if file_annotations: - log_commander.info(note.log_command(style)) + log_commander.info(advice.log_command(style)) count += 1 for note in GlobalParser.tidy_notes: ret_val = True @@ -746,8 +750,7 @@ def parse_ignore_option(paths: str) -> tuple: - index 1 is the `not_ignored` list """ ignored, not_ignored = ([], []) - paths = paths.split("|") - for path in paths: + for path in paths.split("|"): is_included = path.startswith("!") if path.startswith("!./" if is_included else "./"): path = path.replace("./", "", 1) # relative dir is assumed diff --git a/cpp_linter/thread_comments.py b/cpp_linter/thread_comments.py index 4313d60a..b6e8aceb 100644 --- a/cpp_linter/thread_comments.py +++ b/cpp_linter/thread_comments.py @@ -1,6 +1,6 @@ """A module to house the various functions for traversing/adjusting comments""" import os -from typing import Union +from typing import Union, cast, List, Optional import json import requests from . import Globals, GlobalParser, logger, API_HEADERS, GITHUB_SHA, log_response_msg @@ -59,7 +59,7 @@ def aggregate_tidy_advice() -> list: body += diag.name + "**\n>" + diag.message # get original code - filename = Globals.FILES[index]["filename"].replace("/", os.sep) + filename = cast(str, Globals.FILES[index]["filename"]).replace("/", os.sep) if not os.path.exists(filename): # the file had to be downloaded (no git checkout). # thus use only the filename (without the path to the file) @@ -71,7 +71,7 @@ def aggregate_tidy_advice() -> list: # aggregate clang-tidy advice suggestion = "\n```suggestion\n" is_multiline_fix = False - fix_lines = [] # a list of line numbers for the suggested fixes + fix_lines: List[int] = [] # a list of line numbers for the suggested fixes line = "" # the line that concerns the fix/comment for i, tidy_fix in enumerate(diag.replacements): line = lines[tidy_fix.line - 1] @@ -113,7 +113,7 @@ def aggregate_format_advice() -> list: for index, fmt_advice in enumerate(GlobalParser.format_advice): # get original code - filename = Globals.FILES[index]["filename"].replace("/", os.sep) + filename = cast(str, Globals.FILES[index]["filename"]).replace("/", os.sep) if not os.path.exists(filename): # the file had to be downloaded (no git checkout). # thus use only the filename (without the path to the file) @@ -127,7 +127,7 @@ def aggregate_format_advice() -> list: for fixed_line in fmt_advice.replaced_lines: # clang-format can include advice that starts/ends outside the diff's domain in_range = False - ranges = Globals.FILES[index]["line_filter"]["lines"] + ranges: List[List[int]] = Globals.FILES[index]["line_filter"]["lines"] # type: ignore for scope in ranges: if fixed_line.line in range(scope[0], scope[1] + 1): in_range = True @@ -201,7 +201,7 @@ def list_diff_comments() -> list: return results -def get_review_id(reviews_url: str, user_id: int) -> int: +def get_review_id(reviews_url: str, user_id: int) -> Optional[int]: """Dismiss all stale reviews (only the ones made by our bot). Args: diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 00000000..abf2e2e4 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +show_error_codes = true +pretty = true diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 00000000..ae4f354c --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,3 @@ +types-requests +mypy +pylint From 1374f8b965785877c0df31836c831cb441fbb68f Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 26 Jul 2022 15:27:19 -0700 Subject: [PATCH 02/76] resolve #75 --- cpp_linter/run.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index b3a259f4..fe7d8429 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -109,6 +109,7 @@ "-i", "--ignore", nargs="?", + default=".github", help="Set this option with paths to ignore. In the case of multiple " "paths, you can set this option (multiple times) for each path. This can " "also have files, but the file's relative path has to be specified as well " @@ -783,7 +784,7 @@ def main(): logger.setLevel(int(args.verbosity)) # prepare ignored paths list - ignored, not_ignored = parse_ignore_option("" if not args.ignore else args.ignore) + ignored, not_ignored = parse_ignore_option(args.ignore) # prepare extensions list args.extensions = args.extensions.split(",") From cf96533c7eeea276a9d24e2cc54878ebfcf6c30f Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 26 Jul 2022 15:27:59 -0700 Subject: [PATCH 03/76] resolve #73 --- cpp_linter/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index fe7d8429..4908c044 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -425,7 +425,7 @@ def run_clang_tidy( cmds.append(f"-checks={checks}") if database: cmds.append("-p") - if RUNNER_WORKSPACE: + if RUNNER_WORKSPACE and not os.path.isabs(database): path_to_db = RUNNER_WORKSPACE if repo_root and repo_root != ".": path_to_db += os.sep + repo_root From 4656598920c91951c314c84d05c276149dc237f1 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 26 Jul 2022 17:43:47 -0700 Subject: [PATCH 04/76] run pylint workflow on changes to workflow file - fix a few long line warnings - add rich to the py dev reqs - add types-PyYAML to dev reqs --- .github/workflows/run-pylint.yml | 6 ++++-- cpp_linter/run.py | 8 ++++++-- cpp_linter/thread_comments.py | 4 +++- requirements-dev.txt | 2 ++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/run-pylint.yml b/.github/workflows/run-pylint.yml index 48e96855..14d08e85 100644 --- a/.github/workflows/run-pylint.yml +++ b/.github/workflows/run-pylint.yml @@ -6,15 +6,17 @@ on: - "**.py" - .pylintrc - mypy.ini + - ".github/workflows/run-pylint.yml" pull_request: types: opened paths: - "**.py" - .pylintrc - mypy.ini + - ".github/workflows/run-pylint.yml" jobs: - using-pylint: + check-python-sources: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -22,7 +24,7 @@ jobs: with: python-version: 3.7 - name: Install pylint and action deps - run: python3 -m pip install -r requirements.txt -r requierments-dev.txt + run: python3 -m pip install -r requirements.txt -r requirements-dev.txt - name: run pylint run: | pylint cpp_linter/** diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 4908c044..31f7ef13 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -250,7 +250,9 @@ def filter_out_non_source_files( """ files = [] for file in ( - Globals.FILES if GITHUB_EVENT_NAME == "pull_request" else Globals.FILES["files"] # type: ignore + Globals.FILES + if GITHUB_EVENT_NAME == "pull_request" + else Globals.FILES["files"] # type: ignore ): if ( os.path.splitext(file["filename"])[1][1:] in ext_list @@ -319,7 +321,9 @@ def verify_files_are_present() -> None: directory. This is bad for files with the same name from different folders. """ for file in ( - Globals.FILES if GITHUB_EVENT_NAME == "pull_request" else Globals.FILES["files"] # type: ignore + Globals.FILES + if GITHUB_EVENT_NAME == "pull_request" + else Globals.FILES["files"] # type: ignore ): file_name = file["filename"].replace("/", os.sep) if not os.path.exists(file_name): diff --git a/cpp_linter/thread_comments.py b/cpp_linter/thread_comments.py index b6e8aceb..94ce072a 100644 --- a/cpp_linter/thread_comments.py +++ b/cpp_linter/thread_comments.py @@ -127,7 +127,9 @@ def aggregate_format_advice() -> list: for fixed_line in fmt_advice.replaced_lines: # clang-format can include advice that starts/ends outside the diff's domain in_range = False - ranges: List[List[int]] = Globals.FILES[index]["line_filter"]["lines"] # type: ignore + ranges: List[List[int]] = ( + Globals.FILES[index]["line_filter"]["lines"] # type: ignore + ) for scope in ranges: if fixed_line.line in range(scope[0], scope[1] + 1): in_range = True diff --git a/requirements-dev.txt b/requirements-dev.txt index ae4f354c..92edfd6a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,5 @@ types-requests +types-PyYAML mypy pylint +rich \ No newline at end of file From fb5b09b95aeff3705d31d2bd6542837d3cb70acc Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 26 Jul 2022 18:30:20 -0700 Subject: [PATCH 05/76] resolve #76 normalize submodule path separators per runner's OS --- cpp_linter/run.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 31f7ef13..b0c6f16a 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -348,14 +348,6 @@ def list_source_files(ext_list: list, ignored_paths: list, not_ignored: list) -> [`main()`][cpp_linter.run.main]) when no files to be checked. """ start_log_group("Get list of specified source files") - if os.path.exists(".gitmodules"): - submodules = configparser.ConfigParser() - submodules.read(".gitmodules") - for module in submodules.sections(): - logger.info( - "Appending submodule to ignored paths: %s", submodules[module]["path"] - ) - ignored_paths.append(submodules[module]["path"]) root_path = os.getcwd() for dirpath, _, filenames in os.walk(root_path): @@ -755,16 +747,29 @@ def parse_ignore_option(paths: str) -> tuple: - index 1 is the `not_ignored` list """ ignored, not_ignored = ([], []) + for path in paths.split("|"): is_included = path.startswith("!") if path.startswith("!./" if is_included else "./"): path = path.replace("./", "", 1) # relative dir is assumed path = path.strip() # strip leading/trailing spaces if is_included: - not_ignored.append(path[1:]) + not_ignored.append(path[1:]) # strip leading `!` else: ignored.append(path) + # auto detect submodules + if os.path.exists(".gitmodules"): + submodules = configparser.ConfigParser() + submodules.read(".gitmodules") + for module in submodules.sections(): + logger.info( + "Appending submodule to ignored paths: %s", submodules[module]["path"] + ) + path = submodules[module]["path"].replace("/", os.sep) + if path not in not_ignored: + ignored.append(path) + if ignored: logger.info( "Ignoring the following paths/files:\n\t./%s", From 09034c32aab10b13667fdc81053b42c97d0a25e6 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 26 Jul 2022 18:49:22 -0700 Subject: [PATCH 06/76] add unit tests for ignored paths also make sure the current working directory is appended to the .gitmodules path --- cpp_linter/run.py | 9 ++++----- tests/ignored_paths/.gitmodules | 12 ++++++++++++ tests/ignored_paths/test_ignored_paths.py | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 tests/ignored_paths/.gitmodules create mode 100644 tests/ignored_paths/test_ignored_paths.py diff --git a/cpp_linter/run.py b/cpp_linter/run.py index b0c6f16a..344dd25f 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -759,15 +759,14 @@ def parse_ignore_option(paths: str) -> tuple: ignored.append(path) # auto detect submodules - if os.path.exists(".gitmodules"): + root_path = os.getcwd() + if os.path.exists(root_path + os.sep + ".gitmodules"): submodules = configparser.ConfigParser() - submodules.read(".gitmodules") + submodules.read(root_path + os.sep + ".gitmodules") for module in submodules.sections(): - logger.info( - "Appending submodule to ignored paths: %s", submodules[module]["path"] - ) path = submodules[module]["path"].replace("/", os.sep) if path not in not_ignored: + logger.info("Appending submodule to ignored paths: %s", path) ignored.append(path) if ignored: diff --git a/tests/ignored_paths/.gitmodules b/tests/ignored_paths/.gitmodules new file mode 100644 index 00000000..3696a312 --- /dev/null +++ b/tests/ignored_paths/.gitmodules @@ -0,0 +1,12 @@ +[submodule "RF24"] + path = RF24 + url = https://github.com/nRF24/RF24.git +[submodule "RF24Network"] + path = RF24Network + url = https://github.com/nRF24/RF24Network.git +[submodule "RF24Mesh"] + path = RF24Mesh + url = https://github.com/nRF24/RF24Mesh.git +[submodule "pybind11"] + path = pybind11 + url = https://github.com/pybind/pybind11.git diff --git a/tests/ignored_paths/test_ignored_paths.py b/tests/ignored_paths/test_ignored_paths.py new file mode 100644 index 00000000..6d4d1996 --- /dev/null +++ b/tests/ignored_paths/test_ignored_paths.py @@ -0,0 +1,17 @@ +import os +from cpp_linter.run import parse_ignore_option + +def test_ignored(): + ignored, not_ignored = parse_ignore_option("src") + assert "src" in ignored and not not_ignored + +def test_not_ignored(): + ignored, not_ignored = parse_ignore_option("!src|") + assert "src" in not_ignored and "" in ignored + +def test_ignore_submodule(): + os.chdir(os.path.split(__file__)[0]) + ignored, not_ignored = parse_ignore_option("!pybind11") + for ignored_submodule in ["RF24", "RF24Network", "RF24Mesh"]: + assert ignored_submodule in ignored + assert "pybind11" in not_ignored From cd60a491e0871d05df324b5a3ea1f69b64adaa0f Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 26 Jul 2022 19:05:33 -0700 Subject: [PATCH 07/76] run pytest in CI - add pytest to dev reqs - rename run-pylint.yml to run-dev-tests.yml - install cpp-linter pkg in run-dev-tests.yml workflow - upgrade actions/setup-python to v2 in run-dev-tests.yml workflow - rename step in run-dev-tests.yml workflow --- .github/workflows/{run-pylint.yml => run-dev-tests.yml} | 7 ++++--- requirements-dev.txt | 3 ++- tests/ignored_paths/test_ignored_paths.py | 7 +++++++ 3 files changed, 13 insertions(+), 4 deletions(-) rename .github/workflows/{run-pylint.yml => run-dev-tests.yml} (84%) diff --git a/.github/workflows/run-pylint.yml b/.github/workflows/run-dev-tests.yml similarity index 84% rename from .github/workflows/run-pylint.yml rename to .github/workflows/run-dev-tests.yml index 14d08e85..c04686af 100644 --- a/.github/workflows/run-pylint.yml +++ b/.github/workflows/run-dev-tests.yml @@ -20,13 +20,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-python@v1 + - uses: actions/setup-python@v2 with: python-version: 3.7 - - name: Install pylint and action deps - run: python3 -m pip install -r requirements.txt -r requirements-dev.txt + - name: Install workflow deps + run: python3 -m pip install -r requirements.txt -r requirements-dev.txt . - name: run pylint run: | pylint cpp_linter/** pylint setup.py - run: mypy cpp_linter/ + - run: pytest tests diff --git a/requirements-dev.txt b/requirements-dev.txt index 92edfd6a..d31c096b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,4 +2,5 @@ types-requests types-PyYAML mypy pylint -rich \ No newline at end of file +rich +pytest diff --git a/tests/ignored_paths/test_ignored_paths.py b/tests/ignored_paths/test_ignored_paths.py index 6d4d1996..65dfb6ff 100644 --- a/tests/ignored_paths/test_ignored_paths.py +++ b/tests/ignored_paths/test_ignored_paths.py @@ -1,15 +1,22 @@ +"""Tests that focus on the ``ignore`` option's parsing.""" import os from cpp_linter.run import parse_ignore_option + def test_ignored(): + """test ignoring of a specified path.""" ignored, not_ignored = parse_ignore_option("src") assert "src" in ignored and not not_ignored + def test_not_ignored(): + """test explicit inclusion of a path and ignore the root path.""" ignored, not_ignored = parse_ignore_option("!src|") assert "src" in not_ignored and "" in ignored + def test_ignore_submodule(): + """test auto detection of submodules and ignore the paths appropriately.""" os.chdir(os.path.split(__file__)[0]) ignored, not_ignored = parse_ignore_option("!pybind11") for ignored_submodule in ["RF24", "RF24Network", "RF24Mesh"]: From 1b9b31b1b8d8bffacb1558683de41dd620dc2cc6 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 27 Jul 2022 23:52:49 -0700 Subject: [PATCH 08/76] resolve #74 and add unit tests for it This allows the `lines-changed-only` option to accept the following values: - false: All lines in a file are analyzed - true: All lines in the diff are analyzed (including unchanged lines) - strict: Only lines in the diff that contain additions are analyzed gitignore some test resources as they are fetched running the tests. Retain original repo structure when fetching files. This is only used when the user doesn't checkout the repo being analyzed. --- .github/workflows/run-dev-tests.yml | 2 +- .gitignore | 2 + README.md | 7 +- cpp_linter/__init__.py | 2 +- cpp_linter/clang_format_xml.py | 11 +- cpp_linter/run.py | 117 +++-- cpp_linter/thread_comments.py | 7 +- tests/lines_changed_only/.clang-format | 148 +++++++ tests/lines_changed_only/expected_result.json | 409 ++++++++++++++++++ tests/lines_changed_only/files.json | 319 ++++++++++++++ .../test_lines_changed_only.py | 138 ++++++ 11 files changed, 1109 insertions(+), 53 deletions(-) create mode 100644 tests/lines_changed_only/.clang-format create mode 100644 tests/lines_changed_only/expected_result.json create mode 100644 tests/lines_changed_only/files.json create mode 100644 tests/lines_changed_only/test_lines_changed_only.py diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index c04686af..4ae52588 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -30,4 +30,4 @@ jobs: pylint cpp_linter/** pylint setup.py - run: mypy cpp_linter/ - - run: pytest tests + - run: pytest -vv tests diff --git a/.gitignore b/.gitignore index 7806c15a..52b39040 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,8 @@ coverage.xml *.py,cover .hypothesis/ .pytest_cache/ +tests/*/test*.json +tests/lines_changed_only/**/*.c # Translations *.mo diff --git a/README.md b/README.md index 0fd6b589..5992a325 100644 --- a/README.md +++ b/README.md @@ -87,8 +87,11 @@ jobs: #### `lines-changed-only` -- **Description**: Set this option to true to only analyze changes in the event's diff. -- Default: false +- **Description**: This controls what part of the files are analyzed. The following values are accepted: + - false: All lines in a file are analyzed. + - true: All lines in the diff are analyzed (including unchanged lines but not subtractions). + - strict: Only lines in the diff that contain additions are analyzed. +- Default: false. #### `files-changed-only` diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index 503f92ef..9c117b61 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -12,7 +12,7 @@ from cpp_linter.clang_tidy import TidyNotification # A type alias for custom line filter objects -LINE_FILTER = Dict[str, Union[str, List[List[int]]]] +LINE_FILTER = Dict[str, List[List[int]]] FOUND_RICH_LIB = False try: diff --git a/cpp_linter/clang_format_xml.py b/cpp_linter/clang_format_xml.py index 6626df5a..1c9ef123 100644 --- a/cpp_linter/clang_format_xml.py +++ b/cpp_linter/clang_format_xml.py @@ -83,7 +83,7 @@ def __repr__(self) -> str: f"replacements for {self.filename}>" ) - def log_command(self, style: str) -> str: + def log_command(self, style: str, line_filter: List[List[int]]) -> str: """Output a notification as a github log command. !!! info See Also @@ -105,13 +105,18 @@ def log_command(self, style: str) -> str: style = style.upper() else: style = style.title() - + line_list = [] + for fix in self.replaced_lines: + for line_range in line_filter: + if fix.line in range(*line_range): + line_list.append(str(fix.line)) + break return ( "::notice file={name},title=Run clang-format on {name}::" "File {name} (lines {lines}): Code does not conform to {style_guide} " "style guidelines.".format( name=self.filename, - lines=", ".join(str(f.line) for f in self.replaced_lines), + lines=", ".join(line_list), style_guide=style, ) ) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 344dd25f..5e58fd0b 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -27,9 +27,7 @@ GITHUB_SHA, API_HEADERS, log_response_msg, - LINE_FILTER, ) - from .clang_tidy_yml import parse_tidy_suggestions_yml from .clang_format_xml import parse_format_replacements_xml from .clang_tidy import parse_tidy_output @@ -118,9 +116,10 @@ cli_arg_parser.add_argument( "-l", "--lines-changed-only", - default="false", - type=lambda input: input.lower() == "true", + default=0, + type=lambda a: 1 if a.lower() == "true" else (2 if a.lower() == "strict" else 0), help="Set this option to 'true' to only analyze changes in the event's diff. " + "Set this to 'strict' to only analyze additions in the event's diff. " "Defaults to %(default)s.", ) cli_arg_parser.add_argument( @@ -231,8 +230,26 @@ def get_list_of_changed_files() -> None: Globals.FILES = requests.get(files_link, headers=API_HEADERS).json() +def consolidate_list_to_ranges(just_numbers: List[int]) -> List[List[int]]: + """A helper function to [`filter_out_non_source_files()`] that is only used when + extracting the lines from a diff that contain additions.""" + result: List[List[int]] = [] + for i, n in enumerate(just_numbers): + if not i: + result.append([n]) + elif n - 1 != just_numbers[i - 1]: + result[-1].append(just_numbers[i - 1] + 1) + result.append([n]) + if i == len(just_numbers) - 1: + result[-1].append(n + 1) + return result + + def filter_out_non_source_files( - ext_list: list, ignored: list, not_ignored: list, lines_changed_only: bool + ext_list: list, + ignored: list, + not_ignored: list, + lines_changed_only: int, ) -> bool: """Exclude undesired files (specified by user input 'extensions'). This filter applies to the event's [`FILES`][cpp_linter.Globals.FILES] attribute. @@ -264,33 +281,25 @@ def filter_out_non_source_files( ): if lines_changed_only and "patch" in file.keys(): # get diff details for the file's changes - line_filter: LINE_FILTER = dict( - name=file["filename"].replace("/", os.sep), - lines=[], - ) - file["diff_line_map"], line_numb_in_diff = ({}, 0) - # diff_line_map is a dict for which each - # - key is the line number in the file - # - value is the line's "position" in the diff - for i, line in enumerate(file["patch"].splitlines()): + # ranges is a list of start/end line numbers shown in the diff + ranges: List[List[int]] = [] + # additions is a list line numbers in the diff containing additions + additions: List[int] = [] + line_numb_in_diff: int = 0 + for line in file["patch"].splitlines(): + if line.startswith("+"): + additions.append(line_numb_in_diff) if line.startswith("@@ -"): - changed_hunk = line[line.find(" +") + 2 : line.find(" @@")] - changed_hunk = changed_hunk.split(",") - start_line = int(changed_hunk[0]) - hunk_length = int(changed_hunk[1]) - cast(List[List[int]], line_filter["lines"]).append( - [start_line, hunk_length + start_line] - ) + hunk = line[line.find(" +") + 2 : line.find(" @@")].split(",") + start_line, hunk_length = [int(x) for x in hunk] + ranges.append([start_line, hunk_length + start_line]) line_numb_in_diff = start_line elif not line.startswith("-"): - file["diff_line_map"][line_numb_in_diff] = i - cast(List[List[int]], line_filter["lines"])[-1][ - 1 - ] = line_numb_in_diff line_numb_in_diff += 1 - file["line_filter"] = line_filter - elif lines_changed_only: - continue + file["line_filter"] = dict( + diff_chunks=ranges, + lines_added=consolidate_list_to_ranges(additions), + ) files.append(file) if files: @@ -330,7 +339,9 @@ def verify_files_are_present() -> None: logger.warning("Could not find %s! Did you checkout the repo?", file_name) logger.info("Downloading file from url: %s", file["raw_url"]) Globals.response_buffer = requests.get(file["raw_url"]) - with open(os.path.split(file_name)[1], "w", encoding="utf-8") as temp: + # retain the repo's original structure + os.makedirs(os.path.split(file_name)[0], exist_ok=True) + with open(file_name, "w", encoding="utf-8") as temp: temp.write(Globals.response_buffer.text) @@ -387,7 +398,7 @@ def run_clang_tidy( file_obj: dict, version: str, checks: str, - lines_changed_only: bool, + lines_changed_only: int, database: str, repo_root: str, ) -> None: @@ -406,6 +417,7 @@ def run_clang_tidy( # clear the clang-tidy output file and exit function with open("clang_tidy_report.txt", "wb") as f_out: return + filename = filename.replace("/", os.sep) cmds = [ "clang-tidy" + ("" if not version else f"-{version}"), "--export-fixes=clang_tidy_output.yml", @@ -429,9 +441,11 @@ def run_clang_tidy( else: cmds.append(database) if lines_changed_only: - logger.info("line_filter = %s", json.dumps(file_obj["line_filter"]["lines"])) - cmds.append(f"--line-filter={json.dumps([file_obj['line_filter']])}") - cmds.append(filename.replace("/", os.sep)) + ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" + line_ranges = dict(name=filename, lines=file_obj["line_filter"][ranges]) + logger.info("line_filter = %s", json.dumps([line_ranges])) + cmds.append(f"--line-filter={json.dumps([line_ranges])}") + cmds.append(filename) with open("clang_tidy_output.yml", "wb"): pass # clear yml file's content before running clang-tidy logger.info('Running "%s"', " ".join(cmds)) @@ -441,14 +455,14 @@ def run_clang_tidy( logger.debug("Output from clang-tidy:\n%s", results.stdout.decode()) if os.path.getsize("clang_tidy_output.yml"): parse_tidy_suggestions_yml() # get clang-tidy fixes from yml - if results.returncode: - logger.warning( - "%s raised the following error(s):\n%s", cmds[0], results.stderr.decode() + if results.stderr: + logger.info( + "clang-tidy made the following summary:\n%s", results.stderr.decode() ) def run_clang_format( - filename: str, file_obj: dict, version: str, style: str, lines_changed_only: bool + filename: str, file_obj: dict, version: str, style: str, lines_changed_only: int ) -> None: """Run clang-format on a certain file @@ -474,7 +488,8 @@ def run_clang_format( logger.warning("ignoring invalid version number %s.", version) cmds[0] = "clang-format" if lines_changed_only: - for line_range in file_obj["line_filter"]["lines"]: + ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" + for line_range in file_obj["line_filter"][ranges]: cmds.append(f"--lines={line_range[0]}:{line_range[1]}") cmds.append(filename.replace("/", os.sep)) logger.info('Running "%s"', " ".join(cmds)) @@ -708,7 +723,9 @@ def post_results(use_diff_comments: bool, user_id: int = 41898282): set_exit_code(1 if checks_passed else 0) -def make_annotations(style: str, file_annotations: bool) -> bool: +def make_annotations( + style: str, file_annotations: bool, lines_changed_only: int +) -> bool: """Use github log commands to make annotations from clang-format and clang-tidy output. @@ -719,11 +736,21 @@ def make_annotations(style: str, file_annotations: bool) -> bool: # log_commander obj's verbosity is hard-coded to show debug statements ret_val = False count = 0 - for advice in GlobalParser.format_advice: + files = ( + Globals.FILES + if GITHUB_EVENT_NAME == "pull_request" + else Globals.FILES["files"] # type: ignore + ) + for advice, file in zip(GlobalParser.format_advice, files): if advice.replaced_lines: ret_val = True + line_filter = [] + if lines_changed_only == 1: + line_filter = file["line_filter"]["diff_chunks"] + elif lines_changed_only == 2: + line_filter = file["line_filter"]["lines_added"] if file_annotations: - log_commander.info(advice.log_command(style)) + log_commander.info(advice.log_command(style, line_filter)) count += 1 for note in GlobalParser.tidy_notes: ret_val = True @@ -817,7 +844,7 @@ def main(): args.extensions, ignored, not_ignored, - args.lines_changed_only if args.files_changed_only else False, + args.lines_changed_only, ) if not exit_early: verify_files_are_present() @@ -844,7 +871,11 @@ def main(): ) if args.thread_comments and thread_comments_allowed: post_results(False) # False is hard-coded to disable diff comments. - set_exit_code(int(make_annotations(args.style, args.file_annotations))) + set_exit_code( + int( + make_annotations(args.style, args.file_annotations, args.lines_changed_only) + ) + ) end_log_group() diff --git a/cpp_linter/thread_comments.py b/cpp_linter/thread_comments.py index 94ce072a..70b07a87 100644 --- a/cpp_linter/thread_comments.py +++ b/cpp_linter/thread_comments.py @@ -106,7 +106,7 @@ def aggregate_tidy_advice() -> list: return results -def aggregate_format_advice() -> list: +def aggregate_format_advice(lines_changed_only: int = 1) -> list: """Aggregate a list of json contents representing advice from clang-format suggestions.""" results = [] @@ -127,8 +127,9 @@ def aggregate_format_advice() -> list: for fixed_line in fmt_advice.replaced_lines: # clang-format can include advice that starts/ends outside the diff's domain in_range = False + line_ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" ranges: List[List[int]] = ( - Globals.FILES[index]["line_filter"]["lines"] # type: ignore + Globals.FILES[index]["line_filter"][line_ranges] # type: ignore ) for scope in ranges: if fixed_line.line in range(scope[0], scope[1] + 1): @@ -192,7 +193,7 @@ def concatenate_comments(tidy_advice: list, format_advice: list) -> list: def list_diff_comments() -> list: """Aggregate list of comments for use in the event's diff. This function assumes - that the CLI option `--diff-only` is set to True. + that the CLI option `--lines_changed_only` is set to True. Returns: A list of comments (each element as json content). diff --git a/tests/lines_changed_only/.clang-format b/tests/lines_changed_only/.clang-format new file mode 100644 index 00000000..69971928 --- /dev/null +++ b/tests/lines_changed_only/.clang-format @@ -0,0 +1,148 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: false + BeforeCatch: false + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE +... diff --git a/tests/lines_changed_only/expected_result.json b/tests/lines_changed_only/expected_result.json new file mode 100644 index 00000000..28344bc9 --- /dev/null +++ b/tests/lines_changed_only/expected_result.json @@ -0,0 +1,409 @@ +{ + "sha": "3c35acde7d398c32f6fad50fa902de391f573ffa", + "node_id": "C_kwDOAAOGANoAKDNjMzVhY2RlN2QzOThjMzJmNmZhZDUwZmE5MDJkZTM5MWY1NzNmZmE", + "commit": { + "author": { + "name": "Turo Lamminen", + "email": "turol@users.noreply.github.com", + "date": "2022-07-12T17:58:17Z" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com", + "date": "2022-07-12T17:58:17Z" + }, + "message": "Merge 1acdd067d8b168099de009b2cb625c3e4565561a into 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", + "tree": { + "sha": "61aafe76912a4e79bfe9e2e0620d5fc09792922e", + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/trees/61aafe76912a4e79bfe9e2e0620d5fc09792922e" + }, + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", + "comment_count": 0, + "verification": { + "verified": true, + "reason": "valid", + "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsBcBAABCAAQBQJizbY5CRBK7hj4Ov3rIwAAd90IAEK0v5LTMD8TaaSlWOiXQ6Jh\nYqjVo248+3MuFEH2Em+QFt6RVbhA/HzsaD2E1qwigyOd0VXu2PZvGUP/hvB/x4AM\nEBxFAdGpP+nLhGF3uWJTZ6K/hfuvL6r4xV+EiqCBb1mSpy13N7kbBy3phSJfWgGM\nyrzR6qv40fgZgGRtFaOkP96SWNO+XnpHzoHqpVXaqYzj3sn1kZwbF6LoZUJy+7YZ\nJJFWZUg0mxsvlGZUZBO7e0KMZmPzLXfAA+heF7UqaDE6mT/lP/FSXHrZHH8J3Iju\nWOWECb2qRgNVYGuxhqW7+iN8ZvbDPI1+lPEvRAl4u72+piN++XrQgh5zgiNzDOU=\n=+D8A\n-----END PGP SIGNATURE-----\n", + "payload": "tree 61aafe76912a4e79bfe9e2e0620d5fc09792922e\nparent 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8\nparent 1acdd067d8b168099de009b2cb625c3e4565561a\nauthor Turo Lamminen 1657648697 +0000\ncommitter GitHub 1657648697 +0000\n\nMerge 1acdd067d8b168099de009b2cb625c3e4565561a into 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8\n" + } + }, + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", + "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/3c35acde7d398c32f6fad50fa902de391f573ffa", + "comments_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa/comments", + "author": { + "login": "turol", + "id": 805057, + "node_id": "MDQ6VXNlcjgwNTA1Nw==", + "avatar_url": "https://avatars.githubusercontent.com/u/805057?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/turol", + "html_url": "https://github.com/turol", + "followers_url": "https://api.github.com/users/turol/followers", + "following_url": "https://api.github.com/users/turol/following{/other_user}", + "gists_url": "https://api.github.com/users/turol/gists{/gist_id}", + "starred_url": "https://api.github.com/users/turol/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/turol/subscriptions", + "organizations_url": "https://api.github.com/users/turol/orgs", + "repos_url": "https://api.github.com/users/turol/repos", + "events_url": "https://api.github.com/users/turol/events{/privacy}", + "received_events_url": "https://api.github.com/users/turol/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "web-flow", + "id": 19864447, + "node_id": "MDQ6VXNlcjE5ODY0NDQ3", + "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/web-flow", + "html_url": "https://github.com/web-flow", + "followers_url": "https://api.github.com/users/web-flow/followers", + "following_url": "https://api.github.com/users/web-flow/following{/other_user}", + "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", + "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", + "organizations_url": "https://api.github.com/users/web-flow/orgs", + "repos_url": "https://api.github.com/users/web-flow/repos", + "events_url": "https://api.github.com/users/web-flow/events{/privacy}", + "received_events_url": "https://api.github.com/users/web-flow/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", + "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/7afbf68abcaad446c3f287ed502c6ebbb2fb10e8" + }, + { + "sha": "1acdd067d8b168099de009b2cb625c3e4565561a", + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/1acdd067d8b168099de009b2cb625c3e4565561a", + "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/1acdd067d8b168099de009b2cb625c3e4565561a" + } + ], + "stats": { + "total": 334, + "additions": 297, + "deletions": 37 + }, + "files": [ + { + "sha": "46e082cf77c5e60affc7689f7357c926fc00cda3", + "filename": "opl/opl.c", + "status": "modified", + "additions": 2, + "deletions": 0, + "changes": 2, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -50,7 +50,9 @@ static opl_driver_t *drivers[] =\n #ifdef _WIN32\n &opl_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &opl_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL\n };\n ", + "line_filter": { + "diff_chunks": [ + [ + 50, + 59 + ] + ], + "lines_added": [ + [ + 53, + 54 + ], + [ + 55, + 56 + ] + ] + } + }, + { + "sha": "6bd4e7e1f3374e289d3dc19972dcb1d5379d6b03", + "filename": "opl/opl_sdl.c", + "status": "modified", + "additions": 6, + "deletions": 0, + "changes": 6, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -33,6 +33,10 @@\n \n #include \"opl_queue.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 100 /* ms */\n \n typedef struct\n@@ -511,3 +515,5 @@ opl_driver_t opl_sdl_driver =\n OPL_SDL_AdjustCallbacks,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 33, + 43 + ], + [ + 515, + 520 + ] + ], + "lines_added": [ + [ + 36, + 40 + ], + [ + 518, + 520 + ] + ] + } + }, + { + "sha": "58f9b75c2affd5f1dd990aaedab79d834575bf83", + "filename": "pcsound/pcsound.c", + "status": "modified", + "additions": 2, + "deletions": 0, + "changes": 2, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -56,7 +56,9 @@ static pcsound_driver_t *drivers[] =\n #ifdef _WIN32\n &pcsound_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &pcsound_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL,\n };\n ", + "line_filter": { + "diff_chunks": [ + [ + 56, + 65 + ] + ], + "lines_added": [ + [ + 59, + 60 + ], + [ + 61, + 62 + ] + ] + } + }, + { + "sha": "e77c7b0d29de1b0c665686004dfda311c9d96719", + "filename": "pcsound/pcsound_sdl.c", + "status": "modified", + "additions": 6, + "deletions": 0, + "changes": 6, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -24,6 +24,10 @@\n #include \"pcsound.h\"\n #include \"pcsound_internal.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 70 /* ms */\n #define SQUARE_WAVE_AMP 0x2000\n \n@@ -248,3 +252,5 @@ pcsound_driver_t pcsound_sdl_driver =\n PCSound_SDL_Shutdown,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 24, + 34 + ], + [ + 252, + 257 + ] + ], + "lines_added": [ + [ + 27, + 31 + ], + [ + 255, + 257 + ] + ] + } + }, + { + "sha": "3facce6f01d02c5e8eef3088fa60576b9e949829", + "filename": "src/i_musicpack.c", + "status": "modified", + "additions": 87, + "deletions": 1, + "changes": 88, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_musicpack.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -44,6 +44,13 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n+\n+char *music_pack_path = \"\";\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MID_HEADER_MAGIC \"MThd\"\n #define MUS_HEADER_MAGIC \"MUS\\x1a\"\n \n@@ -99,7 +106,6 @@ static boolean music_initialized = false;\n \n static boolean sdl_was_initialized = false;\n \n-char *music_pack_path = \"\";\n \n // If true, we are playing a substitute digital track rather than in-WAD\n // MIDI/MUS track, and file_metadata contains loop metadata.\n@@ -1375,3 +1381,83 @@ music_module_t music_pack_module =\n I_MP_PollMusic,\n };\n \n+\n+#else // DISABLE_SDL2MIXER\n+\n+\n+static boolean I_NULL_InitMusic(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_ShutdownMusic(void)\n+{\n+}\n+\n+\n+static void I_NULL_SetMusicVolume(int volume)\n+{\n+}\n+\n+\n+static void I_NULL_PauseSong(void)\n+{\n+}\n+\n+\n+static void I_NULL_ResumeSong(void)\n+{\n+}\n+\n+\n+static void *I_NULL_RegisterSong(void *data, int len)\n+{\n+ return NULL;\n+}\n+\n+\n+static void I_NULL_UnRegisterSong(void *handle)\n+{\n+}\n+\n+\n+static void I_NULL_PlaySong(void *handle, boolean looping)\n+{\n+}\n+\n+\n+static void I_NULL_StopSong(void)\n+{\n+}\n+\n+\n+static boolean I_NULL_MusicIsPlaying(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_PollMusic(void)\n+{\n+}\n+\n+music_module_t music_pack_module =\n+{\n+ NULL,\n+ 0,\n+ I_NULL_InitMusic,\n+ I_NULL_ShutdownMusic,\n+ I_NULL_SetMusicVolume,\n+ I_NULL_PauseSong,\n+ I_NULL_ResumeSong,\n+ I_NULL_RegisterSong,\n+ I_NULL_UnRegisterSong,\n+ I_NULL_PlaySong,\n+ I_NULL_StopSong,\n+ I_NULL_MusicIsPlaying,\n+ I_NULL_PollMusic,\n+};\n+\n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 44, + 57 + ], + [ + 106, + 112 + ], + [ + 1381, + 1464 + ] + ], + "lines_added": [ + [ + 47, + 54 + ], + [ + 1384, + 1464 + ] + ] + } + }, + { + "sha": "48fedfbd7608ad8c6575a4bd82a5e1cb3646e071", + "filename": "src/i_sdlmusic.c", + "status": "modified", + "additions": 21, + "deletions": 13, + "changes": 34, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlmusic.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -44,19 +44,6 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n-#define MAXMIDLENGTH (96 * 1024)\n-\n-static boolean music_initialized = false;\n-\n-// If this is true, this module initialized SDL sound and has the \n-// responsibility to shut it down\n-\n-static boolean sdl_was_initialized = false;\n-\n-static boolean win_midi_stream_opened = false;\n-\n-static boolean musicpaused = false;\n-static int current_music_volume;\n \n char *fluidsynth_sf_path = \"\";\n char *timidity_cfg_path = \"\";\n@@ -138,6 +125,25 @@ void I_InitTimidityConfig(void)\n }\n }\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n+#define MAXMIDLENGTH (96 * 1024)\n+\n+static boolean music_initialized = false;\n+\n+// If this is true, this module initialized SDL sound and has the\n+// responsibility to shut it down\n+\n+static boolean sdl_was_initialized = false;\n+\n+static boolean win_midi_stream_opened = false;\n+\n+static boolean musicpaused = false;\n+static int current_music_volume;\n+\n+\n // Remove the temporary config file generated by I_InitTimidityConfig().\n \n static void RemoveTimidityConfig(void)\n@@ -588,3 +594,5 @@ music_module_t music_sdl_module =\n NULL, // Poll\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 44, + 50 + ], + [ + 125, + 150 + ], + [ + 594, + 599 + ] + ], + "lines_added": [ + [ + 128, + 147 + ], + [ + 597, + 599 + ] + ] + } + }, + { + "sha": "7f2a26096b218c5323f5dc569c6f70ab399782bf", + "filename": "src/i_sdlsound.c", + "status": "modified", + "additions": 17, + "deletions": 9, + "changes": 26, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -41,6 +41,21 @@\n \n #include \"doomtype.h\"\n \n+\n+int use_libsamplerate = 0;\n+\n+// Scale factor used when converting libsamplerate floating point numbers\n+// to integers. Too high means the sounds can clip; too low means they\n+// will be too quiet. This is an amount that should avoid clipping most\n+// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n+// is used, clipping might occur.\n+\n+float libsamplerate_scale = 0.65f;\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define LOW_PASS_FILTER\n //#define DEBUG_DUMP_WAVS\n #define NUM_CHANNELS 16\n@@ -77,15 +92,6 @@ static allocated_sound_t *allocated_sounds_head = NULL;\n static allocated_sound_t *allocated_sounds_tail = NULL;\n static int allocated_sounds_size = 0;\n \n-int use_libsamplerate = 0;\n-\n-// Scale factor used when converting libsamplerate floating point numbers\n-// to integers. Too high means the sounds can clip; too low means they\n-// will be too quiet. This is an amount that should avoid clipping most\n-// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n-// is used, clipping might occur.\n-\n-float libsamplerate_scale = 0.65f;\n \n // Hook a sound into the linked list at the head.\n \n@@ -1135,3 +1141,5 @@ sound_module_t sound_sdl_module =\n I_SDL_PrecacheSounds,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 41, + 62 + ], + [ + 92, + 98 + ], + [ + 1141, + 1146 + ] + ], + "lines_added": [ + [ + 44, + 59 + ], + [ + 1144, + 1146 + ] + ] + } + }, + { + "sha": "9cf1fd95db13504ffc6f98ead8c9150f03db72aa", + "filename": "src/i_sound.c", + "status": "modified", + "additions": 4, + "deletions": 0, + "changes": 4, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -99,7 +99,9 @@ static int snd_mport = 0;\n \n static sound_module_t *sound_modules[] = \n {\n+#ifndef DISABLE_SDL2MIXER\n &sound_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &sound_pcsound_module,\n NULL,\n };\n@@ -108,7 +110,9 @@ static sound_module_t *sound_modules[] =\n \n static music_module_t *music_modules[] =\n {\n+#ifndef DISABLE_SDL2MIXER\n &music_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &music_opl_module,\n NULL,\n };", + "line_filter": { + "diff_chunks": [ + [ + 99, + 108 + ], + [ + 110, + 119 + ] + ], + "lines_added": [ + [ + 102, + 103 + ], + [ + 104, + 105 + ], + [ + 113, + 114 + ], + [ + 115, + 116 + ] + ] + } + }, + { + "sha": "c1f701c0b9f653eb3a36b71627747a6eda963d8f", + "filename": "src/net_sdl.c", + "status": "modified", + "additions": 63, + "deletions": 0, + "changes": 63, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fnet_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -33,6 +33,10 @@\n // NETWORKING\n //\n \n+\n+#ifndef DISABLE_SDL2NET\n+\n+\n #include \n \n #define DEFAULT_PORT 2342\n@@ -376,3 +380,62 @@ net_module_t net_sdl_module =\n NET_SDL_ResolveAddress,\n };\n \n+\n+#else // DISABLE_SDL2NET\n+\n+// no-op implementation\n+\n+\n+static boolean NET_NULL_InitClient(void)\n+{\n+ return false;\n+}\n+\n+\n+static boolean NET_NULL_InitServer(void)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_SendPacket(net_addr_t *addr, net_packet_t *packet)\n+{\n+}\n+\n+\n+static boolean NET_NULL_RecvPacket(net_addr_t **addr, net_packet_t **packet)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)\n+{\n+\n+}\n+\n+\n+static void NET_NULL_FreeAddress(net_addr_t *addr)\n+{\n+}\n+\n+\n+net_addr_t *NET_NULL_ResolveAddress(const char *address)\n+{\n+ return NULL;\n+}\n+\n+\n+net_module_t net_sdl_module =\n+{\n+ NET_NULL_InitClient,\n+ NET_NULL_InitServer,\n+ NET_NULL_SendPacket,\n+ NET_NULL_RecvPacket,\n+ NET_NULL_AddrToString,\n+ NET_NULL_FreeAddress,\n+ NET_NULL_ResolveAddress,\n+};\n+\n+\n+#endif // DISABLE_SDL2NET", + "line_filter": { + "diff_chunks": [ + [ + 33, + 43 + ], + [ + 380, + 442 + ] + ], + "lines_added": [ + [ + 36, + 40 + ], + [ + 383, + 442 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/tests/lines_changed_only/files.json b/tests/lines_changed_only/files.json new file mode 100644 index 00000000..1952842b --- /dev/null +++ b/tests/lines_changed_only/files.json @@ -0,0 +1,319 @@ +{ + "sha": "3c35acde7d398c32f6fad50fa902de391f573ffa", + "node_id": "C_kwDOAAOGANoAKDNjMzVhY2RlN2QzOThjMzJmNmZhZDUwZmE5MDJkZTM5MWY1NzNmZmE", + "commit": { + "author": { + "name": "Turo Lamminen", + "email": "turol@users.noreply.github.com", + "date": "2022-07-12T17:58:17Z" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com", + "date": "2022-07-12T17:58:17Z" + }, + "message": "Merge 1acdd067d8b168099de009b2cb625c3e4565561a into 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", + "tree": { + "sha": "61aafe76912a4e79bfe9e2e0620d5fc09792922e", + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/trees/61aafe76912a4e79bfe9e2e0620d5fc09792922e" + }, + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", + "comment_count": 0, + "verification": { + "verified": true, + "reason": "valid", + "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsBcBAABCAAQBQJizbY5CRBK7hj4Ov3rIwAAd90IAEK0v5LTMD8TaaSlWOiXQ6Jh\nYqjVo248+3MuFEH2Em+QFt6RVbhA/HzsaD2E1qwigyOd0VXu2PZvGUP/hvB/x4AM\nEBxFAdGpP+nLhGF3uWJTZ6K/hfuvL6r4xV+EiqCBb1mSpy13N7kbBy3phSJfWgGM\nyrzR6qv40fgZgGRtFaOkP96SWNO+XnpHzoHqpVXaqYzj3sn1kZwbF6LoZUJy+7YZ\nJJFWZUg0mxsvlGZUZBO7e0KMZmPzLXfAA+heF7UqaDE6mT/lP/FSXHrZHH8J3Iju\nWOWECb2qRgNVYGuxhqW7+iN8ZvbDPI1+lPEvRAl4u72+piN++XrQgh5zgiNzDOU=\n=+D8A\n-----END PGP SIGNATURE-----\n", + "payload": "tree 61aafe76912a4e79bfe9e2e0620d5fc09792922e\nparent 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8\nparent 1acdd067d8b168099de009b2cb625c3e4565561a\nauthor Turo Lamminen 1657648697 +0000\ncommitter GitHub 1657648697 +0000\n\nMerge 1acdd067d8b168099de009b2cb625c3e4565561a into 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8\n" + } + }, + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", + "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/3c35acde7d398c32f6fad50fa902de391f573ffa", + "comments_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa/comments", + "author": { + "login": "turol", + "id": 805057, + "node_id": "MDQ6VXNlcjgwNTA1Nw==", + "avatar_url": "https://avatars.githubusercontent.com/u/805057?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/turol", + "html_url": "https://github.com/turol", + "followers_url": "https://api.github.com/users/turol/followers", + "following_url": "https://api.github.com/users/turol/following{/other_user}", + "gists_url": "https://api.github.com/users/turol/gists{/gist_id}", + "starred_url": "https://api.github.com/users/turol/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/turol/subscriptions", + "organizations_url": "https://api.github.com/users/turol/orgs", + "repos_url": "https://api.github.com/users/turol/repos", + "events_url": "https://api.github.com/users/turol/events{/privacy}", + "received_events_url": "https://api.github.com/users/turol/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "web-flow", + "id": 19864447, + "node_id": "MDQ6VXNlcjE5ODY0NDQ3", + "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/web-flow", + "html_url": "https://github.com/web-flow", + "followers_url": "https://api.github.com/users/web-flow/followers", + "following_url": "https://api.github.com/users/web-flow/following{/other_user}", + "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", + "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", + "organizations_url": "https://api.github.com/users/web-flow/orgs", + "repos_url": "https://api.github.com/users/web-flow/repos", + "events_url": "https://api.github.com/users/web-flow/events{/privacy}", + "received_events_url": "https://api.github.com/users/web-flow/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", + "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/7afbf68abcaad446c3f287ed502c6ebbb2fb10e8" + }, + { + "sha": "1acdd067d8b168099de009b2cb625c3e4565561a", + "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/1acdd067d8b168099de009b2cb625c3e4565561a", + "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/1acdd067d8b168099de009b2cb625c3e4565561a" + } + ], + "stats": { + "total": 334, + "additions": 297, + "deletions": 37 + }, + "files": [ + { + "sha": "7f1eed09c6c07682738de7b5141fd151d16cf368", + "filename": "CMakeLists.txt", + "status": "modified", + "additions": 14, + "deletions": 2, + "changes": 16, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/CMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/CMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/CMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -28,9 +28,21 @@ else()\n \"-Wredundant-decls\")\n endif()\n \n+option(ENABLE_SDL2_NET \"Enable SDL2_net\" On)\n+option(ENABLE_SDL2_MIXER \"Enable SDL2_mixer\" On)\n+\n find_package(SDL2 2.0.7)\n-find_package(SDL2_mixer 2.0.2)\n-find_package(SDL2_net 2.0.0)\n+if(ENABLE_SDL2_MIXER)\n+ find_package(SDL2_mixer 2.0.2)\n+else()\n+ add_compile_definitions(DISABLE_SDL2MIXER=1)\n+endif()\n+\n+if(ENABLE_SDL2_NET)\n+ find_package(SDL2_net 2.0.0)\n+else()\n+ add_compile_definitions(DISABLE_SDL2NET=1)\n+endif()\n \n # Check for libsamplerate.\n find_package(samplerate)" + }, + { + "sha": "fd5d8bcecd8a6edb6d77c8686ae32a995b571066", + "filename": "configure.ac", + "status": "modified", + "additions": 17, + "deletions": 2, + "changes": 19, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/configure.ac", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/configure.ac", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/configure.ac?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -32,8 +32,23 @@ then\n fi\n \n PKG_CHECK_MODULES(SDL, [sdl2 >= 2.0.7])\n-PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.2])\n-PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])\n+# Check for SDL2_mixer\n+AC_ARG_ENABLE([sdl2mixer],\n+AS_HELP_STRING([--disable-sdl2mixer], [Disable SDL2_mixer support])\n+)\n+AS_IF([test \"x$enable_sdl2mixer\" != xno], [\n+ PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.2])], [\n+ AC_DEFINE([DISABLE_SDL2MIXER], [1], [SDL2_mixer disabled])\n+])\n+\n+# Check for networking\n+AC_ARG_ENABLE([sdl2net],\n+AS_HELP_STRING([--disable-sdl2net], [Disable SDL2_net support])\n+)\n+AS_IF([test \"x$enable_sdl2net\" != xno], [\n+ PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])], [\n+ AC_DEFINE([DISABLE_SDL2NET], [1], [SDL2_net disabled])\n+])\n \n # Check for bash-completion.\n AC_ARG_ENABLE([bash-completion]," + }, + { + "sha": "151f7617dde7d1216f7212b45bb5aeb7661bc86b", + "filename": "opl/CMakeLists.txt", + "status": "modified", + "additions": 4, + "deletions": 1, + "changes": 5, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -12,4 +12,7 @@ add_library(opl STATIC\n target_include_directories(opl\n INTERFACE \".\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(opl SDL2::mixer)\n+target_link_libraries(opl SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(opl SDL2::mixer)\n+endif()" + }, + { + "sha": "46e082cf77c5e60affc7689f7357c926fc00cda3", + "filename": "opl/opl.c", + "status": "modified", + "additions": 2, + "deletions": 0, + "changes": 2, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -50,7 +50,9 @@ static opl_driver_t *drivers[] =\n #ifdef _WIN32\n &opl_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &opl_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL\n };\n " + }, + { + "sha": "6bd4e7e1f3374e289d3dc19972dcb1d5379d6b03", + "filename": "opl/opl_sdl.c", + "status": "modified", + "additions": 6, + "deletions": 0, + "changes": 6, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -33,6 +33,10 @@\n \n #include \"opl_queue.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 100 /* ms */\n \n typedef struct\n@@ -511,3 +515,5 @@ opl_driver_t opl_sdl_driver =\n OPL_SDL_AdjustCallbacks,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "9924263aea24261091948e455dfd2521787a04c4", + "filename": "pcsound/CMakeLists.txt", + "status": "modified", + "additions": 4, + "deletions": 1, + "changes": 5, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -8,4 +8,7 @@ add_library(pcsound STATIC\n target_include_directories(pcsound\n INTERFACE \".\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(pcsound SDL2::mixer)\n+target_link_libraries(pcsound SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(pcsound SDL2::mixer)\n+endif()" + }, + { + "sha": "58f9b75c2affd5f1dd990aaedab79d834575bf83", + "filename": "pcsound/pcsound.c", + "status": "modified", + "additions": 2, + "deletions": 0, + "changes": 2, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -56,7 +56,9 @@ static pcsound_driver_t *drivers[] =\n #ifdef _WIN32\n &pcsound_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &pcsound_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL,\n };\n " + }, + { + "sha": "e77c7b0d29de1b0c665686004dfda311c9d96719", + "filename": "pcsound/pcsound_sdl.c", + "status": "modified", + "additions": 6, + "deletions": 0, + "changes": 6, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -24,6 +24,10 @@\n #include \"pcsound.h\"\n #include \"pcsound_internal.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 70 /* ms */\n #define SQUARE_WAVE_AMP 0x2000\n \n@@ -248,3 +252,5 @@ pcsound_driver_t pcsound_sdl_driver =\n PCSound_SDL_Shutdown,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "bbb877641f2a8de6e6eb7dad5b8c866e147faf7d", + "filename": "src/CMakeLists.txt", + "status": "modified", + "additions": 18, + "deletions": 3, + "changes": 21, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -32,7 +32,10 @@ set(DEDSERV_FILES\n add_executable(\"${PROGRAM_PREFIX}server\" WIN32 ${COMMON_SOURCE_FILES} ${DEDSERV_FILES})\n target_include_directories(\"${PROGRAM_PREFIX}server\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::SDL2main SDL2::net)\n+target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::SDL2main SDL2::SDL2)\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::net)\n+endif()\n \n # Source files used by the game binaries (chocolate-doom, etc.)\n \n@@ -121,7 +124,13 @@ set(DEHACKED_SOURCE_FILES\n set(SOURCE_FILES ${COMMON_SOURCE_FILES} ${GAME_SOURCE_FILES})\n set(SOURCE_FILES_WITH_DEH ${SOURCE_FILES} ${DEHACKED_SOURCE_FILES})\n \n-set(EXTRA_LIBS SDL2::SDL2main SDL2::SDL2 SDL2::mixer SDL2::net textscreen pcsound opl)\n+set(EXTRA_LIBS SDL2::SDL2main SDL2::SDL2 textscreen pcsound opl)\n+if(ENABLE_SDL2_MIXER)\n+ list(APPEND EXTRA_LIBS SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ list(APPEND EXTRA_LIBS SDL2::net)\n+endif()\n if(SAMPLERATE_FOUND)\n list(APPEND EXTRA_LIBS samplerate::samplerate)\n endif()\n@@ -213,7 +222,13 @@ endif()\n \n target_include_directories(\"${PROGRAM_PREFIX}setup\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::SDL2main SDL2::SDL2 SDL2::mixer SDL2::net setup textscreen)\n+target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::SDL2main SDL2::SDL2 setup textscreen)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::net)\n+endif()\n \n if(MSVC)\n set_target_properties(\"${PROGRAM_PREFIX}setup\" PROPERTIES" + }, + { + "sha": "82b114b4178595085c6745bc70a570922415be1f", + "filename": "src/doom/CMakeLists.txt", + "status": "modified", + "additions": 7, + "deletions": 1, + "changes": 8, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fdoom%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fdoom%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fdoom%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -68,4 +68,10 @@ add_library(doom STATIC\n wi_stuff.c wi_stuff.h)\n \n target_include_directories(doom PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(doom SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(doom SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(doom SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(doom SDL2::net)\n+endif()" + }, + { + "sha": "1ea060bfdb8b3147e36b3431fee27934c8a93b34", + "filename": "src/heretic/CMakeLists.txt", + "status": "modified", + "additions": 7, + "deletions": 1, + "changes": 8, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fheretic%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fheretic%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fheretic%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -54,4 +54,10 @@ add_library(heretic STATIC\n s_sound.c s_sound.h)\n \n target_include_directories(heretic PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(heretic textscreen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(heretic textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(heretic SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(heretic SDL2::net)\n+endif()" + }, + { + "sha": "0dbd170bfdb06c8209ec654d4d5377e334be886e", + "filename": "src/hexen/CMakeLists.txt", + "status": "modified", + "additions": 7, + "deletions": 1, + "changes": 8, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fhexen%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fhexen%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fhexen%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -55,4 +55,10 @@ add_library(hexen STATIC\n xddefs.h)\n \n target_include_directories(hexen PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(hexen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(hexen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(hexen SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(hexen SDL2::net)\n+endif()" + }, + { + "sha": "3facce6f01d02c5e8eef3088fa60576b9e949829", + "filename": "src/i_musicpack.c", + "status": "modified", + "additions": 87, + "deletions": 1, + "changes": 88, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_musicpack.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -44,6 +44,13 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n+\n+char *music_pack_path = \"\";\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MID_HEADER_MAGIC \"MThd\"\n #define MUS_HEADER_MAGIC \"MUS\\x1a\"\n \n@@ -99,7 +106,6 @@ static boolean music_initialized = false;\n \n static boolean sdl_was_initialized = false;\n \n-char *music_pack_path = \"\";\n \n // If true, we are playing a substitute digital track rather than in-WAD\n // MIDI/MUS track, and file_metadata contains loop metadata.\n@@ -1375,3 +1381,83 @@ music_module_t music_pack_module =\n I_MP_PollMusic,\n };\n \n+\n+#else // DISABLE_SDL2MIXER\n+\n+\n+static boolean I_NULL_InitMusic(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_ShutdownMusic(void)\n+{\n+}\n+\n+\n+static void I_NULL_SetMusicVolume(int volume)\n+{\n+}\n+\n+\n+static void I_NULL_PauseSong(void)\n+{\n+}\n+\n+\n+static void I_NULL_ResumeSong(void)\n+{\n+}\n+\n+\n+static void *I_NULL_RegisterSong(void *data, int len)\n+{\n+ return NULL;\n+}\n+\n+\n+static void I_NULL_UnRegisterSong(void *handle)\n+{\n+}\n+\n+\n+static void I_NULL_PlaySong(void *handle, boolean looping)\n+{\n+}\n+\n+\n+static void I_NULL_StopSong(void)\n+{\n+}\n+\n+\n+static boolean I_NULL_MusicIsPlaying(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_PollMusic(void)\n+{\n+}\n+\n+music_module_t music_pack_module =\n+{\n+ NULL,\n+ 0,\n+ I_NULL_InitMusic,\n+ I_NULL_ShutdownMusic,\n+ I_NULL_SetMusicVolume,\n+ I_NULL_PauseSong,\n+ I_NULL_ResumeSong,\n+ I_NULL_RegisterSong,\n+ I_NULL_UnRegisterSong,\n+ I_NULL_PlaySong,\n+ I_NULL_StopSong,\n+ I_NULL_MusicIsPlaying,\n+ I_NULL_PollMusic,\n+};\n+\n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "48fedfbd7608ad8c6575a4bd82a5e1cb3646e071", + "filename": "src/i_sdlmusic.c", + "status": "modified", + "additions": 21, + "deletions": 13, + "changes": 34, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlmusic.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -44,19 +44,6 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n-#define MAXMIDLENGTH (96 * 1024)\n-\n-static boolean music_initialized = false;\n-\n-// If this is true, this module initialized SDL sound and has the \n-// responsibility to shut it down\n-\n-static boolean sdl_was_initialized = false;\n-\n-static boolean win_midi_stream_opened = false;\n-\n-static boolean musicpaused = false;\n-static int current_music_volume;\n \n char *fluidsynth_sf_path = \"\";\n char *timidity_cfg_path = \"\";\n@@ -138,6 +125,25 @@ void I_InitTimidityConfig(void)\n }\n }\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n+#define MAXMIDLENGTH (96 * 1024)\n+\n+static boolean music_initialized = false;\n+\n+// If this is true, this module initialized SDL sound and has the\n+// responsibility to shut it down\n+\n+static boolean sdl_was_initialized = false;\n+\n+static boolean win_midi_stream_opened = false;\n+\n+static boolean musicpaused = false;\n+static int current_music_volume;\n+\n+\n // Remove the temporary config file generated by I_InitTimidityConfig().\n \n static void RemoveTimidityConfig(void)\n@@ -588,3 +594,5 @@ music_module_t music_sdl_module =\n NULL, // Poll\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "7f2a26096b218c5323f5dc569c6f70ab399782bf", + "filename": "src/i_sdlsound.c", + "status": "modified", + "additions": 17, + "deletions": 9, + "changes": 26, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -41,6 +41,21 @@\n \n #include \"doomtype.h\"\n \n+\n+int use_libsamplerate = 0;\n+\n+// Scale factor used when converting libsamplerate floating point numbers\n+// to integers. Too high means the sounds can clip; too low means they\n+// will be too quiet. This is an amount that should avoid clipping most\n+// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n+// is used, clipping might occur.\n+\n+float libsamplerate_scale = 0.65f;\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define LOW_PASS_FILTER\n //#define DEBUG_DUMP_WAVS\n #define NUM_CHANNELS 16\n@@ -77,15 +92,6 @@ static allocated_sound_t *allocated_sounds_head = NULL;\n static allocated_sound_t *allocated_sounds_tail = NULL;\n static int allocated_sounds_size = 0;\n \n-int use_libsamplerate = 0;\n-\n-// Scale factor used when converting libsamplerate floating point numbers\n-// to integers. Too high means the sounds can clip; too low means they\n-// will be too quiet. This is an amount that should avoid clipping most\n-// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n-// is used, clipping might occur.\n-\n-float libsamplerate_scale = 0.65f;\n \n // Hook a sound into the linked list at the head.\n \n@@ -1135,3 +1141,5 @@ sound_module_t sound_sdl_module =\n I_SDL_PrecacheSounds,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "9cf1fd95db13504ffc6f98ead8c9150f03db72aa", + "filename": "src/i_sound.c", + "status": "modified", + "additions": 4, + "deletions": 0, + "changes": 4, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -99,7 +99,9 @@ static int snd_mport = 0;\n \n static sound_module_t *sound_modules[] = \n {\n+#ifndef DISABLE_SDL2MIXER\n &sound_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &sound_pcsound_module,\n NULL,\n };\n@@ -108,7 +110,9 @@ static sound_module_t *sound_modules[] =\n \n static music_module_t *music_modules[] =\n {\n+#ifndef DISABLE_SDL2MIXER\n &music_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &music_opl_module,\n NULL,\n };" + }, + { + "sha": "c1f701c0b9f653eb3a36b71627747a6eda963d8f", + "filename": "src/net_sdl.c", + "status": "modified", + "additions": 63, + "deletions": 0, + "changes": 63, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fnet_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -33,6 +33,10 @@\n // NETWORKING\n //\n \n+\n+#ifndef DISABLE_SDL2NET\n+\n+\n #include \n \n #define DEFAULT_PORT 2342\n@@ -376,3 +380,62 @@ net_module_t net_sdl_module =\n NET_SDL_ResolveAddress,\n };\n \n+\n+#else // DISABLE_SDL2NET\n+\n+// no-op implementation\n+\n+\n+static boolean NET_NULL_InitClient(void)\n+{\n+ return false;\n+}\n+\n+\n+static boolean NET_NULL_InitServer(void)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_SendPacket(net_addr_t *addr, net_packet_t *packet)\n+{\n+}\n+\n+\n+static boolean NET_NULL_RecvPacket(net_addr_t **addr, net_packet_t **packet)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)\n+{\n+\n+}\n+\n+\n+static void NET_NULL_FreeAddress(net_addr_t *addr)\n+{\n+}\n+\n+\n+net_addr_t *NET_NULL_ResolveAddress(const char *address)\n+{\n+ return NULL;\n+}\n+\n+\n+net_module_t net_sdl_module =\n+{\n+ NET_NULL_InitClient,\n+ NET_NULL_InitServer,\n+ NET_NULL_SendPacket,\n+ NET_NULL_RecvPacket,\n+ NET_NULL_AddrToString,\n+ NET_NULL_FreeAddress,\n+ NET_NULL_ResolveAddress,\n+};\n+\n+\n+#endif // DISABLE_SDL2NET" + }, + { + "sha": "90df2114163152ff732a9ba4a8bc18ef3d45d1bd", + "filename": "src/setup/CMakeLists.txt", + "status": "modified", + "additions": 4, + "deletions": 1, + "changes": 5, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fsetup%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fsetup%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fsetup%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -15,4 +15,7 @@ add_library(setup STATIC\n txt_mouseinput.c txt_mouseinput.h)\n \n target_include_directories(setup PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(setup textscreen SDL2::SDL2 SDL2::mixer)\n+target_link_libraries(setup textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(setup SDL2::mixer)\n+endif()" + }, + { + "sha": "37b17ade983155369c0897c0935d40dfeb2048c7", + "filename": "src/strife/CMakeLists.txt", + "status": "modified", + "additions": 7, + "deletions": 1, + "changes": 8, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fstrife%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fstrife%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fstrife%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -70,4 +70,10 @@ set(STRIFE_SOURCES\n add_library(strife STATIC ${STRIFE_SOURCES})\n \n target_include_directories(strife PRIVATE \"../\" \"../../win32/\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(strife textscreen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(strife textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(strife SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(strife SDL2::net)\n+endif()" + } + ] +} diff --git a/tests/lines_changed_only/test_lines_changed_only.py b/tests/lines_changed_only/test_lines_changed_only.py new file mode 100644 index 00000000..91871d9c --- /dev/null +++ b/tests/lines_changed_only/test_lines_changed_only.py @@ -0,0 +1,138 @@ +"""Various tests realated to the ``lines_changed_only`` option.""" +import os +import logging +from pathlib import Path +import json +import re +from pytest import LogCaptureFixture +import cpp_linter +from cpp_linter.clang_format_xml import parse_format_replacements_xml +from cpp_linter.run import ( + filter_out_non_source_files, + verify_files_are_present, + run_clang_format, + make_annotations, + log_commander, +) + + +def test_lines_changed_only(): + """Test for lines changes in diff. + + This checks for + 1. ranges of diff chunks. + 2. ranges of lines in diff that only contain additions. + """ + os.chdir(os.path.split(__file__)[0]) + cpp_linter.Globals.FILES = json.loads( + Path("files.json").read_text(encoding="utf-8") + ) + if filter_out_non_source_files( + ext_list=["h", "cpp", "c"], + ignored=[".github"], + not_ignored=[], + lines_changed_only=True, + ): + test_result = Path("expected_result.json").read_text(encoding="utf-8") + for file, result in zip( + cpp_linter.Globals.FILES["files"], + json.loads(test_result)["files"], + ): + expected = result["line_filter"]["diff_chunks"] + assert file["line_filter"]["diff_chunks"] == expected + expected = result["line_filter"]["lines_added"] + assert file["line_filter"]["lines_added"] == expected + else: + raise RuntimeError("test failed to find files") + + +def test_run_clang_format_diff_only(caplog: LogCaptureFixture): + """Using the output (expected_result.json) from ``test_lines_changed_only()``, + run clang-format with lines-changed-only set to 'true'. + + This will make sure clang-format warnings are filtered to + only lines in the diff's chunks.""" + # log_commander.setLevel(logging.INFO) + caplog.set_level(logging.INFO, logger=log_commander.name) + lines_changed_only = 1 # 1 means entire diff chunks + style = "file" # this test includes a custom style guide + os.chdir(os.path.split(__file__)[0]) + cpp_linter.Globals.FILES = json.loads( + Path("expected_result.json").read_text(encoding="utf-8") + ) + verify_files_are_present() + for file in cpp_linter.Globals.FILES["files"]: + filename: str = file["filename"] + run_clang_format( + filename=filename, + file_obj=file, + version="", + style=style, + lines_changed_only=lines_changed_only, + ) + if os.path.getsize("clang_format_output.xml"): + parse_format_replacements_xml(filename.replace("/", os.sep)) + make_annotations( + style=style, file_annotations=True, lines_changed_only=lines_changed_only + ) + record_lines = re.compile(r"\(lines (.*)\)") + record_file = re.compile(r"File (.*)\s") + for record in caplog.records: + if record_lines.search(record.message) is not None: + lines = [ + int(l.strip()) + for l in record_lines.sub("\\1", record.message).split(",") + ] + filename = record_file.sub("\\1", record.message) + for file in cpp_linter.Globals.FILES["files"]: + if file["filename"] == filename: + ranges = file["line_filter"]["diff_chunks"] + for line in lines: + assert line in [range(r[0], r[1]) for r in ranges] + break + + +def test_run_clang_format_diff_adds(caplog: LogCaptureFixture): + """Using the output (expected_result.json) from ``test_lines_changed_only()``, + run clang-format with lines-changed-only set to 'true'. + + This will make sure clang-format warnings are filtered to + only lines in the diff containing additions.""" + # log_commander.setLevel(logging.INFO) + caplog.set_level(logging.INFO, logger=log_commander.name) + lines_changed_only = 2 # 2 means only lines in diff containing additions + style = "file" # this test includes a custom style guide + os.chdir(os.path.split(__file__)[0]) + cpp_linter.Globals.FILES = json.loads( + Path("expected_result.json").read_text(encoding="utf-8") + ) + verify_files_are_present() + for file in cpp_linter.Globals.FILES["files"]: + filename: str = file["filename"] + run_clang_format( + filename=filename, + file_obj=file, + version="", + style=style, + lines_changed_only=lines_changed_only, + ) + if os.path.getsize("clang_format_output.xml"): + parse_format_replacements_xml(filename.replace("/", os.sep)) + make_annotations( + style=style, file_annotations=True, lines_changed_only=lines_changed_only + ) + record_lines = re.compile(r"\(lines (.*)\)") + record_file = re.compile(r"File (.*)\s") + for record in caplog.records: + if record_lines.search(record.message) is not None: + lines = [ + int(l.strip()) + for l in record_lines.sub("\\1", record.message).split(",") + ] + filename = record_file.sub("\\1", record.message) + for file in cpp_linter.Globals.FILES["files"]: + if file["filename"] == filename: + ranges = file["line_filter"]["lines_added"] + for line in lines: + assert line in [range(r[0], r[1]) for r in ranges] + break From a9d911ae4799b74458e2a4697483ef03df817053 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 27 Jul 2022 23:55:53 -0700 Subject: [PATCH 09/76] improve and test CLI arg parsing --- cpp_linter/run.py | 10 ++-- tests/test_cli_args.py | 116 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 tests/test_cli_args.py diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 5e58fd0b..a14487a3 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -50,7 +50,8 @@ cli_arg_parser.add_argument( "-v", "--verbosity", - default="10", + type=int, + default=10, help="The logging level. Defaults to level 20 (aka 'logging.INFO').", ) cli_arg_parser.add_argument( @@ -92,7 +93,8 @@ cli_arg_parser.add_argument( "-e", "--extensions", - default="c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx", + default=["c", "h", "C", "H", "cpp", "hpp", "cc", "hh", "c++", "h++", "cxx", "hxx"], + type=lambda i: [ext.strip().lstrip(".") for ext in i.split(",")], help="The file extensions to run the action against. This comma-separated string " "defaults to %(default)s.", ) @@ -106,7 +108,6 @@ cli_arg_parser.add_argument( "-i", "--ignore", - nargs="?", default=".github", help="Set this option with paths to ignore. In the case of multiple " "paths, you can set this option (multiple times) for each path. This can " @@ -821,9 +822,6 @@ def main(): # prepare ignored paths list ignored, not_ignored = parse_ignore_option(args.ignore) - # prepare extensions list - args.extensions = args.extensions.split(",") - logger.info("processing %s event", GITHUB_EVENT_NAME) # change working directory diff --git a/tests/test_cli_args.py b/tests/test_cli_args.py new file mode 100644 index 00000000..a198786c --- /dev/null +++ b/tests/test_cli_args.py @@ -0,0 +1,116 @@ +"""Tests related parsing input from CLI arguments.""" +from typing import List +from cpp_linter.run import cli_arg_parser + + +class TestArgs: + """Grouped tests using a common namespace declaration""" + + class Args: + """A pseudo namespace declaration. Each attribute is initialized with the + corresponding CLI arg's default value.""" + + verbosity: int = 10 + database: str = "" + style: str = "llvm" + tidy_checks: str = ( + "boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*," + "clang-analyzer-*,cppcoreguidelines-*" + ) + version: str = "" + extensions: List[str] = [ + "c", + "h", + "C", + "H", + "cpp", + "hpp", + "cc", + "hh", + "c++", + "h++", + "cxx", + "hxx", + ] + repo_root: str = "." + ignore: str = ".github" + lines_changed_only: int = 0 + files_changed_only: bool = False + thread_comments: bool = False + file_annotations: bool = True + + def test_defaults(self): + """test default values""" + args = cli_arg_parser.parse_args("") + expected = self.Args() + for key in args.__dict__.keys(): + assert args.__dict__[key] == getattr(expected, key) + + def test_verbosity(self): + """test verbosity option""" + args = cli_arg_parser.parse_args(["--verbosity=20"]) + assert args.verbosity == 20 + + def test_database(self): + """test database option""" + args = cli_arg_parser.parse_args(["--database=build"]) + assert args.database == "build" + + def test_style(self): + """test style option""" + args = cli_arg_parser.parse_args(["--style=file"]) + assert args.style == "file" + + def test_tidy_checks(self): + """test tidy-checks option""" + args = cli_arg_parser.parse_args(["--tidy-checks=-*"]) + assert args.tidy_checks == "-*" + + def test_version(self): + """test version option""" + args = cli_arg_parser.parse_args(["--version=14"]) + assert args.version == "14" + + def test_extensions(self): + """test extensions option""" + args = cli_arg_parser.parse_args(["--extensions", ".cpp, .h"]) + assert args.extensions == ["cpp", "h"] + args = cli_arg_parser.parse_args(["--extensions=cxx, .hpp"]) + assert args.extensions == ["cxx", "hpp"] + + def test_repo_root(self): + """test repo-root option""" + args = cli_arg_parser.parse_args(["--repo-root=src"]) + assert args.repo_root == "src" + + def test_ignore(self): + """test ignore option""" + args = cli_arg_parser.parse_args(["--ignore=!src|"]) + assert args.ignore == "!src|" + + def test_lines_changed_only(self): + """test lines-changed-only option""" + args = cli_arg_parser.parse_args(["--lines-changed-only=True"]) + assert args.lines_changed_only == 1 + args = cli_arg_parser.parse_args(["--lines-changed-only=strict"]) + assert args.lines_changed_only == 2 + + def test_files_changed_only(self): + """test files-changed-only option""" + args = cli_arg_parser.parse_args(["--files-changed-only=True"]) + assert args.files_changed_only is True + + def test_thread_comments(self): + """test thread-comments option""" + args = cli_arg_parser.parse_args(["--thread-comments=True"]) + assert args.thread_comments is True + + def test_file_annotations(self): + """test file-annotations option""" + args = cli_arg_parser.parse_args(["--file-annotations=False"]) + assert args.file_annotations is False + + +if __name__ == "__main__": + test = TestArgs() + test.test_defaults() From 9e37e03422b140e02e29c034ba230dd5951f37c6 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 00:20:37 -0700 Subject: [PATCH 10/76] add unit test for database also fix a typo in demo.hpp variable name --- cpp_linter/thread_comments.py | 16 ++- demo/demo.hpp | 2 +- tests/database_path/test_database_path.py | 152 ++++++++++++++++++++++ 3 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 tests/database_path/test_database_path.py diff --git a/cpp_linter/thread_comments.py b/cpp_linter/thread_comments.py index 70b07a87..8c3f3348 100644 --- a/cpp_linter/thread_comments.py +++ b/cpp_linter/thread_comments.py @@ -126,15 +126,17 @@ def aggregate_format_advice(lines_changed_only: int = 1) -> list: line = "" # the line that concerns the fix for fixed_line in fmt_advice.replaced_lines: # clang-format can include advice that starts/ends outside the diff's domain - in_range = False - line_ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" - ranges: List[List[int]] = ( - Globals.FILES[index]["line_filter"][line_ranges] # type: ignore - ) + ranges: List[List[int]] = Globals.FILES[index][ # type: ignore + "line_filter" + ][ + "diff_chunks" # type: ignore + if lines_changed_only == 1 + else "lines_added" + ] for scope in ranges: if fixed_line.line in range(scope[0], scope[1] + 1): - in_range = True - if not in_range: + break + else: continue # line is out of scope for diff, so skip this fix # assemble the suggestion diff --git a/demo/demo.hpp b/demo/demo.hpp index 40db149d..f93d0122 100644 --- a/demo/demo.hpp +++ b/demo/demo.hpp @@ -8,7 +8,7 @@ class Dummy { Dummy() :numb(0), useless("\0"){} public: - void *not_usefull(char *str){useless = str;} + void *not_useful(char *str){useless = str;} }; diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py new file mode 100644 index 00000000..8d7cc325 --- /dev/null +++ b/tests/database_path/test_database_path.py @@ -0,0 +1,152 @@ +"""Tests specific to specifying the compilation database path.""" +import os +import logging +import re +from pytest import LogCaptureFixture +from cpp_linter import logger +import cpp_linter.run +from cpp_linter.run import run_clang_tidy + +CLANG_TIDY_COMMAND = re.compile(r"\"clang-tidy(.*)(?:\")") + + +def test_db_implicit(caplog: LogCaptureFixture): + """test clang-tidy using a implicit path to the compilation database.""" + os.chdir(os.path.split(__file__)[0]) + caplog.set_level(logging.DEBUG, logger=logger.name) + run_clang_tidy( + filename="../../demo/demo.cpp", + file_obj={}, # only used when using a line filter + version="", # use whatever default is available on the test platform + checks="", # let clang-tidy use a .clang-tidy config file + lines_changed_only=0, # analyze complete file + database="", + repo_root="../../", # relative to this test directory + ) + matched_args = [] + for record in caplog.records: + msg_match = CLANG_TIDY_COMMAND.search(record.message) + if msg_match is not None: + matched_args = msg_match.group(0)[:-1].split()[1:] + matched_args = [m.replace("\\", "/") for m in matched_args] + assert "Error while trying to load a compilation database" not in record.message + assert matched_args == [ + "--export-fixes=clang_tidy_output.yml", + "../../demo/demo.cpp", + ] + + +def test_db_explicit_rel(caplog: LogCaptureFixture): + """test clang-tidy using a explicit relative path to the compilation database.""" + os.chdir(os.path.split(__file__)[0]) + caplog.set_level(logging.DEBUG, logger=logger.name) + run_clang_tidy( + filename="../../demo/demo.cpp", + file_obj={}, # only used when using a line filter + version="", # use whatever default is available on the test platform + checks="", # let clang-tidy use a .clang-tidy config file + lines_changed_only=0, # analyze complete file + database="../../demo", + repo_root="../../", # relative to this test directory + ) + matched_args = [] + for record in caplog.records: + msg_match = CLANG_TIDY_COMMAND.search(record.message) + if msg_match is not None: + matched_args = msg_match.group(0)[:-1].split()[1:] + matched_args = [m.replace("\\", "/") for m in matched_args] + assert "Error while trying to load a compilation database" not in record.message + assert matched_args == [ + "--export-fixes=clang_tidy_output.yml", + "-p", + "../../demo", + "../../demo/demo.cpp", + ] + + +def test_db_explicit_abs(caplog: LogCaptureFixture): + """test clang-tidy using a explicit absolute path to the compilation database.""" + os.chdir(os.path.split(__file__)[0]) + caplog.set_level(logging.DEBUG, logger=logger.name) + run_clang_tidy( + filename="../../demo/demo.cpp", + file_obj={}, # only used when using a line filter + version="", # use whatever default is available on the test platform + checks="", # let clang-tidy use a .clang-tidy config file + lines_changed_only=0, # analyze complete file + database=os.path.abspath("../../demo"), + repo_root="../../", # relative to this test directory + ) + matched_args = [] + for record in caplog.records: + msg_match = CLANG_TIDY_COMMAND.search(record.message) + if msg_match is not None: + matched_args = msg_match.group(0)[:-1].split()[1:] + matched_args = [m.replace("\\", "/") for m in matched_args] + assert "Error while trying to load a compilation database" not in record.message + assert matched_args == [ + "--export-fixes=clang_tidy_output.yml", + "-p", + os.path.abspath("../../demo").replace("\\", "/"), + "../../demo/demo.cpp", + ] + + +def test_db_explicit_rel_runner(caplog: LogCaptureFixture): + """test clang-tidy using a explicit relative path to the compilation database + with the added context of a RUNNER_WORKSPACE env var.""" + os.chdir(os.path.split(__file__)[0]) + cpp_linter.run.RUNNER_WORKSPACE = os.path.abspath("../../") + caplog.set_level(logging.DEBUG, logger=logger.name) + run_clang_tidy( + filename="../../demo/demo.cpp", + file_obj={}, # only used when using a line filter + version="", # use whatever default is available on the test platform + checks="", # let clang-tidy use a .clang-tidy config file + lines_changed_only=0, # analyze complete file + database="demo", + repo_root=".", # should be overridden by the RUNNER_WORKSPACE value + ) + matched_args = [] + for record in caplog.records: + msg_match = CLANG_TIDY_COMMAND.search(record.message) + if msg_match is not None: + matched_args = msg_match.group(0)[:-1].split()[1:] + matched_args = [m.replace("\\", "/") for m in matched_args] + assert "Error while trying to load a compilation database" not in record.message + assert matched_args == [ + "--export-fixes=clang_tidy_output.yml", + "-p", + os.path.abspath("../../demo").replace("\\", "/"), + "../../demo/demo.cpp", + ] + + +def test_db_explicit_abs_runner(caplog: LogCaptureFixture): + """test clang-tidy using a explicit absolute path to the compilation database + with the added context of a RUNNER_WORKSPACE env var.""" + os.chdir(os.path.split(__file__)[0]) + cpp_linter.run.RUNNER_WORKSPACE = "../../" + caplog.set_level(logging.DEBUG, logger=logger.name) + run_clang_tidy( + filename="../../demo/demo.cpp", + file_obj={}, # only used when using a line filter + version="", # use whatever default is available on the test platform + checks="", # let clang-tidy use a .clang-tidy config file + lines_changed_only=0, # analyze complete file + database=os.path.abspath("../../demo"), + repo_root=".", # should be overridden by the RUNNER_WORKSPACE value + ) + matched_args = [] + for record in caplog.records: + msg_match = CLANG_TIDY_COMMAND.search(record.message) + if msg_match is not None: + matched_args = msg_match.group(0)[:-1].split()[1:] + matched_args = [m.replace("\\", "/") for m in matched_args] + assert "Error while trying to load a compilation database" not in record.message + assert matched_args == [ + "--export-fixes=clang_tidy_output.yml", + "-p", + os.path.abspath("../../demo").replace("\\", "/"), + "../../demo/demo.cpp", + ] From b5c721fa97d6038353d7a4b465c6a275b3879293 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 18:33:23 -0700 Subject: [PATCH 11/76] switch to pre-commit; run pytest in a matrix --- .github/workflows/run-dev-tests.yml | 28 +++++++++++++++++-------- .pre-commit-config.yaml | 31 ++++++++++++++++++++++++++++ cpp_linter/__init__.py | 10 ++++----- cpp_linter/run.py | 32 ++++++++++++++++++----------- cpp_linter/thread_comments.py | 18 ++++++++-------- 5 files changed, 84 insertions(+), 35 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 4ae52588..0e10417c 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -6,14 +6,14 @@ on: - "**.py" - .pylintrc - mypy.ini - - ".github/workflows/run-pylint.yml" + - ".github/workflows/run-dev-tests.yml" pull_request: types: opened paths: - "**.py" - .pylintrc - mypy.ini - - ".github/workflows/run-pylint.yml" + - ".github/workflows/run-dev-tests.yml" jobs: check-python-sources: @@ -22,12 +22,22 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: 3.10 + - run: python3 -m pip install pre-commit + - run: pre-commit run --all-files + + run-pytest: + strategy: + fail-fast: false + matrix: + - os: ['windows-latest', ubuntu-latest] + - py: ['3.7', '3.8', '3.9', '3.10'] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.py }} - name: Install workflow deps - run: python3 -m pip install -r requirements.txt -r requirements-dev.txt . - - name: run pylint - run: | - pylint cpp_linter/** - pylint setup.py - - run: mypy cpp_linter/ + run: python3 -m pip install pytest . - run: pytest -vv tests diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..7fbad1a2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,31 @@ +repos: + - repo: https://github.com/python/black + rev: '22.6.0' + hooks: + - id: black + - repo: https://github.com/pycqa/pylint + rev: v2.14.5 + hooks: + - id: pylint + name: pylint (action code) + types: [python] + exclude: "^(docs/|tests/|setup.py$)" + additional_dependencies: [pyyaml, requests] + - id: pylint + name: pylint (test code) + description: Run pylint rules on "tests/*.py" files + types: [python] + files: "^tests/" + additional_dependencies: [pyyaml, requests] + - repo: local + # this is a "local" hook to run mypy (see https://pre-commit.com/#repository-local-hooks) + # because the mypy project doesn't seem to be compatible with pre-commit hooks + hooks: + - id: mypy + name: mypy + description: type checking with mypy tool + language: python + types: [python] + entry: mypy + exclude: "^(docs/|setup.py$)" + additional_dependencies: [mypy, types-pyyaml, types-requests, rich] diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index 9c117b61..33e31a09 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -11,9 +11,6 @@ from cpp_linter.clang_tidy_yml import YMLFixit from cpp_linter.clang_tidy import TidyNotification -# A type alias for custom line filter objects -LINE_FILTER = Dict[str, List[List[int]]] - FOUND_RICH_LIB = False try: from rich.logging import RichHandler @@ -37,10 +34,13 @@ IS_ON_RUNNER = bool(os.getenv("CI")) GITHUB_SHA = os.getenv("GITHUB_SHA", "") GITHUB_TOKEN = os.getenv("GITHUB_TOKEN", os.getenv("GIT_REST_API", "")) -API_HEADERS = {"Accept": "application/vnd.github.v3.text+json",} +API_HEADERS = { + "Accept": "application/vnd.github.v3.text+json", +} if GITHUB_TOKEN: API_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" + class Globals: """Global variables for re-use (non-constant).""" @@ -48,7 +48,7 @@ class Globals: """The accumulated output of clang-tidy (gets appended to OUTPUT)""" OUTPUT: str = "" """The accumulated body of the resulting comment that gets posted.""" - FILES: List[Dict[str, Union[str, int, LINE_FILTER]]] = [] + FILES: Union[List[Dict[str, Any]], Dict[str, Any]] = [] """The responding payload containing info about changed files.""" EVENT_PAYLOAD: Dict[str, Any] = {} """The parsed JSON of the event payload.""" diff --git a/cpp_linter/run.py b/cpp_linter/run.py index a14487a3..41db7916 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -16,7 +16,7 @@ import argparse import configparser import json -from typing import cast, List +from typing import cast, List, Dict, Any import requests from . import ( Globals, @@ -270,7 +270,7 @@ def filter_out_non_source_files( for file in ( Globals.FILES if GITHUB_EVENT_NAME == "pull_request" - else Globals.FILES["files"] # type: ignore + else cast(Dict[str, Any], Globals.FILES)["files"] ): if ( os.path.splitext(file["filename"])[1][1:] in ext_list @@ -310,8 +310,8 @@ def filter_out_non_source_files( ) if GITHUB_EVENT_NAME == "pull_request": Globals.FILES = files - else: - Globals.FILES["files"] = files # type: ignore + elif isinstance(Globals.FILES, dict): + Globals.FILES["files"] = files if not os.getenv("CI"): # if not executed on a github runner with open(".changed_files.json", "w", encoding="utf-8") as temp: # dump altered json of changed files @@ -333,7 +333,7 @@ def verify_files_are_present() -> None: for file in ( Globals.FILES if GITHUB_EVENT_NAME == "pull_request" - else Globals.FILES["files"] # type: ignore + else cast(Dict[str, Any], Globals.FILES)["files"] ): file_name = file["filename"].replace("/", os.sep) if not os.path.exists(file_name): @@ -381,12 +381,16 @@ def list_source_files(ext_list: list, ignored_paths: list, not_ignored: list) -> if not is_file_in_list( ignored_paths, file_path, "ignored" ) or is_file_in_list(not_ignored, file_path, "not ignored"): - Globals.FILES.append({"filename": file_path}) + cast(List[Dict[str, Any]], Globals.FILES).append( + {"filename": file_path} + ) if Globals.FILES: logger.info( "Giving attention to the following files:\n\t%s", - "\n\t".join([f["filename"] for f in Globals.FILES]), # type: ignore + "\n\t".join( + [f["filename"] for f in cast(List[Dict[str, Any]], Globals.FILES)] + ), ) else: logger.info("No source files found.") # this might need to be warning @@ -396,7 +400,7 @@ def list_source_files(ext_list: list, ignored_paths: list, not_ignored: list) -> def run_clang_tidy( filename: str, - file_obj: dict, + file_obj: Dict[str, Any], version: str, checks: str, lines_changed_only: int, @@ -428,7 +432,7 @@ def run_clang_tidy( if os.path.exists(version + "\\bin"): cmds[0] = f"{version}\\bin\\clang-tidy.exe" elif not version.isdigit(): - logger.warning("ignoring invalid version number %s.", version) + logger.warning("ignoring invalid version number '%s'.", version) cmds[0] = "clang-tidy" if checks: cmds.append(f"-checks={checks}") @@ -463,7 +467,11 @@ def run_clang_tidy( def run_clang_format( - filename: str, file_obj: dict, version: str, style: str, lines_changed_only: int + filename: str, + file_obj: Dict[str, Any], + version: str, + style: str, + lines_changed_only: int, ) -> None: """Run clang-format on a certain file @@ -527,7 +535,7 @@ def capture_clang_tools_output( for file in ( Globals.FILES if GITHUB_EVENT_NAME == "pull_request" or isinstance(Globals.FILES, list) - else Globals.FILES["files"] # type: ignore + else Globals.FILES["files"] ): filename = cast(str, file["filename"]) if not os.path.exists(filename): @@ -740,7 +748,7 @@ def make_annotations( files = ( Globals.FILES if GITHUB_EVENT_NAME == "pull_request" - else Globals.FILES["files"] # type: ignore + else cast(Dict[str, Any], Globals.FILES)["files"] ) for advice, file in zip(GlobalParser.format_advice, files): if advice.replaced_lines: diff --git a/cpp_linter/thread_comments.py b/cpp_linter/thread_comments.py index 8c3f3348..8491318b 100644 --- a/cpp_linter/thread_comments.py +++ b/cpp_linter/thread_comments.py @@ -1,6 +1,6 @@ """A module to house the various functions for traversing/adjusting comments""" import os -from typing import Union, cast, List, Optional +from typing import Union, cast, List, Optional, Dict, Any import json import requests from . import Globals, GlobalParser, logger, API_HEADERS, GITHUB_SHA, log_response_msg @@ -59,7 +59,9 @@ def aggregate_tidy_advice() -> list: body += diag.name + "**\n>" + diag.message # get original code - filename = cast(str, Globals.FILES[index]["filename"]).replace("/", os.sep) + filename = cast(List[Dict[str, str]], Globals.FILES)[index][ + "filename" + ].replace("/", os.sep) if not os.path.exists(filename): # the file had to be downloaded (no git checkout). # thus use only the filename (without the path to the file) @@ -113,7 +115,9 @@ def aggregate_format_advice(lines_changed_only: int = 1) -> list: for index, fmt_advice in enumerate(GlobalParser.format_advice): # get original code - filename = cast(str, Globals.FILES[index]["filename"]).replace("/", os.sep) + filename = cast(List[Dict[str, str]], Globals.FILES)[index]["filename"].replace( + "/", os.sep + ) if not os.path.exists(filename): # the file had to be downloaded (no git checkout). # thus use only the filename (without the path to the file) @@ -126,13 +130,9 @@ def aggregate_format_advice(lines_changed_only: int = 1) -> list: line = "" # the line that concerns the fix for fixed_line in fmt_advice.replaced_lines: # clang-format can include advice that starts/ends outside the diff's domain - ranges: List[List[int]] = Globals.FILES[index][ # type: ignore + ranges: List[List[int]] = cast(List[Dict[str, Any]], Globals.FILES)[index][ "line_filter" - ][ - "diff_chunks" # type: ignore - if lines_changed_only == 1 - else "lines_added" - ] + ]["diff_chunks" if lines_changed_only == 1 else "lines_added"] for scope in ranges: if fixed_line.line in range(scope[0], scope[1] + 1): break From 4b4e18ad8fe4141d596d31d6bd13bcf1ef179e65 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 18:51:43 -0700 Subject: [PATCH 12/76] parametrize unit tests --- .pre-commit-config.yaml | 8 +- tests/database_path/test_database_path.py | 189 ++++++------------ .../test_lines_changed_only.py | 81 +++----- tests/test_cli_args.py | 183 +++++++---------- 4 files changed, 160 insertions(+), 301 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7fbad1a2..5bdd6452 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,12 +11,6 @@ repos: types: [python] exclude: "^(docs/|tests/|setup.py$)" additional_dependencies: [pyyaml, requests] - - id: pylint - name: pylint (test code) - description: Run pylint rules on "tests/*.py" files - types: [python] - files: "^tests/" - additional_dependencies: [pyyaml, requests] - repo: local # this is a "local" hook to run mypy (see https://pre-commit.com/#repository-local-hooks) # because the mypy project doesn't seem to be compatible with pre-commit hooks @@ -28,4 +22,4 @@ repos: types: [python] entry: mypy exclude: "^(docs/|setup.py$)" - additional_dependencies: [mypy, types-pyyaml, types-requests, rich] + additional_dependencies: [mypy, types-pyyaml, types-requests, rich, requests, pytest, pyyaml, '.'] diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py index 8d7cc325..477af1e5 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/database_path/test_database_path.py @@ -1,8 +1,9 @@ """Tests specific to specifying the compilation database path.""" import os +from typing import Optional, List import logging import re -from pytest import LogCaptureFixture +import pytest from cpp_linter import logger import cpp_linter.run from cpp_linter.run import run_clang_tidy @@ -10,143 +11,73 @@ CLANG_TIDY_COMMAND = re.compile(r"\"clang-tidy(.*)(?:\")") -def test_db_implicit(caplog: LogCaptureFixture): +@pytest.mark.parametrize( + "database,repo_root,runner,expected_args", + [ + # implicit path to the compilation database + ("", "../../", "", ["../../demo/demo.cpp"]), + # explicit relative path to the compilation database + ("../../demo", "../../", "", ["-p", "../../demo", "../../demo/demo.cpp"]), + # explicit absolute path to the compilation database + ( + os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + "../../", + "", + [ + "-p", + os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + "../../demo/demo.cpp", + ], + ), + # explicit relative path to the compilation database w/ RUNNER_WORKSPACE + ( + "demo", + ".", + os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../")), + [ + "-p", + os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + "../../demo/demo.cpp", + ], + ), + # explicit absolute path to the compilation database w/ RUNNER_WORKSPACE + ( + os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + ".", + "../../", + [ + "-p", + os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + "../../demo/demo.cpp", + ], + ), + ], +) +def test_db_detection( + caplog: pytest.LogCaptureFixture, + database: str, + repo_root: str, + runner: Optional[str], + expected_args: List[str], +): """test clang-tidy using a implicit path to the compilation database.""" os.chdir(os.path.split(__file__)[0]) + if runner: + cpp_linter.run.RUNNER_WORKSPACE = runner caplog.set_level(logging.DEBUG, logger=logger.name) run_clang_tidy( - filename="../../demo/demo.cpp", - file_obj={}, # only used when using a line filter - version="", # use whatever default is available on the test platform + filename=("../../demo/demo.cpp").replace("/", os.sep), + file_obj={}, # only used when filtering lines + version="", checks="", # let clang-tidy use a .clang-tidy config file lines_changed_only=0, # analyze complete file - database="", - repo_root="../../", # relative to this test directory + database=database.replace("/", os.sep), + repo_root=repo_root.replace("/", os.sep), ) matched_args = [] for record in caplog.records: msg_match = CLANG_TIDY_COMMAND.search(record.message) if msg_match is not None: - matched_args = msg_match.group(0)[:-1].split()[1:] - matched_args = [m.replace("\\", "/") for m in matched_args] + matched_args = msg_match.group(0)[:-1].split()[2:] assert "Error while trying to load a compilation database" not in record.message - assert matched_args == [ - "--export-fixes=clang_tidy_output.yml", - "../../demo/demo.cpp", - ] - - -def test_db_explicit_rel(caplog: LogCaptureFixture): - """test clang-tidy using a explicit relative path to the compilation database.""" - os.chdir(os.path.split(__file__)[0]) - caplog.set_level(logging.DEBUG, logger=logger.name) - run_clang_tidy( - filename="../../demo/demo.cpp", - file_obj={}, # only used when using a line filter - version="", # use whatever default is available on the test platform - checks="", # let clang-tidy use a .clang-tidy config file - lines_changed_only=0, # analyze complete file - database="../../demo", - repo_root="../../", # relative to this test directory - ) - matched_args = [] - for record in caplog.records: - msg_match = CLANG_TIDY_COMMAND.search(record.message) - if msg_match is not None: - matched_args = msg_match.group(0)[:-1].split()[1:] - matched_args = [m.replace("\\", "/") for m in matched_args] - assert "Error while trying to load a compilation database" not in record.message - assert matched_args == [ - "--export-fixes=clang_tidy_output.yml", - "-p", - "../../demo", - "../../demo/demo.cpp", - ] - - -def test_db_explicit_abs(caplog: LogCaptureFixture): - """test clang-tidy using a explicit absolute path to the compilation database.""" - os.chdir(os.path.split(__file__)[0]) - caplog.set_level(logging.DEBUG, logger=logger.name) - run_clang_tidy( - filename="../../demo/demo.cpp", - file_obj={}, # only used when using a line filter - version="", # use whatever default is available on the test platform - checks="", # let clang-tidy use a .clang-tidy config file - lines_changed_only=0, # analyze complete file - database=os.path.abspath("../../demo"), - repo_root="../../", # relative to this test directory - ) - matched_args = [] - for record in caplog.records: - msg_match = CLANG_TIDY_COMMAND.search(record.message) - if msg_match is not None: - matched_args = msg_match.group(0)[:-1].split()[1:] - matched_args = [m.replace("\\", "/") for m in matched_args] - assert "Error while trying to load a compilation database" not in record.message - assert matched_args == [ - "--export-fixes=clang_tidy_output.yml", - "-p", - os.path.abspath("../../demo").replace("\\", "/"), - "../../demo/demo.cpp", - ] - - -def test_db_explicit_rel_runner(caplog: LogCaptureFixture): - """test clang-tidy using a explicit relative path to the compilation database - with the added context of a RUNNER_WORKSPACE env var.""" - os.chdir(os.path.split(__file__)[0]) - cpp_linter.run.RUNNER_WORKSPACE = os.path.abspath("../../") - caplog.set_level(logging.DEBUG, logger=logger.name) - run_clang_tidy( - filename="../../demo/demo.cpp", - file_obj={}, # only used when using a line filter - version="", # use whatever default is available on the test platform - checks="", # let clang-tidy use a .clang-tidy config file - lines_changed_only=0, # analyze complete file - database="demo", - repo_root=".", # should be overridden by the RUNNER_WORKSPACE value - ) - matched_args = [] - for record in caplog.records: - msg_match = CLANG_TIDY_COMMAND.search(record.message) - if msg_match is not None: - matched_args = msg_match.group(0)[:-1].split()[1:] - matched_args = [m.replace("\\", "/") for m in matched_args] - assert "Error while trying to load a compilation database" not in record.message - assert matched_args == [ - "--export-fixes=clang_tidy_output.yml", - "-p", - os.path.abspath("../../demo").replace("\\", "/"), - "../../demo/demo.cpp", - ] - - -def test_db_explicit_abs_runner(caplog: LogCaptureFixture): - """test clang-tidy using a explicit absolute path to the compilation database - with the added context of a RUNNER_WORKSPACE env var.""" - os.chdir(os.path.split(__file__)[0]) - cpp_linter.run.RUNNER_WORKSPACE = "../../" - caplog.set_level(logging.DEBUG, logger=logger.name) - run_clang_tidy( - filename="../../demo/demo.cpp", - file_obj={}, # only used when using a line filter - version="", # use whatever default is available on the test platform - checks="", # let clang-tidy use a .clang-tidy config file - lines_changed_only=0, # analyze complete file - database=os.path.abspath("../../demo"), - repo_root=".", # should be overridden by the RUNNER_WORKSPACE value - ) - matched_args = [] - for record in caplog.records: - msg_match = CLANG_TIDY_COMMAND.search(record.message) - if msg_match is not None: - matched_args = msg_match.group(0)[:-1].split()[1:] - matched_args = [m.replace("\\", "/") for m in matched_args] - assert "Error while trying to load a compilation database" not in record.message - assert matched_args == [ - "--export-fixes=clang_tidy_output.yml", - "-p", - os.path.abspath("../../demo").replace("\\", "/"), - "../../demo/demo.cpp", - ] + assert matched_args == [a.replace("/", os.sep) for a in expected_args] diff --git a/tests/lines_changed_only/test_lines_changed_only.py b/tests/lines_changed_only/test_lines_changed_only.py index 91871d9c..da637ea8 100644 --- a/tests/lines_changed_only/test_lines_changed_only.py +++ b/tests/lines_changed_only/test_lines_changed_only.py @@ -1,10 +1,11 @@ """Various tests realated to the ``lines_changed_only`` option.""" import os import logging +from typing import Dict, Any, cast from pathlib import Path import json import re -from pytest import LogCaptureFixture +import pytest import cpp_linter from cpp_linter.clang_format_xml import parse_format_replacements_xml from cpp_linter.run import ( @@ -46,66 +47,40 @@ def test_lines_changed_only(): raise RuntimeError("test failed to find files") -def test_run_clang_format_diff_only(caplog: LogCaptureFixture): - """Using the output (expected_result.json) from ``test_lines_changed_only()``, - run clang-format with lines-changed-only set to 'true'. - - This will make sure clang-format warnings are filtered to - only lines in the diff's chunks.""" - # log_commander.setLevel(logging.INFO) - caplog.set_level(logging.INFO, logger=log_commander.name) - lines_changed_only = 1 # 1 means entire diff chunks - style = "file" # this test includes a custom style guide - os.chdir(os.path.split(__file__)[0]) - cpp_linter.Globals.FILES = json.loads( - Path("expected_result.json").read_text(encoding="utf-8") - ) - verify_files_are_present() - for file in cpp_linter.Globals.FILES["files"]: - filename: str = file["filename"] - run_clang_format( - filename=filename, - file_obj=file, - version="", - style=style, - lines_changed_only=lines_changed_only, - ) - if os.path.getsize("clang_format_output.xml"): - parse_format_replacements_xml(filename.replace("/", os.sep)) - make_annotations( - style=style, file_annotations=True, lines_changed_only=lines_changed_only - ) - record_lines = re.compile(r"\(lines (.*)\)") - record_file = re.compile(r"File (.*)\s") - for record in caplog.records: - if record_lines.search(record.message) is not None: - lines = [ - int(l.strip()) - for l in record_lines.sub("\\1", record.message).split(",") - ] - filename = record_file.sub("\\1", record.message) - for file in cpp_linter.Globals.FILES["files"]: - if file["filename"] == filename: - ranges = file["line_filter"]["diff_chunks"] - for line in lines: - assert line in [range(r[0], r[1]) for r in ranges] - break +TEST_REPO = re.compile( + "https://api.github.com/repos/(?:\\w|\\-|_)+/((?:\\w|\\-|_)+)/.*" +) -def test_run_clang_format_diff_adds(caplog: LogCaptureFixture): +@pytest.mark.parametrize("lines_changed_only", [1, 2]) +def test_run_clang_format_on_diff( + caplog: pytest.LogCaptureFixture, lines_changed_only: int +): """Using the output (expected_result.json) from ``test_lines_changed_only()``, - run clang-format with lines-changed-only set to 'true'. + run clang-format with lines-changed-only set to accordingly. + + tested input values: + + - 1 = means entire diff chunks + - 2 = means only lines in diff containing additions This will make sure clang-format warnings are filtered to only lines in the diff containing additions.""" - # log_commander.setLevel(logging.INFO) caplog.set_level(logging.INFO, logger=log_commander.name) - lines_changed_only = 2 # 2 means only lines in diff containing additions style = "file" # this test includes a custom style guide - os.chdir(os.path.split(__file__)[0]) - cpp_linter.Globals.FILES = json.loads( - Path("expected_result.json").read_text(encoding="utf-8") + range_focus = "lines_added" + if lines_changed_only == 1: + range_focus = "diff_chunks" + test_root = os.path.split(__file__)[0] + os.chdir(test_root) + cpp_linter.Globals.FILES = cast( + Dict[str, Any], + json.loads(Path("expected_result.json").read_text(encoding="utf-8")), ) + repo_root = TEST_REPO.sub("\\1", cpp_linter.Globals.FILES["url"]) + if not os.path.exists(repo_root): + os.mkdir(repo_root) + os.chdir(os.path.join(test_root, repo_root)) verify_files_are_present() for file in cpp_linter.Globals.FILES["files"]: filename: str = file["filename"] @@ -132,7 +107,7 @@ def test_run_clang_format_diff_adds(caplog: LogCaptureFixture): filename = record_file.sub("\\1", record.message) for file in cpp_linter.Globals.FILES["files"]: if file["filename"] == filename: - ranges = file["line_filter"]["lines_added"] + ranges = file["line_filter"][range_focus] for line in lines: assert line in [range(r[0], r[1]) for r in ranges] break diff --git a/tests/test_cli_args.py b/tests/test_cli_args.py index a198786c..764cb6a9 100644 --- a/tests/test_cli_args.py +++ b/tests/test_cli_args.py @@ -1,116 +1,75 @@ """Tests related parsing input from CLI arguments.""" -from typing import List +from typing import List, Union +import pytest from cpp_linter.run import cli_arg_parser -class TestArgs: - """Grouped tests using a common namespace declaration""" - - class Args: - """A pseudo namespace declaration. Each attribute is initialized with the - corresponding CLI arg's default value.""" - - verbosity: int = 10 - database: str = "" - style: str = "llvm" - tidy_checks: str = ( - "boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*," - "clang-analyzer-*,cppcoreguidelines-*" - ) - version: str = "" - extensions: List[str] = [ - "c", - "h", - "C", - "H", - "cpp", - "hpp", - "cc", - "hh", - "c++", - "h++", - "cxx", - "hxx", - ] - repo_root: str = "." - ignore: str = ".github" - lines_changed_only: int = 0 - files_changed_only: bool = False - thread_comments: bool = False - file_annotations: bool = True - - def test_defaults(self): - """test default values""" - args = cli_arg_parser.parse_args("") - expected = self.Args() - for key in args.__dict__.keys(): - assert args.__dict__[key] == getattr(expected, key) - - def test_verbosity(self): - """test verbosity option""" - args = cli_arg_parser.parse_args(["--verbosity=20"]) - assert args.verbosity == 20 - - def test_database(self): - """test database option""" - args = cli_arg_parser.parse_args(["--database=build"]) - assert args.database == "build" - - def test_style(self): - """test style option""" - args = cli_arg_parser.parse_args(["--style=file"]) - assert args.style == "file" - - def test_tidy_checks(self): - """test tidy-checks option""" - args = cli_arg_parser.parse_args(["--tidy-checks=-*"]) - assert args.tidy_checks == "-*" - - def test_version(self): - """test version option""" - args = cli_arg_parser.parse_args(["--version=14"]) - assert args.version == "14" - - def test_extensions(self): - """test extensions option""" - args = cli_arg_parser.parse_args(["--extensions", ".cpp, .h"]) - assert args.extensions == ["cpp", "h"] - args = cli_arg_parser.parse_args(["--extensions=cxx, .hpp"]) - assert args.extensions == ["cxx", "hpp"] - - def test_repo_root(self): - """test repo-root option""" - args = cli_arg_parser.parse_args(["--repo-root=src"]) - assert args.repo_root == "src" - - def test_ignore(self): - """test ignore option""" - args = cli_arg_parser.parse_args(["--ignore=!src|"]) - assert args.ignore == "!src|" - - def test_lines_changed_only(self): - """test lines-changed-only option""" - args = cli_arg_parser.parse_args(["--lines-changed-only=True"]) - assert args.lines_changed_only == 1 - args = cli_arg_parser.parse_args(["--lines-changed-only=strict"]) - assert args.lines_changed_only == 2 - - def test_files_changed_only(self): - """test files-changed-only option""" - args = cli_arg_parser.parse_args(["--files-changed-only=True"]) - assert args.files_changed_only is True - - def test_thread_comments(self): - """test thread-comments option""" - args = cli_arg_parser.parse_args(["--thread-comments=True"]) - assert args.thread_comments is True - - def test_file_annotations(self): - """test file-annotations option""" - args = cli_arg_parser.parse_args(["--file-annotations=False"]) - assert args.file_annotations is False - - -if __name__ == "__main__": - test = TestArgs() - test.test_defaults() +class Args: + """A pseudo namespace declaration. Each attribute is initialized with the + corresponding CLI arg's default value.""" + + verbosity: int = 10 + database: str = "" + style: str = "llvm" + tidy_checks: str = ( + "boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*," + "clang-analyzer-*,cppcoreguidelines-*" + ) + version: str = "" + extensions: List[str] = [ + "c", + "h", + "C", + "H", + "cpp", + "hpp", + "cc", + "hh", + "c++", + "h++", + "cxx", + "hxx", + ] + repo_root: str = "." + ignore: str = ".github" + lines_changed_only: int = 0 + files_changed_only: bool = False + thread_comments: bool = False + file_annotations: bool = True + + +def test_defaults(): + """test default values""" + args = cli_arg_parser.parse_args("") + for key in args.__dict__.keys(): + assert args.__dict__[key] == getattr(Args, key) + + +@pytest.mark.parametrize( + "arg_name,arg_value,attr_name,attr_value", + [ + ("verbosity", "20", "verbosity", 20), + ("database", "build", "database", "build"), + ("style", "file", "style", "file"), + ("tidy-checks", "-*", "tidy_checks", "-*"), + ("version", "14", "version", "14"), + ("extensions", ".cpp, .h", "extensions", ["cpp", "h"]), + ("extensions", "cxx,.hpp", "extensions", ["cxx", "hpp"]), + ("repo-root", "src", "repo_root", "src"), + ("ignore", "!src|", "ignore", "!src|"), + ("lines-changed-only", "True", "lines_changed_only", 1), + ("lines-changed-only", "stricT", "lines_changed_only", 2), + ("files-changed-only", "True", "files_changed_only", True), + ("thread-comments", "True", "thread_comments", True), + ("file-annotations", "False", "file_annotations", False), + ], +) +def test_arg_parser( + arg_name: str, + arg_value: str, + attr_name: str, + attr_value: Union[int, str, List[str], bool], +): + """parameterized test of specific args compared to their parsed value""" + args = cli_arg_parser.parse_args([f"--{arg_name}={arg_value}"]) + assert getattr(args, attr_name) == attr_value From b48ac79c127757c4d437e7f0d8d250b5c90dd8e1 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 18:53:44 -0700 Subject: [PATCH 13/76] fix changes to dev-test yaml --- .github/workflows/run-dev-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 0e10417c..6845ad06 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -30,8 +30,8 @@ jobs: strategy: fail-fast: false matrix: - - os: ['windows-latest', ubuntu-latest] - - py: ['3.7', '3.8', '3.9', '3.10'] + os: ['windows-latest', ubuntu-latest] + py: ['3.7', '3.8', '3.9', '3.10'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 From b0c3ebba0a66936f3b51d4635c023165da96ca41 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 19:41:11 -0700 Subject: [PATCH 14/76] make database path absolute --- .github/workflows/run-dev-tests.yml | 2 +- cpp_linter/run.py | 2 +- tests/database_path/test_database_path.py | 11 ++++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 6845ad06..c7051b19 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: 3.10 + python-version: '3.10' - run: python3 -m pip install pre-commit - run: pre-commit run --all-files diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 41db7916..e2d2f7d2 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -444,7 +444,7 @@ def run_clang_tidy( path_to_db += os.sep + repo_root cmds.append(os.path.join(path_to_db, database)) else: - cmds.append(database) + cmds.append(os.path.abspath(os.path.join(repo_root, database))) if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" line_ranges = dict(name=filename, lines=file_obj["line_filter"][ranges]) diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py index 477af1e5..4244da31 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/database_path/test_database_path.py @@ -17,7 +17,16 @@ # implicit path to the compilation database ("", "../../", "", ["../../demo/demo.cpp"]), # explicit relative path to the compilation database - ("../../demo", "../../", "", ["-p", "../../demo", "../../demo/demo.cpp"]), + ( + "../../demo", + ".", + "", + [ + "-p", + os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + "../../demo/demo.cpp", + ], + ), # explicit absolute path to the compilation database ( os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), From 8c89f4504753018d40eee11f6cb9bc71a0af4a03 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 20:52:06 -0700 Subject: [PATCH 15/76] use pathlib to resolve() relative paths in test --- tests/database_path/test_database_path.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py index 4244da31..bd516150 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/database_path/test_database_path.py @@ -1,6 +1,7 @@ """Tests specific to specifying the compilation database path.""" import os from typing import Optional, List +from pathlib import Path import logging import re import pytest @@ -23,18 +24,18 @@ "", [ "-p", - os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + str(Path(Path(__file__).parent / "../../demo").resolve()), "../../demo/demo.cpp", ], ), # explicit absolute path to the compilation database ( - os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + str(Path(Path(__file__).parent / "../../demo")), "../../", "", [ "-p", - os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + str(Path(Path(__file__).parent / "../../demo").resolve()), "../../demo/demo.cpp", ], ), @@ -42,21 +43,21 @@ ( "demo", ".", - os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../")), + str(Path(Path(__file__).parent / "../../").resolve()), [ "-p", - os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + str(Path(Path(__file__).parent / "../../demo").resolve()), "../../demo/demo.cpp", ], ), # explicit absolute path to the compilation database w/ RUNNER_WORKSPACE ( - os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), - ".", - "../../", + str(Path(Path(__file__).parent / "../../demo").resolve()), + ".", # overridden by abs path to db + str(Path(Path(__file__).parent / "../../").resolve()), [ "-p", - os.path.abspath(os.path.join(os.path.split(__file__)[0], "../../demo")), + str(Path(Path(__file__).parent / "../../demo").resolve()), "../../demo/demo.cpp", ], ), @@ -70,7 +71,7 @@ def test_db_detection( expected_args: List[str], ): """test clang-tidy using a implicit path to the compilation database.""" - os.chdir(os.path.split(__file__)[0]) + os.chdir(str(Path(__file__).parent)) if runner: cpp_linter.run.RUNNER_WORKSPACE = runner caplog.set_level(logging.DEBUG, logger=logger.name) From 6fe57ef5bc728c66611dc128dc469437d560d0d3 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 22:08:26 -0700 Subject: [PATCH 16/76] let db path be independent of repo-root w/o docker --- cpp_linter/run.py | 2 +- tests/database_path/test_database_path.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index e2d2f7d2..4d972faf 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -444,7 +444,7 @@ def run_clang_tidy( path_to_db += os.sep + repo_root cmds.append(os.path.join(path_to_db, database)) else: - cmds.append(os.path.abspath(os.path.join(repo_root, database))) + cmds.append(os.path.abspath(database)) if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" line_ranges = dict(name=filename, lines=file_obj["line_filter"][ranges]) diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py index bd516150..ed183a79 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/database_path/test_database_path.py @@ -20,8 +20,8 @@ # explicit relative path to the compilation database ( "../../demo", - ".", - "", + ".", # only used if RUNNER_WORKSPACE is given + "", # RUNNER_WORKSPACE not set [ "-p", str(Path(Path(__file__).parent / "../../demo").resolve()), @@ -30,9 +30,9 @@ ), # explicit absolute path to the compilation database ( - str(Path(Path(__file__).parent / "../../demo")), - "../../", - "", + str(Path(Path(__file__).parent / "../../demo").resolve()), + ".", # only used if RUNNER_WORKSPACE is given + "", # RUNNER_WORKSPACE not set [ "-p", str(Path(Path(__file__).parent / "../../demo").resolve()), @@ -42,7 +42,7 @@ # explicit relative path to the compilation database w/ RUNNER_WORKSPACE ( "demo", - ".", + ".", # only used if db path is abs str(Path(Path(__file__).parent / "../../").resolve()), [ "-p", From c0b20bcfedf54bf0cc7bf437cda57c358236a312 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 22:13:49 -0700 Subject: [PATCH 17/76] this fails locally --- tests/database_path/test_database_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py index ed183a79..1dd817b3 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/database_path/test_database_path.py @@ -19,7 +19,7 @@ ("", "../../", "", ["../../demo/demo.cpp"]), # explicit relative path to the compilation database ( - "../../demo", + "demo", ".", # only used if RUNNER_WORKSPACE is given "", # RUNNER_WORKSPACE not set [ From cf295d6f4c77f994e22eb14679ae074c6fbc5e42 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 22:20:52 -0700 Subject: [PATCH 18/76] show me value for RUNNER_WORKSPACE --- cpp_linter/run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 4d972faf..5fa33bda 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -438,6 +438,7 @@ def run_clang_tidy( cmds.append(f"-checks={checks}") if database: cmds.append("-p") + logger.debug("RUNNER_WORKSPACE = %s", RUNNER_WORKSPACE) if RUNNER_WORKSPACE and not os.path.isabs(database): path_to_db = RUNNER_WORKSPACE if repo_root and repo_root != ".": From a656f059f0a38342ba57b19b74afd05cafe7bcd4 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 22:35:16 -0700 Subject: [PATCH 19/76] use gh workspace if not in docker env --- cpp_linter/run.py | 13 ++++++++----- tests/database_path/test_database_path.py | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 5fa33bda..f4ee6f0e 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -39,8 +39,11 @@ GITHUB_API_URL = os.getenv("GITHUB_API_URL", "https://api.github.com") GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY", "") GITHUB_EVENT_NAME = os.getenv("GITHUB_EVENT_NAME", "unknown") -RUNNER_WORKSPACE = os.getenv("RUNNER_WORKSPACE", "") - +GITHUB_WORKSPACE = os.getenv("GITHUB_WORKSPACE", "") +IS_USING_DOCKER = os.getenv("CLANG_VERSIONS", "") +RUNNER_WORKSPACE = ( + os.getenv("RUNNER_WORKSPACE", "") if not IS_USING_DOCKER else GITHUB_WORKSPACE +) IS_ON_WINDOWS = sys.platform.startswith("win32") # setup CLI args @@ -439,13 +442,13 @@ def run_clang_tidy( if database: cmds.append("-p") logger.debug("RUNNER_WORKSPACE = %s", RUNNER_WORKSPACE) - if RUNNER_WORKSPACE and not os.path.isabs(database): + if not os.path.isabs(database): path_to_db = RUNNER_WORKSPACE if repo_root and repo_root != ".": path_to_db += os.sep + repo_root - cmds.append(os.path.join(path_to_db, database)) + cmds.append(os.path.abspath(os.path.join(path_to_db, database))) else: - cmds.append(os.path.abspath(database)) + cmds.append(database) if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" line_ranges = dict(name=filename, lines=file_obj["line_filter"][ranges]) diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py index 1dd817b3..ed183a79 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/database_path/test_database_path.py @@ -19,7 +19,7 @@ ("", "../../", "", ["../../demo/demo.cpp"]), # explicit relative path to the compilation database ( - "demo", + "../../demo", ".", # only used if RUNNER_WORKSPACE is given "", # RUNNER_WORKSPACE not set [ From b2c751a40715624efc3db059ceda4c47562b36bd Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 23:10:42 -0700 Subject: [PATCH 20/76] simplify the paths' concatenation --- cpp_linter/run.py | 11 ++-- tests/database_path/test_database_path.py | 64 +++++------------------ 2 files changed, 18 insertions(+), 57 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index f4ee6f0e..68d5e188 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -441,14 +441,11 @@ def run_clang_tidy( cmds.append(f"-checks={checks}") if database: cmds.append("-p") - logger.debug("RUNNER_WORKSPACE = %s", RUNNER_WORKSPACE) if not os.path.isabs(database): - path_to_db = RUNNER_WORKSPACE - if repo_root and repo_root != ".": - path_to_db += os.sep + repo_root - cmds.append(os.path.abspath(os.path.join(path_to_db, database))) - else: - cmds.append(database) + database = os.path.abspath( + os.path.join(RUNNER_WORKSPACE, repo_root, database) + ) + cmds.append(database) if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" line_ranges = dict(name=filename, lines=file_obj["line_filter"][ranges]) diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py index ed183a79..d4cb48ba 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/database_path/test_database_path.py @@ -11,78 +11,41 @@ CLANG_TIDY_COMMAND = re.compile(r"\"clang-tidy(.*)(?:\")") +ABS_DB_PATH = str(Path(Path(__file__).parent / "../../demo").resolve()) + @pytest.mark.parametrize( - "database,repo_root,runner,expected_args", + "database,expected_args", [ # implicit path to the compilation database - ("", "../../", "", ["../../demo/demo.cpp"]), + ("", []), # explicit relative path to the compilation database - ( - "../../demo", - ".", # only used if RUNNER_WORKSPACE is given - "", # RUNNER_WORKSPACE not set - [ - "-p", - str(Path(Path(__file__).parent / "../../demo").resolve()), - "../../demo/demo.cpp", - ], - ), + ("../../demo", ["-p", ABS_DB_PATH]), # explicit absolute path to the compilation database - ( - str(Path(Path(__file__).parent / "../../demo").resolve()), - ".", # only used if RUNNER_WORKSPACE is given - "", # RUNNER_WORKSPACE not set - [ - "-p", - str(Path(Path(__file__).parent / "../../demo").resolve()), - "../../demo/demo.cpp", - ], - ), - # explicit relative path to the compilation database w/ RUNNER_WORKSPACE - ( - "demo", - ".", # only used if db path is abs - str(Path(Path(__file__).parent / "../../").resolve()), - [ - "-p", - str(Path(Path(__file__).parent / "../../demo").resolve()), - "../../demo/demo.cpp", - ], - ), - # explicit absolute path to the compilation database w/ RUNNER_WORKSPACE - ( - str(Path(Path(__file__).parent / "../../demo").resolve()), - ".", # overridden by abs path to db - str(Path(Path(__file__).parent / "../../").resolve()), - [ - "-p", - str(Path(Path(__file__).parent / "../../demo").resolve()), - "../../demo/demo.cpp", - ], - ), + (ABS_DB_PATH, ["-p", ABS_DB_PATH]), ], ) def test_db_detection( caplog: pytest.LogCaptureFixture, database: str, - repo_root: str, - runner: Optional[str], expected_args: List[str], ): """test clang-tidy using a implicit path to the compilation database.""" os.chdir(str(Path(__file__).parent)) - if runner: - cpp_linter.run.RUNNER_WORKSPACE = runner + demo_src = "../../demo/demo.cpp" + rel_root = str(Path(*Path(__file__).parts[-2:])) + cpp_linter.run.RUNNER_WORKSPACE = str( + Path(Path(__file__).parent / "../../").resolve() + ) caplog.set_level(logging.DEBUG, logger=logger.name) run_clang_tidy( - filename=("../../demo/demo.cpp").replace("/", os.sep), + filename=(demo_src).replace("/", os.sep), file_obj={}, # only used when filtering lines version="", checks="", # let clang-tidy use a .clang-tidy config file lines_changed_only=0, # analyze complete file database=database.replace("/", os.sep), - repo_root=repo_root.replace("/", os.sep), + repo_root=rel_root.replace("/", os.sep), ) matched_args = [] for record in caplog.records: @@ -90,4 +53,5 @@ def test_db_detection( if msg_match is not None: matched_args = msg_match.group(0)[:-1].split()[2:] assert "Error while trying to load a compilation database" not in record.message + expected_args.append(demo_src) assert matched_args == [a.replace("/", os.sep) for a in expected_args] From 454e158d1ac1cb33d1b940cb24cba334cb7d4969 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 23:40:57 -0700 Subject: [PATCH 21/76] fix assignment of `Globals.FILES` --- cpp_linter/run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 68d5e188..80b3db4e 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -313,8 +313,8 @@ def filter_out_non_source_files( ) if GITHUB_EVENT_NAME == "pull_request": Globals.FILES = files - elif isinstance(Globals.FILES, dict): - Globals.FILES["files"] = files + else: + cast(Dict[str, Any], Globals.FILES)["files"] = files if not os.getenv("CI"): # if not executed on a github runner with open(".changed_files.json", "w", encoding="utf-8") as temp: # dump altered json of changed files From 6911a49982324d49db268af678fc5bca7192aaf7 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 28 Jul 2022 23:49:37 -0700 Subject: [PATCH 22/76] treat unsupport events like a push --- cpp_linter/run.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 80b3db4e..04b22b7d 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -225,11 +225,13 @@ def get_list_of_changed_files() -> None: files_link = f"{GITHUB_API_URL}/repos/{GITHUB_REPOSITORY}/" if GITHUB_EVENT_NAME == "pull_request": files_link += f"pulls/{Globals.EVENT_PAYLOAD['number']}/files" - elif GITHUB_EVENT_NAME == "push": - files_link += f"commits/{GITHUB_SHA}" else: - logger.warning("triggered on unsupported event.") - sys.exit(set_exit_code(0)) + if GITHUB_EVENT_NAME != "push": + logger.warning( + "Triggered on unsupported event '%s'. Behaving like a push event.", + GITHUB_EVENT_NAME, + ) + files_link += f"commits/{GITHUB_SHA}" logger.info("Fetching files list from url: %s", files_link) Globals.FILES = requests.get(files_link, headers=API_HEADERS).json() From 767417af4f235650236cd3aa116ec0350dcabbbb Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 00:02:39 -0700 Subject: [PATCH 23/76] explicitly set a env var when using docker --- action.yml | 2 ++ cpp_linter/run.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 21385ccc..f2249c3c 100644 --- a/action.yml +++ b/action.yml @@ -80,6 +80,8 @@ outputs: runs: using: "docker" image: "Dockerfile" + env: + USING_CLANG_TOOLS_DOCKER: true args: - --style=${{ inputs.style }} - --extensions=${{ inputs.extensions }} diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 04b22b7d..68a9f598 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -40,7 +40,7 @@ GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY", "") GITHUB_EVENT_NAME = os.getenv("GITHUB_EVENT_NAME", "unknown") GITHUB_WORKSPACE = os.getenv("GITHUB_WORKSPACE", "") -IS_USING_DOCKER = os.getenv("CLANG_VERSIONS", "") +IS_USING_DOCKER = os.getenv("USING_CLANG_TOOLS_DOCKER", "") RUNNER_WORKSPACE = ( os.getenv("RUNNER_WORKSPACE", "") if not IS_USING_DOCKER else GITHUB_WORKSPACE ) From 95189854c8893b8378d8253a81f43c690b378e9b Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 00:22:19 -0700 Subject: [PATCH 24/76] ammend some logic --- cpp_linter/run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 68a9f598..3ea70d91 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -42,7 +42,7 @@ GITHUB_WORKSPACE = os.getenv("GITHUB_WORKSPACE", "") IS_USING_DOCKER = os.getenv("USING_CLANG_TOOLS_DOCKER", "") RUNNER_WORKSPACE = ( - os.getenv("RUNNER_WORKSPACE", "") if not IS_USING_DOCKER else GITHUB_WORKSPACE + os.getenv("RUNNER_WORKSPACE", "") if IS_USING_DOCKER else GITHUB_WORKSPACE ) IS_ON_WINDOWS = sys.platform.startswith("win32") @@ -750,7 +750,7 @@ def make_annotations( count = 0 files = ( Globals.FILES - if GITHUB_EVENT_NAME == "pull_request" + if GITHUB_EVENT_NAME == "pull_request" or isinstance(Globals.FILES, list) else cast(Dict[str, Any], Globals.FILES)["files"] ) for advice, file in zip(GlobalParser.format_advice, files): From ccf8f33f6fec77737825333fdf253f5cd8301724 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 10:28:32 -0700 Subject: [PATCH 25/76] show me some contents of folders on docker --- cpp_linter/run.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 3ea70d91..5d61e63e 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -821,6 +821,18 @@ def parse_ignore_option(paths: str) -> tuple: return (ignored, not_ignored) +def list_toc(dir_name: str) -> List[str]: + """pythonic ls implementation.""" + result = [] + for _, dirs, files in os.walk(dir_name): + for name in dirs: + result.append(name) + for name in files: + result.append(name) + break # shallow depth + return result + + def main(): """The main script.""" @@ -835,6 +847,26 @@ def main(): logger.info("processing %s event", GITHUB_EVENT_NAME) + start_log_group(f"working dir: {os.getcwd()}") + logger.debug("\n\t%s", "\n\t".join(list_toc(os.getcwd()))) + end_log_group() + + start_log_group("ls '/'") + logger.debug("\n\t%s", "\n\t".join(list_toc("/"))) + end_log_group() + + start_log_group("ls '.'") + logger.debug("\n\t%s", "\n\t".join(list_toc("."))) + end_log_group() + + start_log_group(f"ls {RUNNER_WORKSPACE}") + logger.debug("\n\t%s", "\n\t".join(list_toc(RUNNER_WORKSPACE))) + end_log_group() + + start_log_group(f"ls {GITHUB_WORKSPACE}") + logger.debug("\n\t%s", "\n\t".join(list_toc(GITHUB_WORKSPACE))) + end_log_group() + # change working directory os.chdir(args.repo_root) From 903d351ab406735ad40d798b4c921dc659b80b6b Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 10:57:46 -0700 Subject: [PATCH 26/76] hardcode the correct worspace dir --- cpp_linter/run.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 5d61e63e..a69a066f 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -41,9 +41,7 @@ GITHUB_EVENT_NAME = os.getenv("GITHUB_EVENT_NAME", "unknown") GITHUB_WORKSPACE = os.getenv("GITHUB_WORKSPACE", "") IS_USING_DOCKER = os.getenv("USING_CLANG_TOOLS_DOCKER", "") -RUNNER_WORKSPACE = ( - os.getenv("RUNNER_WORKSPACE", "") if IS_USING_DOCKER else GITHUB_WORKSPACE -) +RUNNER_WORKSPACE = "/github/workspace" if IS_USING_DOCKER else GITHUB_WORKSPACE IS_ON_WINDOWS = sys.platform.startswith("win32") # setup CLI args From 99bbfd9beee60f72a5b05777c12ab66a196f5dd4 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 10:58:07 -0700 Subject: [PATCH 27/76] remove unused import --- tests/database_path/test_database_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/database_path/test_database_path.py b/tests/database_path/test_database_path.py index d4cb48ba..54c2e1d4 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/database_path/test_database_path.py @@ -1,6 +1,6 @@ """Tests specific to specifying the compilation database path.""" import os -from typing import Optional, List +from typing import List from pathlib import Path import logging import re From 8fa467e287a2efc08b006530f418fe8c97399cab Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 11:05:51 -0700 Subject: [PATCH 28/76] try detecting the docker env better --- cpp_linter/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index a69a066f..f1e1ef55 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -40,7 +40,7 @@ GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY", "") GITHUB_EVENT_NAME = os.getenv("GITHUB_EVENT_NAME", "unknown") GITHUB_WORKSPACE = os.getenv("GITHUB_WORKSPACE", "") -IS_USING_DOCKER = os.getenv("USING_CLANG_TOOLS_DOCKER", "") +IS_USING_DOCKER = os.getenv("USING_CLANG_TOOLS_DOCKER", os.getenv("CLANG_VERSIONS")) RUNNER_WORKSPACE = "/github/workspace" if IS_USING_DOCKER else GITHUB_WORKSPACE IS_ON_WINDOWS = sys.platform.startswith("win32") From 400b61554afa2fda76b086a16a3eb0d4dfe03ace Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 11:08:16 -0700 Subject: [PATCH 29/76] set the docker env var w/ a str --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index f2249c3c..a3b9e2fb 100644 --- a/action.yml +++ b/action.yml @@ -81,7 +81,7 @@ runs: using: "docker" image: "Dockerfile" env: - USING_CLANG_TOOLS_DOCKER: true + USING_CLANG_TOOLS_DOCKER: 'true' args: - --style=${{ inputs.style }} - --extensions=${{ inputs.extensions }} From 0367cf4e6a5ad17adab088b1a04029dd9ee89ed3 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 11:20:37 -0700 Subject: [PATCH 30/76] assume that RUNNER_WORKSPACE is abs --- cpp_linter/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index f1e1ef55..bd90f6de 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -442,7 +442,7 @@ def run_clang_tidy( if database: cmds.append("-p") if not os.path.isabs(database): - database = os.path.abspath( + database = os.path.normpath( os.path.join(RUNNER_WORKSPACE, repo_root, database) ) cmds.append(database) From 37e3083971e7f649d130c69fff475e164d7ee420 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 11:40:58 -0700 Subject: [PATCH 31/76] use only relativer path to db on docker --- cpp_linter/run.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index bd90f6de..f4448c77 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -441,10 +441,9 @@ def run_clang_tidy( cmds.append(f"-checks={checks}") if database: cmds.append("-p") - if not os.path.isabs(database): - database = os.path.normpath( - os.path.join(RUNNER_WORKSPACE, repo_root, database) - ) + if IS_USING_DOCKER and os.path.isabs(database): + repo_root += os.sep # temp non-op to make use of the arg + database = database.replace(GITHUB_WORKSPACE + os.sep, "") cmds.append(database) if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" From 120919b398e484579d5951c998b72d71fd6f6b43 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 29 Jul 2022 11:40:58 -0700 Subject: [PATCH 32/76] Revert "use only relativer path to db on docker" This reverts commit 37e3083971e7f649d130c69fff475e164d7ee420. --- cpp_linter/run.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index f4448c77..bd90f6de 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -441,9 +441,10 @@ def run_clang_tidy( cmds.append(f"-checks={checks}") if database: cmds.append("-p") - if IS_USING_DOCKER and os.path.isabs(database): - repo_root += os.sep # temp non-op to make use of the arg - database = database.replace(GITHUB_WORKSPACE + os.sep, "") + if not os.path.isabs(database): + database = os.path.normpath( + os.path.join(RUNNER_WORKSPACE, repo_root, database) + ) cmds.append(database) if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" From 0810b1a07029b878afa3f0f630b0eca4b4fbcf8a Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 4 Aug 2022 22:17:37 -0700 Subject: [PATCH 33/76] better test coverage --- .coveragerc | 32 + .github/workflows/run-dev-tests.yml | 67 +- .gitignore | 2 +- .pylintrc | 2 +- coverage.json | 840 ++++++++++++++++++ cpp_linter/__init__.py | 43 +- cpp_linter/clang_format_xml.py | 30 +- cpp_linter/clang_tidy.py | 35 +- cpp_linter/clang_tidy_yml.py | 19 +- cpp_linter/run.py | 182 ++-- cpp_linter/thread_comments.py | 104 ++- requirements-dev.txt | 1 + .../.clang-format | 0 tests/capture_tools_output/.clang-tidy | 349 ++++++++ .../event_files.json} | 0 .../expected_result.json | 0 .../test_database_path.py | 3 +- .../capture_tools_output/test_tools_output.py | 196 ++++ tests/ignored_paths/test_ignored_paths.py | 34 +- .../test_lines_changed_only.py | 113 --- tests/test_misc.py | 94 ++ 21 files changed, 1796 insertions(+), 350 deletions(-) create mode 100644 .coveragerc create mode 100644 coverage.json rename tests/{lines_changed_only => capture_tools_output}/.clang-format (100%) create mode 100644 tests/capture_tools_output/.clang-tidy rename tests/{lines_changed_only/files.json => capture_tools_output/event_files.json} (100%) rename tests/{lines_changed_only => capture_tools_output}/expected_result.json (100%) rename tests/{database_path => capture_tools_output}/test_database_path.py (95%) create mode 100644 tests/capture_tools_output/test_tools_output.py delete mode 100644 tests/lines_changed_only/test_lines_changed_only.py create mode 100644 tests/test_misc.py diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..b2775553 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,32 @@ +[run] +dynamic_context = test_function +omit= + # don't include tests in coverage + tests/* + +[json] +pretty_print=true + +[html] +show_contexts=true + +[report] +# Regexes for lines to exclude from consideration +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about missing debug-only code: + def __repr__ + + # the point of unit tests is to test parts of main() + def main + + # ignore any branch that makes the module executable + if __name__ == "__main__" + + # ignore branches specific to type checking + if TYPE_CHECKING + + # ignore the local secific debug statement related to not having rich installed + if not FOUND_RICH_LIB diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index c7051b19..e443a56f 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -30,14 +30,75 @@ jobs: strategy: fail-fast: false matrix: - os: ['windows-latest', ubuntu-latest] py: ['3.7', '3.8', '3.9', '3.10'] + os: ['windows-latest', ubuntu-latest] + version: ['14', '13', '12', '11', '10'] + include: + - tools_dir: 'N/A' + - os: 'windows-latest' + version: '10' + tools_dir: ${{ runner.temp }}/llvm + - os: 'windows-latest' + version: '10' + tools_dir: ${{ runner.temp }}/llvm + - os: 'windows-latest' + version: '11' + tools_dir: ${{ runner.temp }}/llvm + - os: 'windows-latest' + version: '12' + tools_dir: ${{ runner.temp }}/llvm + - os: 'ubuntu-latest' + version: '13' + tools_dir: ${{ runner.temp }}/llvm + - version: '14' + tools_dir: ${{ runner.temp }}/llvm + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 with: python-version: ${{ matrix.py }} + - name: Install workflow deps - run: python3 -m pip install pytest . - - run: pytest -vv tests + run: python3 -m pip install pytest coverage . + + # - name: Install clang-tools + # if: matrix.tools_dir != 'N/A' + # run: | + # python -m pip install clang-tools + # clang-tools --install ${{ matrix.version }} --directory ${{ matrix.tools_dir }} + + - name: Install clang-tools + uses: KyleMayes/install-llvm-action@v1 + if: matrix.tools_dir != 'N/A' + with: + version: ${{ matrix.version }} + directory: ${{ matrix.tools_dir }} + + - name: Collect Coverage (native clang) + if: matrix.tools_dir == 'N/A' || matrix.os == 'ubuntu-latest' + env: + CLANG_VERSION: ${{ matrix.version }} + run: coverage run -m pytest -vv tests + + - name: Collect Coverage (non-native clang windows) + if: matrix.tools_dir != 'N/A' && matrix.os = 'windows-latest' + env: + CLANG_VERSION: ${{ matrix.tools.dir }} + run: coverage run -m pytest -vv tests + + - run: coverage report && coverage xml + + - uses: codecov/codecov-action@v3 + env: + OS: ${{ matrix.os }} + PYTHON: CPy${{ matrix.py }} + CLANG: LLVM-v${{ matrix.version }} + with: + token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos + files: ./coverage.xml + flags: unittests # optional + fail_ci_if_error: true # optional (default = false) + verbose: true # optional (default = false) \ No newline at end of file diff --git a/.gitignore b/.gitignore index 52b39040..e4f88937 100644 --- a/.gitignore +++ b/.gitignore @@ -59,7 +59,7 @@ coverage.xml .hypothesis/ .pytest_cache/ tests/*/test*.json -tests/lines_changed_only/**/*.c +tests/**/*.c # Translations *.mo diff --git a/.pylintrc b/.pylintrc index e6a2eed7..691bf317 100644 --- a/.pylintrc +++ b/.pylintrc @@ -371,7 +371,7 @@ max-bool-expr=5 max-branches=12 # Maximum number of locals for function / method body -max-locals=15 +max-locals=18 # Maximum number of parents for a class (see R0901). max-parents=7 diff --git a/coverage.json b/coverage.json new file mode 100644 index 00000000..8a2590bf --- /dev/null +++ b/coverage.json @@ -0,0 +1,840 @@ +{ + "meta": { + "version": "6.4.2", + "timestamp": "2022-08-04T20:24:06.401053", + "branch_coverage": false, + "show_contexts": false + }, + "files": { + "cpp_linter\\__init__.py": { + "executed_lines": [ + 1, + 3, + 4, + 5, + 6, + 7, + 9, + 14, + 15, + 16, + 18, + 20, + 29, + 30, + 34, + 35, + 36, + 37, + 40, + 41, + 44, + 45, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 59, + 60, + 64, + 65, + 67, + 68, + 70, + 71, + 75, + 88, + 90, + 91, + 94, + 110, + 111, + 114, + 115, + 118, + 124, + 125, + 130, + 131 + ], + "summary": { + "covered_lines": 49, + "num_statements": 49, + "percent_covered": 100.0, + "percent_covered_display": "100", + "missing_lines": 0, + "excluded_lines": 8 + }, + "missing_lines": [], + "excluded_lines": [ + 9, + 10, + 11, + 12, + 25, + 26, + 30, + 31 + ] + }, + "cpp_linter\\clang_format_xml.py": { + "executed_lines": [ + 1, + 2, + 3, + 4, + 5, + 8, + 9, + 17, + 24, + 25, + 26, + 28, + 35, + 36, + 45, + 50, + 51, + 53, + 60, + 61, + 71, + 77, + 78, + 80, + 86, + 100, + 102, + 104, + 105, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 125, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 145, + 146, + 147, + 148, + 149, + 150 + ], + "summary": { + "covered_lines": 47, + "num_statements": 47, + "percent_covered": 100.0, + "percent_covered_display": "100", + "missing_lines": 0, + "excluded_lines": 6 + }, + "missing_lines": [], + "excluded_lines": [ + 28, + 29, + 53, + 54, + 80, + 81 + ] + }, + "cpp_linter\\clang_tidy.py": { + "executed_lines": [ + 1, + 2, + 3, + 4, + 5, + 7, + 10, + 11, + 25, + 36, + 45, + 46, + 47, + 48, + 49, + 50, + 52, + 53, + 54, + 55, + 59, + 72, + 83, + 84, + 97, + 99, + 100, + 101, + 102, + 103, + 104, + 110, + 111, + 114 + ], + "summary": { + "covered_lines": 27, + "num_statements": 27, + "percent_covered": 100.0, + "percent_covered_display": "100", + "missing_lines": 0, + "excluded_lines": 5 + }, + "missing_lines": [], + "excluded_lines": [ + 52, + 53, + 54, + 55, + 59 + ] + }, + "cpp_linter\\clang_tidy_yml.py": { + "executed_lines": [ + 1, + 2, + 3, + 4, + 5, + 8, + 13, + 14, + 28, + 33, + 34, + 35, + 36, + 37, + 38, + 40, + 48, + 49, + 58, + 65, + 66, + 67, + 68, + 70, + 77, + 78, + 86, + 91, + 92, + 94, + 101, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 115, + 116, + 119, + 120, + 121, + 126, + 127, + 129 + ], + "summary": { + "covered_lines": 40, + "num_statements": 42, + "percent_covered": 95.23809523809524, + "percent_covered_display": "95", + "missing_lines": 2, + "excluded_lines": 7 + }, + "missing_lines": [ + 122, + 125 + ], + "excluded_lines": [ + 40, + 41, + 42, + 70, + 71, + 94, + 95 + ] + }, + "cpp_linter\\run.py": { + "executed_lines": [ + 1, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 32, + 33, + 34, + 35, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 49, + 52, + 59, + 72, + 79, + 87, + 95, + 103, + 110, + 119, + 128, + 136, + 144, + 154, + 164, + 165, + 166, + 170, + 171, + 172, + 173, + 174, + 177, + 183, + 186, + 188, + 191, + 204, + 205, + 206, + 207, + 215, + 216, + 219, + 222, + 223, + 224, + 227, + 228, + 232, + 233, + 234, + 237, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 252, + 271, + 272, + 277, + 285, + 288, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 306, + 308, + 309, + 313, + 316, + 317, + 318, + 320, + 322, + 323, + 324, + 327, + 335, + 340, + 341, + 342, + 343, + 344, + 346, + 347, + 348, + 351, + 366, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 388, + 392, + 393, + 400, + 401, + 402, + 405, + 425, + 427, + 428, + 429, + 430, + 434, + 435, + 436, + 441, + 442, + 443, + 444, + 445, + 446, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 471, + 489, + 490, + 491, + 492, + 497, + 498, + 499, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 519, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 552, + 553, + 554, + 555, + 556, + 557, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 571, + 592, + 593, + 598, + 599, + 601, + 602, + 605, + 606, + 608, + 610, + 611, + 612, + 614, + 615, + 616, + 617, + 620, + 647, + 724, + 751, + 774, + 784, + 785, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 808, + 809, + 810, + 811, + 812, + 815, + 827, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 837, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 850, + 851, + 855, + 856, + 860, + 863, + 929 + ], + "summary": { + "covered_lines": 290, + "num_statements": 363, + "percent_covered": 79.88980716253444, + "percent_covered_display": "80", + "missing_lines": 73, + "excluded_lines": 35 + }, + "missing_lines": [ + 225, + 314, + 437, + 438, + 439, + 440, + 500, + 501, + 502, + 503, + 514, + 600, + 631, + 632, + 634, + 635, + 636, + 637, + 640, + 643, + 644, + 658, + 659, + 660, + 668, + 669, + 670, + 672, + 673, + 674, + 677, + 679, + 680, + 681, + 682, + 687, + 688, + 689, + 691, + 692, + 693, + 694, + 697, + 698, + 699, + 704, + 710, + 712, + 715, + 720, + 721, + 735, + 736, + 737, + 738, + 739, + 740, + 743, + 746, + 747, + 748, + 759, + 760, + 761, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771 + ], + "excluded_lines": [ + 863, + 864, + 867, + 870, + 873, + 875, + 878, + 881, + 882, + 883, + 884, + 885, + 886, + 888, + 889, + 890, + 891, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 904, + 913, + 914, + 915, + 916, + 919, + 920, + 921, + 926, + 929, + 930 + ] + }, + "cpp_linter\\thread_comments.py": { + "executed_lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 18, + 60, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 72, + 73, + 76, + 78, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 92, + 99, + 100, + 102, + 103, + 104, + 106, + 115, + 118, + 121, + 122, + 123, + 126, + 128, + 131, + 132, + 134, + 135, + 136, + 139, + 140, + 142, + 146, + 153, + 155, + 156, + 160, + 169, + 172, + 177, + 179, + 180, + 181, + 185, + 186, + 187, + 189, + 190, + 191, + 194, + 201, + 207, + 244 + ], + "summary": { + "covered_lines": 70, + "num_statements": 111, + "percent_covered": 63.06306306306306, + "percent_covered_display": "63", + "missing_lines": 41, + "excluded_lines": 0 + }, + "missing_lines": [ + 26, + 27, + 28, + 29, + 30, + 31, + 34, + 40, + 44, + 49, + 50, + 56, + 57, + 89, + 90, + 91, + 93, + 94, + 147, + 148, + 151, + 216, + 217, + 218, + 219, + 220, + 231, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 254, + 255, + 256, + 259, + 260, + 262, + 263 + ], + "excluded_lines": [] + } + }, + "totals": { + "covered_lines": 523, + "num_statements": 639, + "percent_covered": 81.84663536776213, + "percent_covered_display": "82", + "missing_lines": 116, + "excluded_lines": 61 + } +} \ No newline at end of file diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index 33e31a09..3421c4f2 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -1,7 +1,7 @@ """The Base module of the `cpp_linter` package. This holds the objects shared by multiple modules.""" -import io import os +from pathlib import Path import logging from typing import TYPE_CHECKING, List, Dict, Union, Any from requests import Response @@ -22,7 +22,7 @@ handlers=[RichHandler(show_time=False)], ) -except ImportError: +except ImportError: # pragma: no cover logging.basicConfig() #: The logging.Logger object used for outputting data. @@ -85,21 +85,34 @@ def get_line_cnt_from_cols(file_path: str, offset: int) -> tuple: - Index 0 is the line number for the given offset. - Index 1 is the column number for the given offset on the line. """ - line_cnt = 1 - last_lf_pos = 0 - cols = 1 file_path = file_path.replace("/", os.sep) # logger.debug("Getting line count from %s at offset %d", file_path, offset) - with io.open(file_path, "rb") as src_file: - max_len = src_file.seek(0, io.SEEK_END) - src_file.seek(0, io.SEEK_SET) - while src_file.tell() != offset and src_file.tell() < max_len: - char = src_file.read(1) - if char == b"\n": - line_cnt += 1 - last_lf_pos = src_file.tell() - 1 # -1 because LF is part of offset - cols = src_file.tell() - last_lf_pos - return (line_cnt, cols) + contents = Path(file_path).read_bytes()[:offset] + return (contents.count(b"\n") + 1, offset - contents.rfind(b"\n")) + + +def range_of_changed_lines( + file_obj: Dict[str, Any], lines_changed_only: int +) -> List[int]: + """Assemble a list of lines changed. + + Args: + file_obj: The file's JSON object. + lines_changed_only: A flag to indicate the focus of certain lines. + + - 0: focuses on all lines in file. + - 1: focuses on any lines shown in the event's diff + (may include unchanged lines). + - 2: focuses strictly on lines in the diff that contain additions. + Returns: + A list of line numbers for which to give attention. + """ + if lines_changed_only: + ranges = file_obj["line_filter"][ + "diff_chunks" if lines_changed_only == 1 else "lines_added" + ] + return [l for r in ranges for l in range(r[0], r[1])] + return [] def log_response_msg() -> bool: diff --git a/cpp_linter/clang_format_xml.py b/cpp_linter/clang_format_xml.py index 1c9ef123..300c6b77 100644 --- a/cpp_linter/clang_format_xml.py +++ b/cpp_linter/clang_format_xml.py @@ -1,6 +1,6 @@ """Parse output from clang-format's XML suggestions.""" import os -from typing import List +from typing import List, Optional import xml.etree.ElementTree as ET from . import GlobalParser, get_line_cnt_from_cols @@ -83,7 +83,7 @@ def __repr__(self) -> str: f"replacements for {self.filename}>" ) - def log_command(self, style: str, line_filter: List[List[int]]) -> str: + def log_command(self, style: str, line_filter: List[int]) -> Optional[str]: """Output a notification as a github log command. !!! info See Also @@ -107,10 +107,10 @@ def log_command(self, style: str, line_filter: List[List[int]]) -> str: style = style.title() line_list = [] for fix in self.replaced_lines: - for line_range in line_filter: - if fix.line in range(*line_range): - line_list.append(str(fix.line)) - break + if not line_filter or (line_filter and fix.line in line_filter): + line_list.append(str(fix.line)) + if not line_list: + return None return ( "::notice file={name},title=Run clang-format on {name}::" "File {name} (lines {lines}): Code does not conform to {style_guide} " @@ -148,21 +148,3 @@ def parse_format_replacements_xml(src_filename: str): elif fixit.replaced_lines and line == fixit.replaced_lines[-1].line: fixit.replaced_lines[-1].replacements.append(fix) GlobalParser.format_advice.append(fixit) - - -def print_fixits(): - """Print all [`XMLFixit`][cpp_linter.clang_format_xml.XMLFixit] objects in - [`format_advice`][cpp_linter.GlobalParser.format_advice].""" - for fixit in GlobalParser.format_advice: - print(repr(fixit)) - for line_fix in fixit.replaced_lines: - print(" " + repr(line_fix)) - for fix in line_fix.replacements: - print("\t" + repr(fix)) - - -if __name__ == "__main__": - import sys - - parse_format_replacements_xml(sys.argv[1]) - print_fixits() diff --git a/cpp_linter/clang_tidy.py b/cpp_linter/clang_tidy.py index 50582c1d..a57cc9fe 100644 --- a/cpp_linter/clang_tidy.py +++ b/cpp_linter/clang_tidy.py @@ -2,9 +2,9 @@ import os import re from typing import Tuple, Union, List, cast -from . import GlobalParser, IS_ON_RUNNER # , logger +from . import GlobalParser -NOTE_HEADER = re.compile("^(.*):(\d+):(\d+):\s(\w+):(.*)\[(.*)\]$") +NOTE_HEADER = re.compile(r"^(.*):(\d+):(\d+):\s(\w+):(.*)\[(.*)\]$") class TidyNotification: @@ -50,17 +50,22 @@ def __init__( self.fixit_lines: List[str] = [] def __repr__(self) -> str: + concerned_code = "" + if self.fixit_lines: + concerned_code = "```{}\n{}```\n".format( + os.path.splitext(self.filename)[1], + "".join(self.fixit_lines), + ) return ( "
\n{}:{}:{}: {}: [{}]" - "\n\n> {}\n

\n\n```{}\n{}```\n

\n
\n\n".format( + "\n\n> {}\n

\n\n{}

\n\n\n".format( self.filename, self.line, self.cols, self.note_type, self.diagnostic, self.note_info, - os.path.splitext(self.filename)[1], - "".join(self.fixit_lines), + concerned_code, ) ) @@ -75,9 +80,7 @@ def log_command(self) -> str: - [A notice message](https://docs.github.com/en/actions/learn-github- actions/workflow-commands-for-github-actions#setting-a-notice-message) """ - filename = self.filename - if IS_ON_RUNNER: - filename = self.filename.replace(os.sep, "/") + filename = self.filename.replace("\\", "/") return ( "::{} file={file},line={line},title={file}:{line}:{cols} [{diag}]::" "{info}".format( @@ -106,18 +109,6 @@ def parse_tidy_output() -> None: ) GlobalParser.tidy_notes.append(notification) elif notification is not None: + # append lines of code that are part of + # the previous line's notification notification.fixit_lines.append(line) - - -def print_fixits(): - """Print out all clang-tidy notifications from stdout (which are saved to - clang_tidy_report.txt and allocated to - [`tidy_notes`][cpp_linter.GlobalParser.tidy_notes].""" - for notification in GlobalParser.tidy_notes: - print("found", len(GlobalParser.tidy_notes), "tidy_notes") - print(repr(notification)) - - -if __name__ == "__main__": - parse_tidy_output() - print_fixits() diff --git a/cpp_linter/clang_tidy_yml.py b/cpp_linter/clang_tidy_yml.py index cb9dcebb..437aaf69 100644 --- a/cpp_linter/clang_tidy_yml.py +++ b/cpp_linter/clang_tidy_yml.py @@ -2,7 +2,7 @@ import os from typing import List import yaml -from . import GlobalParser, get_line_cnt_from_cols +from . import GlobalParser, get_line_cnt_from_cols, logger CWD_HEADER_GUARD = bytes( @@ -119,7 +119,7 @@ def parse_tidy_suggestions_yml(): fix = TidyReplacement(line_cnt, cols, replacement["Length"]) fix.text = bytes(replacement["ReplacementText"], encoding="utf-8") if fix.text.startswith(b"header is missing header guard"): - print( + logger.debug( "filtering header guard suggestion (making relative to repo root)" ) fix.text = fix.text.replace(CWD_HEADER_GUARD, b"") @@ -127,18 +127,3 @@ def parse_tidy_suggestions_yml(): fixit.diagnostics.append(diag) # filter out absolute header guards GlobalParser.tidy_advice.append(fixit) - - -def print_fixits(): - """Print all [`YMLFixit`][cpp_linter.clang_tidy_yml.YMLFixit] objects in - [`tidy_advice`][cpp_linter.GlobalParser.tidy_advice].""" - for fix in GlobalParser.tidy_advice: - for diag in fix.diagnostics: - print(repr(diag)) - for replac in diag.replacements: - print(" " + repr(replac), f"\n\treplace text:\n{replac.text}") - - -if __name__ == "__main__": - parse_tidy_suggestions_yml() - print_fixits() diff --git a/cpp_linter/run.py b/cpp_linter/run.py index bd90f6de..13702984 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -16,7 +16,7 @@ import argparse import configparser import json -from typing import cast, List, Dict, Any +from typing import cast, List, Dict, Any, Tuple import requests from . import ( Globals, @@ -27,10 +27,11 @@ GITHUB_SHA, API_HEADERS, log_response_msg, + range_of_changed_lines, ) from .clang_tidy_yml import parse_tidy_suggestions_yml from .clang_format_xml import parse_format_replacements_xml -from .clang_tidy import parse_tidy_output +from .clang_tidy import parse_tidy_output, TidyNotification from .thread_comments import remove_bot_comments, list_diff_comments # , get_review_id @@ -88,8 +89,8 @@ "--version", default="", help="The desired version of the clang tools to use. Accepted options are strings " - "which can be 8, 9, 10, 11, 12, 13, 14. Defaults to %(default)s. On Windows, this " - "can also be a path to the install location of LLVM", + "which can be 8, 9, 10, 11, 12, 13, 14. Defaults to '%(default)s'. On Windows, " + "this can also be a path to the install location of LLVM", ) cli_arg_parser.add_argument( "-e", @@ -166,12 +167,11 @@ def set_exit_code(override: int = None) -> int: # setup a separate logger for using github log commands -log_commander = logger.getChild("LOG COMMANDER") # create a child of our logger obj +log_commander = logging.getLogger("LOG COMMANDER") # create a child of our logger obj log_commander.setLevel(logging.DEBUG) # be sure that log commands are output console_handler = logging.StreamHandler() # Create special stdout stream handler console_handler.setFormatter(logging.Formatter("%(message)s")) # no formatted log cmds -log_commander.addHandler(console_handler) # Use special handler for log_commander -log_commander.propagate = False # prevent duplicate messages in the parent logger obj +log_commander.handlers = [console_handler] # Use special handler for log_commander def start_log_group(name: str) -> None: @@ -188,7 +188,7 @@ def end_log_group() -> None: log_commander.fatal("::endgroup::") -def is_file_in_list(paths: list, file_name: str, prompt: str) -> bool: +def is_file_in_list(paths: List[str], file_name: str, prompt: str) -> bool: """Determine if a file is specified in a list of paths and/or filenames. Args: @@ -250,10 +250,9 @@ def consolidate_list_to_ranges(just_numbers: List[int]) -> List[List[int]]: def filter_out_non_source_files( - ext_list: list, - ignored: list, - not_ignored: list, - lines_changed_only: int, + ext_list: List[str], + ignored: List[str], + not_ignored: List[str], ) -> bool: """Exclude undesired files (specified by user input 'extensions'). This filter applies to the event's [`FILES`][cpp_linter.Globals.FILES] attribute. @@ -283,7 +282,7 @@ def filter_out_non_source_files( or is_file_in_list(not_ignored, file["filename"], "not ignored") ) ): - if lines_changed_only and "patch" in file.keys(): + if "patch" in file.keys(): # get diff details for the file's changes # ranges is a list of start/end line numbers shown in the diff ranges: List[List[int]] = [] @@ -349,7 +348,9 @@ def verify_files_are_present() -> None: temp.write(Globals.response_buffer.text) -def list_source_files(ext_list: list, ignored_paths: list, not_ignored: list) -> bool: +def list_source_files( + ext_list: List[str], ignored_paths: List[str], not_ignored: List[str] +) -> bool: """Make a list of source files to be checked. The resulting list is stored in [`FILES`][cpp_linter.Globals.FILES]. @@ -462,7 +463,7 @@ def run_clang_tidy( if os.path.getsize("clang_tidy_output.yml"): parse_tidy_suggestions_yml() # get clang-tidy fixes from yml if results.stderr: - logger.info( + logger.debug( "clang-tidy made the following summary:\n%s", results.stderr.decode() ) @@ -485,6 +486,9 @@ def run_clang_format( lines_changed_only: A flag that forces focus on only changes in the event's diff info. """ + if not style: # if `style` == "" + with open("clang_format_output.xml", "wb"): + return # clear any previous output and exit cmds = [ "clang-format" + ("" if not version else f"-{version}"), f"-style={style}", @@ -507,16 +511,68 @@ def run_clang_format( with open("clang_format_output.xml", "wb") as f_out: f_out.write(results.stdout) if results.returncode: - logger.warning( + logger.debug( "%s raised the following error(s):\n%s", cmds[0], results.stderr.decode() ) +def create_comment_body( + filename: str, + file_obj: Dict[str, Any], + lines_changed_only: int, + tidy_notes: List[TidyNotification], +): + """Create the content for a thread comment about a certain file. + This is a helper function to [`capture_clang_tools_output()`]. + + Args: + filename: The file's name (& path). + file_obj: The file's JSON `dict`. + lines_changed_only: A flag used to filter the comment based on line changes. + tidy_notes: A list of cached notifications from clang-tidy. This is used to + avoid duplicated content in comment, and it is later used again by + [`make_annotations()`] after [`capture_clang_tools_output()`] us finished. + """ + ranges = range_of_changed_lines(file_obj, lines_changed_only) + if os.path.getsize("clang_tidy_report.txt"): + parse_tidy_output() # get clang-tidy fixes from stdout + comment_output = "" + if Globals.PAYLOAD_TIDY: + Globals.PAYLOAD_TIDY += "
" + for fix in GlobalParser.tidy_notes: + if lines_changed_only and fix.line not in ranges: + continue + comment_output += repr(fix) + tidy_notes.append(fix) + if comment_output: + Globals.PAYLOAD_TIDY += f"
{filename}
\n" + Globals.PAYLOAD_TIDY += comment_output + GlobalParser.tidy_notes.clear() # empty list to avoid duplicated output + + if os.path.getsize("clang_format_output.xml"): + parse_format_replacements_xml(filename.replace("/", os.sep)) + if GlobalParser.format_advice and GlobalParser.format_advice[-1].replaced_lines: + should_comment = lines_changed_only == 0 + if not should_comment: + for line in [ + replacement.line + for replacement in GlobalParser.format_advice[-1].replaced_lines + ]: + if line in ranges: + should_comment = True + break + if should_comment: + if not Globals.OUTPUT: + Globals.OUTPUT = "\n## :scroll: " + Globals.OUTPUT += "Run `clang-format` on the following files\n" + Globals.OUTPUT += f"- [ ] {file_obj['filename']}\n" + + def capture_clang_tools_output( version: str, checks: str, style: str, - lines_changed_only: bool, + lines_changed_only: int, database: str, repo_root: str, ): @@ -532,7 +588,8 @@ def capture_clang_tools_output( lines_changed_only: A flag that forces focus on only changes in the event's diff info. """ - tidy_notes = [] # temporary cache of parsed notifications for use in log commands + # temporary cache of parsed notifications for use in log commands + tidy_notes: List[TidyNotification] = [] for file in ( Globals.FILES if GITHUB_EVENT_NAME == "pull_request" or isinstance(Globals.FILES, list) @@ -547,27 +604,8 @@ def capture_clang_tools_output( ) run_clang_format(filename, file, version, style, lines_changed_only) end_log_group() - if os.path.getsize("clang_tidy_report.txt"): - parse_tidy_output() # get clang-tidy fixes from stdout - if Globals.PAYLOAD_TIDY: - Globals.PAYLOAD_TIDY += "
" - Globals.PAYLOAD_TIDY += f"
{filename}
\n" - for fix in GlobalParser.tidy_notes: - Globals.PAYLOAD_TIDY += repr(fix) - for note in GlobalParser.tidy_notes: - tidy_notes.append(note) - GlobalParser.tidy_notes.clear() # empty list to avoid duplicated output - - if os.path.getsize("clang_format_output.xml"): - parse_format_replacements_xml(filename.replace("/", os.sep)) - if ( - GlobalParser.format_advice - and GlobalParser.format_advice[-1].replaced_lines - ): - if not Globals.OUTPUT: - Globals.OUTPUT = "\n## :scroll: " - Globals.OUTPUT += "Run `clang-format` on the following files\n" - Globals.OUTPUT += f"- [ ] {file['filename']}\n" + + create_comment_body(filename, file, lines_changed_only, tidy_notes) if Globals.PAYLOAD_TIDY: if not Globals.OUTPUT: @@ -618,7 +656,7 @@ def post_diff_comments(base_url: str, user_id: int) -> bool: output value (a soft exit code). """ comments_url = base_url + "pulls/comments/" # for use with comment_id - payload = list_diff_comments() + payload = list_diff_comments(2) # only focus on additions in diff logger.info("Posting %d comments", len(payload)) # uncomment the next 3 lines for debug output without posting a comment @@ -743,8 +781,6 @@ def make_annotations( style: The chosen code style guidelines. The value 'file' is replaced with 'custom style'. """ - # log_commander obj's verbosity is hard-coded to show debug statements - ret_val = False count = 0 files = ( Globals.FILES @@ -752,26 +788,31 @@ def make_annotations( else cast(Dict[str, Any], Globals.FILES)["files"] ) for advice, file in zip(GlobalParser.format_advice, files): + line_filter = range_of_changed_lines(file, lines_changed_only) if advice.replaced_lines: - ret_val = True - line_filter = [] - if lines_changed_only == 1: - line_filter = file["line_filter"]["diff_chunks"] - elif lines_changed_only == 2: - line_filter = file["line_filter"]["lines_added"] if file_annotations: - log_commander.info(advice.log_command(style, line_filter)) - count += 1 + output = advice.log_command(style, line_filter) + if output is not None: + log_commander.info(output) + count += 1 for note in GlobalParser.tidy_notes: - ret_val = True - if file_annotations: + if lines_changed_only: + filename = note.filename.replace("\\", "/") + for file in files: + if filename == file["filename"]: + line_filter = range_of_changed_lines(file, lines_changed_only) + if note.line in line_filter: + count += 1 + log_commander.info(note.log_command()) + else: + count += 1 log_commander.info(note.log_command()) count += 1 logger.info("Created %d annotations", count) - return ret_val + return bool(count) -def parse_ignore_option(paths: str) -> tuple: +def parse_ignore_option(paths: str) -> Tuple[List[str], List[str]]: """Parse a given string of paths (separated by a '|') into `ignored` and `not_ignored` lists of strings. @@ -819,18 +860,6 @@ def parse_ignore_option(paths: str) -> tuple: return (ignored, not_ignored) -def list_toc(dir_name: str) -> List[str]: - """pythonic ls implementation.""" - result = [] - for _, dirs, files in os.walk(dir_name): - for name in dirs: - result.append(name) - for name in files: - result.append(name) - break # shallow depth - return result - - def main(): """The main script.""" @@ -845,26 +874,6 @@ def main(): logger.info("processing %s event", GITHUB_EVENT_NAME) - start_log_group(f"working dir: {os.getcwd()}") - logger.debug("\n\t%s", "\n\t".join(list_toc(os.getcwd()))) - end_log_group() - - start_log_group("ls '/'") - logger.debug("\n\t%s", "\n\t".join(list_toc("/"))) - end_log_group() - - start_log_group("ls '.'") - logger.debug("\n\t%s", "\n\t".join(list_toc("."))) - end_log_group() - - start_log_group(f"ls {RUNNER_WORKSPACE}") - logger.debug("\n\t%s", "\n\t".join(list_toc(RUNNER_WORKSPACE))) - end_log_group() - - start_log_group(f"ls {GITHUB_WORKSPACE}") - logger.debug("\n\t%s", "\n\t".join(list_toc(GITHUB_WORKSPACE))) - end_log_group() - # change working directory os.chdir(args.repo_root) @@ -883,7 +892,6 @@ def main(): args.extensions, ignored, not_ignored, - args.lines_changed_only, ) if not exit_early: verify_files_are_present() diff --git a/cpp_linter/thread_comments.py b/cpp_linter/thread_comments.py index 8491318b..a4c5e8b9 100644 --- a/cpp_linter/thread_comments.py +++ b/cpp_linter/thread_comments.py @@ -2,8 +2,17 @@ import os from typing import Union, cast, List, Optional, Dict, Any import json +from pathlib import Path import requests -from . import Globals, GlobalParser, logger, API_HEADERS, GITHUB_SHA, log_response_msg +from . import ( + Globals, + GlobalParser, + logger, + API_HEADERS, + GITHUB_SHA, + log_response_msg, + range_of_changed_lines, +) def remove_bot_comments(comments_url: str, user_id: int): @@ -48,27 +57,25 @@ def remove_bot_comments(comments_url: str, user_id: int): json.dump(comments, json_comments, indent=4) -def aggregate_tidy_advice() -> list: +def aggregate_tidy_advice(lines_changed_only: int) -> List[Dict[str, Any]]: """Aggregate a list of json contents representing advice from clang-tidy suggestions.""" results = [] - for index, fixit in enumerate(GlobalParser.tidy_advice): + files = Globals.FILES if isinstance(Globals.FILES, list) else Globals.FILES["files"] + for fixit, file in zip(GlobalParser.tidy_advice, files): for diag in fixit.diagnostics: + ranges = range_of_changed_lines(file, lines_changed_only) + if lines_changed_only and diag.line not in ranges: + continue + # base body of comment body = "\n## :speech_balloon: Clang-tidy\n**" body += diag.name + "**\n>" + diag.message # get original code - filename = cast(List[Dict[str, str]], Globals.FILES)[index][ - "filename" - ].replace("/", os.sep) - if not os.path.exists(filename): - # the file had to be downloaded (no git checkout). - # thus use only the filename (without the path to the file) - filename = os.path.split(filename)[1] - lines = [] # the list of lines in a file - with open(filename, encoding="utf-8") as temp: - lines = temp.readlines() + filename = cast(str, file["filename"]).replace("/", os.sep) + # the list of lines in a file + lines = Path(filename).read_text(encoding="utf-8").splitlines() # aggregate clang-tidy advice suggestion = "\n```suggestion\n" @@ -97,46 +104,35 @@ def aggregate_tidy_advice() -> list: body += suggestion results.append( - { - "body": body, - "commit_id": GITHUB_SHA, - "line": diag.line, - "path": fixit.filename, - "side": "RIGHT", - } + dict( + body=body, + commit_id=GITHUB_SHA, + line=diag.line, + path=fixit.filename, + side="RIGHT", + ) ) return results -def aggregate_format_advice(lines_changed_only: int = 1) -> list: +def aggregate_format_advice(lines_changed_only: int) -> List[Dict[str, Any]]: """Aggregate a list of json contents representing advice from clang-format suggestions.""" results = [] - for index, fmt_advice in enumerate(GlobalParser.format_advice): + files = Globals.FILES if isinstance(Globals.FILES, list) else Globals.FILES["files"] + for fmt_advice, file in zip(GlobalParser.format_advice, files): # get original code - filename = cast(List[Dict[str, str]], Globals.FILES)[index]["filename"].replace( - "/", os.sep - ) - if not os.path.exists(filename): - # the file had to be downloaded (no git checkout). - # thus use only the filename (without the path to the file) - filename = os.path.split(filename)[1] - lines = [] # the list of lines from the src file - with open(filename, encoding="utf-8") as temp: - lines = temp.readlines() + filename = cast(str, file["filename"]).replace("/", os.sep) + # the list of lines from the src file + lines = Path(filename).read_text(encoding="utf-8").splitlines() # aggregate clang-format suggestion line = "" # the line that concerns the fix for fixed_line in fmt_advice.replaced_lines: # clang-format can include advice that starts/ends outside the diff's domain - ranges: List[List[int]] = cast(List[Dict[str, Any]], Globals.FILES)[index][ - "line_filter" - ]["diff_chunks" if lines_changed_only == 1 else "lines_added"] - for scope in ranges: - if fixed_line.line in range(scope[0], scope[1] + 1): - break - else: + ranges = range_of_changed_lines(file, lines_changed_only) + if lines_changed_only and fixed_line.line not in ranges: continue # line is out of scope for diff, so skip this fix # assemble the suggestion @@ -162,18 +158,20 @@ def aggregate_format_advice(lines_changed_only: int = 1) -> list: # create a suggestion from clang-format advice results.append( - { - "body": body, - "commit_id": GITHUB_SHA, - "line": fixed_line.line, - "path": fmt_advice.filename, - "side": "RIGHT", - } + dict( + body=body, + commit_id=GITHUB_SHA, + line=fixed_line.line, + path=fmt_advice.filename, + side="RIGHT", + ) ) return results -def concatenate_comments(tidy_advice: list, format_advice: list) -> list: +def concatenate_comments( + tidy_advice: list, format_advice: list +) -> List[Dict[str, Union[str, int]]]: """Concatenate comments made to the same line of the same file.""" # traverse comments from clang-format for index, comment_body in enumerate(format_advice): @@ -193,17 +191,17 @@ def concatenate_comments(tidy_advice: list, format_advice: list) -> list: return tidy_advice + format_advice -def list_diff_comments() -> list: +def list_diff_comments(lines_changed_only: int) -> List[Dict[str, Union[str, int]]]: """Aggregate list of comments for use in the event's diff. This function assumes that the CLI option `--lines_changed_only` is set to True. Returns: A list of comments (each element as json content). """ - tidy_advice = aggregate_tidy_advice() - format_advice = aggregate_format_advice() - results = concatenate_comments(tidy_advice, format_advice) - return results + return concatenate_comments( + aggregate_tidy_advice(lines_changed_only), + aggregate_format_advice(lines_changed_only), + ) def get_review_id(reviews_url: str, user_id: int) -> Optional[int]: @@ -243,7 +241,7 @@ def get_review_id(reviews_url: str, user_id: int) -> Optional[int]: return review_id -def find_review(reviews: dict, user_id: int) -> Union[int, None]: +def find_review(reviews: dict, user_id: int) -> Optional[int]: """Find a review created by a certain user ID. Args: diff --git a/requirements-dev.txt b/requirements-dev.txt index d31c096b..9bc46199 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,3 +4,4 @@ mypy pylint rich pytest +coverage diff --git a/tests/lines_changed_only/.clang-format b/tests/capture_tools_output/.clang-format similarity index 100% rename from tests/lines_changed_only/.clang-format rename to tests/capture_tools_output/.clang-format diff --git a/tests/capture_tools_output/.clang-tidy b/tests/capture_tools_output/.clang-tidy new file mode 100644 index 00000000..19dc3ea0 --- /dev/null +++ b/tests/capture_tools_output/.clang-tidy @@ -0,0 +1,349 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*,-boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,clang-analyzer-*,cppcoreguidelines-*,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers' +WarningsAsErrors: '' +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: none +User: ytreh +CheckOptions: + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: cppcoreguidelines-no-malloc.Reallocations + value: '::realloc' + - key: cppcoreguidelines-owning-memory.LegacyResourceConsumers + value: '::free;::realloc;::freopen;::fclose' + - key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold + value: '3' + - key: readability-function-size.VariableThreshold + value: '4294967295' + - key: modernize-use-auto.MinTypeNameLength + value: '5' + - key: bugprone-reserved-identifier.Invert + value: 'false' + - key: performance-move-const-arg.CheckTriviallyCopyableMove + value: 'true' + - key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' + - key: bugprone-narrowing-conversions.WarnOnFloatingPointNarrowingConversion + value: 'true' + - key: readability-identifier-naming.GetConfigPerFile + value: 'true' + - key: bugprone-narrowing-conversions.PedanticMode + value: 'false' + - key: readability-inconsistent-declaration-parameter-name.Strict + value: 'false' + - key: cppcoreguidelines-macro-usage.CheckCapsOnly + value: 'false' + - key: bugprone-unused-return-value.CheckedFunctions + value: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty;::std::back_inserter;::std::distance;::std::find;::std::find_if;::std::inserter;::std::lower_bound;::std::make_pair;::std::map::count;::std::map::find;::std::map::lower_bound;::std::multimap::equal_range;::std::multimap::upper_bound;::std::set::count;::std::set::find;::std::setfill;::std::setprecision;::std::setw;::std::upper_bound;::std::vector::at;::bsearch;::ferror;::feof;::isalnum;::isalpha;::isblank;::iscntrl;::isdigit;::isgraph;::islower;::isprint;::ispunct;::isspace;::isupper;::iswalnum;::iswprint;::iswspace;::isxdigit;::memchr;::memcmp;::strcmp;::strcoll;::strncmp;::strpbrk;::strrchr;::strspn;::strstr;::wcscmp;::access;::bind;::connect;::difftime;::dlsym;::fnmatch;::getaddrinfo;::getopt;::htonl;::htons;::iconv_open;::inet_addr;::isascii;::isatty;::mmap;::newlocale;::openat;::pathconf;::pthread_equal;::pthread_getspecific;::pthread_mutex_trylock;::readdir;::readlink;::recvmsg;::regexec;::scandir;::semget;::setjmp;::shm_open;::shmget;::sigismember;::strcasecmp;::strsignal;::ttyname' + - key: modernize-use-default-member-init.UseAssignment + value: 'false' + - key: readability-function-size.NestingThreshold + value: '4294967295' + - key: modernize-use-override.AllowOverrideAndFinal + value: 'false' + - key: readability-function-size.ParameterThreshold + value: '4294967295' + - key: modernize-pass-by-value.ValuesOnly + value: 'false' + - key: modernize-loop-convert.IncludeStyle + value: llvm + - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons + value: '0' + - key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison + value: 'false' + - key: cppcoreguidelines-explicit-virtual-functions.AllowOverrideAndFinal + value: 'false' + - key: readability-redundant-smartptr-get.IgnoreMacros + value: 'true' + - key: readability-identifier-naming.AggressiveDependentMemberLookup + value: 'false' + - key: bugprone-suspicious-string-compare.WarnOnImplicitComparison + value: 'true' + - key: modernize-use-emplace.TupleTypes + value: '::std::pair;::std::tuple' + - key: modernize-use-emplace.TupleMakeFunctions + value: '::std::make_pair;::std::make_tuple' + - key: cppcoreguidelines-owning-memory.LegacyResourceProducers + value: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile' + - key: bugprone-argument-comment.CommentNullPtrs + value: '0' + - key: bugprone-argument-comment.StrictMode + value: '0' + - key: cppcoreguidelines-init-variables.IncludeStyle + value: llvm + - key: modernize-use-nodiscard.ReplacementString + value: '[[nodiscard]]' + - key: modernize-loop-convert.MakeReverseRangeHeader + value: '' + - key: modernize-replace-random-shuffle.IncludeStyle + value: llvm + - key: cppcoreguidelines-narrowing-conversions.WarnOnFloatingPointNarrowingConversion + value: 'true' + - key: modernize-use-bool-literals.IgnoreMacros + value: 'true' + - key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField + value: 'true' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: bugprone-suspicious-string-compare.StringCompareLikeFunctions + value: '' + - key: modernize-avoid-bind.PermissiveParameterList + value: 'false' + - key: modernize-use-override.FinalSpelling + value: final + - key: performance-move-constructor-init.IncludeStyle + value: llvm + - key: modernize-loop-convert.UseCxx20ReverseRanges + value: 'true' + - key: modernize-use-noexcept.ReplacementString + value: '' + - key: modernize-use-using.IgnoreMacros + value: 'true' + - key: performance-type-promotion-in-math-fn.IncludeStyle + value: llvm + - key: cppcoreguidelines-explicit-virtual-functions.FinalSpelling + value: final + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: bugprone-suspicious-include.ImplementationFileExtensions + value: 'c;cc;cpp;cxx' + - key: cppcoreguidelines-pro-type-member-init.UseAssignment + value: 'false' + - key: modernize-loop-convert.MakeReverseRangeFunction + value: '' + - key: bugprone-suspicious-include.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: performance-no-automatic-move.AllowedTypes + value: '' + - key: performance-for-range-copy.WarnOnAllAutoCopies + value: 'false' + - key: bugprone-argument-comment.CommentIntegerLiterals + value: '0' + - key: bugprone-suspicious-missing-comma.SizeThreshold + value: '5' + - key: readability-inconsistent-declaration-parameter-name.IgnoreMacros + value: 'true' + - key: readability-identifier-naming.IgnoreFailedSplit + value: 'false' + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: bugprone-sizeof-expression.WarnOnSizeOfThis + value: 'true' + - key: readability-qualified-auto.AddConstToQualified + value: 'true' + - key: bugprone-string-constructor.WarnOnLargeLength + value: 'true' + - key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit + value: '16' + - key: readability-simplify-boolean-expr.ChainedConditionalReturn + value: 'false' + - key: cppcoreguidelines-explicit-virtual-functions.OverrideSpelling + value: override + - key: readability-else-after-return.WarnOnConditionVariables + value: 'true' + - key: readability-uppercase-literal-suffix.IgnoreMacros + value: 'true' + - key: modernize-use-nullptr.NullMacros + value: 'NULL' + - key: modernize-make-shared.IgnoreMacros + value: 'true' + - key: bugprone-dynamic-static-initializers.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: bugprone-suspicious-enum-usage.StrictMode + value: 'false' + - key: performance-unnecessary-copy-initialization.AllowedTypes + value: '' + - key: bugprone-suspicious-missing-comma.MaxConcatenatedTokens + value: '5' + - key: modernize-use-transparent-functors.SafeMode + value: 'false' + - key: cppcoreguidelines-macro-usage.AllowedRegexp + value: '^DEBUG_*' + - key: modernize-make-shared.IgnoreDefaultInitialization + value: 'true' + - key: bugprone-argument-comment.CommentCharacterLiterals + value: '0' + - key: cppcoreguidelines-narrowing-conversions.PedanticMode + value: 'false' + - key: bugprone-not-null-terminated-result.WantToUseSafeFunctions + value: 'true' + - key: modernize-make-shared.IncludeStyle + value: llvm + - key: bugprone-string-constructor.LargeLengthThreshold + value: '8388608' + - key: readability-simplify-boolean-expr.ChainedConditionalAssignment + value: 'false' + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions + value: 'false' + - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: '0' + - key: bugprone-exception-escape.FunctionsThatShouldNotThrow + value: '' + - key: bugprone-signed-char-misuse.CharTypdefsToIgnore + value: '' + - key: performance-inefficient-vector-operation.EnableProto + value: 'false' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: bugprone-argument-comment.CommentFloatLiterals + value: '0' + - key: readability-function-size.LineThreshold + value: '4294967295' + - key: portability-simd-intrinsics.Suggest + value: 'false' + - key: modernize-make-shared.MakeSmartPtrFunction + value: 'std::make_shared' + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: 'true' + - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader + value: '' + - key: modernize-make-unique.IgnoreMacros + value: 'true' + - key: modernize-make-shared.MakeSmartPtrFunctionHeader + value: '' + - key: performance-for-range-copy.AllowedTypes + value: '' + - key: modernize-use-override.IgnoreDestructors + value: 'false' + - key: bugprone-sizeof-expression.WarnOnSizeOfConstant + value: 'true' + - key: readability-redundant-string-init.StringNames + value: '::std::basic_string_view;::std::basic_string' + - key: modernize-make-unique.IgnoreDefaultInitialization + value: 'true' + - key: modernize-use-emplace.ContainersWithPushBack + value: '::std::vector;::std::list;::std::deque' + - key: modernize-make-unique.IncludeStyle + value: llvm + - key: readability-braces-around-statements.ShortStatementLines + value: '0' + - key: bugprone-argument-comment.CommentUserDefinedLiterals + value: '0' + - key: bugprone-argument-comment.CommentBoolLiterals + value: '0' + - key: modernize-use-override.OverrideSpelling + value: override + - key: performance-inefficient-string-concatenation.StrictMode + value: 'false' + - key: readability-implicit-bool-conversion.AllowPointerConditions + value: 'false' + - key: readability-redundant-declaration.IgnoreMacros + value: 'true' + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: modernize-make-unique.MakeSmartPtrFunction + value: 'std::make_unique' + - key: cppcoreguidelines-pro-type-member-init.IgnoreArrays + value: 'false' + - key: readability-else-after-return.WarnOnUnfixable + value: 'true' + - key: bugprone-reserved-identifier.AllowedIdentifiers + value: '' + - key: modernize-use-emplace.IgnoreImplicitConstructors + value: 'false' + - key: modernize-make-unique.MakeSmartPtrFunctionHeader + value: '' + - key: portability-restrict-system-includes.Includes + value: '*' + - key: modernize-use-equals-delete.IgnoreMacros + value: 'true' + - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle + value: llvm + - key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros + value: 'true' + - key: bugprone-misplaced-widening-cast.CheckImplicitCasts + value: 'false' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnorePublicMemberVariables + value: 'false' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: performance-unnecessary-value-param.AllowedTypes + value: '' + - key: bugprone-suspicious-missing-comma.RatioThreshold + value: '0.200000' + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted + value: 'false' + - key: readability-uppercase-literal-suffix.NewSuffixes + value: '' + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: readability-function-cognitive-complexity.Threshold + value: '25' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: 'true' + - key: bugprone-argument-comment.IgnoreSingleArgument + value: '0' + - key: cppcoreguidelines-no-malloc.Allocations + value: '::malloc;::calloc' + - key: modernize-use-noexcept.UseNoexceptFalse + value: 'true' + - key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression + value: 'false' + - key: performance-faster-string-find.StringLikeClasses + value: '::std::basic_string;::std::basic_string_view' + - key: bugprone-assert-side-effect.CheckFunctionCalls + value: 'false' + - key: readability-function-size.BranchThreshold + value: '4294967295' + - key: bugprone-string-constructor.StringNames + value: '::std::basic_string;::std::basic_string_view' + - key: bugprone-assert-side-effect.AssertMacros + value: assert + - key: bugprone-exception-escape.IgnoredExceptions + value: '' + - key: readability-function-size.StatementThreshold + value: '800' + - key: modernize-use-default-member-init.IgnoreMacros + value: 'true' + - key: llvm-qualified-auto.AddConstToQualified + value: '0' + - key: bugprone-argument-comment.CommentStringLiterals + value: '0' + - key: readability-identifier-naming.IgnoreMainLikeFunctions + value: 'false' + - key: bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons + value: 'true' + - key: readability-implicit-bool-conversion.AllowIntegerConditions + value: 'false' + - key: cppcoreguidelines-init-variables.MathHeader + value: '' + - key: google-readability-function-size.StatementThreshold + value: '800' + - key: llvm-else-after-return.WarnOnConditionVariables + value: '0' + - key: bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant + value: 'true' + - key: bugprone-reserved-identifier.AggressiveDependentMemberLookup + value: 'false' + - key: modernize-raw-string-literal.DelimiterStem + value: lit + - key: modernize-use-equals-default.IgnoreMacros + value: 'true' + - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor + value: 'false' + - key: modernize-raw-string-literal.ReplaceShorterLiterals + value: 'false' + - key: modernize-use-emplace.SmartPointers + value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' + - key: cppcoreguidelines-no-malloc.Deallocations + value: '::free' + - key: modernize-use-auto.RemoveStars + value: 'false' + - key: bugprone-dangling-handle.HandleClasses + value: 'std::basic_string_view;std::experimental::basic_string_view' + - key: performance-inefficient-vector-operation.VectorLikeClasses + value: '::std::vector' + - key: portability-simd-intrinsics.Std + value: '' + - key: performance-unnecessary-value-param.IncludeStyle + value: llvm + - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors + value: 'false' + - key: modernize-replace-disallow-copy-and-assign-macro.MacroName + value: DISALLOW_COPY_AND_ASSIGN + - key: llvm-else-after-return.WarnOnUnfixable + value: '0' + - key: readability-simplify-subscript-expr.Types + value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' +... diff --git a/tests/lines_changed_only/files.json b/tests/capture_tools_output/event_files.json similarity index 100% rename from tests/lines_changed_only/files.json rename to tests/capture_tools_output/event_files.json diff --git a/tests/lines_changed_only/expected_result.json b/tests/capture_tools_output/expected_result.json similarity index 100% rename from tests/lines_changed_only/expected_result.json rename to tests/capture_tools_output/expected_result.json diff --git a/tests/database_path/test_database_path.py b/tests/capture_tools_output/test_database_path.py similarity index 95% rename from tests/database_path/test_database_path.py rename to tests/capture_tools_output/test_database_path.py index 54c2e1d4..fdd25ef1 100644 --- a/tests/database_path/test_database_path.py +++ b/tests/capture_tools_output/test_database_path.py @@ -27,11 +27,12 @@ ) def test_db_detection( caplog: pytest.LogCaptureFixture, + monkeypatch: pytest.MonkeyPatch, database: str, expected_args: List[str], ): """test clang-tidy using a implicit path to the compilation database.""" - os.chdir(str(Path(__file__).parent)) + monkeypatch.chdir(str(Path(__file__).parent)) demo_src = "../../demo/demo.cpp" rel_root = str(Path(*Path(__file__).parts[-2:])) cpp_linter.run.RUNNER_WORKSPACE = str( diff --git a/tests/capture_tools_output/test_tools_output.py b/tests/capture_tools_output/test_tools_output.py new file mode 100644 index 00000000..ea924465 --- /dev/null +++ b/tests/capture_tools_output/test_tools_output.py @@ -0,0 +1,196 @@ +"""Various tests related to the ``lines_changed_only`` option.""" +import os +import logging +from typing import Dict, Any, cast, List +from pathlib import Path +import json +import re +import pytest +import cpp_linter +from cpp_linter.run import ( + filter_out_non_source_files, + verify_files_are_present, + capture_clang_tools_output, + make_annotations, + log_commander, +) +from cpp_linter.thread_comments import list_diff_comments + +CLANG_VERSION = os.getenv("CLANG_VERSION", "12") + + +@pytest.mark.parametrize( + "extensions", [(["c"]), pytest.param(["h"], marks=pytest.mark.xfail)] +) +def test_lines_changed_only(extensions: List[str], monkeypatch: pytest.MonkeyPatch): + """Test for lines changes in diff. + + This checks for + 1. ranges of diff chunks. + 2. ranges of lines in diff that only contain additions. + """ + monkeypatch.chdir(str(Path(__file__).parent)) + cpp_linter.Globals.FILES = json.loads( + Path("event_files.json").read_text(encoding="utf-8") + ) + if filter_out_non_source_files( + ext_list=extensions, + ignored=[".github"], + not_ignored=[], + ): + test_result = Path("expected_result.json").read_text(encoding="utf-8") + for file, result in zip( + cpp_linter.Globals.FILES["files"], # type: ignore + json.loads(test_result)["files"], + ): + expected = result["line_filter"]["diff_chunks"] + assert file["line_filter"]["diff_chunks"] == expected + expected = result["line_filter"]["lines_added"] + assert file["line_filter"]["lines_added"] == expected + else: + raise RuntimeError("test failed to find files") + + +TEST_REPO = re.compile(r"https://api.github.com/repos/(?:\w|\-|_)+/((?:\w|\-|_)+)/.*") + + +@pytest.fixture(autouse=True) +def setup_test_repo(monkeypatch: pytest.MonkeyPatch) -> None: + """Setup a test repo to run the rest of the tests in this module.""" + test_root = Path(__file__).parent + cpp_linter.Globals.FILES = cast( + Dict[str, Any], + json.loads( + Path(test_root / "expected_result.json").read_text(encoding="utf-8") + ), + ) + # flush output from any previous tests + cpp_linter.Globals.OUTPUT = "" + cpp_linter.GlobalParser.format_advice = [] + cpp_linter.GlobalParser.tidy_notes = [] + cpp_linter.GlobalParser.tidy_advice = [] + + repo_root = TEST_REPO.sub("\\1", cpp_linter.Globals.FILES["url"]) + return_path = test_root / repo_root + if not return_path.exists(): + os.mkdir(str(return_path)) + monkeypatch.chdir(str(return_path)) + verify_files_are_present() + + +def match_file_json(filename: str) -> Dict[str, Any]: + """A helper function to match a given filename with a file's JSON object.""" + for file in cpp_linter.Globals.FILES["files"]: # type: ignore + if file["filename"] == filename: + return file + raise ValueError(f"file {filename} not found in expected_result.json") + + +RECORD_FILE = re.compile(r".*file=(.*?),.*") +FORMAT_RECORD = re.compile(r"Run clang-format on ") +FORMAT_RECORD_LINES = re.compile(r".*\(lines (.*)\).*") +TIDY_RECORD = re.compile(r":\d+:\d+ \[.*\]::") +TIDY_RECORD_LINE = re.compile(r".*,line=(\d+).*") + + +@pytest.mark.parametrize( + "lines_changed_only", [0, 1, 2], ids=["all lines", "only diff", "only added"] +) +@pytest.mark.parametrize("style", ["file", "llvm", "google"]) +def test_format_annotations( + caplog: pytest.LogCaptureFixture, + lines_changed_only: int, + style: str, +): + """Test clang-format annotations.""" + capture_clang_tools_output( + version=CLANG_VERSION, + checks="-*", # disable clang-tidy output + style=style, + lines_changed_only=lines_changed_only, + database="", + repo_root="", + ) + assert "Output from `clang-tidy`" not in cpp_linter.Globals.OUTPUT + caplog.set_level(logging.INFO, logger=log_commander.name) + make_annotations( + style=style, file_annotations=True, lines_changed_only=lines_changed_only + ) + for message in [r.message for r in caplog.records if r.levelno == logging.INFO]: + if FORMAT_RECORD.search(message) is not None: + lines = [ + int(l.strip()) + for l in FORMAT_RECORD_LINES.sub("\\1", message).split(",") + ] + file = match_file_json(RECORD_FILE.sub("\\1", message).replace("\\", "/")) + ranges = cpp_linter.range_of_changed_lines(file, lines_changed_only) + if ranges: # an empty list if lines_changed_only == 0 + for line in lines: + assert line in ranges + else: + raise RuntimeWarning(f"unrecognized record: {message}") + + +@pytest.mark.parametrize( + "lines_changed_only", [0, 1, 2], ids=["all lines", "only diff", "only added"] +) +@pytest.mark.parametrize( + "checks", + [ + "", + "boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*," + "clang-analyzer-*,cppcoreguidelines-*", + ], + ids=["config file", "action defaults"], +) +def test_tidy_annotations( + caplog: pytest.LogCaptureFixture, + lines_changed_only: int, + checks: str, +): + """Test clang-tidy annotations.""" + capture_clang_tools_output( + version=CLANG_VERSION, + checks=checks, + style="", # disable clang-format output + lines_changed_only=lines_changed_only, + database="", + repo_root="", + ) + assert "Run `clang-format` on the following files" not in cpp_linter.Globals.OUTPUT + caplog.set_level(logging.INFO, logger=log_commander.name) + make_annotations( + style="", file_annotations=True, lines_changed_only=lines_changed_only + ) + for message in [r.message for r in caplog.records if r.levelno == logging.INFO]: + if TIDY_RECORD.search(message) is not None: + line = int(TIDY_RECORD_LINE.sub("\\1", message)) + file = match_file_json(RECORD_FILE.sub("\\1", message).replace("\\", "/")) + ranges = cpp_linter.range_of_changed_lines(file, lines_changed_only) + if ranges: # an empty list if lines_changed_only == 0 + assert line in ranges + else: + raise RuntimeWarning(f"unrecognized record: {message}") + + +@pytest.mark.parametrize("lines_changed_only", [1, 2], ids=["only diff", "only added"]) +def test_diff_comment(lines_changed_only: int): + """Tests code that isn't actually used (yet) for posting + comments (not annotations) in the event's diff. + + Remember, diff comments should only focus on lines in the diff.""" + capture_clang_tools_output( + version=CLANG_VERSION, + checks="", + style="file", + lines_changed_only=lines_changed_only, + database="", + repo_root="", + ) + diff_comments = list_diff_comments(lines_changed_only) + # output = Path(__file__).parent / "diff_comments.json" + # output.write_text(json.dumps(diff_comments, indent=2), encoding="utf-8") + for comment in diff_comments: + file = match_file_json(cast(str, comment["path"])) + ranges = cpp_linter.range_of_changed_lines(file, lines_changed_only) + assert comment["line"] in ranges diff --git a/tests/ignored_paths/test_ignored_paths.py b/tests/ignored_paths/test_ignored_paths.py index 65dfb6ff..b27d3b8c 100644 --- a/tests/ignored_paths/test_ignored_paths.py +++ b/tests/ignored_paths/test_ignored_paths.py @@ -1,23 +1,31 @@ """Tests that focus on the ``ignore`` option's parsing.""" -import os -from cpp_linter.run import parse_ignore_option +from pathlib import Path +from typing import List +import pytest +from cpp_linter.run import parse_ignore_option, is_file_in_list -def test_ignored(): +@pytest.mark.parametrize( + "user_in,is_ignored,is_not_ignored,expected", + [ + ("src", "src", "src", [True, False]), + ("!src|./", "", "src", [True, True]), + ], +) +def test_ignore( + user_in: str, is_ignored: str, is_not_ignored: str, expected: List[bool] +): """test ignoring of a specified path.""" - ignored, not_ignored = parse_ignore_option("src") - assert "src" in ignored and not not_ignored + ignored, not_ignored = parse_ignore_option(user_in) + assert expected == [ + is_file_in_list(ignored, is_ignored, "ignored"), + is_file_in_list(not_ignored, is_not_ignored, "not ignored"), + ] -def test_not_ignored(): - """test explicit inclusion of a path and ignore the root path.""" - ignored, not_ignored = parse_ignore_option("!src|") - assert "src" in not_ignored and "" in ignored - - -def test_ignore_submodule(): +def test_ignore_submodule(monkeypatch: pytest.MonkeyPatch): """test auto detection of submodules and ignore the paths appropriately.""" - os.chdir(os.path.split(__file__)[0]) + monkeypatch.chdir(str(Path(__file__).parent)) ignored, not_ignored = parse_ignore_option("!pybind11") for ignored_submodule in ["RF24", "RF24Network", "RF24Mesh"]: assert ignored_submodule in ignored diff --git a/tests/lines_changed_only/test_lines_changed_only.py b/tests/lines_changed_only/test_lines_changed_only.py deleted file mode 100644 index da637ea8..00000000 --- a/tests/lines_changed_only/test_lines_changed_only.py +++ /dev/null @@ -1,113 +0,0 @@ -"""Various tests realated to the ``lines_changed_only`` option.""" -import os -import logging -from typing import Dict, Any, cast -from pathlib import Path -import json -import re -import pytest -import cpp_linter -from cpp_linter.clang_format_xml import parse_format_replacements_xml -from cpp_linter.run import ( - filter_out_non_source_files, - verify_files_are_present, - run_clang_format, - make_annotations, - log_commander, -) - - -def test_lines_changed_only(): - """Test for lines changes in diff. - - This checks for - 1. ranges of diff chunks. - 2. ranges of lines in diff that only contain additions. - """ - os.chdir(os.path.split(__file__)[0]) - cpp_linter.Globals.FILES = json.loads( - Path("files.json").read_text(encoding="utf-8") - ) - if filter_out_non_source_files( - ext_list=["h", "cpp", "c"], - ignored=[".github"], - not_ignored=[], - lines_changed_only=True, - ): - test_result = Path("expected_result.json").read_text(encoding="utf-8") - for file, result in zip( - cpp_linter.Globals.FILES["files"], - json.loads(test_result)["files"], - ): - expected = result["line_filter"]["diff_chunks"] - assert file["line_filter"]["diff_chunks"] == expected - expected = result["line_filter"]["lines_added"] - assert file["line_filter"]["lines_added"] == expected - else: - raise RuntimeError("test failed to find files") - - -TEST_REPO = re.compile( - "https://api.github.com/repos/(?:\\w|\\-|_)+/((?:\\w|\\-|_)+)/.*" -) - - -@pytest.mark.parametrize("lines_changed_only", [1, 2]) -def test_run_clang_format_on_diff( - caplog: pytest.LogCaptureFixture, lines_changed_only: int -): - """Using the output (expected_result.json) from ``test_lines_changed_only()``, - run clang-format with lines-changed-only set to accordingly. - - tested input values: - - - 1 = means entire diff chunks - - 2 = means only lines in diff containing additions - - This will make sure clang-format warnings are filtered to - only lines in the diff containing additions.""" - caplog.set_level(logging.INFO, logger=log_commander.name) - style = "file" # this test includes a custom style guide - range_focus = "lines_added" - if lines_changed_only == 1: - range_focus = "diff_chunks" - test_root = os.path.split(__file__)[0] - os.chdir(test_root) - cpp_linter.Globals.FILES = cast( - Dict[str, Any], - json.loads(Path("expected_result.json").read_text(encoding="utf-8")), - ) - repo_root = TEST_REPO.sub("\\1", cpp_linter.Globals.FILES["url"]) - if not os.path.exists(repo_root): - os.mkdir(repo_root) - os.chdir(os.path.join(test_root, repo_root)) - verify_files_are_present() - for file in cpp_linter.Globals.FILES["files"]: - filename: str = file["filename"] - run_clang_format( - filename=filename, - file_obj=file, - version="", - style=style, - lines_changed_only=lines_changed_only, - ) - if os.path.getsize("clang_format_output.xml"): - parse_format_replacements_xml(filename.replace("/", os.sep)) - make_annotations( - style=style, file_annotations=True, lines_changed_only=lines_changed_only - ) - record_lines = re.compile(r"\(lines (.*)\)") - record_file = re.compile(r"File (.*)\s") - for record in caplog.records: - if record_lines.search(record.message) is not None: - lines = [ - int(l.strip()) - for l in record_lines.sub("\\1", record.message).split(",") - ] - filename = record_file.sub("\\1", record.message) - for file in cpp_linter.Globals.FILES["files"]: - if file["filename"] == filename: - ranges = file["line_filter"][range_focus] - for line in lines: - assert line in [range(r[0], r[1]) for r in ranges] - break diff --git a/tests/test_misc.py b/tests/test_misc.py new file mode 100644 index 00000000..2bad68fe --- /dev/null +++ b/tests/test_misc.py @@ -0,0 +1,94 @@ +"""Tests that complete coverage that aren't prone to failure.""" +import logging +from pathlib import Path +from typing import List, cast, Dict, Any +import pytest +import requests +import cpp_linter +import cpp_linter.run +from cpp_linter import Globals, log_response_msg, get_line_cnt_from_cols +from cpp_linter.run import ( + log_commander, + start_log_group, + end_log_group, + set_exit_code, + list_source_files, + get_list_of_changed_files, +) + + +def test_exit_override(): + """Test exit code that indicates if action encountered lining errors.""" + assert 1 == set_exit_code(1) + + +def test_exit_implicit(): + """Test the exit code issued when a thread comment is to be made.""" + Globals.OUTPUT = "TEST" # fake content for a thread comment + assert 1 == set_exit_code() + + +# see https://github.com/pytest-dev/pytest/issues/5997 +def test_end_group(caplog: pytest.LogCaptureFixture): + """Test the output that concludes a group of runner logs.""" + caplog.set_level(logging.INFO, logger=log_commander.name) + end_log_group() + messages = caplog.messages + assert "::endgroup::" in messages + + +# see https://github.com/pytest-dev/pytest/issues/5997 +def test_start_group(caplog: pytest.LogCaptureFixture): + """Test the output that begins a group of runner logs.""" + caplog.set_level(logging.INFO, logger=log_commander.name) + start_log_group("TEST") + messages = caplog.messages + assert "::group::TEST" in messages + + +@pytest.mark.parametrize( + "url", + [ + ("https://api.github.com/users/cpp-linter/starred"), + pytest.param(("https://github.com/cpp-linter/repo"), marks=pytest.mark.xfail), + ], +) +def test_response_logs(url: str): + """Test the log output for a requests.response buffer.""" + Globals.response_buffer = requests.get(url) + assert log_response_msg() + + +@pytest.mark.parametrize( + "extensions", + [ + (["cpp", "hpp"]), + pytest.param(["cxx", "h"], marks=pytest.mark.xfail), + ], +) +def test_list_src_files(extensions: List[str]): + """List the source files in the demo folder of this repo.""" + Globals.FILES = [] + assert list_source_files(ext_list=extensions, ignored_paths=[], not_ignored=[]) + + +def test_get_changed_files(): + """test getting a list of changed files for an event. + + This is expected to fail if a github token not supplied as an env var. + We don't need to supply one for this test because the tested code will + execute anyway. + """ + cpp_linter.run.GITHUB_REPOSITORY = "cpp-linter/test-cpp-linter-action" + cpp_linter.GITHUB_SHA = "76adde5367196cd57da5bef49a4f09af6175fd3f" + get_list_of_changed_files() + # pylint: disable=no-member + assert "files" not in cast(Dict[str, Any], Globals.FILES).keys() + # pylint: enable=no-member + + +@pytest.mark.parametrize("line,cols,offset", [(13, 5, 144), (19, 1, 189)]) +def test_file_offset_translation(line: int, cols: int, offset: int): + """Validate output from ``get_line_cnt_from_cols()``""" + test_file = str(Path("demo/demo.cpp").resolve()) + assert (line, cols) == get_line_cnt_from_cols(test_file, offset) From d51d8c9f9d9cb14fd68fbadd3aa84f6f9f8f8172 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 4 Aug 2022 23:15:12 -0700 Subject: [PATCH 34/76] mkdocstring doesn't support `Tuple[x, x]` type see mkdocstrings/griffe/#95 --- cpp_linter/run.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 13702984..72e93b0f 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -16,7 +16,7 @@ import argparse import configparser import json -from typing import cast, List, Dict, Any, Tuple +from typing import cast, List, Dict, Any # , Tuple import requests from . import ( Globals, @@ -171,7 +171,7 @@ def set_exit_code(override: int = None) -> int: log_commander.setLevel(logging.DEBUG) # be sure that log commands are output console_handler = logging.StreamHandler() # Create special stdout stream handler console_handler.setFormatter(logging.Formatter("%(message)s")) # no formatted log cmds -log_commander.handlers = [console_handler] # Use special handler for log_commander +log_commander.addHandler(console_handler) # Use special handler for log_commander def start_log_group(name: str) -> None: @@ -261,8 +261,6 @@ def filter_out_non_source_files( ext_list: A list of file extensions that are to be examined. ignored: A list of paths to explicitly ignore. not_ignored: A list of paths to explicitly not ignore. - lines_changed_only: A flag that forces focus on only changes in the event's - diff info. Returns: True if there are files to check. False will invoke a early exit (in @@ -812,7 +810,7 @@ def make_annotations( return bool(count) -def parse_ignore_option(paths: str) -> Tuple[List[str], List[str]]: +def parse_ignore_option(paths: str) -> tuple: # -> Tuple[List[str], List[str]]: """Parse a given string of paths (separated by a '|') into `ignored` and `not_ignored` lists of strings. From d5e39697f3ebb7a59d8237c3c96035f5b8663950 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 4 Aug 2022 23:15:39 -0700 Subject: [PATCH 35/76] fix workflow --- .github/workflows/run-dev-tests.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index e443a56f..ce23d90f 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -37,21 +37,21 @@ jobs: - tools_dir: 'N/A' - os: 'windows-latest' version: '10' - tools_dir: ${{ runner.temp }}/llvm + tools_dir: temp - os: 'windows-latest' version: '10' - tools_dir: ${{ runner.temp }}/llvm + tools_dir: temp - os: 'windows-latest' version: '11' - tools_dir: ${{ runner.temp }}/llvm + tools_dir: temp - os: 'windows-latest' version: '12' - tools_dir: ${{ runner.temp }}/llvm + tools_dir: temp - os: 'ubuntu-latest' version: '13' - tools_dir: ${{ runner.temp }}/llvm + tools_dir: temp - version: '14' - tools_dir: ${{ runner.temp }}/llvm + tools_dir: temp runs-on: ${{ matrix.os }} steps: @@ -65,17 +65,17 @@ jobs: run: python3 -m pip install pytest coverage . # - name: Install clang-tools - # if: matrix.tools_dir != 'N/A' + # if: matrix.tools_dir == 'temp' # run: | # python -m pip install clang-tools - # clang-tools --install ${{ matrix.version }} --directory ${{ matrix.tools_dir }} + # clang-tools --install ${{ matrix.version }} --directory ${{ runner.temp }}/llvm - name: Install clang-tools uses: KyleMayes/install-llvm-action@v1 - if: matrix.tools_dir != 'N/A' + if: matrix.tools_dir == 'temp' with: version: ${{ matrix.version }} - directory: ${{ matrix.tools_dir }} + directory: ${{ runner.temp }}/llvm - name: Collect Coverage (native clang) if: matrix.tools_dir == 'N/A' || matrix.os == 'ubuntu-latest' @@ -84,9 +84,9 @@ jobs: run: coverage run -m pytest -vv tests - name: Collect Coverage (non-native clang windows) - if: matrix.tools_dir != 'N/A' && matrix.os = 'windows-latest' + if: matrix.tools_dir == 'temp' && matrix.os == 'windows-latest' env: - CLANG_VERSION: ${{ matrix.tools.dir }} + CLANG_VERSION: ${{ runner.temp }}/llvm run: coverage run -m pytest -vv tests - run: coverage report && coverage xml @@ -99,6 +99,6 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos files: ./coverage.xml - flags: unittests # optional + env_vars: OS,PYTHON,CLANG # optional fail_ci_if_error: true # optional (default = false) verbose: true # optional (default = false) \ No newline at end of file From ae5bcae49fb8119948cf27ccb9ca78ec796b64ad Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 5 Aug 2022 00:49:16 -0700 Subject: [PATCH 36/76] revert changes to `get_line_cnt_from_cols()` --- cpp_linter/__init__.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index 3421c4f2..438b51f1 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -1,7 +1,7 @@ """The Base module of the `cpp_linter` package. This holds the objects shared by multiple modules.""" import os -from pathlib import Path +import io import logging from typing import TYPE_CHECKING, List, Dict, Union, Any from requests import Response @@ -85,10 +85,21 @@ def get_line_cnt_from_cols(file_path: str, offset: int) -> tuple: - Index 0 is the line number for the given offset. - Index 1 is the column number for the given offset on the line. """ + line_cnt = 1 + last_lf_pos = 0 + cols = 1 file_path = file_path.replace("/", os.sep) # logger.debug("Getting line count from %s at offset %d", file_path, offset) - contents = Path(file_path).read_bytes()[:offset] - return (contents.count(b"\n") + 1, offset - contents.rfind(b"\n")) + with io.open(file_path, "rb") as src_file: + max_len = src_file.seek(0, io.SEEK_END) + src_file.seek(0, io.SEEK_SET) + while src_file.tell() != offset and src_file.tell() < max_len: + char = src_file.read(1) + if char == b"\n": + line_cnt += 1 + last_lf_pos = src_file.tell() - 1 # -1 because LF is part of offset + cols = src_file.tell() - last_lf_pos + return (line_cnt, cols) def range_of_changed_lines( From 8851435408a517083dba7465901693df2e651f58 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 5 Aug 2022 01:47:10 -0700 Subject: [PATCH 37/76] upload without codecov token?? --- .github/workflows/run-dev-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index ce23d90f..2a56103e 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -97,7 +97,7 @@ jobs: PYTHON: CPy${{ matrix.py }} CLANG: LLVM-v${{ matrix.version }} with: - token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos + # token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos files: ./coverage.xml env_vars: OS,PYTHON,CLANG # optional fail_ci_if_error: true # optional (default = false) From 20f0be0d931613c9c178c12e1922fcb27d8ba49c Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 5 Aug 2022 02:07:59 -0700 Subject: [PATCH 38/76] ensure LF used on demo src --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitattributes b/.gitattributes index e1a14d22..f7c5d6a8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,3 +6,5 @@ *.py text eol=lf *.rst text eol=lf *.sh text eol=lf +*.cpp text eol=lf +*.hpp text eol=lf From 540a7d737e42911f07a0da96c580fc36486e1242 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 5 Aug 2022 02:20:19 -0700 Subject: [PATCH 39/76] update workflow --- .github/workflows/run-dev-tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 2a56103e..14ee0ccc 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -97,7 +97,6 @@ jobs: PYTHON: CPy${{ matrix.py }} CLANG: LLVM-v${{ matrix.version }} with: - # token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos files: ./coverage.xml env_vars: OS,PYTHON,CLANG # optional fail_ci_if_error: true # optional (default = false) From f8d03abff7de3fefb5d10aa7d3c80c176fea5b15 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 5 Aug 2022 03:15:25 -0700 Subject: [PATCH 40/76] re-implement newer `get_line_cnt_from_cols()` --- cpp_linter/__init__.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index 438b51f1..dd2615d2 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -1,7 +1,7 @@ """The Base module of the `cpp_linter` package. This holds the objects shared by multiple modules.""" import os -import io +from pathlib import Path import logging from typing import TYPE_CHECKING, List, Dict, Union, Any from requests import Response @@ -85,21 +85,9 @@ def get_line_cnt_from_cols(file_path: str, offset: int) -> tuple: - Index 0 is the line number for the given offset. - Index 1 is the column number for the given offset on the line. """ - line_cnt = 1 - last_lf_pos = 0 - cols = 1 - file_path = file_path.replace("/", os.sep) # logger.debug("Getting line count from %s at offset %d", file_path, offset) - with io.open(file_path, "rb") as src_file: - max_len = src_file.seek(0, io.SEEK_END) - src_file.seek(0, io.SEEK_SET) - while src_file.tell() != offset and src_file.tell() < max_len: - char = src_file.read(1) - if char == b"\n": - line_cnt += 1 - last_lf_pos = src_file.tell() - 1 # -1 because LF is part of offset - cols = src_file.tell() - last_lf_pos - return (line_cnt, cols) + contents = Path(file_path.replace("/", os.sep)).read_bytes()[:offset] + return (contents.count(b"\n") + 1, offset - contents.rfind(b"\n")) def range_of_changed_lines( From d88b54c299be4da0e960271f9654b2c0d64dc2e3 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sun, 7 Aug 2022 12:24:38 -0700 Subject: [PATCH 41/76] switch to pyproject.toml (setup.py is a dummy now) --- .pylintrc | 396 ----------------------- Dockerfile | 2 +- coverage.json | 840 ------------------------------------------------- mypy.ini | 3 - pyproject.toml | 580 ++++++++++++++++++++++++++++++++++ setup.py | 42 +-- 6 files changed, 588 insertions(+), 1275 deletions(-) delete mode 100644 .pylintrc delete mode 100644 coverage.json delete mode 100644 mypy.ini create mode 100644 pyproject.toml diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 691bf317..00000000 --- a/.pylintrc +++ /dev/null @@ -1,396 +0,0 @@ -[MASTER] - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code -extension-pkg-whitelist= - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the blacklist. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. -# jobs=1 -jobs=2 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - -# Pickle collected data for later comparisons. -persistent=yes - -# Specify a configuration file. -#rcfile= - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -# disable=print-statement,parameter-unpacking,unpacking-in-except,backtick,long-suffix,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,bad-whitespace -disable=invalid-sequence-index,anomalous-backslash-in-string,too-few-public-methods,consider-using-f-string,subprocess-run-check - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable= - - -[REPORTS] - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -#msg-template= - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio).You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages -reports=no - -# Activate the evaluation score. -score=yes - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - - -[SPELLING] - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -# notes=FIXME,XXX,TODO -notes=FIXME,XXX - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis. It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_,_cb,_callback - -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,future.builtins - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -# expected-line-ending-format= -expected-line-ending-format=LF - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=88 - -# Maximum number of lines in a module -max-module-lines=1000 - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - -# Minimum lines number of a similarity. -min-similarity-lines=4 - - -[BASIC] - -# Regular expression matching correct argument names -argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct attribute names -attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Regular expression matching correct class names -# class-rgx=[A-Z_][a-zA-Z0-9]+$ -class-rgx=[A-Z_][a-zA-Z0-9_]+$ - -# Regular expression matching correct constant names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Regular expression matching correct function names -function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Good variable names which should always be accepted, separated by a comma -# good-names=i,j,k,ex,Run,_ -good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_ - -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no - -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Regular expression matching correct method names -method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty - -# Regular expression matching correct variable names -variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - - -[IMPORTS] - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=optparse,tkinter.tix - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=8 - -# Maximum number of attributes for a class (see R0902). -# max-attributes=7 -max-attributes=11 - -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 - -# Maximum number of branch for function / method body -max-branches=12 - -# Maximum number of locals for function / method body -max-locals=18 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of statements in function / method body -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=1 - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception diff --git a/Dockerfile b/Dockerfile index 2ac40d28..fbb6128b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ LABEL maintainer="shenxianpeng <20297606+shenxianpeng@users.noreply.github.com>" RUN apt-get update && apt-get -y install python3-pip COPY cpp_linter/ pkg/cpp_linter/ -COPY setup.py pkg/setup.py +COPY pyproject.toml pkg/pyproject.toml RUN python3 -m pip install pkg/ # github action args use the CMD option diff --git a/coverage.json b/coverage.json deleted file mode 100644 index 8a2590bf..00000000 --- a/coverage.json +++ /dev/null @@ -1,840 +0,0 @@ -{ - "meta": { - "version": "6.4.2", - "timestamp": "2022-08-04T20:24:06.401053", - "branch_coverage": false, - "show_contexts": false - }, - "files": { - "cpp_linter\\__init__.py": { - "executed_lines": [ - 1, - 3, - 4, - 5, - 6, - 7, - 9, - 14, - 15, - 16, - 18, - 20, - 29, - 30, - 34, - 35, - 36, - 37, - 40, - 41, - 44, - 45, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 59, - 60, - 64, - 65, - 67, - 68, - 70, - 71, - 75, - 88, - 90, - 91, - 94, - 110, - 111, - 114, - 115, - 118, - 124, - 125, - 130, - 131 - ], - "summary": { - "covered_lines": 49, - "num_statements": 49, - "percent_covered": 100.0, - "percent_covered_display": "100", - "missing_lines": 0, - "excluded_lines": 8 - }, - "missing_lines": [], - "excluded_lines": [ - 9, - 10, - 11, - 12, - 25, - 26, - 30, - 31 - ] - }, - "cpp_linter\\clang_format_xml.py": { - "executed_lines": [ - 1, - 2, - 3, - 4, - 5, - 8, - 9, - 17, - 24, - 25, - 26, - 28, - 35, - 36, - 45, - 50, - 51, - 53, - 60, - 61, - 71, - 77, - 78, - 80, - 86, - 100, - 102, - 104, - 105, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 125, - 133, - 134, - 135, - 136, - 137, - 138, - 139, - 140, - 141, - 142, - 145, - 146, - 147, - 148, - 149, - 150 - ], - "summary": { - "covered_lines": 47, - "num_statements": 47, - "percent_covered": 100.0, - "percent_covered_display": "100", - "missing_lines": 0, - "excluded_lines": 6 - }, - "missing_lines": [], - "excluded_lines": [ - 28, - 29, - 53, - 54, - 80, - 81 - ] - }, - "cpp_linter\\clang_tidy.py": { - "executed_lines": [ - 1, - 2, - 3, - 4, - 5, - 7, - 10, - 11, - 25, - 36, - 45, - 46, - 47, - 48, - 49, - 50, - 52, - 53, - 54, - 55, - 59, - 72, - 83, - 84, - 97, - 99, - 100, - 101, - 102, - 103, - 104, - 110, - 111, - 114 - ], - "summary": { - "covered_lines": 27, - "num_statements": 27, - "percent_covered": 100.0, - "percent_covered_display": "100", - "missing_lines": 0, - "excluded_lines": 5 - }, - "missing_lines": [], - "excluded_lines": [ - 52, - 53, - 54, - 55, - 59 - ] - }, - "cpp_linter\\clang_tidy_yml.py": { - "executed_lines": [ - 1, - 2, - 3, - 4, - 5, - 8, - 13, - 14, - 28, - 33, - 34, - 35, - 36, - 37, - 38, - 40, - 48, - 49, - 58, - 65, - 66, - 67, - 68, - 70, - 77, - 78, - 86, - 91, - 92, - 94, - 101, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 115, - 116, - 119, - 120, - 121, - 126, - 127, - 129 - ], - "summary": { - "covered_lines": 40, - "num_statements": 42, - "percent_covered": 95.23809523809524, - "percent_covered_display": "95", - "missing_lines": 2, - "excluded_lines": 7 - }, - "missing_lines": [ - 122, - 125 - ], - "excluded_lines": [ - 40, - 41, - 42, - 70, - 71, - 94, - 95 - ] - }, - "cpp_linter\\run.py": { - "executed_lines": [ - 1, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 32, - 33, - 34, - 35, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 49, - 52, - 59, - 72, - 79, - 87, - 95, - 103, - 110, - 119, - 128, - 136, - 144, - 154, - 164, - 165, - 166, - 170, - 171, - 172, - 173, - 174, - 177, - 183, - 186, - 188, - 191, - 204, - 205, - 206, - 207, - 215, - 216, - 219, - 222, - 223, - 224, - 227, - 228, - 232, - 233, - 234, - 237, - 240, - 241, - 242, - 243, - 244, - 245, - 246, - 247, - 248, - 249, - 252, - 271, - 272, - 277, - 285, - 288, - 290, - 291, - 292, - 293, - 294, - 295, - 296, - 297, - 298, - 299, - 300, - 301, - 302, - 306, - 308, - 309, - 313, - 316, - 317, - 318, - 320, - 322, - 323, - 324, - 327, - 335, - 340, - 341, - 342, - 343, - 344, - 346, - 347, - 348, - 351, - 366, - 368, - 369, - 370, - 371, - 372, - 373, - 374, - 376, - 377, - 378, - 379, - 380, - 381, - 382, - 383, - 384, - 385, - 388, - 392, - 393, - 400, - 401, - 402, - 405, - 425, - 427, - 428, - 429, - 430, - 434, - 435, - 436, - 441, - 442, - 443, - 444, - 445, - 446, - 449, - 450, - 451, - 452, - 453, - 454, - 455, - 456, - 457, - 458, - 459, - 460, - 461, - 462, - 463, - 464, - 465, - 466, - 471, - 489, - 490, - 491, - 492, - 497, - 498, - 499, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 519, - 536, - 537, - 538, - 539, - 540, - 541, - 542, - 543, - 544, - 545, - 546, - 547, - 548, - 549, - 550, - 552, - 553, - 554, - 555, - 556, - 557, - 561, - 562, - 563, - 564, - 565, - 566, - 567, - 568, - 571, - 592, - 593, - 598, - 599, - 601, - 602, - 605, - 606, - 608, - 610, - 611, - 612, - 614, - 615, - 616, - 617, - 620, - 647, - 724, - 751, - 774, - 784, - 785, - 790, - 791, - 792, - 793, - 794, - 795, - 796, - 797, - 798, - 799, - 800, - 801, - 802, - 803, - 804, - 805, - 806, - 808, - 809, - 810, - 811, - 812, - 815, - 827, - 829, - 830, - 831, - 832, - 833, - 834, - 835, - 837, - 840, - 841, - 842, - 843, - 844, - 845, - 846, - 847, - 848, - 850, - 851, - 855, - 856, - 860, - 863, - 929 - ], - "summary": { - "covered_lines": 290, - "num_statements": 363, - "percent_covered": 79.88980716253444, - "percent_covered_display": "80", - "missing_lines": 73, - "excluded_lines": 35 - }, - "missing_lines": [ - 225, - 314, - 437, - 438, - 439, - 440, - 500, - 501, - 502, - 503, - 514, - 600, - 631, - 632, - 634, - 635, - 636, - 637, - 640, - 643, - 644, - 658, - 659, - 660, - 668, - 669, - 670, - 672, - 673, - 674, - 677, - 679, - 680, - 681, - 682, - 687, - 688, - 689, - 691, - 692, - 693, - 694, - 697, - 698, - 699, - 704, - 710, - 712, - 715, - 720, - 721, - 735, - 736, - 737, - 738, - 739, - 740, - 743, - 746, - 747, - 748, - 759, - 760, - 761, - 763, - 764, - 765, - 766, - 767, - 768, - 769, - 770, - 771 - ], - "excluded_lines": [ - 863, - 864, - 867, - 870, - 873, - 875, - 878, - 881, - 882, - 883, - 884, - 885, - 886, - 888, - 889, - 890, - 891, - 896, - 897, - 898, - 899, - 900, - 901, - 902, - 904, - 913, - 914, - 915, - 916, - 919, - 920, - 921, - 926, - 929, - 930 - ] - }, - "cpp_linter\\thread_comments.py": { - "executed_lines": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 18, - 60, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 72, - 73, - 76, - 78, - 81, - 82, - 83, - 84, - 85, - 86, - 87, - 88, - 92, - 99, - 100, - 102, - 103, - 104, - 106, - 115, - 118, - 121, - 122, - 123, - 126, - 128, - 131, - 132, - 134, - 135, - 136, - 139, - 140, - 142, - 146, - 153, - 155, - 156, - 160, - 169, - 172, - 177, - 179, - 180, - 181, - 185, - 186, - 187, - 189, - 190, - 191, - 194, - 201, - 207, - 244 - ], - "summary": { - "covered_lines": 70, - "num_statements": 111, - "percent_covered": 63.06306306306306, - "percent_covered_display": "63", - "missing_lines": 41, - "excluded_lines": 0 - }, - "missing_lines": [ - 26, - 27, - 28, - 29, - 30, - 31, - 34, - 40, - 44, - 49, - 50, - 56, - 57, - 89, - 90, - 91, - 93, - 94, - 147, - 148, - 151, - 216, - 217, - 218, - 219, - 220, - 231, - 235, - 236, - 237, - 238, - 239, - 240, - 241, - 254, - 255, - 256, - 259, - 260, - 262, - 263 - ], - "excluded_lines": [] - } - }, - "totals": { - "covered_lines": 523, - "num_statements": 639, - "percent_covered": 81.84663536776213, - "percent_covered_display": "82", - "missing_lines": 116, - "excluded_lines": 61 - } -} \ No newline at end of file diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index abf2e2e4..00000000 --- a/mypy.ini +++ /dev/null @@ -1,3 +0,0 @@ -[mypy] -show_error_codes = true -pretty = true diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..ad4be938 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,580 @@ +[build-system] +requires = ["setuptools>=45", "setuptools-scm"] +build-backend = "setuptools.build_meta" + +[project] +name = "cpp_linter" +description = "Install clang-tools (clang-format, clang-tidy) with pip" +readme = "README.md" +keywords = ["clang", "clang-tools", "clang-extra", "clang-tidy", "clang-format"] +license = {text = "MIT License"} +authors = [ + { name = "Brendan Doherty", email = "2bndy5@gmail.com" }, + { name = "Peter Shen", email = "xianpeng.shen@gmail.com" }, +] +dependencies = [ + "requests", + "pyyaml", +] +classifiers = [ + # https://pypi.org/pypi?%3Aaction=list_classifiers + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: MIT License", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "Intended Audience :: Information Technology", + "Natural Language :: English", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS", + "Programming Language :: Python :: 3", + "Topic :: Software Development :: Build Tools", +] +dynamic = ["version"] + +[project.scripts] +cpp-linter = "cpp_linter.run:main" + +[project.urls] +source = "https://github.com/cpp-linter/cpp-linter-action" +tracker = "https://github.com/cpp-linter/cpp-linter-action/issues" + +# ... other project metadata fields as specified in: +# https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ + +[tool.setuptools] +zip-safe = false +packages = ["cpp_linter"] + +[tool.setuptools_scm] +# It would be nice to include the commit hash in the version, but that +# can't be done in a PEP 440-compatible way. +version_scheme= "no-guess-dev" +# Test PyPI does not support local versions. +local_scheme = "no-local-version" +fallback_version = "0.0.0" + +[tool.mypy] +show_error_codes = true +show_column_numbers = true + +[tool.pylint.main] +# Analyse import fallback blocks. This can be used to support both Python 2 and 3 +# compatible code, which means that the block might have code that exists only in +# one or another interpreter, leading to false positives when analysed. +# analyse-fallback-blocks = + +# Always return a 0 (non-error) status code, even if lint errors are found. This +# is primarily useful in continuous integration scripts. +# exit-zero = + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +# extension-pkg-allow-list = + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. (This is an alternative name to extension-pkg-allow-list +# for backward compatibility.) +# extension-pkg-whitelist = + +# Return non-zero exit code if any of these messages/categories are detected, +# even if score is above --fail-under value. Syntax same as enable. Messages +# specified are enabled, while categories only check already-enabled messages. +# fail-on = + +# Specify a score threshold to be exceeded before program exits with error. +fail-under = 10 + +# Interpret the stdin as a python script, whose filename needs to be passed as +# the module_or_package argument. +# from-stdin = + +# Files or directories to be skipped. They should be base names, not paths. +ignore = ["CVS"] + +# Add files or directories matching the regex patterns to the ignore-list. The +# regex matches against paths and can be in Posix or Windows format. +# ignore-paths = + +# Files or directories matching the regex patterns are skipped. The regex matches +# against base names, not paths. The default value ignores Emacs file locks +# ignore-patterns = + +# List of module names for which member attributes should not be checked (useful +# for modules/projects where namespaces are manipulated during runtime and thus +# existing member attributes cannot be deduced by static analysis). It supports +# qualified module names, as well as Unix pattern matching. +# ignored-modules = + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +# init-hook = + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use. +jobs = 2 + +# Control the amount of potential inferred values when inferring a single object. +# This can help the performance when dealing with large functions or complex, +# nested conditions. +limit-inference-results = 100 + +# List of plugins (as comma separated values of python module names) to load, +# usually to register additional checkers. +# load-plugins = + +# Pickle collected data for later comparisons. +persistent = true + +# Minimum Python version to use for version dependent checks. Will default to the +# version used to run pylint. +py-version = "3.10" + +# Discover python modules and packages in the file system subtree. +# recursive = + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages. +suggestion-mode = true + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +# unsafe-load-any-extension = + +[tool.pylint.basic] +# Naming style matching correct argument names. +argument-naming-style = "snake_case" + +# Regular expression matching correct argument names. Overrides argument-naming- +# style. If left empty, argument names will be checked with the set naming style. +argument-rgx = "(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$" + +# Naming style matching correct attribute names. +attr-naming-style = "snake_case" + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. If left empty, attribute names will be checked with the set naming +# style. +attr-rgx = "(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$" + +# Bad variable names which should always be refused, separated by a comma. +bad-names = ["foo", "bar", "baz", "toto", "tutu", "tata"] + +# Bad variable names regexes, separated by a comma. If names match any regex, +# they will always be refused +# bad-names-rgxs = + +# Naming style matching correct class attribute names. +class-attribute-naming-style = "any" + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. If left empty, class attribute names will be checked +# with the set naming style. +class-attribute-rgx = "([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$" + +# Naming style matching correct class constant names. +class-const-naming-style = "UPPER_CASE" + +# Regular expression matching correct class constant names. Overrides class- +# const-naming-style. If left empty, class constant names will be checked with +# the set naming style. +# class-const-rgx = + +# Naming style matching correct class names. +class-naming-style = "PascalCase" + +# Regular expression matching correct class names. Overrides class-naming-style. +# If left empty, class names will be checked with the set naming style. +class-rgx = "[A-Z_][a-zA-Z0-9_]+$" + +# Naming style matching correct constant names. +const-naming-style = "UPPER_CASE" + +# Regular expression matching correct constant names. Overrides const-naming- +# style. If left empty, constant names will be checked with the set naming style. +const-rgx = "(([A-Z_][A-Z0-9_]*)|(__.*__))$" + +# Minimum line length for functions/classes that require docstrings, shorter ones +# are exempt. +docstring-min-length = -1 + +# Naming style matching correct function names. +function-naming-style = "snake_case" + +# Regular expression matching correct function names. Overrides function-naming- +# style. If left empty, function names will be checked with the set naming style. +function-rgx = "(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$" + +# Good variable names which should always be accepted, separated by a comma. +good-names = ["r", "g", "b", "w", "i", "j", "k", "n", "x", "y", "z", "ex", "ok", "Run", "_"] + +# Good variable names regexes, separated by a comma. If names match any regex, +# they will always be accepted +# good-names-rgxs = + +# Include a hint for the correct naming format with invalid-name. +# include-naming-hint = + +# Naming style matching correct inline iteration names. +inlinevar-naming-style = "any" + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. If left empty, inline iteration names will be checked +# with the set naming style. +inlinevar-rgx = "[A-Za-z_][A-Za-z0-9_]*$" + +# Naming style matching correct method names. +method-naming-style = "snake_case" + +# Regular expression matching correct method names. Overrides method-naming- +# style. If left empty, method names will be checked with the set naming style. +method-rgx = "(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$" + +# Naming style matching correct module names. +module-naming-style = "snake_case" + +# Regular expression matching correct module names. Overrides module-naming- +# style. If left empty, module names will be checked with the set naming style. +module-rgx = "(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$" + +# Colon-delimited sets of names that determine each other's naming style when the +# name regexes allow several styles. +# name-group = + +# Regular expression which should only match function or class names that do not +# require a docstring. +no-docstring-rgx = "^_" + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. These +# decorators are taken in consideration only for invalid-name. +property-classes = ["abc.abstractproperty"] + +# Regular expression matching correct type variable names. If left empty, type +# variable names will be checked with the set naming style. +# typevar-rgx = + +# Naming style matching correct variable names. +variable-naming-style = "snake_case" + +# Regular expression matching correct variable names. Overrides variable-naming- +# style. If left empty, variable names will be checked with the set naming style. +variable-rgx = "(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$" + +[tool.pylint.classes] +# Warn about protected attribute access inside special methods +# check-protected-access-in-special-methods = + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods = ["__init__", "__new__", "setUp"] + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected = ["_asdict", "_fields", "_replace", "_source", "_make"] + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg = ["cls"] + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg = ["mcs"] + +[tool.pylint.design] +# List of regular expressions of class ancestor names to ignore when counting +# public methods (see R0903) +# exclude-too-few-public-methods = + +# List of qualified class names to ignore when counting class parents (see R0901) +# ignored-parents = + +# Maximum number of arguments for function / method. +max-args = 8 + +# Maximum number of attributes for a class (see R0902). +max-attributes = 11 + +# Maximum number of boolean expressions in an if statement (see R0916). +max-bool-expr = 5 + +# Maximum number of branch for function / method body. +max-branches = 12 + +# Maximum number of locals for function / method body. +max-locals = 18 + +# Maximum number of parents for a class (see R0901). +max-parents = 7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods = 20 + +# Maximum number of return / yield for function / method body. +max-returns = 6 + +# Maximum number of statements in function / method body. +max-statements = 50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods = 1 + +[tool.pylint.exceptions] +# Exceptions that will emit a warning when caught. +overgeneral-exceptions = ["Exception"] + +[tool.pylint.format] +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format = "LF" + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines = "^\\s*(# )??$" + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren = 4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string = " " + +# Maximum number of characters on a single line. +max-line-length = 88 + +# Maximum number of lines in a module. +max-module-lines = 1000 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +# single-line-class-stmt = + +# Allow the body of an if to be on the same line as the test if there is no else. +# single-line-if-stmt = + +[tool.pylint.imports] +# List of modules that can be imported at any level, not just the top level one. +# allow-any-import-level = + +# Allow wildcard imports from modules that define __all__. +# allow-wildcard-with-all = + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules = ["optparse", "tkinter.tix"] + +# Output a graph (.gv or any supported image format) of external dependencies to +# the given file (report RP0402 must not be disabled). +# ext-import-graph = + +# Output a graph (.gv or any supported image format) of all (i.e. internal and +# external) dependencies to the given file (report RP0402 must not be disabled). +# import-graph = + +# Output a graph (.gv or any supported image format) of internal dependencies to +# the given file (report RP0402 must not be disabled). +# int-import-graph = + +# Force import order to recognize a module as part of the standard compatibility +# libraries. +# known-standard-library = + +# Force import order to recognize a module as part of a third party library. +known-third-party = ["enchant"] + +# Couples of modules and preferred modules, separated by a comma. +# preferred-modules = + +[tool.pylint.logging] +# The type of string formatting that logging methods do. `old` means using % +# formatting, `new` is for `{}` formatting. +logging-format-style = "old" + +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules = ["logging"] + +[tool.pylint."messages control"] +# Only show warnings with the listed confidence levels. Leave empty to show all. +# Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, UNDEFINED. +confidence = ["HIGH", "CONTROL_FLOW", "INFERENCE", "INFERENCE_FAILURE", "UNDEFINED"] + +# Disable the message, report, category or checker with the given id(s). You can +# either give multiple identifiers separated by comma (,) or put this option +# multiple times (only on the command line, not in the configuration file where +# it should appear only once). You can also use "--disable=all" to disable +# everything first and then re-enable specific checks. For example, if you want +# to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable = ["raw-checker-failed", "bad-inline-option", "locally-disabled", "file-ignored", "suppressed-message", "useless-suppression", "deprecated-pragma", "use-symbolic-message-instead", "invalid-sequence-index", "anomalous-backslash-in-string", "too-few-public-methods", "consider-using-f-string", "subprocess-run-check"] + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where it +# should appear only once). See also the "--disable" option for examples. +enable = ["c-extension-no-member"] + +[tool.pylint.miscellaneous] +# List of note tags to take in consideration, separated by a comma. +notes = ["FIXME", "XXX"] + +# Regular expression of note tags to take in consideration. +# notes-rgx = + +[tool.pylint.refactoring] +# Maximum number of nested blocks for function / method body +max-nested-blocks = 5 + +# Complete name of functions that never returns. When checking for inconsistent- +# return-statements if a never returning function is called then it will be +# considered as an explicit return statement and no message will be printed. +never-returning-functions = ["sys.exit", "argparse.parse_error"] + +[tool.pylint.reports] +# Python expression which should return a score less than or equal to 10. You +# have access to the variables 'fatal', 'error', 'warning', 'refactor', +# 'convention', and 'info' which contain the number of messages in each category, +# as well as 'statement' which is the total number of statements analyzed. This +# score is used by the global evaluation report (RP0004). +evaluation = "10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)" + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details. +# msg-template = + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio). You can also give a reporter class, e.g. +# mypackage.mymodule.MyReporterClass. +# output-format = + +# Tells whether to display a full report or only the messages. +# reports = + +# Activate the evaluation score. +score = true + +[tool.pylint.similarities] +# Comments are removed from the similarity computation +ignore-comments = true + +# Docstrings are removed from the similarity computation +ignore-docstrings = true + +# Imports are removed from the similarity computation +# ignore-imports = + +# Signatures are removed from the similarity computation +ignore-signatures = true + +# Minimum lines number of a similarity. +min-similarity-lines = 4 + +[tool.pylint.spelling] +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions = 4 + +# Spelling dictionary name. Available dictionaries: none. To make it work, +# install the 'python-enchant' package. +# spelling-dict = + +# List of comma separated words that should be considered directives if they +# appear at the beginning of a comment and should not be checked. +spelling-ignore-comment-directives = "fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:" + +# List of comma separated words that should not be checked. +# spelling-ignore-words = + +# A path to a file that contains the private dictionary; one word per line. +# spelling-private-dict-file = + +# Tells whether to store unknown words to the private dictionary (see the +# --spelling-private-dict-file option) instead of raising a message. +# spelling-store-unknown-words = + +[tool.pylint.string] +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +# check-quote-consistency = + +# This flag controls whether the implicit-str-concat should generate a warning on +# implicit string concatenation in sequences defined over several lines. +# check-str-concat-over-line-jumps = + +[tool.pylint.typecheck] +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators = ["contextlib.contextmanager"] + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +# generated-members = + +# Tells whether missing members accessed in mixin class should be ignored. A +# class is considered mixin if its name matches the mixin-class-rgx option. +# Tells whether to warn about missing members when the owner of the attribute is +# inferred to be None. +ignore-none = true + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference can +# return multiple potential results while evaluating a Python object, but some +# branches might not be evaluated, which results in partial inference. In that +# case, it might be useful to still emit no-member and other checks for the rest +# of the inferred objects. +ignore-on-opaque-inference = true + +# List of symbolic message names to ignore for Mixin members. +ignored-checks-for-mixins = ["no-member", "not-async-context-manager", "not-context-manager", "attribute-defined-outside-init"] + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes = ["optparse.Values", "thread._local", "_thread._local"] + +# Show a hint with possible names when a member name was not found. The aspect of +# finding the hint is based on edit distance. +missing-member-hint = true + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance = 1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices = 1 + +# Regex pattern to define which classes are considered mixins. +mixin-class-rgx = ".*[Mm]ixin" + +# List of decorators that change the signature of a decorated function. +# signature-mutators = + +[tool.pylint.variables] +# List of additional names supposed to be defined in builtins. Remember that you +# should avoid defining new builtins when possible. +# additional-builtins = + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables = true + +# List of names allowed to shadow builtins +# allowed-redefined-builtins = + +# List of strings which can identify a callback function by name. A callback name +# must start or end with one of those strings. +callbacks = ["cb_", "_cb", "_callback"] + +# A regular expression matching the name of dummy variables (i.e. expected to not +# be used). +dummy-variables-rgx = "_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_" + +# Argument names that match this expression will be ignored. Default to name with +# leading underscore. +ignored-argument-names = "_.*|^ignored_|^unused_" + +# Tells whether we should check for unused import in __init__ files. +# init-import = + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules = ["six.moves", "future.builtins"] diff --git a/setup.py b/setup.py index fcc4d600..1698e52c 100644 --- a/setup.py +++ b/setup.py @@ -1,39 +1,11 @@ -"""Bootstrapper for docker's ENTRYPOINT executable.""" -import os -from setuptools import setup +#!/usr/bin/env python +"""Bootstrapper for docker's ENTRYPOINT executable. +Since using setup.py is no longer std convention, +all install information is located in pyproject.toml +""" -ROOT_DIR = os.path.abspath(os.path.dirname(__file__)) -REPO = "https://github.com/" -repo = os.getenv("GITHUB_REPOSITORY", None) # in case this is published from a fork -REPO += "cpp-linter/cpp-linter-action" if repo is None else repo +import setuptools -setup( - name="cpp_linter", - # use_scm_version=True, - # setup_requires=["setuptools_scm"], - version="1.4.2", - description=__doc__, - long_description=( - "A python package that powers the github action named cpp-linter-action. " - + f"See `the github repository README <{REPO}#readme>`_ for full details." - ), - author="Brendan Doherty", - author_email="2bndy5@gmail.com", - install_requires=["requests", "pyyaml"], # pyyaml is installed with clang-tidy - license="MIT", - # See https://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - ], - keywords="clang clang-tidy clang-format", - packages=["cpp_linter"], - entry_points={"console_scripts": ["cpp-linter=cpp_linter.run:main"]}, - # Specifiy your homepage URL for your project here - url=REPO, - download_url=f"{REPO}/releases", -) +setuptools.setup() From 11f44acc3ea1cc31730c3fc83161f2fcc51d36f2 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sun, 7 Aug 2022 13:52:42 -0700 Subject: [PATCH 42/76] resolve version exe path better --- .github/workflows/run-dev-tests.yml | 33 ++++++++++------------------- .pre-commit-config.yaml | 1 + cpp_linter/__init__.py | 30 ++++++++++++++++++++++++++ cpp_linter/run.py | 20 +++-------------- 4 files changed, 45 insertions(+), 39 deletions(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 14ee0ccc..9e74083c 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -50,8 +50,8 @@ jobs: - os: 'ubuntu-latest' version: '13' tools_dir: temp - - version: '14' - tools_dir: temp + # - version: '14' + # tools_dir: temp runs-on: ${{ matrix.os }} steps: @@ -64,40 +64,29 @@ jobs: - name: Install workflow deps run: python3 -m pip install pytest coverage . - # - name: Install clang-tools - # if: matrix.tools_dir == 'temp' - # run: | - # python -m pip install clang-tools - # clang-tools --install ${{ matrix.version }} --directory ${{ runner.temp }}/llvm - - name: Install clang-tools - uses: KyleMayes/install-llvm-action@v1 if: matrix.tools_dir == 'temp' - with: - version: ${{ matrix.version }} - directory: ${{ runner.temp }}/llvm + run: | + python -m pip install -i https://test.pypi.org/simple/ clang-tools + clang-tools --install ${{ matrix.version }} --directory ${{ runner.temp }}/clang-tools - - name: Collect Coverage (native clang) - if: matrix.tools_dir == 'N/A' || matrix.os == 'ubuntu-latest' + - name: Collect Coverage (native clang install) + if: matrix.tools_dir == 'N/A' env: CLANG_VERSION: ${{ matrix.version }} run: coverage run -m pytest -vv tests - - name: Collect Coverage (non-native clang windows) - if: matrix.tools_dir == 'temp' && matrix.os == 'windows-latest' + - name: Collect Coverage (non-native clang install) + if: matrix.tools_dir == 'temp' env: - CLANG_VERSION: ${{ runner.temp }}/llvm + CLANG_VERSION: ${{ runner.temp }}/clang-tools run: coverage run -m pytest -vv tests - run: coverage report && coverage xml - uses: codecov/codecov-action@v3 - env: - OS: ${{ matrix.os }} - PYTHON: CPy${{ matrix.py }} - CLANG: LLVM-v${{ matrix.version }} + if: matrix.os == 'ubuntu-latest' && matrix.version == '12' with: files: ./coverage.xml - env_vars: OS,PYTHON,CLANG # optional fail_ci_if_error: true # optional (default = false) verbose: true # optional (default = false) \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5bdd6452..31df1b42 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,7 @@ repos: rev: '22.6.0' hooks: - id: black + args: ["--diff"] - repo: https://github.com/pycqa/pylint rev: v2.14.5 hooks: diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index dd2615d2..1b705376 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -2,6 +2,7 @@ multiple modules.""" import os from pathlib import Path +import platform import logging from typing import TYPE_CHECKING, List, Dict, Union, Any from requests import Response @@ -39,6 +40,7 @@ } if GITHUB_TOKEN: API_HEADERS["Authorization"] = f"token {GITHUB_TOKEN}" +IS_ON_WINDOWS = platform.system().lower() == "windows" class Globals: @@ -128,3 +130,31 @@ def log_response_msg() -> bool: ) return False return True + + +def assemble_version_exec(tool_name: str, specified_version: str) -> str: + """Assembles the command to the executable of the given clang tool based on given + version information. + + Args: + tool_name: The name of the clang tool to be executed. + specified_version: The version number or the installed path to a version of + the tool's executable. + """ + suffix = ".exe" if IS_ON_WINDOWS else "" + if specified_version.isdigit(): # version info is not a path + # let's assume the exe is in the PATH env var + if IS_ON_WINDOWS: + # installs don't usually append version number to exe name on Windows + return f"{tool_name}{suffix}" # omit version number + return f"{tool_name}-{specified_version}{suffix}" + version_path = Path(specified_version).resolve() # make absolute + for path in [ + # if installed via KyleMayes/install-llvm-action using the `directory` option + version_path / "bin" / (tool_name + suffix), + # if installed via clang-tools-pip pkg using the `-d` option + version_path / (tool_name + suffix), + ]: + if path.exists(): + return str(path) + return tool_name + suffix diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 72e93b0f..dc8bd280 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -28,6 +28,7 @@ API_HEADERS, log_response_msg, range_of_changed_lines, + assemble_version_exec, ) from .clang_tidy_yml import parse_tidy_suggestions_yml from .clang_format_xml import parse_format_replacements_xml @@ -43,7 +44,6 @@ GITHUB_WORKSPACE = os.getenv("GITHUB_WORKSPACE", "") IS_USING_DOCKER = os.getenv("USING_CLANG_TOOLS_DOCKER", os.getenv("CLANG_VERSIONS")) RUNNER_WORKSPACE = "/github/workspace" if IS_USING_DOCKER else GITHUB_WORKSPACE -IS_ON_WINDOWS = sys.platform.startswith("win32") # setup CLI args cli_arg_parser = argparse.ArgumentParser( @@ -426,16 +426,9 @@ def run_clang_tidy( return filename = filename.replace("/", os.sep) cmds = [ - "clang-tidy" + ("" if not version else f"-{version}"), + assemble_version_exec("clang-tidy", version), "--export-fixes=clang_tidy_output.yml", ] - if IS_ON_WINDOWS: - cmds[0] = "clang-tidy" - if os.path.exists(version + "\\bin"): - cmds[0] = f"{version}\\bin\\clang-tidy.exe" - elif not version.isdigit(): - logger.warning("ignoring invalid version number '%s'.", version) - cmds[0] = "clang-tidy" if checks: cmds.append(f"-checks={checks}") if database: @@ -488,17 +481,10 @@ def run_clang_format( with open("clang_format_output.xml", "wb"): return # clear any previous output and exit cmds = [ - "clang-format" + ("" if not version else f"-{version}"), + assemble_version_exec("clang-format", version), f"-style={style}", "--output-replacements-xml", ] - if IS_ON_WINDOWS: - cmds[0] = "clang-format" - if os.path.exists(version + "\\bin"): - cmds[0] = f"{version}\\bin\\clang-format.exe" - elif not version.isdigit(): - logger.warning("ignoring invalid version number %s.", version) - cmds[0] = "clang-format" if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" for line_range in file_obj["line_filter"][ranges]: From 91aa28bd5aa7edb90ef3dea5a6b3daf950559f04 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sun, 7 Aug 2022 14:14:43 -0700 Subject: [PATCH 43/76] ammend make_annotations() (& its tests) --- .github/workflows/run-dev-tests.yml | 2 +- cpp_linter/run.py | 5 ++++- tests/capture_tools_output/test_tools_output.py | 13 ++++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 9e74083c..c8c2b83d 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -32,7 +32,7 @@ jobs: matrix: py: ['3.7', '3.8', '3.9', '3.10'] os: ['windows-latest', ubuntu-latest] - version: ['14', '13', '12', '11', '10'] + version: ['13', '12', '11', '10'] include: - tools_dir: 'N/A' - os: 'windows-latest' diff --git a/cpp_linter/run.py b/cpp_linter/run.py index dc8bd280..fbe36f98 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -782,16 +782,19 @@ def make_annotations( for note in GlobalParser.tidy_notes: if lines_changed_only: filename = note.filename.replace("\\", "/") + line_filter = [] for file in files: if filename == file["filename"]: line_filter = range_of_changed_lines(file, lines_changed_only) + break + else: + continue if note.line in line_filter: count += 1 log_commander.info(note.log_command()) else: count += 1 log_commander.info(note.log_command()) - count += 1 logger.info("Created %d annotations", count) return bool(count) diff --git a/tests/capture_tools_output/test_tools_output.py b/tests/capture_tools_output/test_tools_output.py index ea924465..a6e14ce9 100644 --- a/tests/capture_tools_output/test_tools_output.py +++ b/tests/capture_tools_output/test_tools_output.py @@ -1,7 +1,7 @@ """Various tests related to the ``lines_changed_only`` option.""" import os import logging -from typing import Dict, Any, cast, List +from typing import Dict, Any, cast, List, Optional from pathlib import Path import json import re @@ -78,12 +78,13 @@ def setup_test_repo(monkeypatch: pytest.MonkeyPatch) -> None: verify_files_are_present() -def match_file_json(filename: str) -> Dict[str, Any]: +def match_file_json(filename: str) -> Optional[Dict[str, Any]]: """A helper function to match a given filename with a file's JSON object.""" for file in cpp_linter.Globals.FILES["files"]: # type: ignore if file["filename"] == filename: return file - raise ValueError(f"file {filename} not found in expected_result.json") + print("file", filename, "not found in expected_result.json") + return None RECORD_FILE = re.compile(r".*file=(.*?),.*") @@ -123,6 +124,8 @@ def test_format_annotations( for l in FORMAT_RECORD_LINES.sub("\\1", message).split(",") ] file = match_file_json(RECORD_FILE.sub("\\1", message).replace("\\", "/")) + if file is None: + continue ranges = cpp_linter.range_of_changed_lines(file, lines_changed_only) if ranges: # an empty list if lines_changed_only == 0 for line in lines: @@ -166,6 +169,8 @@ def test_tidy_annotations( if TIDY_RECORD.search(message) is not None: line = int(TIDY_RECORD_LINE.sub("\\1", message)) file = match_file_json(RECORD_FILE.sub("\\1", message).replace("\\", "/")) + if file is None: + continue ranges = cpp_linter.range_of_changed_lines(file, lines_changed_only) if ranges: # an empty list if lines_changed_only == 0 assert line in ranges @@ -192,5 +197,7 @@ def test_diff_comment(lines_changed_only: int): # output.write_text(json.dumps(diff_comments, indent=2), encoding="utf-8") for comment in diff_comments: file = match_file_json(cast(str, comment["path"])) + if file is None: + continue ranges = cpp_linter.range_of_changed_lines(file, lines_changed_only) assert comment["line"] in ranges From f35ea729644e49aca89b600235da7bd2c17900a5 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sun, 7 Aug 2022 16:04:45 -0700 Subject: [PATCH 44/76] adjust for pypi releases --- .github/workflows/publish-pypi.yml | 51 ++++++++++++++++++++++++++++++ README.md | 11 +++---- pyproject.toml | 4 +-- 3 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/publish-pypi.yml diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml new file mode 100644 index 00000000..c1c981d1 --- /dev/null +++ b/.github/workflows/publish-pypi.yml @@ -0,0 +1,51 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package + +on: + release: + types: [published] + workflow_dispatch: + +permissions: + contents: read + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + # use fetch --all for setuptools_scm to work + with: + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.x' + - name: Install dependencies + run: python -m pip install --upgrade pip twine + - name: Build wheel + run: python -m pip wheel -w dist --no-deps . + - name: Check distribution + run: twine check dist/* + - name: Publish package (to TestPyPI) + if: github.event_name == 'workflow_dispatch' && github.repository == 'cpp-linter/cpp-linter-action' + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} + run: twine upload --repository testpypi dist/* + - name: Publish package (to PyPI) + if: github.event_name == 'release' && github.repository == 'cpp-linter/cpp-linter-action' && github.ref == 'refs/heads/master' + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: twine upload dist/* + diff --git a/README.md b/README.md index 5992a325..a6c897d8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

-icon +icon

@@ -44,8 +44,7 @@ jobs: - name: Fail fast?! if: steps.linter.outputs.checks-failed > 0 - run: | - echo "Some files failed the linting checks!" + run: echo "Some files failed the linting checks!" # for actual deployment # run: exit 1 ``` @@ -236,13 +235,13 @@ is equivalent to ### Annotations -![clang-format annotations](./docs/images/annotations-clang-format.png) +![clang-format annotations](https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/master/docs/images/annotations-clang-format.png) -![clang-tidy annotations](./docs/images/annotations-clang-tidy.png) +![clang-tidy annotations](https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/master/docs/images/annotations-clang-tidy.png) ### Thread Comment -![sample comment](./docs/images/comment.png) +![sample comment](https://raw.githubusercontent.com/cpp-linter/cpp-linter-action/master/docs/images/comment.png) diff --git a/pyproject.toml b/pyproject.toml index ad4be938..b0ffebf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,9 +4,9 @@ build-backend = "setuptools.build_meta" [project] name = "cpp_linter" -description = "Install clang-tools (clang-format, clang-tidy) with pip" +description = "Run clang-format and clang-tidy on a batch of files." readme = "README.md" -keywords = ["clang", "clang-tools", "clang-extra", "clang-tidy", "clang-format"] +keywords = ["clang", "clang-tools", "linter", "clang-tidy", "clang-format"] license = {text = "MIT License"} authors = [ { name = "Brendan Doherty", email = "2bndy5@gmail.com" }, From ac8b4f0ff1c20fce5662bb0a6339dcc9ec756f6e Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sun, 7 Aug 2022 18:20:10 -0700 Subject: [PATCH 45/76] allow running locally & fix duplicate log cmds --- cpp_linter/run.py | 10 +++++++--- tests/capture_tools_output/test_tools_output.py | 2 ++ tests/test_misc.py | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index fbe36f98..db877fc7 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -11,6 +11,7 @@ https://docs.github.com/en/rest/reference/issues) """ import subprocess +from pathlib import Path import os import sys import argparse @@ -172,6 +173,7 @@ def set_exit_code(override: int = None) -> int: console_handler = logging.StreamHandler() # Create special stdout stream handler console_handler.setFormatter(logging.Formatter("%(message)s")) # no formatted log cmds log_commander.addHandler(console_handler) # Use special handler for log_commander +log_commander.propagate = False def start_log_group(name: str) -> None: @@ -864,9 +866,11 @@ def main(): # change working directory os.chdir(args.repo_root) + if GITHUB_EVENT_PATH: # load event's json info about the workflow run - with open(GITHUB_EVENT_PATH, "r", encoding="utf-8") as payload: - Globals.EVENT_PAYLOAD = json.load(payload) + Globals.EVENT_PAYLOAD = json.load( + Path(GITHUB_EVENT_PATH).read_text(encoding="utf-8") + ) if logger.getEffectiveLevel() <= logging.DEBUG: start_log_group("Event json from the runner") logger.debug(json.dumps(Globals.EVENT_PAYLOAD)) @@ -899,7 +903,7 @@ def main(): start_log_group("Posting comment(s)") thread_comments_allowed = True - if "private" in Globals.EVENT_PAYLOAD["repository"]: + if GITHUB_EVENT_PATH and "private" in Globals.EVENT_PAYLOAD["repository"]: thread_comments_allowed = ( Globals.EVENT_PAYLOAD["repository"]["private"] is not True ) diff --git a/tests/capture_tools_output/test_tools_output.py b/tests/capture_tools_output/test_tools_output.py index a6e14ce9..1ff81896 100644 --- a/tests/capture_tools_output/test_tools_output.py +++ b/tests/capture_tools_output/test_tools_output.py @@ -114,6 +114,7 @@ def test_format_annotations( ) assert "Output from `clang-tidy`" not in cpp_linter.Globals.OUTPUT caplog.set_level(logging.INFO, logger=log_commander.name) + log_commander.propagate = True make_annotations( style=style, file_annotations=True, lines_changed_only=lines_changed_only ) @@ -162,6 +163,7 @@ def test_tidy_annotations( ) assert "Run `clang-format` on the following files" not in cpp_linter.Globals.OUTPUT caplog.set_level(logging.INFO, logger=log_commander.name) + log_commander.propagate = True make_annotations( style="", file_annotations=True, lines_changed_only=lines_changed_only ) diff --git a/tests/test_misc.py b/tests/test_misc.py index 2bad68fe..951ddbb8 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -32,6 +32,7 @@ def test_exit_implicit(): def test_end_group(caplog: pytest.LogCaptureFixture): """Test the output that concludes a group of runner logs.""" caplog.set_level(logging.INFO, logger=log_commander.name) + log_commander.propagate = True end_log_group() messages = caplog.messages assert "::endgroup::" in messages @@ -41,6 +42,7 @@ def test_end_group(caplog: pytest.LogCaptureFixture): def test_start_group(caplog: pytest.LogCaptureFixture): """Test the output that begins a group of runner logs.""" caplog.set_level(logging.INFO, logger=log_commander.name) + log_commander.propagate = True start_log_group("TEST") messages = caplog.messages assert "::group::TEST" in messages From d802afb1a48cc639b95b12a4730b0d25d233b620 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sun, 7 Aug 2022 19:02:26 -0700 Subject: [PATCH 46/76] use pathlib.Path to open files --- cpp_linter/clang_tidy.py | 29 +++++++++++++++-------------- cpp_linter/clang_tidy_yml.py | 6 +++--- cpp_linter/run.py | 36 ++++++++++++++++++------------------ 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/cpp_linter/clang_tidy.py b/cpp_linter/clang_tidy.py index a57cc9fe..31a9ac10 100644 --- a/cpp_linter/clang_tidy.py +++ b/cpp_linter/clang_tidy.py @@ -1,5 +1,6 @@ """Parse output from clang-tidy's stdout""" import os +from pathlib import Path import re from typing import Tuple, Union, List, cast from . import GlobalParser @@ -97,18 +98,18 @@ def log_command(self) -> str: def parse_tidy_output() -> None: """Parse clang-tidy output in a file created from stdout.""" notification = None - with open("clang_tidy_report.txt", "r", encoding="utf-8") as tidy_out: - for line in tidy_out.readlines(): - match = re.match(NOTE_HEADER, line) - if match is not None: - notification = TidyNotification( - cast( - Tuple[str, Union[int, str], Union[int, str], str, str, str], - match.groups(), - ) + tidy_out = Path("clang_tidy_report.txt").read_text(encoding="utf-8") + for line in tidy_out.splitlines(): + match = re.match(NOTE_HEADER, line) + if match is not None: + notification = TidyNotification( + cast( + Tuple[str, Union[int, str], Union[int, str], str, str, str], + match.groups(), ) - GlobalParser.tidy_notes.append(notification) - elif notification is not None: - # append lines of code that are part of - # the previous line's notification - notification.fixit_lines.append(line) + ) + GlobalParser.tidy_notes.append(notification) + elif notification is not None: + # append lines of code that are part of + # the previous line's notification + notification.fixit_lines.append(line) diff --git a/cpp_linter/clang_tidy_yml.py b/cpp_linter/clang_tidy_yml.py index 437aaf69..09b23f40 100644 --- a/cpp_linter/clang_tidy_yml.py +++ b/cpp_linter/clang_tidy_yml.py @@ -1,5 +1,6 @@ """Parse output from clang-tidy's YML format""" import os +from pathlib import Path from typing import List import yaml from . import GlobalParser, get_line_cnt_from_cols, logger @@ -102,9 +103,8 @@ def parse_tidy_suggestions_yml(): """Read a YAML file from clang-tidy and create a list of suggestions from it. Output is saved to [`tidy_advice`][cpp_linter.GlobalParser.tidy_advice]. """ - yml = {} - with open("clang_tidy_output.yml", "r", encoding="utf-8") as yml_file: - yml = yaml.safe_load(yml_file) + yml_file = Path("clang_tidy_output.yml").read_text(encoding="utf-8") + yml = yaml.safe_load(yml_file) fixit = YMLFixit(yml["MainSourceFile"]) for diag_results in yml["Diagnostics"]: diag = TidyDiagnostic(diag_results["DiagnosticName"]) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index db877fc7..cf888619 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -27,6 +27,7 @@ GITHUB_TOKEN, GITHUB_SHA, API_HEADERS, + IS_ON_RUNNER, log_response_msg, range_of_changed_lines, assemble_version_exec, @@ -314,10 +315,12 @@ def filter_out_non_source_files( Globals.FILES = files else: cast(Dict[str, Any], Globals.FILES)["files"] = files - if not os.getenv("CI"): # if not executed on a github runner - with open(".changed_files.json", "w", encoding="utf-8") as temp: - # dump altered json of changed files - json.dump(Globals.FILES, temp, indent=2) + if not IS_ON_RUNNER: # if not executed on a github runner + # dump altered json of changed files + Path(".changed_files.json").write_text( + json.dumps(Globals.FILES, indent=2), + encoding="utf-8", + ) else: logger.info("No source files need checking!") return False @@ -344,8 +347,7 @@ def verify_files_are_present() -> None: Globals.response_buffer = requests.get(file["raw_url"]) # retain the repo's original structure os.makedirs(os.path.split(file_name)[0], exist_ok=True) - with open(file_name, "w", encoding="utf-8") as temp: - temp.write(Globals.response_buffer.text) + Path(file_name).write_text(Globals.response_buffer.text, encoding="utf-8") def list_source_files( @@ -424,8 +426,8 @@ def run_clang_tidy( """ if checks == "-*": # if all checks are disabled, then clang-tidy is skipped # clear the clang-tidy output file and exit function - with open("clang_tidy_report.txt", "wb") as f_out: - return + Path("clang_tidy_report.txt").write_bytes(b"") + return filename = filename.replace("/", os.sep) cmds = [ assemble_version_exec("clang-tidy", version), @@ -446,12 +448,11 @@ def run_clang_tidy( logger.info("line_filter = %s", json.dumps([line_ranges])) cmds.append(f"--line-filter={json.dumps([line_ranges])}") cmds.append(filename) - with open("clang_tidy_output.yml", "wb"): - pass # clear yml file's content before running clang-tidy + # clear yml file's content before running clang-tidy + Path("clang_tidy_output.yml").write_bytes(b"") logger.info('Running "%s"', " ".join(cmds)) results = subprocess.run(cmds, capture_output=True) - with open("clang_tidy_report.txt", "wb") as f_out: - f_out.write(results.stdout) + Path("clang_tidy_report.txt").write_bytes(results.stdout) logger.debug("Output from clang-tidy:\n%s", results.stdout.decode()) if os.path.getsize("clang_tidy_output.yml"): parse_tidy_suggestions_yml() # get clang-tidy fixes from yml @@ -480,8 +481,8 @@ def run_clang_format( diff info. """ if not style: # if `style` == "" - with open("clang_format_output.xml", "wb"): - return # clear any previous output and exit + Path("clang_format_output.xml").write_bytes(b"") + return # clear any previous output and exit cmds = [ assemble_version_exec("clang-format", version), f"-style={style}", @@ -494,8 +495,7 @@ def run_clang_format( cmds.append(filename.replace("/", os.sep)) logger.info('Running "%s"', " ".join(cmds)) results = subprocess.run(cmds, capture_output=True) - with open("clang_format_output.xml", "wb") as f_out: - f_out.write(results.stdout) + Path("clang_format_output.xml").write_bytes(results.stdout) if results.returncode: logger.debug( "%s raised the following error(s):\n%s", cmds[0], results.stderr.decode() @@ -867,8 +867,8 @@ def main(): os.chdir(args.repo_root) if GITHUB_EVENT_PATH: - # load event's json info about the workflow run - Globals.EVENT_PAYLOAD = json.load( + # load event's json info about the workflow run + Globals.EVENT_PAYLOAD = json.loads( Path(GITHUB_EVENT_PATH).read_text(encoding="utf-8") ) if logger.getEffectiveLevel() <= logging.DEBUG: From b670e9c60e656eeed4ba959f70bbaf9132459370 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 8 Aug 2022 16:58:37 -0700 Subject: [PATCH 47/76] rely on pathlib, update pkg name & CI workflows --- .github/workflows/publish-pypi.yml | 3 +- .github/workflows/run-dev-tests.yml | 8 +-- cpp_linter/__init__.py | 2 +- cpp_linter/clang_format_xml.py | 4 +- cpp_linter/clang_tidy.py | 7 +- cpp_linter/clang_tidy_yml.py | 7 +- cpp_linter/run.py | 65 +++++++++---------- cpp_linter/thread_comments.py | 9 ++- pyproject.toml | 2 +- .../test_database_path.py | 19 +++--- .../capture_tools_output/test_tools_output.py | 2 +- 11 files changed, 59 insertions(+), 69 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index c1c981d1..aff07937 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -10,6 +10,7 @@ name: Upload Python Package on: release: + branches: [master] types: [published] workflow_dispatch: @@ -43,7 +44,7 @@ jobs: TWINE_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} run: twine upload --repository testpypi dist/* - name: Publish package (to PyPI) - if: github.event_name == 'release' && github.repository == 'cpp-linter/cpp-linter-action' && github.ref == 'refs/heads/master' + if: github.event_name != 'workflow_dispatch' && github.repository == 'cpp-linter/cpp-linter-action' env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index c8c2b83d..61fefffb 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -19,10 +19,10 @@ jobs: check-python-sources: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 with: - python-version: '3.10' + python-version: '3.x' - run: python3 -m pip install pre-commit - run: pre-commit run --all-files @@ -67,7 +67,7 @@ jobs: - name: Install clang-tools if: matrix.tools_dir == 'temp' run: | - python -m pip install -i https://test.pypi.org/simple/ clang-tools + python -m pip install clang-tools clang-tools --install ${{ matrix.version }} --directory ${{ runner.temp }}/clang-tools - name: Collect Coverage (native clang install) diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index 1b705376..7f2b095c 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -88,7 +88,7 @@ def get_line_cnt_from_cols(file_path: str, offset: int) -> tuple: - Index 1 is the column number for the given offset on the line. """ # logger.debug("Getting line count from %s at offset %d", file_path, offset) - contents = Path(file_path.replace("/", os.sep)).read_bytes()[:offset] + contents = Path(file_path).read_bytes()[:offset] return (contents.count(b"\n") + 1, offset - contents.rfind(b"\n")) diff --git a/cpp_linter/clang_format_xml.py b/cpp_linter/clang_format_xml.py index 300c6b77..7ba4c18b 100644 --- a/cpp_linter/clang_format_xml.py +++ b/cpp_linter/clang_format_xml.py @@ -1,5 +1,5 @@ """Parse output from clang-format's XML suggestions.""" -import os +from pathlib import PurePath from typing import List, Optional import xml.etree.ElementTree as ET from . import GlobalParser, get_line_cnt_from_cols @@ -74,7 +74,7 @@ def __init__(self, filename: str): filename: The source file's name for which the contents of the xml file exported by clang-tidy. """ - self.filename = filename.replace(os.sep, "/") + self.filename = PurePath(filename).as_posix() self.replaced_lines: List[FormatReplacementLine] = [] def __repr__(self) -> str: diff --git a/cpp_linter/clang_tidy.py b/cpp_linter/clang_tidy.py index 31a9ac10..4bd21cca 100644 --- a/cpp_linter/clang_tidy.py +++ b/cpp_linter/clang_tidy.py @@ -1,6 +1,5 @@ """Parse output from clang-tidy's stdout""" -import os -from pathlib import Path +from pathlib import Path, PurePath import re from typing import Tuple, Union, List, cast from . import GlobalParser @@ -47,14 +46,14 @@ def __init__( self.note_type = self.note_type.strip() self.line = int(self.line) self.cols = int(self.cols) - self.filename = self.filename.replace(os.getcwd() + os.sep, "") + self.filename = PurePath(self.filename).relative_to(Path.cwd()).as_posix() self.fixit_lines: List[str] = [] def __repr__(self) -> str: concerned_code = "" if self.fixit_lines: concerned_code = "```{}\n{}```\n".format( - os.path.splitext(self.filename)[1], + PurePath(self.filename).suffix.lstrip("."), "".join(self.fixit_lines), ) return ( diff --git a/cpp_linter/clang_tidy_yml.py b/cpp_linter/clang_tidy_yml.py index 09b23f40..3dab430a 100644 --- a/cpp_linter/clang_tidy_yml.py +++ b/cpp_linter/clang_tidy_yml.py @@ -1,13 +1,12 @@ """Parse output from clang-tidy's YML format""" -import os -from pathlib import Path +from pathlib import Path, PurePath from typing import List import yaml from . import GlobalParser, get_line_cnt_from_cols, logger CWD_HEADER_GUARD = bytes( - os.getcwd().upper().replace(os.sep, "_").replace("-", "_"), encoding="utf-8" + "_".join([p.upper().replace("-", "_") for p in Path.cwd().parts]), encoding="utf-8" ) #: The constant used to trim absolute paths from header guard suggestions. @@ -89,7 +88,7 @@ def __init__(self, filename: str) -> None: Args: filename: The source file's name (with path) concerning the suggestion. """ - self.filename = filename.replace(os.getcwd() + os.sep, "").replace(os.sep, "/") + self.filename = PurePath(filename).relative_to(Path.cwd()).as_posix() self.diagnostics: List[TidyDiagnostic] = [] def __repr__(self) -> str: diff --git a/cpp_linter/run.py b/cpp_linter/run.py index cf888619..34a5a260 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -11,7 +11,7 @@ https://docs.github.com/en/rest/reference/issues) """ import subprocess -from pathlib import Path +from pathlib import Path, PurePath import os import sys import argparse @@ -205,14 +205,11 @@ def is_file_in_list(paths: List[str], file_name: str, prompt: str) -> bool: - False if `file_name` is not in the `paths` list. """ for path in paths: - result = os.path.commonpath([path, file_name]).replace(os.sep, "/") - if result == path: + if PurePath(file_name).is_relative_to(PurePath(path)): logger.debug( - '".%s%s" is %s as specified in the domain ".%s%s"', - os.sep, + '"./%s" is %s as specified in the domain "./%s"', file_name, prompt, - os.sep, path, ) return True @@ -276,7 +273,7 @@ def filter_out_non_source_files( else cast(Dict[str, Any], Globals.FILES)["files"] ): if ( - os.path.splitext(file["filename"])[1][1:] in ext_list + PurePath(file["filename"]).suffix[1:] in ext_list and not file["status"].endswith("removed") and ( not is_file_in_list(ignored, file["filename"], "ignored") @@ -340,14 +337,14 @@ def verify_files_are_present() -> None: if GITHUB_EVENT_NAME == "pull_request" else cast(Dict[str, Any], Globals.FILES)["files"] ): - file_name = file["filename"].replace("/", os.sep) - if not os.path.exists(file_name): + file_name = Path(file["filename"]) + if not file_name.exists(): logger.warning("Could not find %s! Did you checkout the repo?", file_name) logger.info("Downloading file from url: %s", file["raw_url"]) Globals.response_buffer = requests.get(file["raw_url"]) # retain the repo's original structure - os.makedirs(os.path.split(file_name)[0], exist_ok=True) - Path(file_name).write_text(Globals.response_buffer.text, encoding="utf-8") + Path.mkdir(file_name.parent, parents=True, exist_ok=True) + file_name.write_text(Globals.response_buffer.text, encoding="utf-8") def list_source_files( @@ -367,23 +364,23 @@ def list_source_files( """ start_log_group("Get list of specified source files") - root_path = os.getcwd() + root_path = Path.cwd().as_posix() for dirpath, _, filenames in os.walk(root_path): - path = dirpath.replace(root_path, "").lstrip(os.sep) - path_parts = path.split(os.sep) + path = PurePath(dirpath.replace(root_path, "")) + path_parts = path.parents is_hidden = False for part in path_parts: - if part.startswith("."): - # logger.debug("Skipping \".%s%s\"", os.sep, path) + if part.as_posix().startswith("."): + # logger.debug("Skipping \"./%s\"", path) is_hidden = True break if is_hidden: continue # skip sources in hidden directories - logger.debug('Crawling ".%s%s"', os.sep, path) + logger.debug('Crawling "./%s"', path.as_posix()) for file in filenames: - if os.path.splitext(file)[1][1:] in ext_list: - file_path = os.path.join(path, file) - logger.debug('".%s%s" is a source code file', os.sep, file_path) + if PurePath(file).suffix.lstrip(".") in ext_list: + file_path = PurePath(path, file).as_posix() + logger.debug('"./%s" is a source code file', file_path) if not is_file_in_list( ignored_paths, file_path, "ignored" ) or is_file_in_list(not_ignored, file_path, "not ignored"): @@ -428,7 +425,7 @@ def run_clang_tidy( # clear the clang-tidy output file and exit function Path("clang_tidy_report.txt").write_bytes(b"") return - filename = filename.replace("/", os.sep) + filename = PurePath(filename).as_posix() cmds = [ assemble_version_exec("clang-tidy", version), "--export-fixes=clang_tidy_output.yml", @@ -437,10 +434,8 @@ def run_clang_tidy( cmds.append(f"-checks={checks}") if database: cmds.append("-p") - if not os.path.isabs(database): - database = os.path.normpath( - os.path.join(RUNNER_WORKSPACE, repo_root, database) - ) + if not PurePath(database).is_absolute(): + database = Path(RUNNER_WORKSPACE, repo_root, database).resolve().as_posix() cmds.append(database) if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" @@ -454,7 +449,7 @@ def run_clang_tidy( results = subprocess.run(cmds, capture_output=True) Path("clang_tidy_report.txt").write_bytes(results.stdout) logger.debug("Output from clang-tidy:\n%s", results.stdout.decode()) - if os.path.getsize("clang_tidy_output.yml"): + if Path("clang_tidy_output.yml").stat().st_size: parse_tidy_suggestions_yml() # get clang-tidy fixes from yml if results.stderr: logger.debug( @@ -492,7 +487,7 @@ def run_clang_format( ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" for line_range in file_obj["line_filter"][ranges]: cmds.append(f"--lines={line_range[0]}:{line_range[1]}") - cmds.append(filename.replace("/", os.sep)) + cmds.append(PurePath(filename).as_posix()) logger.info('Running "%s"', " ".join(cmds)) results = subprocess.run(cmds, capture_output=True) Path("clang_format_output.xml").write_bytes(results.stdout) @@ -520,7 +515,7 @@ def create_comment_body( [`make_annotations()`] after [`capture_clang_tools_output()`] us finished. """ ranges = range_of_changed_lines(file_obj, lines_changed_only) - if os.path.getsize("clang_tidy_report.txt"): + if Path("clang_tidy_report.txt").stat().st_size: parse_tidy_output() # get clang-tidy fixes from stdout comment_output = "" if Globals.PAYLOAD_TIDY: @@ -535,8 +530,8 @@ def create_comment_body( Globals.PAYLOAD_TIDY += comment_output GlobalParser.tidy_notes.clear() # empty list to avoid duplicated output - if os.path.getsize("clang_format_output.xml"): - parse_format_replacements_xml(filename.replace("/", os.sep)) + if Path("clang_format_output.xml").stat().st_size: + parse_format_replacements_xml(PurePath(filename).as_posix()) if GlobalParser.format_advice and GlobalParser.format_advice[-1].replaced_lines: should_comment = lines_changed_only == 0 if not should_comment: @@ -582,8 +577,6 @@ def capture_clang_tools_output( else Globals.FILES["files"] ): filename = cast(str, file["filename"]) - if not os.path.exists(filename): - filename = os.path.split(cast(str, file["raw_url"]))[1] start_log_group(f"Performing checkup on {filename}") run_clang_tidy( filename, file, version, checks, lines_changed_only, database, repo_root @@ -826,12 +819,12 @@ def parse_ignore_option(paths: str) -> tuple: # -> Tuple[List[str], List[str]]: ignored.append(path) # auto detect submodules - root_path = os.getcwd() - if os.path.exists(root_path + os.sep + ".gitmodules"): + gitmodules = Path(".gitmodules") + if gitmodules.exists(): submodules = configparser.ConfigParser() - submodules.read(root_path + os.sep + ".gitmodules") + submodules.read(gitmodules.resolve().as_posix()) for module in submodules.sections(): - path = submodules[module]["path"].replace("/", os.sep) + path = submodules[module]["path"] if path not in not_ignored: logger.info("Appending submodule to ignored paths: %s", path) ignored.append(path) diff --git a/cpp_linter/thread_comments.py b/cpp_linter/thread_comments.py index a4c5e8b9..1c1bbcb2 100644 --- a/cpp_linter/thread_comments.py +++ b/cpp_linter/thread_comments.py @@ -1,5 +1,4 @@ """A module to house the various functions for traversing/adjusting comments""" -import os from typing import Union, cast, List, Optional, Dict, Any import json from pathlib import Path @@ -73,9 +72,9 @@ def aggregate_tidy_advice(lines_changed_only: int) -> List[Dict[str, Any]]: body += diag.name + "**\n>" + diag.message # get original code - filename = cast(str, file["filename"]).replace("/", os.sep) + filename = Path(cast(str, file["filename"])) # the list of lines in a file - lines = Path(filename).read_text(encoding="utf-8").splitlines() + lines = filename.read_text(encoding="utf-8").splitlines() # aggregate clang-tidy advice suggestion = "\n```suggestion\n" @@ -123,9 +122,9 @@ def aggregate_format_advice(lines_changed_only: int) -> List[Dict[str, Any]]: for fmt_advice, file in zip(GlobalParser.format_advice, files): # get original code - filename = cast(str, file["filename"]).replace("/", os.sep) + filename = Path(cast(str, file["filename"])) # the list of lines from the src file - lines = Path(filename).read_text(encoding="utf-8").splitlines() + lines = filename.read_text(encoding="utf-8").splitlines() # aggregate clang-format suggestion line = "" # the line that concerns the fix diff --git a/pyproject.toml b/pyproject.toml index b0ffebf0..cb93e75d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=45", "setuptools-scm"] build-backend = "setuptools.build_meta" [project] -name = "cpp_linter" +name = "cpp-linter" description = "Run clang-format and clang-tidy on a batch of files." readme = "README.md" keywords = ["clang", "clang-tools", "linter", "clang-tidy", "clang-format"] diff --git a/tests/capture_tools_output/test_database_path.py b/tests/capture_tools_output/test_database_path.py index fdd25ef1..70fb2ce7 100644 --- a/tests/capture_tools_output/test_database_path.py +++ b/tests/capture_tools_output/test_database_path.py @@ -1,7 +1,6 @@ """Tests specific to specifying the compilation database path.""" -import os from typing import List -from pathlib import Path +from pathlib import Path, PurePath import logging import re import pytest @@ -11,7 +10,7 @@ CLANG_TIDY_COMMAND = re.compile(r"\"clang-tidy(.*)(?:\")") -ABS_DB_PATH = str(Path(Path(__file__).parent / "../../demo").resolve()) +ABS_DB_PATH = Path(PurePath(__file__).parent / "../../demo").resolve().as_posix() @pytest.mark.parametrize( @@ -32,21 +31,21 @@ def test_db_detection( expected_args: List[str], ): """test clang-tidy using a implicit path to the compilation database.""" - monkeypatch.chdir(str(Path(__file__).parent)) + monkeypatch.chdir(PurePath(__file__).parent.as_posix()) demo_src = "../../demo/demo.cpp" rel_root = str(Path(*Path(__file__).parts[-2:])) - cpp_linter.run.RUNNER_WORKSPACE = str( - Path(Path(__file__).parent / "../../").resolve() + cpp_linter.run.RUNNER_WORKSPACE = ( + Path(PurePath(__file__).parent / "../../").resolve().as_posix() ) caplog.set_level(logging.DEBUG, logger=logger.name) run_clang_tidy( - filename=(demo_src).replace("/", os.sep), + filename=(demo_src), file_obj={}, # only used when filtering lines version="", checks="", # let clang-tidy use a .clang-tidy config file lines_changed_only=0, # analyze complete file - database=database.replace("/", os.sep), - repo_root=rel_root.replace("/", os.sep), + database=database, + repo_root=rel_root, ) matched_args = [] for record in caplog.records: @@ -55,4 +54,4 @@ def test_db_detection( matched_args = msg_match.group(0)[:-1].split()[2:] assert "Error while trying to load a compilation database" not in record.message expected_args.append(demo_src) - assert matched_args == [a.replace("/", os.sep) for a in expected_args] + assert matched_args == [a for a in expected_args] diff --git a/tests/capture_tools_output/test_tools_output.py b/tests/capture_tools_output/test_tools_output.py index 1ff81896..0ce256f0 100644 --- a/tests/capture_tools_output/test_tools_output.py +++ b/tests/capture_tools_output/test_tools_output.py @@ -73,7 +73,7 @@ def setup_test_repo(monkeypatch: pytest.MonkeyPatch) -> None: repo_root = TEST_REPO.sub("\\1", cpp_linter.Globals.FILES["url"]) return_path = test_root / repo_root if not return_path.exists(): - os.mkdir(str(return_path)) + return_path.mkdir() monkeypatch.chdir(str(return_path)) verify_files_are_present() From 6af479482c4262a8b790bed6799854959ae815ad Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 8 Aug 2022 17:08:34 -0700 Subject: [PATCH 48/76] `is_relative_to()` introduced in python v3.9 --- cpp_linter/run.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 34a5a260..ae4a6851 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -205,7 +205,8 @@ def is_file_in_list(paths: List[str], file_name: str, prompt: str) -> bool: - False if `file_name` is not in the `paths` list. """ for path in paths: - if PurePath(file_name).is_relative_to(PurePath(path)): + result = os.path.commonpath([path, file_name]) + if result == path: logger.debug( '"./%s" is %s as specified in the domain "./%s"', file_name, @@ -273,7 +274,7 @@ def filter_out_non_source_files( else cast(Dict[str, Any], Globals.FILES)["files"] ): if ( - PurePath(file["filename"]).suffix[1:] in ext_list + PurePath(file["filename"]).suffix.rstrip(".") in ext_list and not file["status"].endswith("removed") and ( not is_file_in_list(ignored, file["filename"], "ignored") From 3787de4d77e842a00b9509da961af4eddb7a58ce Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 8 Aug 2022 17:23:35 -0700 Subject: [PATCH 49/76] `lstrip(".")` from file's extension --- cpp_linter/run.py | 6 ++++-- tests/capture_tools_output/test_tools_output.py | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index ae4a6851..40dbd831 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -205,7 +205,9 @@ def is_file_in_list(paths: List[str], file_name: str, prompt: str) -> bool: - False if `file_name` is not in the `paths` list. """ for path in paths: - result = os.path.commonpath([path, file_name]) + result = os.path.commonpath( + [PurePath(path).as_posix(), PurePath(file_name).as_posix()] + ) if result == path: logger.debug( '"./%s" is %s as specified in the domain "./%s"', @@ -274,7 +276,7 @@ def filter_out_non_source_files( else cast(Dict[str, Any], Globals.FILES)["files"] ): if ( - PurePath(file["filename"]).suffix.rstrip(".") in ext_list + PurePath(file["filename"]).suffix.lstrip(".") in ext_list and not file["status"].endswith("removed") and ( not is_file_in_list(ignored, file["filename"], "ignored") diff --git a/tests/capture_tools_output/test_tools_output.py b/tests/capture_tools_output/test_tools_output.py index 0ce256f0..8ab0e2bb 100644 --- a/tests/capture_tools_output/test_tools_output.py +++ b/tests/capture_tools_output/test_tools_output.py @@ -22,7 +22,11 @@ @pytest.mark.parametrize( "extensions", [(["c"]), pytest.param(["h"], marks=pytest.mark.xfail)] ) -def test_lines_changed_only(extensions: List[str], monkeypatch: pytest.MonkeyPatch): +def test_lines_changed_only( + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, + extensions: List[str], +): """Test for lines changes in diff. This checks for @@ -30,6 +34,7 @@ def test_lines_changed_only(extensions: List[str], monkeypatch: pytest.MonkeyPat 2. ranges of lines in diff that only contain additions. """ monkeypatch.chdir(str(Path(__file__).parent)) + caplog.set_level(logging.DEBUG, logger=cpp_linter.logger.name) cpp_linter.Globals.FILES = json.loads( Path("event_files.json").read_text(encoding="utf-8") ) From 8867252753b5267487c3686581a1924c1b48a915 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 8 Aug 2022 17:41:18 -0700 Subject: [PATCH 50/76] tidy v13 use abs path to std libs in output error --- cpp_linter/clang_tidy.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp_linter/clang_tidy.py b/cpp_linter/clang_tidy.py index 4bd21cca..757f95e7 100644 --- a/cpp_linter/clang_tidy.py +++ b/cpp_linter/clang_tidy.py @@ -46,7 +46,9 @@ def __init__( self.note_type = self.note_type.strip() self.line = int(self.line) self.cols = int(self.cols) - self.filename = PurePath(self.filename).relative_to(Path.cwd()).as_posix() + self.filename = ( + PurePath(self.filename).as_posix().replace(Path.cwd().as_posix(), "") + ) self.fixit_lines: List[str] = [] def __repr__(self) -> str: From f7dad018e1e2d47dc50d7abb06c0b7b6d09bd65f Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 8 Aug 2022 18:02:22 -0700 Subject: [PATCH 51/76] build/install wheel in test CI --- .github/workflows/run-dev-tests.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 61fefffb..98e93b80 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -25,8 +25,16 @@ jobs: python-version: '3.x' - run: python3 -m pip install pre-commit - run: pre-commit run --all-files + - name: Build wheel + run: python3 -m pip wheel --no-deps -w dist . + - name: Upload wheel as artifact + uses: actions/upload-artifact@v3 + with: + name: cpp-linter-action_wheel + path: ${{ github.workspace }}/dist/*.whl run-pytest: + needs: [check-python-sources] strategy: fail-fast: false matrix: @@ -61,8 +69,16 @@ jobs: with: python-version: ${{ matrix.py }} + - name: download wheel artifact + uses: actions/download-artifact@v2 + with: + name: clang-linter-action_wheel + path: dist + - name: Install workflow deps - run: python3 -m pip install pytest coverage . + # using a wildcard as filename on Windows requires a bash shell + shell: bash + run: python3 -m pip install pytest coverage dist/*.whl - name: Install clang-tools if: matrix.tools_dir == 'temp' From 2c8fb6d232944e94007bd35ff2318f9e1db33965 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 8 Aug 2022 18:09:41 -0700 Subject: [PATCH 52/76] oops, use correct artifact name --- .github/workflows/run-dev-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 98e93b80..15d64e86 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -72,7 +72,7 @@ jobs: - name: download wheel artifact uses: actions/download-artifact@v2 with: - name: clang-linter-action_wheel + name: cpp-linter-action_wheel path: dist - name: Install workflow deps From 6a1f91d2e62230fb9cacf1e741d680b8d3bc72b6 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 8 Aug 2022 19:01:41 -0700 Subject: [PATCH 53/76] remove identifying info from test's event payload --- tests/capture_tools_output/event_files.json | 52 +++------------------ 1 file changed, 7 insertions(+), 45 deletions(-) diff --git a/tests/capture_tools_output/event_files.json b/tests/capture_tools_output/event_files.json index 1952842b..b4bcad0e 100644 --- a/tests/capture_tools_output/event_files.json +++ b/tests/capture_tools_output/event_files.json @@ -3,8 +3,8 @@ "node_id": "C_kwDOAAOGANoAKDNjMzVhY2RlN2QzOThjMzJmNmZhZDUwZmE5MDJkZTM5MWY1NzNmZmE", "commit": { "author": { - "name": "Turo Lamminen", - "email": "turol@users.noreply.github.com", + "name": "info-removed", + "email": "noreply@github.com", "date": "2022-07-12T17:58:17Z" }, "committer": { @@ -18,56 +18,18 @@ "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/trees/61aafe76912a4e79bfe9e2e0620d5fc09792922e" }, "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", - "comment_count": 0, - "verification": { - "verified": true, - "reason": "valid", - "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsBcBAABCAAQBQJizbY5CRBK7hj4Ov3rIwAAd90IAEK0v5LTMD8TaaSlWOiXQ6Jh\nYqjVo248+3MuFEH2Em+QFt6RVbhA/HzsaD2E1qwigyOd0VXu2PZvGUP/hvB/x4AM\nEBxFAdGpP+nLhGF3uWJTZ6K/hfuvL6r4xV+EiqCBb1mSpy13N7kbBy3phSJfWgGM\nyrzR6qv40fgZgGRtFaOkP96SWNO+XnpHzoHqpVXaqYzj3sn1kZwbF6LoZUJy+7YZ\nJJFWZUg0mxsvlGZUZBO7e0KMZmPzLXfAA+heF7UqaDE6mT/lP/FSXHrZHH8J3Iju\nWOWECb2qRgNVYGuxhqW7+iN8ZvbDPI1+lPEvRAl4u72+piN++XrQgh5zgiNzDOU=\n=+D8A\n-----END PGP SIGNATURE-----\n", - "payload": "tree 61aafe76912a4e79bfe9e2e0620d5fc09792922e\nparent 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8\nparent 1acdd067d8b168099de009b2cb625c3e4565561a\nauthor Turo Lamminen 1657648697 +0000\ncommitter GitHub 1657648697 +0000\n\nMerge 1acdd067d8b168099de009b2cb625c3e4565561a into 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8\n" - } + "comment_count": 0 }, "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/3c35acde7d398c32f6fad50fa902de391f573ffa", "comments_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa/comments", "author": { - "login": "turol", - "id": 805057, - "node_id": "MDQ6VXNlcjgwNTA1Nw==", - "avatar_url": "https://avatars.githubusercontent.com/u/805057?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/turol", - "html_url": "https://github.com/turol", - "followers_url": "https://api.github.com/users/turol/followers", - "following_url": "https://api.github.com/users/turol/following{/other_user}", - "gists_url": "https://api.github.com/users/turol/gists{/gist_id}", - "starred_url": "https://api.github.com/users/turol/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/turol/subscriptions", - "organizations_url": "https://api.github.com/users/turol/orgs", - "repos_url": "https://api.github.com/users/turol/repos", - "events_url": "https://api.github.com/users/turol/events{/privacy}", - "received_events_url": "https://api.github.com/users/turol/received_events", - "type": "User", - "site_admin": false + "login": "info-removed", + "type": "User" }, "committer": { - "login": "web-flow", - "id": 19864447, - "node_id": "MDQ6VXNlcjE5ODY0NDQ3", - "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/web-flow", - "html_url": "https://github.com/web-flow", - "followers_url": "https://api.github.com/users/web-flow/followers", - "following_url": "https://api.github.com/users/web-flow/following{/other_user}", - "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", - "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", - "organizations_url": "https://api.github.com/users/web-flow/orgs", - "repos_url": "https://api.github.com/users/web-flow/repos", - "events_url": "https://api.github.com/users/web-flow/events{/privacy}", - "received_events_url": "https://api.github.com/users/web-flow/received_events", - "type": "User", - "site_admin": false + "login": "info-removed", + "type": "User" }, "parents": [ { From da9da357d225807bca78d16cd981f12fda723b1a Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 9 Aug 2022 02:44:20 -0700 Subject: [PATCH 54/76] make files list simpler for any event --- cpp_linter/__init__.py | 2 +- cpp_linter/run.py | 32 +- cpp_linter/thread_comments.py | 8 +- tests/capture_tools_output/event_files.json | 503 ++++++------- .../capture_tools_output/expected_result.json | 679 ++++++++---------- .../capture_tools_output/test_tools_output.py | 17 +- tests/test_misc.py | 8 +- 7 files changed, 548 insertions(+), 701 deletions(-) diff --git a/cpp_linter/__init__.py b/cpp_linter/__init__.py index 7f2b095c..84394cdf 100644 --- a/cpp_linter/__init__.py +++ b/cpp_linter/__init__.py @@ -50,7 +50,7 @@ class Globals: """The accumulated output of clang-tidy (gets appended to OUTPUT)""" OUTPUT: str = "" """The accumulated body of the resulting comment that gets posted.""" - FILES: Union[List[Dict[str, Any]], Dict[str, Any]] = [] + FILES: List[Dict[str, Any]] = [] """The responding payload containing info about changed files.""" EVENT_PAYLOAD: Dict[str, Any] = {} """The parsed JSON of the event payload.""" diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 40dbd831..30e05b5c 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -234,7 +234,12 @@ def get_list_of_changed_files() -> None: ) files_link += f"commits/{GITHUB_SHA}" logger.info("Fetching files list from url: %s", files_link) - Globals.FILES = requests.get(files_link, headers=API_HEADERS).json() + Globals.response_buffer = requests.get(files_link, headers=API_HEADERS) + log_response_msg() + if GITHUB_EVENT_NAME == "pull_request": + Globals.FILES = Globals.response_buffer.json() + else: + Globals.FILES = Globals.response_buffer.json()["files"] def consolidate_list_to_ranges(just_numbers: List[int]) -> List[List[int]]: @@ -270,11 +275,7 @@ def filter_out_non_source_files( [`main()`][cpp_linter.run.main]) when no files to be checked. """ files = [] - for file in ( - Globals.FILES - if GITHUB_EVENT_NAME == "pull_request" - else cast(Dict[str, Any], Globals.FILES)["files"] - ): + for file in Globals.FILES: if ( PurePath(file["filename"]).suffix.lstrip(".") in ext_list and not file["status"].endswith("removed") @@ -311,10 +312,7 @@ def filter_out_non_source_files( "Giving attention to the following files:\n\t%s", "\n\t".join([f["filename"] for f in files]), ) - if GITHUB_EVENT_NAME == "pull_request": - Globals.FILES = files - else: - cast(Dict[str, Any], Globals.FILES)["files"] = files + Globals.FILES = files if not IS_ON_RUNNER: # if not executed on a github runner # dump altered json of changed files Path(".changed_files.json").write_text( @@ -335,11 +333,7 @@ def verify_files_are_present() -> None: repository. If files are not found, then they are downloaded to the working directory. This is bad for files with the same name from different folders. """ - for file in ( - Globals.FILES - if GITHUB_EVENT_NAME == "pull_request" - else cast(Dict[str, Any], Globals.FILES)["files"] - ): + for file in Globals.FILES: file_name = Path(file["filename"]) if not file_name.exists(): logger.warning("Could not find %s! Did you checkout the repo?", file_name) @@ -395,7 +389,7 @@ def list_source_files( logger.info( "Giving attention to the following files:\n\t%s", "\n\t".join( - [f["filename"] for f in cast(List[Dict[str, Any]], Globals.FILES)] + [f["filename"] for f in Globals.FILES] ), ) else: @@ -574,11 +568,7 @@ def capture_clang_tools_output( """ # temporary cache of parsed notifications for use in log commands tidy_notes: List[TidyNotification] = [] - for file in ( - Globals.FILES - if GITHUB_EVENT_NAME == "pull_request" or isinstance(Globals.FILES, list) - else Globals.FILES["files"] - ): + for file in Globals.FILES: filename = cast(str, file["filename"]) start_log_group(f"Performing checkup on {filename}") run_clang_tidy( diff --git a/cpp_linter/thread_comments.py b/cpp_linter/thread_comments.py index 1c1bbcb2..915eb776 100644 --- a/cpp_linter/thread_comments.py +++ b/cpp_linter/thread_comments.py @@ -60,8 +60,7 @@ def aggregate_tidy_advice(lines_changed_only: int) -> List[Dict[str, Any]]: """Aggregate a list of json contents representing advice from clang-tidy suggestions.""" results = [] - files = Globals.FILES if isinstance(Globals.FILES, list) else Globals.FILES["files"] - for fixit, file in zip(GlobalParser.tidy_advice, files): + for fixit, file in zip(GlobalParser.tidy_advice, Globals.FILES): for diag in fixit.diagnostics: ranges = range_of_changed_lines(file, lines_changed_only) if lines_changed_only and diag.line not in ranges: @@ -118,11 +117,10 @@ def aggregate_format_advice(lines_changed_only: int) -> List[Dict[str, Any]]: """Aggregate a list of json contents representing advice from clang-format suggestions.""" results = [] - files = Globals.FILES if isinstance(Globals.FILES, list) else Globals.FILES["files"] - for fmt_advice, file in zip(GlobalParser.format_advice, files): + for fmt_advice, file in zip(GlobalParser.format_advice, Globals.FILES): # get original code - filename = Path(cast(str, file["filename"])) + filename = Path(file["filename"]) # the list of lines from the src file lines = filename.read_text(encoding="utf-8").splitlines() diff --git a/tests/capture_tools_output/event_files.json b/tests/capture_tools_output/event_files.json index b4bcad0e..baf9c44c 100644 --- a/tests/capture_tools_output/event_files.json +++ b/tests/capture_tools_output/event_files.json @@ -1,281 +1,230 @@ -{ - "sha": "3c35acde7d398c32f6fad50fa902de391f573ffa", - "node_id": "C_kwDOAAOGANoAKDNjMzVhY2RlN2QzOThjMzJmNmZhZDUwZmE5MDJkZTM5MWY1NzNmZmE", - "commit": { - "author": { - "name": "info-removed", - "email": "noreply@github.com", - "date": "2022-07-12T17:58:17Z" - }, - "committer": { - "name": "GitHub", - "email": "noreply@github.com", - "date": "2022-07-12T17:58:17Z" - }, - "message": "Merge 1acdd067d8b168099de009b2cb625c3e4565561a into 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", - "tree": { - "sha": "61aafe76912a4e79bfe9e2e0620d5fc09792922e", - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/trees/61aafe76912a4e79bfe9e2e0620d5fc09792922e" - }, - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", - "comment_count": 0 +[ + { + "sha": "7f1eed09c6c07682738de7b5141fd151d16cf368", + "filename": "CMakeLists.txt", + "status": "modified", + "additions": 14, + "deletions": 2, + "changes": 16, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/CMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/CMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/CMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -28,9 +28,21 @@ else()\n \"-Wredundant-decls\")\n endif()\n \n+option(ENABLE_SDL2_NET \"Enable SDL2_net\" On)\n+option(ENABLE_SDL2_MIXER \"Enable SDL2_mixer\" On)\n+\n find_package(SDL2 2.0.7)\n-find_package(SDL2_mixer 2.0.2)\n-find_package(SDL2_net 2.0.0)\n+if(ENABLE_SDL2_MIXER)\n+ find_package(SDL2_mixer 2.0.2)\n+else()\n+ add_compile_definitions(DISABLE_SDL2MIXER=1)\n+endif()\n+\n+if(ENABLE_SDL2_NET)\n+ find_package(SDL2_net 2.0.0)\n+else()\n+ add_compile_definitions(DISABLE_SDL2NET=1)\n+endif()\n \n # Check for libsamplerate.\n find_package(samplerate)" }, - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", - "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/3c35acde7d398c32f6fad50fa902de391f573ffa", - "comments_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa/comments", - "author": { - "login": "info-removed", - "type": "User" + { + "sha": "fd5d8bcecd8a6edb6d77c8686ae32a995b571066", + "filename": "configure.ac", + "status": "modified", + "additions": 17, + "deletions": 2, + "changes": 19, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/configure.ac", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/configure.ac", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/configure.ac?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -32,8 +32,23 @@ then\n fi\n \n PKG_CHECK_MODULES(SDL, [sdl2 >= 2.0.7])\n-PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.2])\n-PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])\n+# Check for SDL2_mixer\n+AC_ARG_ENABLE([sdl2mixer],\n+AS_HELP_STRING([--disable-sdl2mixer], [Disable SDL2_mixer support])\n+)\n+AS_IF([test \"x$enable_sdl2mixer\" != xno], [\n+ PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.2])], [\n+ AC_DEFINE([DISABLE_SDL2MIXER], [1], [SDL2_mixer disabled])\n+])\n+\n+# Check for networking\n+AC_ARG_ENABLE([sdl2net],\n+AS_HELP_STRING([--disable-sdl2net], [Disable SDL2_net support])\n+)\n+AS_IF([test \"x$enable_sdl2net\" != xno], [\n+ PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])], [\n+ AC_DEFINE([DISABLE_SDL2NET], [1], [SDL2_net disabled])\n+])\n \n # Check for bash-completion.\n AC_ARG_ENABLE([bash-completion]," }, - "committer": { - "login": "info-removed", - "type": "User" + { + "sha": "151f7617dde7d1216f7212b45bb5aeb7661bc86b", + "filename": "opl/CMakeLists.txt", + "status": "modified", + "additions": 4, + "deletions": 1, + "changes": 5, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -12,4 +12,7 @@ add_library(opl STATIC\n target_include_directories(opl\n INTERFACE \".\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(opl SDL2::mixer)\n+target_link_libraries(opl SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(opl SDL2::mixer)\n+endif()" }, - "parents": [ - { - "sha": "7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", - "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/7afbf68abcaad446c3f287ed502c6ebbb2fb10e8" - }, - { - "sha": "1acdd067d8b168099de009b2cb625c3e4565561a", - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/1acdd067d8b168099de009b2cb625c3e4565561a", - "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/1acdd067d8b168099de009b2cb625c3e4565561a" - } - ], - "stats": { - "total": 334, - "additions": 297, - "deletions": 37 + { + "sha": "46e082cf77c5e60affc7689f7357c926fc00cda3", + "filename": "opl/opl.c", + "status": "modified", + "additions": 2, + "deletions": 0, + "changes": 2, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -50,7 +50,9 @@ static opl_driver_t *drivers[] =\n #ifdef _WIN32\n &opl_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &opl_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL\n };\n " }, - "files": [ - { - "sha": "7f1eed09c6c07682738de7b5141fd151d16cf368", - "filename": "CMakeLists.txt", - "status": "modified", - "additions": 14, - "deletions": 2, - "changes": 16, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/CMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/CMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/CMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -28,9 +28,21 @@ else()\n \"-Wredundant-decls\")\n endif()\n \n+option(ENABLE_SDL2_NET \"Enable SDL2_net\" On)\n+option(ENABLE_SDL2_MIXER \"Enable SDL2_mixer\" On)\n+\n find_package(SDL2 2.0.7)\n-find_package(SDL2_mixer 2.0.2)\n-find_package(SDL2_net 2.0.0)\n+if(ENABLE_SDL2_MIXER)\n+ find_package(SDL2_mixer 2.0.2)\n+else()\n+ add_compile_definitions(DISABLE_SDL2MIXER=1)\n+endif()\n+\n+if(ENABLE_SDL2_NET)\n+ find_package(SDL2_net 2.0.0)\n+else()\n+ add_compile_definitions(DISABLE_SDL2NET=1)\n+endif()\n \n # Check for libsamplerate.\n find_package(samplerate)" - }, - { - "sha": "fd5d8bcecd8a6edb6d77c8686ae32a995b571066", - "filename": "configure.ac", - "status": "modified", - "additions": 17, - "deletions": 2, - "changes": 19, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/configure.ac", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/configure.ac", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/configure.ac?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -32,8 +32,23 @@ then\n fi\n \n PKG_CHECK_MODULES(SDL, [sdl2 >= 2.0.7])\n-PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.2])\n-PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])\n+# Check for SDL2_mixer\n+AC_ARG_ENABLE([sdl2mixer],\n+AS_HELP_STRING([--disable-sdl2mixer], [Disable SDL2_mixer support])\n+)\n+AS_IF([test \"x$enable_sdl2mixer\" != xno], [\n+ PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.2])], [\n+ AC_DEFINE([DISABLE_SDL2MIXER], [1], [SDL2_mixer disabled])\n+])\n+\n+# Check for networking\n+AC_ARG_ENABLE([sdl2net],\n+AS_HELP_STRING([--disable-sdl2net], [Disable SDL2_net support])\n+)\n+AS_IF([test \"x$enable_sdl2net\" != xno], [\n+ PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])], [\n+ AC_DEFINE([DISABLE_SDL2NET], [1], [SDL2_net disabled])\n+])\n \n # Check for bash-completion.\n AC_ARG_ENABLE([bash-completion]," - }, - { - "sha": "151f7617dde7d1216f7212b45bb5aeb7661bc86b", - "filename": "opl/CMakeLists.txt", - "status": "modified", - "additions": 4, - "deletions": 1, - "changes": 5, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2FCMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2FCMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -12,4 +12,7 @@ add_library(opl STATIC\n target_include_directories(opl\n INTERFACE \".\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(opl SDL2::mixer)\n+target_link_libraries(opl SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(opl SDL2::mixer)\n+endif()" - }, - { - "sha": "46e082cf77c5e60affc7689f7357c926fc00cda3", - "filename": "opl/opl.c", - "status": "modified", - "additions": 2, - "deletions": 0, - "changes": 2, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -50,7 +50,9 @@ static opl_driver_t *drivers[] =\n #ifdef _WIN32\n &opl_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &opl_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL\n };\n " - }, - { - "sha": "6bd4e7e1f3374e289d3dc19972dcb1d5379d6b03", - "filename": "opl/opl_sdl.c", - "status": "modified", - "additions": 6, - "deletions": 0, - "changes": 6, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -33,6 +33,10 @@\n \n #include \"opl_queue.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 100 /* ms */\n \n typedef struct\n@@ -511,3 +515,5 @@ opl_driver_t opl_sdl_driver =\n OPL_SDL_AdjustCallbacks,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" - }, - { - "sha": "9924263aea24261091948e455dfd2521787a04c4", - "filename": "pcsound/CMakeLists.txt", - "status": "modified", - "additions": 4, - "deletions": 1, - "changes": 5, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2FCMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2FCMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -8,4 +8,7 @@ add_library(pcsound STATIC\n target_include_directories(pcsound\n INTERFACE \".\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(pcsound SDL2::mixer)\n+target_link_libraries(pcsound SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(pcsound SDL2::mixer)\n+endif()" - }, - { - "sha": "58f9b75c2affd5f1dd990aaedab79d834575bf83", - "filename": "pcsound/pcsound.c", - "status": "modified", - "additions": 2, - "deletions": 0, - "changes": 2, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -56,7 +56,9 @@ static pcsound_driver_t *drivers[] =\n #ifdef _WIN32\n &pcsound_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &pcsound_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL,\n };\n " - }, - { - "sha": "e77c7b0d29de1b0c665686004dfda311c9d96719", - "filename": "pcsound/pcsound_sdl.c", - "status": "modified", - "additions": 6, - "deletions": 0, - "changes": 6, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -24,6 +24,10 @@\n #include \"pcsound.h\"\n #include \"pcsound_internal.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 70 /* ms */\n #define SQUARE_WAVE_AMP 0x2000\n \n@@ -248,3 +252,5 @@ pcsound_driver_t pcsound_sdl_driver =\n PCSound_SDL_Shutdown,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" - }, - { - "sha": "bbb877641f2a8de6e6eb7dad5b8c866e147faf7d", - "filename": "src/CMakeLists.txt", - "status": "modified", - "additions": 18, - "deletions": 3, - "changes": 21, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2FCMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2FCMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -32,7 +32,10 @@ set(DEDSERV_FILES\n add_executable(\"${PROGRAM_PREFIX}server\" WIN32 ${COMMON_SOURCE_FILES} ${DEDSERV_FILES})\n target_include_directories(\"${PROGRAM_PREFIX}server\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::SDL2main SDL2::net)\n+target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::SDL2main SDL2::SDL2)\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::net)\n+endif()\n \n # Source files used by the game binaries (chocolate-doom, etc.)\n \n@@ -121,7 +124,13 @@ set(DEHACKED_SOURCE_FILES\n set(SOURCE_FILES ${COMMON_SOURCE_FILES} ${GAME_SOURCE_FILES})\n set(SOURCE_FILES_WITH_DEH ${SOURCE_FILES} ${DEHACKED_SOURCE_FILES})\n \n-set(EXTRA_LIBS SDL2::SDL2main SDL2::SDL2 SDL2::mixer SDL2::net textscreen pcsound opl)\n+set(EXTRA_LIBS SDL2::SDL2main SDL2::SDL2 textscreen pcsound opl)\n+if(ENABLE_SDL2_MIXER)\n+ list(APPEND EXTRA_LIBS SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ list(APPEND EXTRA_LIBS SDL2::net)\n+endif()\n if(SAMPLERATE_FOUND)\n list(APPEND EXTRA_LIBS samplerate::samplerate)\n endif()\n@@ -213,7 +222,13 @@ endif()\n \n target_include_directories(\"${PROGRAM_PREFIX}setup\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::SDL2main SDL2::SDL2 SDL2::mixer SDL2::net setup textscreen)\n+target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::SDL2main SDL2::SDL2 setup textscreen)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::net)\n+endif()\n \n if(MSVC)\n set_target_properties(\"${PROGRAM_PREFIX}setup\" PROPERTIES" - }, - { - "sha": "82b114b4178595085c6745bc70a570922415be1f", - "filename": "src/doom/CMakeLists.txt", - "status": "modified", - "additions": 7, - "deletions": 1, - "changes": 8, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fdoom%2FCMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fdoom%2FCMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fdoom%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -68,4 +68,10 @@ add_library(doom STATIC\n wi_stuff.c wi_stuff.h)\n \n target_include_directories(doom PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(doom SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(doom SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(doom SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(doom SDL2::net)\n+endif()" - }, - { - "sha": "1ea060bfdb8b3147e36b3431fee27934c8a93b34", - "filename": "src/heretic/CMakeLists.txt", - "status": "modified", - "additions": 7, - "deletions": 1, - "changes": 8, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fheretic%2FCMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fheretic%2FCMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fheretic%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -54,4 +54,10 @@ add_library(heretic STATIC\n s_sound.c s_sound.h)\n \n target_include_directories(heretic PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(heretic textscreen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(heretic textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(heretic SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(heretic SDL2::net)\n+endif()" - }, - { - "sha": "0dbd170bfdb06c8209ec654d4d5377e334be886e", - "filename": "src/hexen/CMakeLists.txt", - "status": "modified", - "additions": 7, - "deletions": 1, - "changes": 8, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fhexen%2FCMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fhexen%2FCMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fhexen%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -55,4 +55,10 @@ add_library(hexen STATIC\n xddefs.h)\n \n target_include_directories(hexen PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(hexen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(hexen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(hexen SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(hexen SDL2::net)\n+endif()" - }, - { - "sha": "3facce6f01d02c5e8eef3088fa60576b9e949829", - "filename": "src/i_musicpack.c", - "status": "modified", - "additions": 87, - "deletions": 1, - "changes": 88, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_musicpack.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -44,6 +44,13 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n+\n+char *music_pack_path = \"\";\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MID_HEADER_MAGIC \"MThd\"\n #define MUS_HEADER_MAGIC \"MUS\\x1a\"\n \n@@ -99,7 +106,6 @@ static boolean music_initialized = false;\n \n static boolean sdl_was_initialized = false;\n \n-char *music_pack_path = \"\";\n \n // If true, we are playing a substitute digital track rather than in-WAD\n // MIDI/MUS track, and file_metadata contains loop metadata.\n@@ -1375,3 +1381,83 @@ music_module_t music_pack_module =\n I_MP_PollMusic,\n };\n \n+\n+#else // DISABLE_SDL2MIXER\n+\n+\n+static boolean I_NULL_InitMusic(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_ShutdownMusic(void)\n+{\n+}\n+\n+\n+static void I_NULL_SetMusicVolume(int volume)\n+{\n+}\n+\n+\n+static void I_NULL_PauseSong(void)\n+{\n+}\n+\n+\n+static void I_NULL_ResumeSong(void)\n+{\n+}\n+\n+\n+static void *I_NULL_RegisterSong(void *data, int len)\n+{\n+ return NULL;\n+}\n+\n+\n+static void I_NULL_UnRegisterSong(void *handle)\n+{\n+}\n+\n+\n+static void I_NULL_PlaySong(void *handle, boolean looping)\n+{\n+}\n+\n+\n+static void I_NULL_StopSong(void)\n+{\n+}\n+\n+\n+static boolean I_NULL_MusicIsPlaying(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_PollMusic(void)\n+{\n+}\n+\n+music_module_t music_pack_module =\n+{\n+ NULL,\n+ 0,\n+ I_NULL_InitMusic,\n+ I_NULL_ShutdownMusic,\n+ I_NULL_SetMusicVolume,\n+ I_NULL_PauseSong,\n+ I_NULL_ResumeSong,\n+ I_NULL_RegisterSong,\n+ I_NULL_UnRegisterSong,\n+ I_NULL_PlaySong,\n+ I_NULL_StopSong,\n+ I_NULL_MusicIsPlaying,\n+ I_NULL_PollMusic,\n+};\n+\n+\n+#endif // DISABLE_SDL2MIXER" - }, - { - "sha": "48fedfbd7608ad8c6575a4bd82a5e1cb3646e071", - "filename": "src/i_sdlmusic.c", - "status": "modified", - "additions": 21, - "deletions": 13, - "changes": 34, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlmusic.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -44,19 +44,6 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n-#define MAXMIDLENGTH (96 * 1024)\n-\n-static boolean music_initialized = false;\n-\n-// If this is true, this module initialized SDL sound and has the \n-// responsibility to shut it down\n-\n-static boolean sdl_was_initialized = false;\n-\n-static boolean win_midi_stream_opened = false;\n-\n-static boolean musicpaused = false;\n-static int current_music_volume;\n \n char *fluidsynth_sf_path = \"\";\n char *timidity_cfg_path = \"\";\n@@ -138,6 +125,25 @@ void I_InitTimidityConfig(void)\n }\n }\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n+#define MAXMIDLENGTH (96 * 1024)\n+\n+static boolean music_initialized = false;\n+\n+// If this is true, this module initialized SDL sound and has the\n+// responsibility to shut it down\n+\n+static boolean sdl_was_initialized = false;\n+\n+static boolean win_midi_stream_opened = false;\n+\n+static boolean musicpaused = false;\n+static int current_music_volume;\n+\n+\n // Remove the temporary config file generated by I_InitTimidityConfig().\n \n static void RemoveTimidityConfig(void)\n@@ -588,3 +594,5 @@ music_module_t music_sdl_module =\n NULL, // Poll\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" - }, - { - "sha": "7f2a26096b218c5323f5dc569c6f70ab399782bf", - "filename": "src/i_sdlsound.c", - "status": "modified", - "additions": 17, - "deletions": 9, - "changes": 26, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -41,6 +41,21 @@\n \n #include \"doomtype.h\"\n \n+\n+int use_libsamplerate = 0;\n+\n+// Scale factor used when converting libsamplerate floating point numbers\n+// to integers. Too high means the sounds can clip; too low means they\n+// will be too quiet. This is an amount that should avoid clipping most\n+// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n+// is used, clipping might occur.\n+\n+float libsamplerate_scale = 0.65f;\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define LOW_PASS_FILTER\n //#define DEBUG_DUMP_WAVS\n #define NUM_CHANNELS 16\n@@ -77,15 +92,6 @@ static allocated_sound_t *allocated_sounds_head = NULL;\n static allocated_sound_t *allocated_sounds_tail = NULL;\n static int allocated_sounds_size = 0;\n \n-int use_libsamplerate = 0;\n-\n-// Scale factor used when converting libsamplerate floating point numbers\n-// to integers. Too high means the sounds can clip; too low means they\n-// will be too quiet. This is an amount that should avoid clipping most\n-// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n-// is used, clipping might occur.\n-\n-float libsamplerate_scale = 0.65f;\n \n // Hook a sound into the linked list at the head.\n \n@@ -1135,3 +1141,5 @@ sound_module_t sound_sdl_module =\n I_SDL_PrecacheSounds,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" - }, - { - "sha": "9cf1fd95db13504ffc6f98ead8c9150f03db72aa", - "filename": "src/i_sound.c", - "status": "modified", - "additions": 4, - "deletions": 0, - "changes": 4, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -99,7 +99,9 @@ static int snd_mport = 0;\n \n static sound_module_t *sound_modules[] = \n {\n+#ifndef DISABLE_SDL2MIXER\n &sound_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &sound_pcsound_module,\n NULL,\n };\n@@ -108,7 +110,9 @@ static sound_module_t *sound_modules[] =\n \n static music_module_t *music_modules[] =\n {\n+#ifndef DISABLE_SDL2MIXER\n &music_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &music_opl_module,\n NULL,\n };" - }, - { - "sha": "c1f701c0b9f653eb3a36b71627747a6eda963d8f", - "filename": "src/net_sdl.c", - "status": "modified", - "additions": 63, - "deletions": 0, - "changes": 63, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fnet_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -33,6 +33,10 @@\n // NETWORKING\n //\n \n+\n+#ifndef DISABLE_SDL2NET\n+\n+\n #include \n \n #define DEFAULT_PORT 2342\n@@ -376,3 +380,62 @@ net_module_t net_sdl_module =\n NET_SDL_ResolveAddress,\n };\n \n+\n+#else // DISABLE_SDL2NET\n+\n+// no-op implementation\n+\n+\n+static boolean NET_NULL_InitClient(void)\n+{\n+ return false;\n+}\n+\n+\n+static boolean NET_NULL_InitServer(void)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_SendPacket(net_addr_t *addr, net_packet_t *packet)\n+{\n+}\n+\n+\n+static boolean NET_NULL_RecvPacket(net_addr_t **addr, net_packet_t **packet)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)\n+{\n+\n+}\n+\n+\n+static void NET_NULL_FreeAddress(net_addr_t *addr)\n+{\n+}\n+\n+\n+net_addr_t *NET_NULL_ResolveAddress(const char *address)\n+{\n+ return NULL;\n+}\n+\n+\n+net_module_t net_sdl_module =\n+{\n+ NET_NULL_InitClient,\n+ NET_NULL_InitServer,\n+ NET_NULL_SendPacket,\n+ NET_NULL_RecvPacket,\n+ NET_NULL_AddrToString,\n+ NET_NULL_FreeAddress,\n+ NET_NULL_ResolveAddress,\n+};\n+\n+\n+#endif // DISABLE_SDL2NET" - }, - { - "sha": "90df2114163152ff732a9ba4a8bc18ef3d45d1bd", - "filename": "src/setup/CMakeLists.txt", - "status": "modified", - "additions": 4, - "deletions": 1, - "changes": 5, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fsetup%2FCMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fsetup%2FCMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fsetup%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -15,4 +15,7 @@ add_library(setup STATIC\n txt_mouseinput.c txt_mouseinput.h)\n \n target_include_directories(setup PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(setup textscreen SDL2::SDL2 SDL2::mixer)\n+target_link_libraries(setup textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(setup SDL2::mixer)\n+endif()" - }, - { - "sha": "37b17ade983155369c0897c0935d40dfeb2048c7", - "filename": "src/strife/CMakeLists.txt", - "status": "modified", - "additions": 7, - "deletions": 1, - "changes": 8, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fstrife%2FCMakeLists.txt", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fstrife%2FCMakeLists.txt", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fstrife%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -70,4 +70,10 @@ set(STRIFE_SOURCES\n add_library(strife STATIC ${STRIFE_SOURCES})\n \n target_include_directories(strife PRIVATE \"../\" \"../../win32/\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(strife textscreen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(strife textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(strife SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(strife SDL2::net)\n+endif()" - } - ] -} + { + "sha": "6bd4e7e1f3374e289d3dc19972dcb1d5379d6b03", + "filename": "opl/opl_sdl.c", + "status": "modified", + "additions": 6, + "deletions": 0, + "changes": 6, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -33,6 +33,10 @@\n \n #include \"opl_queue.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 100 /* ms */\n \n typedef struct\n@@ -511,3 +515,5 @@ opl_driver_t opl_sdl_driver =\n OPL_SDL_AdjustCallbacks,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "9924263aea24261091948e455dfd2521787a04c4", + "filename": "pcsound/CMakeLists.txt", + "status": "modified", + "additions": 4, + "deletions": 1, + "changes": 5, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -8,4 +8,7 @@ add_library(pcsound STATIC\n target_include_directories(pcsound\n INTERFACE \".\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(pcsound SDL2::mixer)\n+target_link_libraries(pcsound SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(pcsound SDL2::mixer)\n+endif()" + }, + { + "sha": "58f9b75c2affd5f1dd990aaedab79d834575bf83", + "filename": "pcsound/pcsound.c", + "status": "modified", + "additions": 2, + "deletions": 0, + "changes": 2, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -56,7 +56,9 @@ static pcsound_driver_t *drivers[] =\n #ifdef _WIN32\n &pcsound_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &pcsound_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL,\n };\n " + }, + { + "sha": "e77c7b0d29de1b0c665686004dfda311c9d96719", + "filename": "pcsound/pcsound_sdl.c", + "status": "modified", + "additions": 6, + "deletions": 0, + "changes": 6, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -24,6 +24,10 @@\n #include \"pcsound.h\"\n #include \"pcsound_internal.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 70 /* ms */\n #define SQUARE_WAVE_AMP 0x2000\n \n@@ -248,3 +252,5 @@ pcsound_driver_t pcsound_sdl_driver =\n PCSound_SDL_Shutdown,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "bbb877641f2a8de6e6eb7dad5b8c866e147faf7d", + "filename": "src/CMakeLists.txt", + "status": "modified", + "additions": 18, + "deletions": 3, + "changes": 21, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -32,7 +32,10 @@ set(DEDSERV_FILES\n add_executable(\"${PROGRAM_PREFIX}server\" WIN32 ${COMMON_SOURCE_FILES} ${DEDSERV_FILES})\n target_include_directories(\"${PROGRAM_PREFIX}server\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::SDL2main SDL2::net)\n+target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::SDL2main SDL2::SDL2)\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(\"${PROGRAM_PREFIX}server\" SDL2::net)\n+endif()\n \n # Source files used by the game binaries (chocolate-doom, etc.)\n \n@@ -121,7 +124,13 @@ set(DEHACKED_SOURCE_FILES\n set(SOURCE_FILES ${COMMON_SOURCE_FILES} ${GAME_SOURCE_FILES})\n set(SOURCE_FILES_WITH_DEH ${SOURCE_FILES} ${DEHACKED_SOURCE_FILES})\n \n-set(EXTRA_LIBS SDL2::SDL2main SDL2::SDL2 SDL2::mixer SDL2::net textscreen pcsound opl)\n+set(EXTRA_LIBS SDL2::SDL2main SDL2::SDL2 textscreen pcsound opl)\n+if(ENABLE_SDL2_MIXER)\n+ list(APPEND EXTRA_LIBS SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ list(APPEND EXTRA_LIBS SDL2::net)\n+endif()\n if(SAMPLERATE_FOUND)\n list(APPEND EXTRA_LIBS samplerate::samplerate)\n endif()\n@@ -213,7 +222,13 @@ endif()\n \n target_include_directories(\"${PROGRAM_PREFIX}setup\"\n PRIVATE \"${CMAKE_CURRENT_BINARY_DIR}/../\")\n-target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::SDL2main SDL2::SDL2 SDL2::mixer SDL2::net setup textscreen)\n+target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::SDL2main SDL2::SDL2 setup textscreen)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(\"${PROGRAM_PREFIX}setup\" SDL2::net)\n+endif()\n \n if(MSVC)\n set_target_properties(\"${PROGRAM_PREFIX}setup\" PROPERTIES" + }, + { + "sha": "82b114b4178595085c6745bc70a570922415be1f", + "filename": "src/doom/CMakeLists.txt", + "status": "modified", + "additions": 7, + "deletions": 1, + "changes": 8, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fdoom%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fdoom%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fdoom%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -68,4 +68,10 @@ add_library(doom STATIC\n wi_stuff.c wi_stuff.h)\n \n target_include_directories(doom PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(doom SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(doom SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(doom SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(doom SDL2::net)\n+endif()" + }, + { + "sha": "1ea060bfdb8b3147e36b3431fee27934c8a93b34", + "filename": "src/heretic/CMakeLists.txt", + "status": "modified", + "additions": 7, + "deletions": 1, + "changes": 8, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fheretic%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fheretic%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fheretic%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -54,4 +54,10 @@ add_library(heretic STATIC\n s_sound.c s_sound.h)\n \n target_include_directories(heretic PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(heretic textscreen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(heretic textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(heretic SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(heretic SDL2::net)\n+endif()" + }, + { + "sha": "0dbd170bfdb06c8209ec654d4d5377e334be886e", + "filename": "src/hexen/CMakeLists.txt", + "status": "modified", + "additions": 7, + "deletions": 1, + "changes": 8, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fhexen%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fhexen%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fhexen%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -55,4 +55,10 @@ add_library(hexen STATIC\n xddefs.h)\n \n target_include_directories(hexen PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(hexen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(hexen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(hexen SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(hexen SDL2::net)\n+endif()" + }, + { + "sha": "3facce6f01d02c5e8eef3088fa60576b9e949829", + "filename": "src/i_musicpack.c", + "status": "modified", + "additions": 87, + "deletions": 1, + "changes": 88, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_musicpack.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -44,6 +44,13 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n+\n+char *music_pack_path = \"\";\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MID_HEADER_MAGIC \"MThd\"\n #define MUS_HEADER_MAGIC \"MUS\\x1a\"\n \n@@ -99,7 +106,6 @@ static boolean music_initialized = false;\n \n static boolean sdl_was_initialized = false;\n \n-char *music_pack_path = \"\";\n \n // If true, we are playing a substitute digital track rather than in-WAD\n // MIDI/MUS track, and file_metadata contains loop metadata.\n@@ -1375,3 +1381,83 @@ music_module_t music_pack_module =\n I_MP_PollMusic,\n };\n \n+\n+#else // DISABLE_SDL2MIXER\n+\n+\n+static boolean I_NULL_InitMusic(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_ShutdownMusic(void)\n+{\n+}\n+\n+\n+static void I_NULL_SetMusicVolume(int volume)\n+{\n+}\n+\n+\n+static void I_NULL_PauseSong(void)\n+{\n+}\n+\n+\n+static void I_NULL_ResumeSong(void)\n+{\n+}\n+\n+\n+static void *I_NULL_RegisterSong(void *data, int len)\n+{\n+ return NULL;\n+}\n+\n+\n+static void I_NULL_UnRegisterSong(void *handle)\n+{\n+}\n+\n+\n+static void I_NULL_PlaySong(void *handle, boolean looping)\n+{\n+}\n+\n+\n+static void I_NULL_StopSong(void)\n+{\n+}\n+\n+\n+static boolean I_NULL_MusicIsPlaying(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_PollMusic(void)\n+{\n+}\n+\n+music_module_t music_pack_module =\n+{\n+ NULL,\n+ 0,\n+ I_NULL_InitMusic,\n+ I_NULL_ShutdownMusic,\n+ I_NULL_SetMusicVolume,\n+ I_NULL_PauseSong,\n+ I_NULL_ResumeSong,\n+ I_NULL_RegisterSong,\n+ I_NULL_UnRegisterSong,\n+ I_NULL_PlaySong,\n+ I_NULL_StopSong,\n+ I_NULL_MusicIsPlaying,\n+ I_NULL_PollMusic,\n+};\n+\n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "48fedfbd7608ad8c6575a4bd82a5e1cb3646e071", + "filename": "src/i_sdlmusic.c", + "status": "modified", + "additions": 21, + "deletions": 13, + "changes": 34, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlmusic.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -44,19 +44,6 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n-#define MAXMIDLENGTH (96 * 1024)\n-\n-static boolean music_initialized = false;\n-\n-// If this is true, this module initialized SDL sound and has the \n-// responsibility to shut it down\n-\n-static boolean sdl_was_initialized = false;\n-\n-static boolean win_midi_stream_opened = false;\n-\n-static boolean musicpaused = false;\n-static int current_music_volume;\n \n char *fluidsynth_sf_path = \"\";\n char *timidity_cfg_path = \"\";\n@@ -138,6 +125,25 @@ void I_InitTimidityConfig(void)\n }\n }\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n+#define MAXMIDLENGTH (96 * 1024)\n+\n+static boolean music_initialized = false;\n+\n+// If this is true, this module initialized SDL sound and has the\n+// responsibility to shut it down\n+\n+static boolean sdl_was_initialized = false;\n+\n+static boolean win_midi_stream_opened = false;\n+\n+static boolean musicpaused = false;\n+static int current_music_volume;\n+\n+\n // Remove the temporary config file generated by I_InitTimidityConfig().\n \n static void RemoveTimidityConfig(void)\n@@ -588,3 +594,5 @@ music_module_t music_sdl_module =\n NULL, // Poll\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "7f2a26096b218c5323f5dc569c6f70ab399782bf", + "filename": "src/i_sdlsound.c", + "status": "modified", + "additions": 17, + "deletions": 9, + "changes": 26, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -41,6 +41,21 @@\n \n #include \"doomtype.h\"\n \n+\n+int use_libsamplerate = 0;\n+\n+// Scale factor used when converting libsamplerate floating point numbers\n+// to integers. Too high means the sounds can clip; too low means they\n+// will be too quiet. This is an amount that should avoid clipping most\n+// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n+// is used, clipping might occur.\n+\n+float libsamplerate_scale = 0.65f;\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define LOW_PASS_FILTER\n //#define DEBUG_DUMP_WAVS\n #define NUM_CHANNELS 16\n@@ -77,15 +92,6 @@ static allocated_sound_t *allocated_sounds_head = NULL;\n static allocated_sound_t *allocated_sounds_tail = NULL;\n static int allocated_sounds_size = 0;\n \n-int use_libsamplerate = 0;\n-\n-// Scale factor used when converting libsamplerate floating point numbers\n-// to integers. Too high means the sounds can clip; too low means they\n-// will be too quiet. This is an amount that should avoid clipping most\n-// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n-// is used, clipping might occur.\n-\n-float libsamplerate_scale = 0.65f;\n \n // Hook a sound into the linked list at the head.\n \n@@ -1135,3 +1141,5 @@ sound_module_t sound_sdl_module =\n I_SDL_PrecacheSounds,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER" + }, + { + "sha": "9cf1fd95db13504ffc6f98ead8c9150f03db72aa", + "filename": "src/i_sound.c", + "status": "modified", + "additions": 4, + "deletions": 0, + "changes": 4, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -99,7 +99,9 @@ static int snd_mport = 0;\n \n static sound_module_t *sound_modules[] = \n {\n+#ifndef DISABLE_SDL2MIXER\n &sound_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &sound_pcsound_module,\n NULL,\n };\n@@ -108,7 +110,9 @@ static sound_module_t *sound_modules[] =\n \n static music_module_t *music_modules[] =\n {\n+#ifndef DISABLE_SDL2MIXER\n &music_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &music_opl_module,\n NULL,\n };" + }, + { + "sha": "c1f701c0b9f653eb3a36b71627747a6eda963d8f", + "filename": "src/net_sdl.c", + "status": "modified", + "additions": 63, + "deletions": 0, + "changes": 63, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fnet_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -33,6 +33,10 @@\n // NETWORKING\n //\n \n+\n+#ifndef DISABLE_SDL2NET\n+\n+\n #include \n \n #define DEFAULT_PORT 2342\n@@ -376,3 +380,62 @@ net_module_t net_sdl_module =\n NET_SDL_ResolveAddress,\n };\n \n+\n+#else // DISABLE_SDL2NET\n+\n+// no-op implementation\n+\n+\n+static boolean NET_NULL_InitClient(void)\n+{\n+ return false;\n+}\n+\n+\n+static boolean NET_NULL_InitServer(void)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_SendPacket(net_addr_t *addr, net_packet_t *packet)\n+{\n+}\n+\n+\n+static boolean NET_NULL_RecvPacket(net_addr_t **addr, net_packet_t **packet)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)\n+{\n+\n+}\n+\n+\n+static void NET_NULL_FreeAddress(net_addr_t *addr)\n+{\n+}\n+\n+\n+net_addr_t *NET_NULL_ResolveAddress(const char *address)\n+{\n+ return NULL;\n+}\n+\n+\n+net_module_t net_sdl_module =\n+{\n+ NET_NULL_InitClient,\n+ NET_NULL_InitServer,\n+ NET_NULL_SendPacket,\n+ NET_NULL_RecvPacket,\n+ NET_NULL_AddrToString,\n+ NET_NULL_FreeAddress,\n+ NET_NULL_ResolveAddress,\n+};\n+\n+\n+#endif // DISABLE_SDL2NET" + }, + { + "sha": "90df2114163152ff732a9ba4a8bc18ef3d45d1bd", + "filename": "src/setup/CMakeLists.txt", + "status": "modified", + "additions": 4, + "deletions": 1, + "changes": 5, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fsetup%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fsetup%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fsetup%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -15,4 +15,7 @@ add_library(setup STATIC\n txt_mouseinput.c txt_mouseinput.h)\n \n target_include_directories(setup PRIVATE \"../\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(setup textscreen SDL2::SDL2 SDL2::mixer)\n+target_link_libraries(setup textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(setup SDL2::mixer)\n+endif()" + }, + { + "sha": "37b17ade983155369c0897c0935d40dfeb2048c7", + "filename": "src/strife/CMakeLists.txt", + "status": "modified", + "additions": 7, + "deletions": 1, + "changes": 8, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fstrife%2FCMakeLists.txt", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fstrife%2FCMakeLists.txt", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fstrife%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -70,4 +70,10 @@ set(STRIFE_SOURCES\n add_library(strife STATIC ${STRIFE_SOURCES})\n \n target_include_directories(strife PRIVATE \"../\" \"../../win32/\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(strife textscreen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(strife textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(strife SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(strife SDL2::net)\n+endif()" + } +] \ No newline at end of file diff --git a/tests/capture_tools_output/expected_result.json b/tests/capture_tools_output/expected_result.json index 28344bc9..bde9ab51 100644 --- a/tests/capture_tools_output/expected_result.json +++ b/tests/capture_tools_output/expected_result.json @@ -1,409 +1,320 @@ -{ - "sha": "3c35acde7d398c32f6fad50fa902de391f573ffa", - "node_id": "C_kwDOAAOGANoAKDNjMzVhY2RlN2QzOThjMzJmNmZhZDUwZmE5MDJkZTM5MWY1NzNmZmE", - "commit": { - "author": { - "name": "Turo Lamminen", - "email": "turol@users.noreply.github.com", - "date": "2022-07-12T17:58:17Z" - }, - "committer": { - "name": "GitHub", - "email": "noreply@github.com", - "date": "2022-07-12T17:58:17Z" - }, - "message": "Merge 1acdd067d8b168099de009b2cb625c3e4565561a into 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", - "tree": { - "sha": "61aafe76912a4e79bfe9e2e0620d5fc09792922e", - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/trees/61aafe76912a4e79bfe9e2e0620d5fc09792922e" - }, - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/git/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", - "comment_count": 0, - "verification": { - "verified": true, - "reason": "valid", - "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsBcBAABCAAQBQJizbY5CRBK7hj4Ov3rIwAAd90IAEK0v5LTMD8TaaSlWOiXQ6Jh\nYqjVo248+3MuFEH2Em+QFt6RVbhA/HzsaD2E1qwigyOd0VXu2PZvGUP/hvB/x4AM\nEBxFAdGpP+nLhGF3uWJTZ6K/hfuvL6r4xV+EiqCBb1mSpy13N7kbBy3phSJfWgGM\nyrzR6qv40fgZgGRtFaOkP96SWNO+XnpHzoHqpVXaqYzj3sn1kZwbF6LoZUJy+7YZ\nJJFWZUg0mxsvlGZUZBO7e0KMZmPzLXfAA+heF7UqaDE6mT/lP/FSXHrZHH8J3Iju\nWOWECb2qRgNVYGuxhqW7+iN8ZvbDPI1+lPEvRAl4u72+piN++XrQgh5zgiNzDOU=\n=+D8A\n-----END PGP SIGNATURE-----\n", - "payload": "tree 61aafe76912a4e79bfe9e2e0620d5fc09792922e\nparent 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8\nparent 1acdd067d8b168099de009b2cb625c3e4565561a\nauthor Turo Lamminen 1657648697 +0000\ncommitter GitHub 1657648697 +0000\n\nMerge 1acdd067d8b168099de009b2cb625c3e4565561a into 7afbf68abcaad446c3f287ed502c6ebbb2fb10e8\n" +[ + { + "sha": "46e082cf77c5e60affc7689f7357c926fc00cda3", + "filename": "opl/opl.c", + "status": "modified", + "additions": 2, + "deletions": 0, + "changes": 2, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -50,7 +50,9 @@ static opl_driver_t *drivers[] =\n #ifdef _WIN32\n &opl_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &opl_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL\n };\n ", + "line_filter": { + "diff_chunks": [ + [ + 50, + 59 + ] + ], + "lines_added": [ + [ + 53, + 54 + ], + [ + 55, + 56 + ] + ] } }, - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa", - "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/3c35acde7d398c32f6fad50fa902de391f573ffa", - "comments_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/3c35acde7d398c32f6fad50fa902de391f573ffa/comments", - "author": { - "login": "turol", - "id": 805057, - "node_id": "MDQ6VXNlcjgwNTA1Nw==", - "avatar_url": "https://avatars.githubusercontent.com/u/805057?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/turol", - "html_url": "https://github.com/turol", - "followers_url": "https://api.github.com/users/turol/followers", - "following_url": "https://api.github.com/users/turol/following{/other_user}", - "gists_url": "https://api.github.com/users/turol/gists{/gist_id}", - "starred_url": "https://api.github.com/users/turol/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/turol/subscriptions", - "organizations_url": "https://api.github.com/users/turol/orgs", - "repos_url": "https://api.github.com/users/turol/repos", - "events_url": "https://api.github.com/users/turol/events{/privacy}", - "received_events_url": "https://api.github.com/users/turol/received_events", - "type": "User", - "site_admin": false + { + "sha": "6bd4e7e1f3374e289d3dc19972dcb1d5379d6b03", + "filename": "opl/opl_sdl.c", + "status": "modified", + "additions": 6, + "deletions": 0, + "changes": 6, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -33,6 +33,10 @@\n \n #include \"opl_queue.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 100 /* ms */\n \n typedef struct\n@@ -511,3 +515,5 @@ opl_driver_t opl_sdl_driver =\n OPL_SDL_AdjustCallbacks,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 33, + 43 + ], + [ + 515, + 520 + ] + ], + "lines_added": [ + [ + 36, + 40 + ], + [ + 518, + 520 + ] + ] + } }, - "committer": { - "login": "web-flow", - "id": 19864447, - "node_id": "MDQ6VXNlcjE5ODY0NDQ3", - "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/web-flow", - "html_url": "https://github.com/web-flow", - "followers_url": "https://api.github.com/users/web-flow/followers", - "following_url": "https://api.github.com/users/web-flow/following{/other_user}", - "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", - "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", - "organizations_url": "https://api.github.com/users/web-flow/orgs", - "repos_url": "https://api.github.com/users/web-flow/repos", - "events_url": "https://api.github.com/users/web-flow/events{/privacy}", - "received_events_url": "https://api.github.com/users/web-flow/received_events", - "type": "User", - "site_admin": false + { + "sha": "58f9b75c2affd5f1dd990aaedab79d834575bf83", + "filename": "pcsound/pcsound.c", + "status": "modified", + "additions": 2, + "deletions": 0, + "changes": 2, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -56,7 +56,9 @@ static pcsound_driver_t *drivers[] =\n #ifdef _WIN32\n &pcsound_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &pcsound_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL,\n };\n ", + "line_filter": { + "diff_chunks": [ + [ + 56, + 65 + ] + ], + "lines_added": [ + [ + 59, + 60 + ], + [ + 61, + 62 + ] + ] + } }, - "parents": [ - { - "sha": "7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/7afbf68abcaad446c3f287ed502c6ebbb2fb10e8", - "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/7afbf68abcaad446c3f287ed502c6ebbb2fb10e8" - }, - { - "sha": "1acdd067d8b168099de009b2cb625c3e4565561a", - "url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/commits/1acdd067d8b168099de009b2cb625c3e4565561a", - "html_url": "https://github.com/chocolate-doom/chocolate-doom/commit/1acdd067d8b168099de009b2cb625c3e4565561a" + { + "sha": "e77c7b0d29de1b0c665686004dfda311c9d96719", + "filename": "pcsound/pcsound_sdl.c", + "status": "modified", + "additions": 6, + "deletions": 0, + "changes": 6, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -24,6 +24,10 @@\n #include \"pcsound.h\"\n #include \"pcsound_internal.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 70 /* ms */\n #define SQUARE_WAVE_AMP 0x2000\n \n@@ -248,3 +252,5 @@ pcsound_driver_t pcsound_sdl_driver =\n PCSound_SDL_Shutdown,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 24, + 34 + ], + [ + 252, + 257 + ] + ], + "lines_added": [ + [ + 27, + 31 + ], + [ + 255, + 257 + ] + ] } - ], - "stats": { - "total": 334, - "additions": 297, - "deletions": 37 }, - "files": [ - { - "sha": "46e082cf77c5e60affc7689f7357c926fc00cda3", - "filename": "opl/opl.c", - "status": "modified", - "additions": 2, - "deletions": 0, - "changes": 2, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -50,7 +50,9 @@ static opl_driver_t *drivers[] =\n #ifdef _WIN32\n &opl_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &opl_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL\n };\n ", - "line_filter": { - "diff_chunks": [ - [ - 50, - 59 - ] + { + "sha": "3facce6f01d02c5e8eef3088fa60576b9e949829", + "filename": "src/i_musicpack.c", + "status": "modified", + "additions": 87, + "deletions": 1, + "changes": 88, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_musicpack.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -44,6 +44,13 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n+\n+char *music_pack_path = \"\";\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MID_HEADER_MAGIC \"MThd\"\n #define MUS_HEADER_MAGIC \"MUS\\x1a\"\n \n@@ -99,7 +106,6 @@ static boolean music_initialized = false;\n \n static boolean sdl_was_initialized = false;\n \n-char *music_pack_path = \"\";\n \n // If true, we are playing a substitute digital track rather than in-WAD\n // MIDI/MUS track, and file_metadata contains loop metadata.\n@@ -1375,3 +1381,83 @@ music_module_t music_pack_module =\n I_MP_PollMusic,\n };\n \n+\n+#else // DISABLE_SDL2MIXER\n+\n+\n+static boolean I_NULL_InitMusic(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_ShutdownMusic(void)\n+{\n+}\n+\n+\n+static void I_NULL_SetMusicVolume(int volume)\n+{\n+}\n+\n+\n+static void I_NULL_PauseSong(void)\n+{\n+}\n+\n+\n+static void I_NULL_ResumeSong(void)\n+{\n+}\n+\n+\n+static void *I_NULL_RegisterSong(void *data, int len)\n+{\n+ return NULL;\n+}\n+\n+\n+static void I_NULL_UnRegisterSong(void *handle)\n+{\n+}\n+\n+\n+static void I_NULL_PlaySong(void *handle, boolean looping)\n+{\n+}\n+\n+\n+static void I_NULL_StopSong(void)\n+{\n+}\n+\n+\n+static boolean I_NULL_MusicIsPlaying(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_PollMusic(void)\n+{\n+}\n+\n+music_module_t music_pack_module =\n+{\n+ NULL,\n+ 0,\n+ I_NULL_InitMusic,\n+ I_NULL_ShutdownMusic,\n+ I_NULL_SetMusicVolume,\n+ I_NULL_PauseSong,\n+ I_NULL_ResumeSong,\n+ I_NULL_RegisterSong,\n+ I_NULL_UnRegisterSong,\n+ I_NULL_PlaySong,\n+ I_NULL_StopSong,\n+ I_NULL_MusicIsPlaying,\n+ I_NULL_PollMusic,\n+};\n+\n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 44, + 57 ], - "lines_added": [ - [ - 53, - 54 - ], - [ - 55, - 56 - ] + [ + 106, + 112 + ], + [ + 1381, + 1464 ] - } - }, - { - "sha": "6bd4e7e1f3374e289d3dc19972dcb1d5379d6b03", - "filename": "opl/opl_sdl.c", - "status": "modified", - "additions": 6, - "deletions": 0, - "changes": 6, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/opl%2Fopl_sdl.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/opl%2Fopl_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -33,6 +33,10 @@\n \n #include \"opl_queue.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 100 /* ms */\n \n typedef struct\n@@ -511,3 +515,5 @@ opl_driver_t opl_sdl_driver =\n OPL_SDL_AdjustCallbacks,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", - "line_filter": { - "diff_chunks": [ - [ - 33, - 43 - ], - [ - 515, - 520 - ] + ], + "lines_added": [ + [ + 47, + 54 ], - "lines_added": [ - [ - 36, - 40 - ], - [ - 518, - 520 - ] + [ + 1384, + 1464 ] - } - }, - { - "sha": "58f9b75c2affd5f1dd990aaedab79d834575bf83", - "filename": "pcsound/pcsound.c", - "status": "modified", - "additions": 2, - "deletions": 0, - "changes": 2, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -56,7 +56,9 @@ static pcsound_driver_t *drivers[] =\n #ifdef _WIN32\n &pcsound_win32_driver,\n #endif\n+#ifndef DISABLE_SDL2MIXER\n &pcsound_sdl_driver,\n+#endif // DISABLE_SDL2MIXER\n NULL,\n };\n ", - "line_filter": { - "diff_chunks": [ - [ - 56, - 65 - ] + ] + } + }, + { + "sha": "48fedfbd7608ad8c6575a4bd82a5e1cb3646e071", + "filename": "src/i_sdlmusic.c", + "status": "modified", + "additions": 21, + "deletions": 13, + "changes": 34, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlmusic.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -44,19 +44,6 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n-#define MAXMIDLENGTH (96 * 1024)\n-\n-static boolean music_initialized = false;\n-\n-// If this is true, this module initialized SDL sound and has the \n-// responsibility to shut it down\n-\n-static boolean sdl_was_initialized = false;\n-\n-static boolean win_midi_stream_opened = false;\n-\n-static boolean musicpaused = false;\n-static int current_music_volume;\n \n char *fluidsynth_sf_path = \"\";\n char *timidity_cfg_path = \"\";\n@@ -138,6 +125,25 @@ void I_InitTimidityConfig(void)\n }\n }\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n+#define MAXMIDLENGTH (96 * 1024)\n+\n+static boolean music_initialized = false;\n+\n+// If this is true, this module initialized SDL sound and has the\n+// responsibility to shut it down\n+\n+static boolean sdl_was_initialized = false;\n+\n+static boolean win_midi_stream_opened = false;\n+\n+static boolean musicpaused = false;\n+static int current_music_volume;\n+\n+\n // Remove the temporary config file generated by I_InitTimidityConfig().\n \n static void RemoveTimidityConfig(void)\n@@ -588,3 +594,5 @@ music_module_t music_sdl_module =\n NULL, // Poll\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 44, + 50 + ], + [ + 125, + 150 ], - "lines_added": [ - [ - 59, - 60 - ], - [ - 61, - 62 - ] + [ + 594, + 599 ] - } - }, - { - "sha": "e77c7b0d29de1b0c665686004dfda311c9d96719", - "filename": "pcsound/pcsound_sdl.c", - "status": "modified", - "additions": 6, - "deletions": 0, - "changes": 6, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/pcsound%2Fpcsound_sdl.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/pcsound%2Fpcsound_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -24,6 +24,10 @@\n #include \"pcsound.h\"\n #include \"pcsound_internal.h\"\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MAX_SOUND_SLICE_TIME 70 /* ms */\n #define SQUARE_WAVE_AMP 0x2000\n \n@@ -248,3 +252,5 @@ pcsound_driver_t pcsound_sdl_driver =\n PCSound_SDL_Shutdown,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", - "line_filter": { - "diff_chunks": [ - [ - 24, - 34 - ], - [ - 252, - 257 - ] + ], + "lines_added": [ + [ + 128, + 147 ], - "lines_added": [ - [ - 27, - 31 - ], - [ - 255, - 257 - ] + [ + 597, + 599 ] - } - }, - { - "sha": "3facce6f01d02c5e8eef3088fa60576b9e949829", - "filename": "src/i_musicpack.c", - "status": "modified", - "additions": 87, - "deletions": 1, - "changes": 88, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_musicpack.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_musicpack.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -44,6 +44,13 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n+\n+char *music_pack_path = \"\";\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define MID_HEADER_MAGIC \"MThd\"\n #define MUS_HEADER_MAGIC \"MUS\\x1a\"\n \n@@ -99,7 +106,6 @@ static boolean music_initialized = false;\n \n static boolean sdl_was_initialized = false;\n \n-char *music_pack_path = \"\";\n \n // If true, we are playing a substitute digital track rather than in-WAD\n // MIDI/MUS track, and file_metadata contains loop metadata.\n@@ -1375,3 +1381,83 @@ music_module_t music_pack_module =\n I_MP_PollMusic,\n };\n \n+\n+#else // DISABLE_SDL2MIXER\n+\n+\n+static boolean I_NULL_InitMusic(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_ShutdownMusic(void)\n+{\n+}\n+\n+\n+static void I_NULL_SetMusicVolume(int volume)\n+{\n+}\n+\n+\n+static void I_NULL_PauseSong(void)\n+{\n+}\n+\n+\n+static void I_NULL_ResumeSong(void)\n+{\n+}\n+\n+\n+static void *I_NULL_RegisterSong(void *data, int len)\n+{\n+ return NULL;\n+}\n+\n+\n+static void I_NULL_UnRegisterSong(void *handle)\n+{\n+}\n+\n+\n+static void I_NULL_PlaySong(void *handle, boolean looping)\n+{\n+}\n+\n+\n+static void I_NULL_StopSong(void)\n+{\n+}\n+\n+\n+static boolean I_NULL_MusicIsPlaying(void)\n+{\n+ return false;\n+}\n+\n+\n+static void I_NULL_PollMusic(void)\n+{\n+}\n+\n+music_module_t music_pack_module =\n+{\n+ NULL,\n+ 0,\n+ I_NULL_InitMusic,\n+ I_NULL_ShutdownMusic,\n+ I_NULL_SetMusicVolume,\n+ I_NULL_PauseSong,\n+ I_NULL_ResumeSong,\n+ I_NULL_RegisterSong,\n+ I_NULL_UnRegisterSong,\n+ I_NULL_PlaySong,\n+ I_NULL_StopSong,\n+ I_NULL_MusicIsPlaying,\n+ I_NULL_PollMusic,\n+};\n+\n+\n+#endif // DISABLE_SDL2MIXER", - "line_filter": { - "diff_chunks": [ - [ - 44, - 57 - ], - [ - 106, - 112 - ], - [ - 1381, - 1464 - ] + ] + } + }, + { + "sha": "7f2a26096b218c5323f5dc569c6f70ab399782bf", + "filename": "src/i_sdlsound.c", + "status": "modified", + "additions": 17, + "deletions": 9, + "changes": 26, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -41,6 +41,21 @@\n \n #include \"doomtype.h\"\n \n+\n+int use_libsamplerate = 0;\n+\n+// Scale factor used when converting libsamplerate floating point numbers\n+// to integers. Too high means the sounds can clip; too low means they\n+// will be too quiet. This is an amount that should avoid clipping most\n+// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n+// is used, clipping might occur.\n+\n+float libsamplerate_scale = 0.65f;\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define LOW_PASS_FILTER\n //#define DEBUG_DUMP_WAVS\n #define NUM_CHANNELS 16\n@@ -77,15 +92,6 @@ static allocated_sound_t *allocated_sounds_head = NULL;\n static allocated_sound_t *allocated_sounds_tail = NULL;\n static int allocated_sounds_size = 0;\n \n-int use_libsamplerate = 0;\n-\n-// Scale factor used when converting libsamplerate floating point numbers\n-// to integers. Too high means the sounds can clip; too low means they\n-// will be too quiet. This is an amount that should avoid clipping most\n-// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n-// is used, clipping might occur.\n-\n-float libsamplerate_scale = 0.65f;\n \n // Hook a sound into the linked list at the head.\n \n@@ -1135,3 +1141,5 @@ sound_module_t sound_sdl_module =\n I_SDL_PrecacheSounds,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", + "line_filter": { + "diff_chunks": [ + [ + 41, + 62 ], - "lines_added": [ - [ - 47, - 54 - ], - [ - 1384, - 1464 - ] + [ + 92, + 98 + ], + [ + 1141, + 1146 ] - } - }, - { - "sha": "48fedfbd7608ad8c6575a4bd82a5e1cb3646e071", - "filename": "src/i_sdlmusic.c", - "status": "modified", - "additions": 21, - "deletions": 13, - "changes": 34, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlmusic.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlmusic.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -44,19 +44,6 @@\n #include \"w_wad.h\"\n #include \"z_zone.h\"\n \n-#define MAXMIDLENGTH (96 * 1024)\n-\n-static boolean music_initialized = false;\n-\n-// If this is true, this module initialized SDL sound and has the \n-// responsibility to shut it down\n-\n-static boolean sdl_was_initialized = false;\n-\n-static boolean win_midi_stream_opened = false;\n-\n-static boolean musicpaused = false;\n-static int current_music_volume;\n \n char *fluidsynth_sf_path = \"\";\n char *timidity_cfg_path = \"\";\n@@ -138,6 +125,25 @@ void I_InitTimidityConfig(void)\n }\n }\n \n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n+#define MAXMIDLENGTH (96 * 1024)\n+\n+static boolean music_initialized = false;\n+\n+// If this is true, this module initialized SDL sound and has the\n+// responsibility to shut it down\n+\n+static boolean sdl_was_initialized = false;\n+\n+static boolean win_midi_stream_opened = false;\n+\n+static boolean musicpaused = false;\n+static int current_music_volume;\n+\n+\n // Remove the temporary config file generated by I_InitTimidityConfig().\n \n static void RemoveTimidityConfig(void)\n@@ -588,3 +594,5 @@ music_module_t music_sdl_module =\n NULL, // Poll\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", - "line_filter": { - "diff_chunks": [ - [ - 44, - 50 - ], - [ - 125, - 150 - ], - [ - 594, - 599 - ] + ], + "lines_added": [ + [ + 44, + 59 ], - "lines_added": [ - [ - 128, - 147 - ], - [ - 597, - 599 - ] + [ + 1144, + 1146 ] - } - }, - { - "sha": "7f2a26096b218c5323f5dc569c6f70ab399782bf", - "filename": "src/i_sdlsound.c", - "status": "modified", - "additions": 17, - "deletions": 9, - "changes": 26, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sdlsound.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sdlsound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -41,6 +41,21 @@\n \n #include \"doomtype.h\"\n \n+\n+int use_libsamplerate = 0;\n+\n+// Scale factor used when converting libsamplerate floating point numbers\n+// to integers. Too high means the sounds can clip; too low means they\n+// will be too quiet. This is an amount that should avoid clipping most\n+// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n+// is used, clipping might occur.\n+\n+float libsamplerate_scale = 0.65f;\n+\n+\n+#ifndef DISABLE_SDL2MIXER\n+\n+\n #define LOW_PASS_FILTER\n //#define DEBUG_DUMP_WAVS\n #define NUM_CHANNELS 16\n@@ -77,15 +92,6 @@ static allocated_sound_t *allocated_sounds_head = NULL;\n static allocated_sound_t *allocated_sounds_tail = NULL;\n static int allocated_sounds_size = 0;\n \n-int use_libsamplerate = 0;\n-\n-// Scale factor used when converting libsamplerate floating point numbers\n-// to integers. Too high means the sounds can clip; too low means they\n-// will be too quiet. This is an amount that should avoid clipping most\n-// of the time: with all the Doom IWAD sound effects, at least. If a PWAD\n-// is used, clipping might occur.\n-\n-float libsamplerate_scale = 0.65f;\n \n // Hook a sound into the linked list at the head.\n \n@@ -1135,3 +1141,5 @@ sound_module_t sound_sdl_module =\n I_SDL_PrecacheSounds,\n };\n \n+\n+#endif // DISABLE_SDL2MIXER", - "line_filter": { - "diff_chunks": [ - [ - 41, - 62 - ], - [ - 92, - 98 - ], - [ - 1141, - 1146 - ] + ] + } + }, + { + "sha": "9cf1fd95db13504ffc6f98ead8c9150f03db72aa", + "filename": "src/i_sound.c", + "status": "modified", + "additions": 4, + "deletions": 0, + "changes": 4, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -99,7 +99,9 @@ static int snd_mport = 0;\n \n static sound_module_t *sound_modules[] = \n {\n+#ifndef DISABLE_SDL2MIXER\n &sound_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &sound_pcsound_module,\n NULL,\n };\n@@ -108,7 +110,9 @@ static sound_module_t *sound_modules[] =\n \n static music_module_t *music_modules[] =\n {\n+#ifndef DISABLE_SDL2MIXER\n &music_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &music_opl_module,\n NULL,\n };", + "line_filter": { + "diff_chunks": [ + [ + 99, + 108 ], - "lines_added": [ - [ - 44, - 59 - ], - [ - 1144, - 1146 - ] + [ + 110, + 119 ] - } - }, - { - "sha": "9cf1fd95db13504ffc6f98ead8c9150f03db72aa", - "filename": "src/i_sound.c", - "status": "modified", - "additions": 4, - "deletions": 0, - "changes": 4, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fi_sound.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fi_sound.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -99,7 +99,9 @@ static int snd_mport = 0;\n \n static sound_module_t *sound_modules[] = \n {\n+#ifndef DISABLE_SDL2MIXER\n &sound_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &sound_pcsound_module,\n NULL,\n };\n@@ -108,7 +110,9 @@ static sound_module_t *sound_modules[] =\n \n static music_module_t *music_modules[] =\n {\n+#ifndef DISABLE_SDL2MIXER\n &music_sdl_module,\n+#endif // DISABLE_SDL2MIXER\n &music_opl_module,\n NULL,\n };", - "line_filter": { - "diff_chunks": [ - [ - 99, - 108 - ], - [ - 110, - 119 - ] + ], + "lines_added": [ + [ + 102, + 103 + ], + [ + 104, + 105 + ], + [ + 113, + 114 + ], + [ + 115, + 116 + ] + ] + } + }, + { + "sha": "c1f701c0b9f653eb3a36b71627747a6eda963d8f", + "filename": "src/net_sdl.c", + "status": "modified", + "additions": 63, + "deletions": 0, + "changes": 63, + "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", + "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", + "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fnet_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", + "patch": "@@ -33,6 +33,10 @@\n // NETWORKING\n //\n \n+\n+#ifndef DISABLE_SDL2NET\n+\n+\n #include \n \n #define DEFAULT_PORT 2342\n@@ -376,3 +380,62 @@ net_module_t net_sdl_module =\n NET_SDL_ResolveAddress,\n };\n \n+\n+#else // DISABLE_SDL2NET\n+\n+// no-op implementation\n+\n+\n+static boolean NET_NULL_InitClient(void)\n+{\n+ return false;\n+}\n+\n+\n+static boolean NET_NULL_InitServer(void)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_SendPacket(net_addr_t *addr, net_packet_t *packet)\n+{\n+}\n+\n+\n+static boolean NET_NULL_RecvPacket(net_addr_t **addr, net_packet_t **packet)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)\n+{\n+\n+}\n+\n+\n+static void NET_NULL_FreeAddress(net_addr_t *addr)\n+{\n+}\n+\n+\n+net_addr_t *NET_NULL_ResolveAddress(const char *address)\n+{\n+ return NULL;\n+}\n+\n+\n+net_module_t net_sdl_module =\n+{\n+ NET_NULL_InitClient,\n+ NET_NULL_InitServer,\n+ NET_NULL_SendPacket,\n+ NET_NULL_RecvPacket,\n+ NET_NULL_AddrToString,\n+ NET_NULL_FreeAddress,\n+ NET_NULL_ResolveAddress,\n+};\n+\n+\n+#endif // DISABLE_SDL2NET", + "line_filter": { + "diff_chunks": [ + [ + 33, + 43 ], - "lines_added": [ - [ - 102, - 103 - ], - [ - 104, - 105 - ], - [ - 113, - 114 - ], - [ - 115, - 116 - ] + [ + 380, + 442 ] - } - }, - { - "sha": "c1f701c0b9f653eb3a36b71627747a6eda963d8f", - "filename": "src/net_sdl.c", - "status": "modified", - "additions": 63, - "deletions": 0, - "changes": 63, - "blob_url": "https://github.com/chocolate-doom/chocolate-doom/blob/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", - "raw_url": "https://github.com/chocolate-doom/chocolate-doom/raw/3c35acde7d398c32f6fad50fa902de391f573ffa/src%2Fnet_sdl.c", - "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fnet_sdl.c?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", - "patch": "@@ -33,6 +33,10 @@\n // NETWORKING\n //\n \n+\n+#ifndef DISABLE_SDL2NET\n+\n+\n #include \n \n #define DEFAULT_PORT 2342\n@@ -376,3 +380,62 @@ net_module_t net_sdl_module =\n NET_SDL_ResolveAddress,\n };\n \n+\n+#else // DISABLE_SDL2NET\n+\n+// no-op implementation\n+\n+\n+static boolean NET_NULL_InitClient(void)\n+{\n+ return false;\n+}\n+\n+\n+static boolean NET_NULL_InitServer(void)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_SendPacket(net_addr_t *addr, net_packet_t *packet)\n+{\n+}\n+\n+\n+static boolean NET_NULL_RecvPacket(net_addr_t **addr, net_packet_t **packet)\n+{\n+ return false;\n+}\n+\n+\n+static void NET_NULL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)\n+{\n+\n+}\n+\n+\n+static void NET_NULL_FreeAddress(net_addr_t *addr)\n+{\n+}\n+\n+\n+net_addr_t *NET_NULL_ResolveAddress(const char *address)\n+{\n+ return NULL;\n+}\n+\n+\n+net_module_t net_sdl_module =\n+{\n+ NET_NULL_InitClient,\n+ NET_NULL_InitServer,\n+ NET_NULL_SendPacket,\n+ NET_NULL_RecvPacket,\n+ NET_NULL_AddrToString,\n+ NET_NULL_FreeAddress,\n+ NET_NULL_ResolveAddress,\n+};\n+\n+\n+#endif // DISABLE_SDL2NET", - "line_filter": { - "diff_chunks": [ - [ - 33, - 43 - ], - [ - 380, - 442 - ] + ], + "lines_added": [ + [ + 36, + 40 ], - "lines_added": [ - [ - 36, - 40 - ], - [ - 383, - 442 - ] + [ + 383, + 442 ] - } + ] } - ] -} \ No newline at end of file + } +] \ No newline at end of file diff --git a/tests/capture_tools_output/test_tools_output.py b/tests/capture_tools_output/test_tools_output.py index 8ab0e2bb..c7467fa3 100644 --- a/tests/capture_tools_output/test_tools_output.py +++ b/tests/capture_tools_output/test_tools_output.py @@ -45,8 +45,8 @@ def test_lines_changed_only( ): test_result = Path("expected_result.json").read_text(encoding="utf-8") for file, result in zip( - cpp_linter.Globals.FILES["files"], # type: ignore - json.loads(test_result)["files"], + cpp_linter.Globals.FILES, + json.loads(test_result), ): expected = result["line_filter"]["diff_chunks"] assert file["line_filter"]["diff_chunks"] == expected @@ -56,18 +56,15 @@ def test_lines_changed_only( raise RuntimeError("test failed to find files") -TEST_REPO = re.compile(r"https://api.github.com/repos/(?:\w|\-|_)+/((?:\w|\-|_)+)/.*") +TEST_REPO = re.compile(r".*github.com/(?:\w|\-|_)+/((?:\w|\-|_)+)/.*") @pytest.fixture(autouse=True) def setup_test_repo(monkeypatch: pytest.MonkeyPatch) -> None: """Setup a test repo to run the rest of the tests in this module.""" test_root = Path(__file__).parent - cpp_linter.Globals.FILES = cast( - Dict[str, Any], - json.loads( - Path(test_root / "expected_result.json").read_text(encoding="utf-8") - ), + cpp_linter.Globals.FILES = json.loads( + Path(test_root / "expected_result.json").read_text(encoding="utf-8") ) # flush output from any previous tests cpp_linter.Globals.OUTPUT = "" @@ -75,7 +72,7 @@ def setup_test_repo(monkeypatch: pytest.MonkeyPatch) -> None: cpp_linter.GlobalParser.tidy_notes = [] cpp_linter.GlobalParser.tidy_advice = [] - repo_root = TEST_REPO.sub("\\1", cpp_linter.Globals.FILES["url"]) + repo_root = TEST_REPO.sub("\\1", cpp_linter.Globals.FILES[0]["blob_url"]) return_path = test_root / repo_root if not return_path.exists(): return_path.mkdir() @@ -85,7 +82,7 @@ def setup_test_repo(monkeypatch: pytest.MonkeyPatch) -> None: def match_file_json(filename: str) -> Optional[Dict[str, Any]]: """A helper function to match a given filename with a file's JSON object.""" - for file in cpp_linter.Globals.FILES["files"]: # type: ignore + for file in cpp_linter.Globals.FILES: if file["filename"] == filename: return file print("file", filename, "not found in expected_result.json") diff --git a/tests/test_misc.py b/tests/test_misc.py index 951ddbb8..da52659a 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -74,18 +74,20 @@ def test_list_src_files(extensions: List[str]): assert list_source_files(ext_list=extensions, ignored_paths=[], not_ignored=[]) -def test_get_changed_files(): +def test_get_changed_files(caplog: pytest.LogCaptureFixture): """test getting a list of changed files for an event. This is expected to fail if a github token not supplied as an env var. We don't need to supply one for this test because the tested code will execute anyway. """ + caplog.set_level(logging.DEBUG, logger=cpp_linter.logger.name) cpp_linter.run.GITHUB_REPOSITORY = "cpp-linter/test-cpp-linter-action" - cpp_linter.GITHUB_SHA = "76adde5367196cd57da5bef49a4f09af6175fd3f" + cpp_linter.run.GITHUB_SHA = "76adde5367196cd57da5bef49a4f09af6175fd3f" + cpp_linter.run.GITHUB_EVENT_NAME = "push" get_list_of_changed_files() # pylint: disable=no-member - assert "files" not in cast(Dict[str, Any], Globals.FILES).keys() + assert Globals.FILES # pylint: enable=no-member From 269b22cb9a9998889a9762cd1e9bbe242398a0cc Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 9 Aug 2022 03:02:40 -0700 Subject: [PATCH 55/76] ammend walking the repo files/folders This could probably get changed to using pathlib's glob mechanism. --- cpp_linter/run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 30e05b5c..6a1313b4 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -291,7 +291,7 @@ def filter_out_non_source_files( # additions is a list line numbers in the diff containing additions additions: List[int] = [] line_numb_in_diff: int = 0 - for line in file["patch"].splitlines(): + for line in cast(str, file["patch"]).splitlines(): if line.startswith("+"): additions.append(line_numb_in_diff) if line.startswith("@@ -"): @@ -363,7 +363,7 @@ def list_source_files( root_path = Path.cwd().as_posix() for dirpath, _, filenames in os.walk(root_path): - path = PurePath(dirpath.replace(root_path, "")) + path = PurePath(PurePath(dirpath).as_posix().replace(root_path, "").lstrip("/")) path_parts = path.parents is_hidden = False for part in path_parts: From 8f48baa797b712a11f7e21af6753931575970faa Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 9 Aug 2022 04:14:48 -0700 Subject: [PATCH 56/76] replace os.walk() with pathlib's rglob() --- cpp_linter/run.py | 32 ++++++++++---------------------- tests/test_misc.py | 10 ++++++++-- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 6a1313b4..999b6e79 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -361,36 +361,24 @@ def list_source_files( """ start_log_group("Get list of specified source files") - root_path = Path.cwd().as_posix() - for dirpath, _, filenames in os.walk(root_path): - path = PurePath(PurePath(dirpath).as_posix().replace(root_path, "").lstrip("/")) - path_parts = path.parents - is_hidden = False - for part in path_parts: - if part.as_posix().startswith("."): - # logger.debug("Skipping \"./%s\"", path) - is_hidden = True - break - if is_hidden: - continue # skip sources in hidden directories - logger.debug('Crawling "./%s"', path.as_posix()) - for file in filenames: - if PurePath(file).suffix.lstrip(".") in ext_list: - file_path = PurePath(path, file).as_posix() + root_path = Path(".") + for ext in ext_list: + for rel_path in root_path.rglob(f"*.{ext}"): + for parent in rel_path.parts[:-1]: + if parent.startswith("."): + break + else: + file_path = rel_path.as_posix() logger.debug('"./%s" is a source code file', file_path) if not is_file_in_list( ignored_paths, file_path, "ignored" ) or is_file_in_list(not_ignored, file_path, "not ignored"): - cast(List[Dict[str, Any]], Globals.FILES).append( - {"filename": file_path} - ) + Globals.FILES.append(dict(filename=file_path)) if Globals.FILES: logger.info( "Giving attention to the following files:\n\t%s", - "\n\t".join( - [f["filename"] for f in Globals.FILES] - ), + "\n\t".join([f["filename"] for f in Globals.FILES]), ) else: logger.info("No source files found.") # this might need to be warning diff --git a/tests/test_misc.py b/tests/test_misc.py index da52659a..df624fb6 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,7 +1,7 @@ """Tests that complete coverage that aren't prone to failure.""" import logging from pathlib import Path -from typing import List, cast, Dict, Any +from typing import List import pytest import requests import cpp_linter @@ -68,9 +68,15 @@ def test_response_logs(url: str): pytest.param(["cxx", "h"], marks=pytest.mark.xfail), ], ) -def test_list_src_files(extensions: List[str]): +def test_list_src_files( + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, + extensions: List[str], +): """List the source files in the demo folder of this repo.""" Globals.FILES = [] + monkeypatch.chdir(Path(__file__).parent.parent.as_posix()) + caplog.set_level(logging.DEBUG, logger=cpp_linter.logger.name) assert list_source_files(ext_list=extensions, ignored_paths=[], not_ignored=[]) From 97f48dbd37b153b48f46585c86a942cc08958872 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 9 Aug 2022 04:58:31 -0700 Subject: [PATCH 57/76] only upload coverage report once from test CI --- .github/workflows/run-dev-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 15d64e86..95fb6b8a 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -101,7 +101,7 @@ jobs: - run: coverage report && coverage xml - uses: codecov/codecov-action@v3 - if: matrix.os == 'ubuntu-latest' && matrix.version == '12' + if: matrix.os == 'ubuntu-latest' && matrix.version == '12' && matrix.py == '3.10' with: files: ./coverage.xml fail_ci_if_error: true # optional (default = false) From b9aa4cc6a4dab39ecd08d4d0bf9685f41cb954cc Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 10 Aug 2022 04:09:08 -0700 Subject: [PATCH 58/76] use OS dependent path separators for DB path --- cpp_linter/run.py | 2 +- tests/capture_tools_output/test_database_path.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index 999b6e79..a03c48af 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -420,7 +420,7 @@ def run_clang_tidy( if database: cmds.append("-p") if not PurePath(database).is_absolute(): - database = Path(RUNNER_WORKSPACE, repo_root, database).resolve().as_posix() + database = str(Path(RUNNER_WORKSPACE, repo_root, database).resolve()) cmds.append(database) if lines_changed_only: ranges = "diff_chunks" if lines_changed_only == 1 else "lines_added" diff --git a/tests/capture_tools_output/test_database_path.py b/tests/capture_tools_output/test_database_path.py index 70fb2ce7..da275a30 100644 --- a/tests/capture_tools_output/test_database_path.py +++ b/tests/capture_tools_output/test_database_path.py @@ -10,7 +10,7 @@ CLANG_TIDY_COMMAND = re.compile(r"\"clang-tidy(.*)(?:\")") -ABS_DB_PATH = Path(PurePath(__file__).parent / "../../demo").resolve().as_posix() +ABS_DB_PATH = str(Path(PurePath(__file__).parent / "../../demo").resolve()) @pytest.mark.parametrize( @@ -54,4 +54,4 @@ def test_db_detection( matched_args = msg_match.group(0)[:-1].split()[2:] assert "Error while trying to load a compilation database" not in record.message expected_args.append(demo_src) - assert matched_args == [a for a in expected_args] + assert matched_args == expected_args From 0a8a7a4fe486a52c9776bf9da176bb06fb6b1b2d Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 11 Aug 2022 14:50:50 -0700 Subject: [PATCH 59/76] resolve #82 --- cpp_linter/run.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index a03c48af..b489b8b3 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -829,6 +829,10 @@ def main(): # The parsed CLI args args = cli_arg_parser.parse_args() + # force files-changed-only to reflect value of lines-changed-only + if args.lines_changed_only: + args.files_changed_only = True + # set logging verbosity logger.setLevel(int(args.verbosity)) From 7d8b850603999398dc7e0ac25c82bc3f5ecaef9f Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 11 Aug 2022 23:52:41 -0700 Subject: [PATCH 60/76] ensure tidy fixit_lines end w/ a LF --- cpp_linter/clang_tidy.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cpp_linter/clang_tidy.py b/cpp_linter/clang_tidy.py index 757f95e7..29a736ab 100644 --- a/cpp_linter/clang_tidy.py +++ b/cpp_linter/clang_tidy.py @@ -53,10 +53,13 @@ def __init__( def __repr__(self) -> str: concerned_code = "" + if not self.fixit_lines[-1].endswith("\n"): + # some notifications' code-blocks don't end in a LF + self.fixit_lines[-1] += "\n" # and they should for us if self.fixit_lines: concerned_code = "```{}\n{}```\n".format( PurePath(self.filename).suffix.lstrip("."), - "".join(self.fixit_lines), + "\n".join(self.fixit_lines), ) return ( "
\n{}:{}:{}: {}: [{}]" From 6e781f14d15bf761f1dca1879a30c58bd09190a0 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 15 Aug 2022 15:22:19 -0700 Subject: [PATCH 61/76] workflow continue only if `latest` tag was added --- .github/workflows/run-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index f8fd8ad3..ce6b8084 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -23,6 +23,7 @@ jobs: git push origin latest test-action: + needs: [add-tag] runs-on: ubuntu-latest steps: - uses: convictional/trigger-workflow-and-wait@v1.6.3 @@ -38,6 +39,7 @@ jobs: trigger_workflow: true wait_workflow: true test-package: + needs: [add-tag] runs-on: ubuntu-latest steps: - uses: convictional/trigger-workflow-and-wait@v1.6.3 From 25df1876d1c1b1537c31e05b8c0ac2c6db759db9 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 13:43:45 -0700 Subject: [PATCH 62/76] include v7-9 for CI tests --- .github/workflows/run-dev-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 95fb6b8a..19e9ecff 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -40,7 +40,7 @@ jobs: matrix: py: ['3.7', '3.8', '3.9', '3.10'] os: ['windows-latest', ubuntu-latest] - version: ['13', '12', '11', '10'] + version: ['13', '12', '11', '10', '9', '8', '7'] include: - tools_dir: 'N/A' - os: 'windows-latest' From 6425065a2f5f9f880a5bc5b18565c0c601f84694 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 13:45:12 -0700 Subject: [PATCH 63/76] fix docs about `parse_ignore_option()` Also, docs show type annotations in the function signatures --- cpp_linter/run.py | 11 +++++------ mkdocs.yml | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp_linter/run.py b/cpp_linter/run.py index b489b8b3..4418bd34 100644 --- a/cpp_linter/run.py +++ b/cpp_linter/run.py @@ -17,7 +17,7 @@ import argparse import configparser import json -from typing import cast, List, Dict, Any # , Tuple +from typing import cast, List, Dict, Any, Tuple import requests from . import ( Globals, @@ -775,17 +775,16 @@ def make_annotations( return bool(count) -def parse_ignore_option(paths: str) -> tuple: # -> Tuple[List[str], List[str]]: +def parse_ignore_option(paths: str) -> Tuple[List[str], List[str]]: """Parse a given string of paths (separated by a '|') into `ignored` and `not_ignored` lists of strings. Args: paths: This argument conforms to the CLI arg `--ignore` (or `-i`). - Returns: - A tuple of lists in which each list is a set of strings. - - index 0 is the `ignored` list - - index 1 is the `not_ignored` list + Returns: Returns a tuple of lists in which each list is a set of strings. + index 0 is the `ignored` list + index 1 is the `not_ignored` list """ ignored, not_ignored = ([], []) diff --git a/mkdocs.yml b/mkdocs.yml index bfcac0a5..7b392874 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -50,6 +50,7 @@ plugins: rendering: # show_if_no_docstring: true show_source: true + show_signature_annotations: true heading_level: 2 watch: - cpp_linter From 9e75bbe6d78e16c36a5801058e46866bf71f4de8 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 13:54:44 -0700 Subject: [PATCH 64/76] fix `TidyNotification.__repr__()` --- cpp_linter/clang_tidy.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp_linter/clang_tidy.py b/cpp_linter/clang_tidy.py index 29a736ab..3eb0167c 100644 --- a/cpp_linter/clang_tidy.py +++ b/cpp_linter/clang_tidy.py @@ -53,10 +53,10 @@ def __init__( def __repr__(self) -> str: concerned_code = "" - if not self.fixit_lines[-1].endswith("\n"): - # some notifications' code-blocks don't end in a LF - self.fixit_lines[-1] += "\n" # and they should for us if self.fixit_lines: + if not self.fixit_lines[-1].endswith("\n"): + # some notifications' code-blocks don't end in a LF + self.fixit_lines[-1] += "\n" # and they should for us concerned_code = "```{}\n{}```\n".format( PurePath(self.filename).suffix.lstrip("."), "\n".join(self.fixit_lines), From 31c332fab4f67d03a86d46d12163764824e4b838 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 14:14:18 -0700 Subject: [PATCH 65/76] tell CI to download clang-tools v7-9 --- .github/workflows/run-dev-tests.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 19e9ecff..330d5cca 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -60,6 +60,12 @@ jobs: tools_dir: temp # - version: '14' # tools_dir: temp + - version: '7' + tools_dir: temp + - version: '8' + tools_dir: temp + - version: '9' + tools_dir: temp runs-on: ${{ matrix.os }} steps: From 3925f768d1ce9790da2dc3aef4ad76aab653ea61 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 14:43:13 -0700 Subject: [PATCH 66/76] support older versions of clang-tidy YML output --- cpp_linter/clang_tidy_yml.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/cpp_linter/clang_tidy_yml.py b/cpp_linter/clang_tidy_yml.py index 3dab430a..f97ce802 100644 --- a/cpp_linter/clang_tidy_yml.py +++ b/cpp_linter/clang_tidy_yml.py @@ -1,6 +1,6 @@ """Parse output from clang-tidy's YML format""" from pathlib import Path, PurePath -from typing import List +from typing import List, cast, Dict, Any import yaml from . import GlobalParser, get_line_cnt_from_cols, logger @@ -105,13 +105,20 @@ def parse_tidy_suggestions_yml(): yml_file = Path("clang_tidy_output.yml").read_text(encoding="utf-8") yml = yaml.safe_load(yml_file) fixit = YMLFixit(yml["MainSourceFile"]) + for diag_results in yml["Diagnostics"]: diag = TidyDiagnostic(diag_results["DiagnosticName"]) - diag.message = diag_results["DiagnosticMessage"]["Message"] - diag.line, diag.cols = get_line_cnt_from_cols( - yml["MainSourceFile"], diag_results["DiagnosticMessage"]["FileOffset"] - ) - for replacement in diag_results["DiagnosticMessage"]["Replacements"]: + if "DiagnosticMessage" in cast(Dict[str, Any], diag_results).keys(): + msg = diag_results["DiagnosticMessage"]["Message"] + offset = diag_results["DiagnosticMessage"]["FileOffset"] + replacements = diag_results["DiagnosticMessage"]["Replacements"] + else: # prior to clang-tidy v9, the YML output was structured differently + msg = diag_results["Message"] + offset = diag_results["FileOffset"] + replacements = diag_results["Replacements"] + diag.message = msg + diag.line, diag.cols = get_line_cnt_from_cols(yml["MainSourceFile"], offset) + for replacement in replacements: line_cnt, cols = get_line_cnt_from_cols( yml["MainSourceFile"], replacement["Offset"] ) From 0608d9bf3d307fe80b792229653edadcabab54c8 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 15:01:54 -0700 Subject: [PATCH 67/76] don't try to traverse a `None` obj --- cpp_linter/clang_tidy_yml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp_linter/clang_tidy_yml.py b/cpp_linter/clang_tidy_yml.py index f97ce802..26de4e7c 100644 --- a/cpp_linter/clang_tidy_yml.py +++ b/cpp_linter/clang_tidy_yml.py @@ -118,7 +118,7 @@ def parse_tidy_suggestions_yml(): replacements = diag_results["Replacements"] diag.message = msg diag.line, diag.cols = get_line_cnt_from_cols(yml["MainSourceFile"], offset) - for replacement in replacements: + for replacement in [] if replacements is None else replacements: line_cnt, cols = get_line_cnt_from_cols( yml["MainSourceFile"], replacement["Offset"] ) From 2a3240d89aa4e3b29afead5f5fb9319a6dc535a9 Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 23:47:08 -0700 Subject: [PATCH 68/76] add common hooks to pre-commit config --- .pre-commit-config.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 31df1b42..e5ea8a37 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,14 @@ repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-docstring-first + - id: check-added-large-files + - id: check-yaml + - id: check-toml + - id: requirements-txt-fixer - repo: https://github.com/python/black rev: '22.6.0' hooks: From ef5b6e8758c582d67c2b611392f027a8a0b9d89e Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 23:51:52 -0700 Subject: [PATCH 69/76] add more configs to toml This removes the need for a separate .coveragerc file pytest can be executed without args based on the config in the toml --- .coveragerc | 32 ------------------------- .github/workflows/run-dev-tests.yml | 6 ++--- pyproject.toml | 36 +++++++++++++++++++++++++++++ requirements-dev.txt | 2 +- 4 files changed, 40 insertions(+), 36 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index b2775553..00000000 --- a/.coveragerc +++ /dev/null @@ -1,32 +0,0 @@ -[run] -dynamic_context = test_function -omit= - # don't include tests in coverage - tests/* - -[json] -pretty_print=true - -[html] -show_contexts=true - -[report] -# Regexes for lines to exclude from consideration -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain about missing debug-only code: - def __repr__ - - # the point of unit tests is to test parts of main() - def main - - # ignore any branch that makes the module executable - if __name__ == "__main__" - - # ignore branches specific to type checking - if TYPE_CHECKING - - # ignore the local secific debug statement related to not having rich installed - if not FOUND_RICH_LIB diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index 330d5cca..f6486996 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -84,7 +84,7 @@ jobs: - name: Install workflow deps # using a wildcard as filename on Windows requires a bash shell shell: bash - run: python3 -m pip install pytest coverage dist/*.whl + run: python3 -m pip install pytest coverage[toml] dist/*.whl - name: Install clang-tools if: matrix.tools_dir == 'temp' @@ -96,13 +96,13 @@ jobs: if: matrix.tools_dir == 'N/A' env: CLANG_VERSION: ${{ matrix.version }} - run: coverage run -m pytest -vv tests + run: coverage run -m pytest - name: Collect Coverage (non-native clang install) if: matrix.tools_dir == 'temp' env: CLANG_VERSION: ${{ runner.temp }}/clang-tools - run: coverage run -m pytest -vv tests + run: coverage run -m pytest - run: coverage report && coverage xml diff --git a/pyproject.toml b/pyproject.toml index cb93e75d..c06ca881 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,42 @@ fallback_version = "0.0.0" show_error_codes = true show_column_numbers = true +[tool.pytest.ini_options] +minversion = "6.0" +addopts = "-vv" +testpaths = ["tests"] + +[tool.coverage] +[tool.coverage.run] +dynamic_context = "test_function" +omit = [ + # don't include tests in coverage + "tests/*", +] + +[tool.coverage.json] +pretty_print = true + +[tool.coverage.html] +show_contexts = true + +[tool.coverage.report] +# Regexes for lines to exclude from consideration +exclude_lines = [ + # Have to re-enable the standard pragma + "pragma: no cover", + # Don\'t complain about missing debug-only code: + "def __repr__", + # the point of unit tests is to test parts of main() + "def main", + # ignore any branch that makes the module executable + 'if __name__ == "__main__"', + # ignore branches specific to type checking + "if TYPE_CHECKING", + # ignore the local secific debug statement related to not having rich installed + "if not FOUND_RICH_LIB", +] + [tool.pylint.main] # Analyse import fallback blocks. This can be used to support both Python 2 and 3 # compatible code, which means that the block might have code that exists only in diff --git a/requirements-dev.txt b/requirements-dev.txt index 9bc46199..52d65263 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,4 +4,4 @@ mypy pylint rich pytest -coverage +coverage[toml] From 29239724dc36f9b1e0c1b29dc067af54cc415c76 Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Wed, 17 Aug 2022 23:52:30 -0700 Subject: [PATCH 70/76] update event triggers on dev-test CI workflow --- .github/workflows/run-dev-tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index f6486996..e5e2a959 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -4,15 +4,15 @@ on: push: paths: - "**.py" - - .pylintrc - - mypy.ini + - pyproject.toml + - pre-commit-config.yaml - ".github/workflows/run-dev-tests.yml" pull_request: types: opened paths: - "**.py" - - .pylintrc - - mypy.ini + - pyproject.toml + - pre-commit-config.yaml - ".github/workflows/run-dev-tests.yml" jobs: From 23622e1efccbff34aa4ab0b299bef38deb127a5f Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Thu, 18 Aug 2022 00:02:24 -0700 Subject: [PATCH 71/76] sort requirements.txt contents --- docs/requirements.txt | 4 ++-- requirements-dev.txt | 8 ++++---- requirements.txt | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 2c86af4b..36951be8 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ mkdocs -mkdocstrings[python] -mkdocs-material mkdocs-autorefs mkdocs-include-markdown-plugin +mkdocs-material +mkdocstrings[python] diff --git a/requirements-dev.txt b/requirements-dev.txt index 52d65263..fe21d76f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,7 @@ -types-requests -types-PyYAML +coverage[toml] mypy pylint -rich pytest -coverage[toml] +rich +types-PyYAML +types-requests diff --git a/requirements.txt b/requirements.txt index ae1f79e0..1c6d8b40 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -requests pyyaml +requests From 02abc8fda11f6fc5948e91ede7e5c819c3451ec3 Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Thu, 18 Aug 2022 00:35:19 -0700 Subject: [PATCH 72/76] split pre-commit step into its own CI workflow update version of used (external) actions --- .github/workflows/mkdocs-deploy.yml | 4 ++-- .github/workflows/pre-commit-hooks.yml | 17 +++++++++++++++++ .github/workflows/publish-pypi.yml | 3 +-- .github/workflows/run-dev-tests.yml | 19 +++++++++---------- README.md | 4 ++-- 5 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/pre-commit-hooks.yml diff --git a/.github/workflows/mkdocs-deploy.yml b/.github/workflows/mkdocs-deploy.yml index eebd301c..7ca30a6f 100644 --- a/.github/workflows/mkdocs-deploy.yml +++ b/.github/workflows/mkdocs-deploy.yml @@ -8,8 +8,8 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 with: python-version: 3.x - name: Install python action for doc extraction diff --git a/.github/workflows/pre-commit-hooks.yml b/.github/workflows/pre-commit-hooks.yml new file mode 100644 index 00000000..e9426fc7 --- /dev/null +++ b/.github/workflows/pre-commit-hooks.yml @@ -0,0 +1,17 @@ +name: Pre-commit + +on: + push: + pull_request: + types: opened + +jobs: + check-source-files: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.x' + - run: python3 -m pip install pre-commit + - run: pre-commit run --all-files diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index aff07937..00ad109a 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -28,7 +28,7 @@ jobs: with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: '3.x' - name: Install dependencies @@ -49,4 +49,3 @@ jobs: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} run: twine upload dist/* - diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index e5e2a959..ae17ce5d 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -11,20 +11,19 @@ on: types: opened paths: - "**.py" + - "**requirements*.txt" - pyproject.toml - pre-commit-config.yaml - ".github/workflows/run-dev-tests.yml" jobs: - check-python-sources: + build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 with: python-version: '3.x' - - run: python3 -m pip install pre-commit - - run: pre-commit run --all-files - name: Build wheel run: python3 -m pip wheel --no-deps -w dist . - name: Upload wheel as artifact @@ -33,8 +32,8 @@ jobs: name: cpp-linter-action_wheel path: ${{ github.workspace }}/dist/*.whl - run-pytest: - needs: [check-python-sources] + test: + needs: [build] strategy: fail-fast: false matrix: @@ -69,14 +68,14 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: python-version: ${{ matrix.py }} - name: download wheel artifact - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: cpp-linter-action_wheel path: dist @@ -111,4 +110,4 @@ jobs: with: files: ./coverage.xml fail_ci_if_error: true # optional (default = false) - verbose: true # optional (default = false) \ No newline at end of file + verbose: true # optional (default = false) diff --git a/README.md b/README.md index 4e97b15a..cdf0fb81 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 # this step can be skipped if the desired # version already comes with the runner's OS @@ -190,7 +190,7 @@ jobs: # Any other OS-based runners only take the version number. # Example. run: cpp-linter --version=14 # Omit the version option if using the default version available in the OS. - run: cpp-linter --version=${{ runner.temp }}/llvm + run: cpp-linter --version=${{ runner.temp }}/llvm - name: Fail fast?! if: steps.linter.outputs.checks-failed > 0 From e68e928e68b10f7f18b39238a7c046eada7049df Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Thu, 18 Aug 2022 00:40:46 -0700 Subject: [PATCH 73/76] pleasing pre-commit hooks --- .gitpod.yml | 2 +- tests/capture_tools_output/event_files.json | 2 +- tests/capture_tools_output/expected_result.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index 7fd69193..c21ea2f0 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,2 +1,2 @@ tasks: - - init: pip install -r requirements.txt \ No newline at end of file + - init: pip install -r requirements.txt diff --git a/tests/capture_tools_output/event_files.json b/tests/capture_tools_output/event_files.json index baf9c44c..ba8947ac 100644 --- a/tests/capture_tools_output/event_files.json +++ b/tests/capture_tools_output/event_files.json @@ -227,4 +227,4 @@ "contents_url": "https://api.github.com/repos/chocolate-doom/chocolate-doom/contents/src%2Fstrife%2FCMakeLists.txt?ref=3c35acde7d398c32f6fad50fa902de391f573ffa", "patch": "@@ -70,4 +70,10 @@ set(STRIFE_SOURCES\n add_library(strife STATIC ${STRIFE_SOURCES})\n \n target_include_directories(strife PRIVATE \"../\" \"../../win32/\" \"${CMAKE_CURRENT_BINARY_DIR}/../../\")\n-target_link_libraries(strife textscreen SDL2::SDL2 SDL2::mixer SDL2::net)\n+target_link_libraries(strife textscreen SDL2::SDL2)\n+if(ENABLE_SDL2_mixer)\n+ target_link_libraries(strife SDL2::mixer)\n+endif()\n+if(ENABLE_SDL2_NET)\n+ target_link_libraries(strife SDL2::net)\n+endif()" } -] \ No newline at end of file +] diff --git a/tests/capture_tools_output/expected_result.json b/tests/capture_tools_output/expected_result.json index bde9ab51..0912b966 100644 --- a/tests/capture_tools_output/expected_result.json +++ b/tests/capture_tools_output/expected_result.json @@ -317,4 +317,4 @@ ] } } -] \ No newline at end of file +] From a1787309cce72d953c7bae2b3d25f95140c99268 Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Thu, 18 Aug 2022 00:46:59 -0700 Subject: [PATCH 74/76] fix run-test.yml (trailing whitespaces) --- .github/workflows/run-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index ce6b8084..eaf19106 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -29,7 +29,7 @@ jobs: - uses: convictional/trigger-workflow-and-wait@v1.6.3 with: owner: cpp-linter - repo: test-cpp-linter-action + repo: test-cpp-linter-action github_token: ${{ secrets.PAT_TOKEN }} workflow_file_name: cpp-lint-action.yml ref: master @@ -45,7 +45,7 @@ jobs: - uses: convictional/trigger-workflow-and-wait@v1.6.3 with: owner: cpp-linter - repo: test-cpp-linter-action + repo: test-cpp-linter-action github_token: ${{ secrets.PAT_TOKEN }} workflow_file_name: cpp-lint-package.yml ref: master From d3a85851b89a2ff8705d10ba167b8ef6d9f6ed8d Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Thu, 18 Aug 2022 02:02:03 -0700 Subject: [PATCH 75/76] revise README & remove .ci-ignore file --- .ci-ignore | 2 -- README.md | 42 +++++++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 21 deletions(-) delete mode 100644 .ci-ignore diff --git a/.ci-ignore b/.ci-ignore deleted file mode 100644 index b9610532..00000000 --- a/.ci-ignore +++ /dev/null @@ -1,2 +0,0 @@ -cpp_linter -mkdocs.yml diff --git a/README.md b/README.md index cdf0fb81..465fd1a7 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,9 @@ jobs: #### `style` -- **Description**: The style rules to use. Set this to 'file' to have clang-format use the closest relative .clang-format file. +- **Description**: The style rules to use. + - Set this to 'file' to have clang-format use the closest relative .clang-format file. + - Set this to a blank string (`''`) to disable the use of clang-format entirely. - Default: 'llvm' #### `extensions` @@ -59,9 +61,9 @@ jobs: #### `tidy-checks` -- **Description**: Comma-separated list of globs with optional '-' prefix. Globs are processed in order of appearance in the list. Globs without '-' prefix add checks with matching names to the set, globs with the '-' prefix remove checks with matching names from the set of enabled checks. This option's value is appended to the value of the 'Checks' option in a .clang-tidy file (if any). - - It is possible to disable clang-tidy entirely by setting this option to '-\*'. This allows using only clang-format to lint your source files. - - It is also possible to rely solely on a .clang-tidy config file by specifying this option as a blank string (''). +- **Description**: Comma-separated list of globs with optional `-` prefix. Globs are processed in order of appearance in the list. Globs without `-` prefix add checks with matching names to the set, globs with the `-` prefix remove checks with matching names from the set of enabled checks. This option's value is appended to the value of the 'Checks' option in a .clang-tidy file (if any). + - It is possible to disable clang-tidy entirely by setting this option to `'-*'`. + - It is also possible to rely solely on a .clang-tidy config file by specifying this option as a blank string (`''`). - Default: 'boost-\*,bugprone-\*,performance-\*,readability-\*,portability-\*,modernize-\*,clang-analyzer-\*,cppcoreguidelines-\*' #### `repo-root` @@ -72,42 +74,43 @@ jobs: #### `version` - **Description**: The desired version of the [clang-tools](https://hub.docker.com/r/xianpengshen/clang-tools) to use. Accepted options are strings which can be 14, 13, 12, 11, 10, 9, or 8. - - Set this option to a blank string ('') to use the platform's default installed version. + - Set this option to a blank string (`''`) to use the platform's default installed version. + - This value can also be a path to where the clang tools are installed (if using a custom install location). Because all paths specified here are converted to absolute, using a relative path as a value may not be compatible when using the docker environment (see [Running without the docker container](#running-without-the-docker-container)). - Default: '12' #### `verbosity` -- **Description**: This controls the action's verbosity in the workflow's logs. Supported options are defined by the python logging library's log levels. This option does not affect the verbosity of resulting comments or annotations. +- **Description**: This controls the action's verbosity in the workflow's logs. Supported options are defined by the [python logging library's log levels](https://docs.python.org/3/library/logging.html#logging-levels). This option does not affect the verbosity of resulting thread comments or file annotations. - Default: '10' #### `lines-changed-only` - **Description**: This controls what part of the files are analyzed. The following values are accepted: - - false: All lines in a file are analyzed. - - true: All lines in the diff are analyzed (including unchanged lines but not subtractions). - - strict: Only lines in the diff that contain additions are analyzed. + - false: All lines in a file are analyzed. + - true: Only lines in the diff that contain additions are analyzed. + - diff: All lines in the diff are analyzed (including unchanged lines but not subtractions). - Default: false. #### `files-changed-only` -- **Description**: Set this option to false to analyze any source files in the repo. +- **Description**: Set this option to false to analyze any source files in the repo. This is automatically enabled if lines-changed-only is enabled. - Default: true - NOTE: The `GITHUB_TOKEN` should be supplied when running on a private repository with this option enabled, otherwise the runner does not not have the privilege to list changed files for an event. See [Authenticating with the GITHUB_TOKEN](https://docs.github.com/en/actions/reference/authentication-in-a-workflow) #### `ignore` - **Description**: Set this option with string of path(s) to ignore. - - In the case of multiple paths, you can use a pipe character ('|') + - In the case of multiple paths, you can use a pipe character (`|`) to separate the multiple paths. Multiple lines are forbidden as an input to this option; it must be a single string. - This can also have files, but the file's relative path has to be specified as well. - - There is no need to use './' for each entry; a blank string ('') represents + - There is no need to use `./` for each entry; a blank string (`''`) represents the repo-root path (specified by the `repo-root` input option). - - Submodules are automatically ignored. Hidden directories (beginning with a '.') are also ignored automatically. - - Prefix a path with a bang ('!') to make it explicitly _not_ ignored - order of - multiple paths does _not_ take precedence. The '!' prefix can be applied to + - Submodules are automatically ignored. Hidden directories (beginning with a `.`) are also ignored automatically. + - Prefix a path with a bang (`!`) to make it explicitly _not_ ignored. The order of + multiple paths does _not_ take precedence. The `!` prefix can be applied to a submodule's path (if desired) but not hidden directories. - - Glob patterns are not supported here. All asterisk characters ('\*') are literal. + - Glob patterns are not supported here. All asterisk characters (`*`) are literal. - Default: '.github' #### `thread-comments` @@ -126,6 +129,7 @@ jobs: #### `database` - **Description**: The directory containing compilation database (like compile_commands.json) file. + - This option doesn't seems to work properly from the docker environment. Instead we recommend using this option when see [running without the docker container](#running-without-the-docker-container). - Default: '' ### Outputs @@ -175,7 +179,7 @@ jobs: - name: Install clang-tools uses: KyleMayes/install-llvm-action@v1 with: - # v12 is the recommended minimum for the Visual Studio compiler (on Windows) + # v13 is the recommended minimum for the Visual Studio compiler (on Windows) version: 14 # specifying an install path is required (on Windows) because installing # multiple versions on Windows runners needs non-default install paths. @@ -186,8 +190,8 @@ jobs: - name: run linter as a python package id: linter - # pass the installed path to the '--version' argument (Windows only). - # Any other OS-based runners only take the version number. + # Pass the installed path to the '--version' argument. + # Alternatively, pass the version number. # Example. run: cpp-linter --version=14 # Omit the version option if using the default version available in the OS. run: cpp-linter --version=${{ runner.temp }}/llvm From b36ee44b2575ad8f6f5ded09bad033876f34dd65 Mon Sep 17 00:00:00 2001 From: Brendan Doherty <2bndy5@gmail.com> Date: Thu, 18 Aug 2022 02:48:24 -0700 Subject: [PATCH 76/76] add code coverage badge to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 465fd1a7..b854411e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/cpp-linter/cpp-linter-action/cpp-linter?label=cpp-linter&logo=Github&style=flat-square)](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/cpp-linter.yml) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/cpp-linter/cpp-linter-action/MkDocs%20Deploy?label=docs&logo=Github&style=flat-square)](https://github.com/cpp-linter/cpp-linter-action/actions/workflows/mkdocs-deploy.yml) ![GitHub](https://img.shields.io/github/license/cpp-linter/cpp-linter-action?label=license&logo=github&style=flat-square) +[![codecov](https://codecov.io/gh/cpp-linter/cpp-linter-action/branch/master/graph/badge.svg?token=4SF7UEDEZ2)](https://codecov.io/gh/cpp-linter/cpp-linter-action) A Github Action for linting C/C++ code integrating clang-tidy and clang-format to collect feedback provided in the form of thread comments and/or annotations.