资讯详情

资讯详情

lefthook 配置指南:`glob` 文件过滤规则与 `glob_matcher` 匹配引擎详解

lefthook 配置指南glob文件过滤规则与glob_matcher匹配引擎详解【免费下载链接】lefthookFast and powerful Git hooks manager for any type of projects.项目地址: https://gitcode.com/GitHub_Trending/le/lefthookglob是 lefthook 中用于按文件名模式过滤文件的配置项它决定一条 command/job 究竟作用于哪些文件是编写精准、高效的 Git hooks 的核心工具。本篇指南将完整讲解glob的配置语法、与run模板及files命令的配合方式、**通配符的特殊语义并结合源码剖析 gobwas 与 doublestar 两种匹配引擎的底层差异帮助你写出可复现、可维护的文件过滤规则。一、glob是什么为命令划定作用文件范围在 lefthook 中glob用于为某条命令设置一个或多个文件匹配模式从而把命令的执行范围限制在符合模式的文件上。需要特别注意的是glob只有在两种场景下才会生效glob 官方文档 明确说明你在run选项中使用了文件模板如{staged_files}、{files}、{push_files}、{all_files}你为命令提供了自定义的files命令。换言之glob是一个过滤器它本身不产生文件列表只负责从已有文件集合中筛出符合条件的子集。基础用法示例# lefthook.yml pre-commit: jobs: - name: lint run: yarn eslint {staged_files} glob: *.{js,ts,jsx,tsx}当pre-commit钩子触发时lefthook 收集暂存区文件即{staged_files}再通过glob: *.{js,ts,jsx,tsx}只保留.js、.ts、.jsx、.tsx结尾的文件最后把过滤后的文件列表替换进run命令执行。二、多个 glob 模式从 1.10.10 起支持列表从 lefthook 版本1.10.10开始glob除了接受单个字符串还可以接收一个模式列表# lefthook.yml pre-commit: jobs: - run: yarn lint {staged_files} glob: - *.ts - *.js列表中的多个模式是并集关系只要文件匹配其中任意一个模式就会被保留。这在需要覆盖多种扩展名而每种扩展名又有独立模式时非常实用。从源码结构看这一能力在配置层已经全面支持无论是Job.Glob还是Command.Glob其类型都是[]string并且带jsonschema:oneof_typestring;array注解说明 YAML/TOML/JSON 中既可以写单字符串也可以写数组。过滤时filter.go的byGlob函数 会遍历所有模式把每个模式命中的文件累积合并。三、模式语法基于 gobwas/glob 库lefthook 的默认 glob 匹配引擎是 gobwas/glob 库该链接为文档原文所引供参考。这意味着默认情况下你可以使用以下语法*— 匹配路径片段内任意数量的字符不跨目录分隔符?— 匹配单个任意字符[...]— 字符集匹配如[abc]{a,b,c}— 花括号分组匹配如*.{js,ts}等价于*.js或*.ts**— 匹配一层或多层目录详见下文**的特殊行为!— 取反排除匹配的模式。对应到源码matchFilesGobwas通过glob.MustCompile(lowerMatcher)编译模式并逐一对文件路径做Match判断。值得注意的实现细节是匹配前会把模式和文件路径都转为小写strings.ToLower因此默认情况下 glob 匹配是不区分大小写的。四、**的特殊行为与大多数工具不同glob文档中特别强调了一个容易踩坑的差异**模式匹配1 层或更多层目录而不是像大多数工具那样匹配 0 层或更多层。也就是说默认gobwas引擎下glob: src/**/*.js # 不会匹配 src/file.js glob: src/*.js # 只会匹配 src/file.jssrc/**/*.js要求**至少匹配一层目录因此src/app/util.js能命中但src/file.js**匹配了 0 层不会命中若需要同时覆盖顶层和嵌套层文件需要分别写两个模式或者切换匹配引擎见下文glob_matcher。这一行为对应源码中的 doublestar 与 gobwas 的分支逻辑同时也被 filter_test.go 的测试用例直接验证例如**/*.rb在 gobwas 与 doublestar 两种引擎下的命中结果对比。五、与root的交互glob 永远基于 Git 仓库根计算如果你在命令上配置了root来指定命令执行的工作目录请注意glob 始终基于 Git 仓库的实际根目录计算root会被忽略。这意味着即使你把命令的root指定为某个子目录glob 模式仍然要按仓库根目录下的相对路径来书写。例如仓库根目录下有一个src/目录那么匹配其中所有 JS 文件应写成glob: src/**/*.js而不是glob: **/*.js。这条规则对exclude等同样基于文件路径的过滤项也适用。六、没有文件模板时glob仍可触发过滤与跳过一个经常被忽略但非常实用的行为是即使你的run中没有使用任何文件模板glob依然生效。此时 lefthook 会自动检查pre-commit钩子的{staged_files}和pre-push钩子的{push_files}并对其应用 glob 过滤如果过滤后没有任何文件剩余该命令会被直接跳过。# lefthook.yml pre-commit: jobs: - name: lint run: npm run lint # 如果没有暂存任何 .js 文件这条命令会被跳过 glob: *.js这是一个非常实用的按需执行手段当你不想让某些 lint 工具在无关变更时白白空跑时用glob即可实现没有匹配文件就不执行。同样的逻辑也适用于exclude当指定了exclude而没有文件模板时lefthook 会检查暂存/推送文件并应用排除过滤若无文件剩余则跳过命令。七、glob_matcher切换标准**语义的全局开关如果你从其他工具如 bash、gitignore、pre-commit 生态迁移而来习惯了**匹配 0 层或更多层的标准语义可以通过顶层配置glob_matcher切换匹配引擎。可选值值说明gobwas默认使用 gobwas/glob 库**匹配 1 层或更多层目录doublestar使用 bmatcuk/doublestar 库**为标准的 Bash 式行为匹配 0 层或更多层配置示例# lefthook.yml glob_matcher: doublestar pre-commit: jobs: - name: lint run: yarn eslint {staged_files} glob: **/*.{js,ts}两种引擎的行为对比# gobwas默认**/*.js 匹配 src/app.js但不匹配 app.js # doublestar **/*.js 匹配 app.js、src/app.js、a/b/c/app.js也就是说切到doublestar后**/*.js会同时命中根目录下的app.js和任意深度的嵌套文件这更符合大多数人的直觉。适用范围与兼容性从配置结构与源码可以确认以下几点全局生效glob_matcher是Config的顶层字段即仓库级配置它同时影响所有glob和exclude模式向后兼容默认值仍是gobwas不显式配置时行为与旧版本完全一致源码实现过滤链Filter.Apply中byGlob与byExclude都会接收GlobMatcher参数并据此选择matchFilesDoublestar/matchFilesGobwas以及对应的 exclude 分支对 exclude 同样生效exclude文档 明确指出其模式同样受glob_matcher影响因此切换引擎后要同时复核glob与exclude两处模式的写法。八、源码视角一条命令的完整过滤链路了解底层实现有助于你预测glob在复杂配置下的实际行为。核心代码位于 internal/run/controller/filter/filter.go一次文件过滤按以下顺序执行files byGlob(files, f.Glob, f.GlobMatcher) // 1. glob 正向匹配 files byExclude(files, f.ExcludeFiles, f.GlobMatcher) // 2. exclude 反向排除 files byRoot(files, f.Root) // 3. root 路径裁剪 files f.byType(f.fs, files, f.FileTypes) // 4. file_types 类型过滤几点值得注意byGlob的语义是并集传入多个模式时任一模式命中即保留见byGlob不会做交集空模式会被跳过如果模式列表为空字符串会被忽略全部为空时视为未设置返回原文件列表exclude是第二步先正向匹配再反向排除两者使用同一个glob_matcher引擎过滤顺序可组合glob之后还有root裁剪和file_types类型过滤因此你可以把扩展名过滤 目录裁剪 文件类型过滤组合成精确的执行范围控制大小写不敏感无论是 gobwas 还是 doublestar 分支匹配前都会把路径和模式转小写调试输出Apply会以 debug 级别日志打印过滤前后的文件列表filtered [ ]→filtered [x]运行lefthook时开启 verbose 即可观察每个 job 实际接收了哪些文件。九、实战组合globfiles 模板glob最常见的完整用法是配合自定义files命令与{files}模板把自定义文件来源 扩展名过滤 批量执行串成一条流水线。场景一对自定义命令输出的文件做过滤# lefthook.yml pre-push: commands: stylelint: tags: - frontend - style files: git diff --name-only master glob: *.js run: yarn stylelint {files}流程git diff --name-only master输出变更文件 →glob: *.js只保留 JS 文件 → 替换进{files}执行 stylelint。场景二多语言仓库分别过滤# lefthook.yml pre-commit: jobs: - name: rubocop glob: *.rb exclude: - config/application.rb - config/routes.rb run: bundle exec rubocop --force-exclusion -- {staged_files} - name: eslint glob: - *.js - *.jsx - *.ts - *.tsx run: yarn eslint {staged_files}这里同时演示了glob的单字符串与列表写法、exclude排除特定文件以及run文档 中推荐的 RuboCop--force-exclusion配合方式避免 RuboCop 自身的 Exclude 配置被忽略。场景三没有匹配文件时自动跳过# lefthook.yml pre-commit: jobs: - name: lint run: npm run lint # 只有暂存了 .js 文件才会真正执行 glob: *.js利用第六节所述的无模板时自动过滤并跳过行为让命令在无相关文件变更时零开销退出。十、常见误区与建议**在默认引擎下不匹配根目录文件glob: **/*.js不会命中app.js。要么分别写*.js与**/*.js两个模式要么全局切换到glob_matcher: doublestarglob与root的基准不同glob 始终基于 Git 仓库根计算不要因为设置了root就改写相对路径glob列表是并集而非交集写多模式时不要误以为文件必须同时满足所有模式切换glob_matcher后检查exclude两者共用引擎引擎切换可能让原先的排除模式失效或意外扩大范围大小写不敏感默认匹配会忽略大小写若你需要大小写敏感匹配需要额外手段如文件命名规范约束。结语glob是 lefthook 文件过滤体系的基石配合run模板、自定义files命令与exclude排除规则可以精确控制每条钩子命令的作用范围而glob_matcher则为迁移用户提供了标准的**语义开关。理解**在不同引擎下的差异、glob 与root的计算基准、以及无模板时的自动跳过行为是写出既不误伤也不漏跑的高质量 lefthook 配置的关键。【免费下载链接】lefthookFast and powerful Git hooks manager for any type of projects.项目地址: https://gitcode.com/GitHub_Trending/le/lefthook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →