Repository: pre-commit/pre-commit
Pull request #1750 (2021-01-01 18:58:39)

extended warning if globs are used instead of regex to top level
extends #1702 (see [this](https://github.com/pre-commit/pre-commit/pull/1707#issuecomment-753351851) comment).

i used the same validator. to distinguish between a hook field and a top-level field i checked if `id` is present in the dictionary. i think this should be fine, but if you have a better idea just let me know :)


Patch:
diff --git a/pre_commit/clientlib.py b/pre_commit/clientlib.py
index 5dfaf7a..8f35057 100644
--- a/pre_commit/clientlib.py
+++ b/pre_commit/clientlib.py
@@ -132,7 +132,7 @@ class WarnMutableRev(cfgv.ConditionalOptional):
                 )
 
 
-class OptionalSensibleRegex(cfgv.OptionalNoDefault):
+class OptionalSensibleRegexAtHook(cfgv.OptionalNoDefault):
     def check(self, dct: Dict[str, Any]) -> None:
         super().check(dct)
 
@@ -144,6 +144,17 @@ class OptionalSensibleRegex(cfgv.OptionalNoDefault):
             )
 
 
+class OptionalSensibleRegexAtTop(cfgv.OptionalNoDefault):
+    def check(self, dct: Dict[str, Any]) -> None:
+        super().check(dct)
+
+        if '/*' in dct.get(self.key, ''):
+            logger.warning(
+                f'The top-level {self.key!r} field is a regex, not a glob -- '
+                f"matching '/*' probably isn't what you want here",
+            )
+
+
 class MigrateShaToRev:
     key = 'rev'
 
@@ -259,8 +270,8 @@ CONFIG_HOOK_DICT = cfgv.Map(
         for item in MANIFEST_HOOK_DICT.items
         if item.key != 'id'
     ),
-    OptionalSensibleRegex('files', cfgv.check_string),
-    OptionalSensibleRegex('exclude', cfgv.check_string),
+    OptionalSensibleRegexAtHook('files', cfgv.check_string),
+    OptionalSensibleRegexAtHook('exclude', cfgv.check_string),
 )
 CONFIG_REPO_DICT = cfgv.Map(
     'Repository', 'repo',
@@ -329,6 +340,8 @@ CONFIG_SCHEMA = cfgv.Map(
         ),
         warn_unknown_keys_root,
     ),
+    OptionalSensibleRegexAtTop('files', cfgv.check_string),
+    OptionalSensibleRegexAtTop('exclude', cfgv.check_string),
 
     # do not warn about configuration for pre-commit.ci
     cfgv.OptionalNoDefault('ci', cfgv.check_type(dict)),


Test patch:
diff --git a/tests/clientlib_test.py b/tests/clientlib_test.py
index d08ecdf..6bdb0d6 100644
--- a/tests/clientlib_test.py
+++ b/tests/clientlib_test.py
@@ -244,7 +244,7 @@ def test_warn_mutable_rev_conditional():
         cfgv.validate(config_obj, CONFIG_REPO_DICT)
 
 
-def test_validate_optional_sensible_regex(caplog):
+def test_validate_optional_sensible_regex_at_hook_level(caplog):
     config_obj = {
         'id': 'flake8',
         'files': 'dir/*.py',
@@ -261,6 +261,23 @@ def test_validate_optional_sensible_regex(caplog):
     ]
 
 
+def test_validate_optional_sensible_regex_at_top_level(caplog):
+    config_obj = {
+        'files': 'dir/*.py',
+        'repos': [],
+    }
+    cfgv.validate(config_obj, CONFIG_SCHEMA)
+
+    assert caplog.record_tuples == [
+        (
+            'pre_commit',
+            logging.WARNING,
+            "The top-level 'files' field is a regex, not a glob -- matching "
+            "'/*' probably isn't what you want here",
+        ),
+    ]
+
+
 @pytest.mark.parametrize('fn', (validate_config_main, validate_manifest_main))
 def test_mains_not_ok(tmpdir, fn):
     not_yaml = tmpdir.join('f.notyaml')