]> git.lttng.org Git - lttng-tools.git/commitdiff
misc: Allow users to override the location of clang-format
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 12 Dec 2024 19:16:22 +0000 (19:16 +0000)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 18 Dec 2024 15:50:26 +0000 (15:50 +0000)
Since the coding imposes a specific version of clang-format (16),
the pre-commit hook can fail for reasons out of the contributor's
control.

Local git config settings are used to allow the user to specify
the location of these tools.

  git config --local hooks.clangFormatPath /path/to/clang-format-16

The settings are retrieved by the script and used if they were
specified.

Note that we should probably do the same for `black` as they
change the formatting from version to version. Right now I
feel we imply "use the latest version", but we should probably
impose one and update it on a release-to-release basis.

Change-Id: Iabb3e3964dc137075474ae4a240f30e0ecf4ec0d
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
extras/pre-commit.py

index 788ea720528a41928704b7f543d82842579fff7c..f7013a73e7aab85db3d0fd60e54eaf3b93782c2e 100755 (executable)
@@ -13,15 +13,77 @@ import sys
 import clang.cindex
 
 
+def get_git_config_value(key, default=None):
+    """
+    Get a Git configuration value from the local repository.
+    Returns the default value if the key is not set.
+    """
+    try:
+        value = subprocess.check_output(
+            ["git", "config", "--local", key], stderr=subprocess.DEVNULL
+        ).strip()
+        return value
+    except subprocess.CalledProcessError:
+        return default
+
+
+def get_clang_format_version(clang_format_path):
+    try:
+        # Run the clang-format --version command
+        result = subprocess.check_output(
+            [clang_format_path, "--version"], text=True
+        ).strip()
+
+        # Use regex to extract the version tuple
+        match = re.search(r"version (\d+)\.(\d+)\.(\d+)", result)
+        if match:
+            # Convert the matched groups to integers and return as a tuple
+            version_tuple = tuple(map(int, match.groups()))
+            return version_tuple
+        else:
+            logging.error("Failed to extract version from clang-format output.")
+            return None
+    except FileNotFoundError:
+        logging.error(
+            f"clang-format binary could not be found using {clang_format_path}"
+        )
+        return None
+    except subprocess.CalledProcessError as e:
+        logging.error(f"Failed to run clang-format: {e}")
+        return None
+
+
 def clang_format(files):
+    required_clang_format_major_version = 16
+
     source_files_re = re.compile(r"^.*(\.cpp|\.hpp|\.c|\.h)$")
     files = [f for f in files if source_files_re.match(f)]
     if not files:
         return "No source files for clang-format check", 0
 
+    # Extract the git config value that overrides the location of clang-format.
+    # If none can be found, use the sytem's clang-format.
+    clang_format_path = get_git_config_value("hooks.clangFormatPath", "clang-format")
+    clang_format_version = get_clang_format_version(clang_format_path)
+
+    if clang_format_version is None:
+        return "Failed to determine clang-format version", 1
+
+    cf_major, cf_minor, cf_patch = clang_format_version
+    if cf_major != required_clang_format_major_version:
+        return (
+            f"Invalid clang-format version: binary `{clang_format_path}` is version {cf_major}.{cf_minor}.{cf_patch}, expected version {required_clang_format_major_version}.y.z",
+            1,
+        )
+
     logging.debug("Files for clang-format: {}".format(files))
     format_process = subprocess.Popen(
-        ["clang-format", "--dry-run", "-Werror"] + files,
+        [
+            clang_format_path,
+            "--dry-run",
+            "-Werror",
+        ]
+        + files,
         stdout=subprocess.PIPE,
         stderr=subprocess.STDOUT,
     )
This page took 0.031413 seconds and 4 git commands to generate.