--- /dev/null
+#!/usr/bin/env python3
+
+# Copyright (C) 2025 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Occasionally we add new stages to default_install_hook_types in
+# .pre-commit-config.yaml. The new stages are not used until somebody runs
+# pre-commit install again. This script, meant to run as a pre-commit hook in
+# the pre-commit stage, detects this situation.
+
+import os
+import re
+import sys
+
+import yaml
+
+cfg = ".pre-commit-config.yaml"
+with open(cfg, "r") as f:
+ data = yaml.load(f, Loader=yaml.SafeLoader)
+stages = data.get("default_install_hook_types", ["pre-commit"])
+
+if os.path.isfile(".git"):
+ # Handle worktrees.
+ fp = open(".git")
+ text = fp.read()
+ m = re.search("gitdir: (.*)", text)
+ dir = os.path.join(m.group(1), "..", "..")
+else:
+ dir = ".git"
+
+if not os.path.isdir(dir):
+ # Not a git repository.
+ print("no .git dir found, skipping")
+ sys.exit(0)
+
+for val in stages:
+ f = os.path.join(dir, "hooks", val)
+
+ if not (os.path.isfile(f)):
+ if val == "pre-commit":
+ print("pre-commit framework hooks not installed, skipping")
+ sys.exit(0)
+ print("missing hook: " + val + " (please run pre-commit install)")
+ sys.exit(1)
+
+ fp = open(f)
+ text = fp.read()
+ m = re.search("File generated by pre-commit", text)
+ if not m:
+ print("not a pre-commit framework hook: " + f)
+ sys.exit(1)