十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

lefthook 的 source_dir 配置详解:自定义脚本存放目录的完整指南

lefthook 的 source_dir 配置详解:自定义脚本存放目录的完整指南 lefthook 的 source_dir 配置详解自定义脚本存放目录的完整指南【免费下载链接】lefthookFast and powerful Git hooks manager for any type of projects.项目地址: https://gitcode.com/GitHub_Trending/le/lefthooksource_dir是 lefthook 中控制脚本scripts存放位置的核心配置项默认值为.lefthook/。本指南围绕 docs/configuration/source_dir.md 展开结合仓库源码说明其默认行为、目录约定、配置方法与底层解析逻辑帮助你彻底掌握脚本文件该放在哪、为什么放在哪、如何按需修改这一 lefthook 使用中的基础问题。一、source_dir是什么在 lefthook 中除了在lefthook.yml里直接通过commands内联命令外还可以把可执行脚本scripts放在独立目录中由 lefthook 在触发对应 Git hook 时负责查找并执行。source_dir就是用来改变这个脚本存放目录的顶层配置项。按照官方文档的定义Change a directory for script files. The directory contains subfolders named after git hooks, each containing script files.即source_dir指定脚本文件的根目录该目录下的子文件夹以 Git hook 名称命名每个子文件夹中再存放对应 hook 要执行的脚本文件。默认值source_dir默认值.lefthook/source_dir_local默认值.lefthook-local/见 docs/configuration/source_dir_local.md默认目录结构如下.lefthook/ ├── pre-commit/ │ ├── lint.sh │ └── test.py └── pre-push/ └── check-files.rb这意味着pre-commithook 会去.lefthook/pre-commit/下寻找配置中声明的脚本pre-pushhook 则会去.lefthook/pre-push/下寻找依此类推。二、脚本与source_dir的配合方式source_dir不是孤立存在的它服务于 lefthook 的Scripts机制。完整流程参见 docs/configuration/Scripts.md在lefthook.yml的某个 hook 下声明scripts条目键名即脚本文件名把实际脚本文件放入source_dir/hook-name/目录触发该 hook 时lefthook 会在项目根目录下定位并执行这些脚本。一个最小示例脚本放在默认目录.lefthook/pre-commit/# lefthook.yml pre-commit: scripts: my-script.sh: runner: bash文件布局.lefthook/ └── pre-commit/ └── my-script.sh也可以使用lefthook add命令快速搭建目录骨架lefthook add -d pre-commit该命令会检查 hook 名称是否合法参考 internal/config/available_hooks.go 中的AvailableHooks列表并在传入-d时同时创建全局与本地两个 source 目录下的对应 hook 子目录逻辑见 internal/command/add.go。三、如何自定义source_dir在lefthook.yml顶层添加source_dir键即可# lefthook.yml source_dir: .my-hooks/ pre-commit: scripts: my-script.sh: runner: bash此时脚本应放在.my-hooks/ └── pre-commit/ └── my-script.sh若使用本地配置lefthook-local.yml不入库的个人配置还可配合source_dir_local单独指定本地脚本目录# lefthook-local.yml source_dir_local: .lefthook-local/这种全局脚本 本地脚本的双目录设计正是 lefthook 支持本地化、个人化脚本如仅本机需要的格式化工具的基础详见 docs/configuration/source_dir_local.md。四、源码视角source_dir如何被解析和使用1. 配置字段与默认值定义source_dir对应 internal/config/config.go 中的Config.SourceDir字段其 JSON Schema 注解明确给出默认值.lefthook/与用途说明SourceDir string json:source_dir,omitempty jsonschema:default.lefthook/,descriptionChange a directory for script files. Directory for script files contains folders with git hook names which contain script files. koanf:source_dir mapstructure:source_dir,omitempty实际的默认值常量定义在 internal/config/loader.goconst ( DefaultConfigName lefthook.yml DefaultSourceDir .lefthook DefaultSourceDirLocal .lefthook-local )并且在配置反序列化阶段internal/config/loader.go会先为SourceDir、SourceDirLocal赋上默认值再通过unmarshalConfigs用实际配置文件覆盖config.SourceDir DefaultSourceDir config.SourceDirLocal DefaultSourceDirLocal因此即使lefthook.yml中不写source_dir其行为也是确定的脚本统一从.lefthook/下按 hook 名子目录查找。2. 运行期SourceDirs 列表的组装当执行某个 hook 时internal/command/run.go 中的getSourceDirs会依据配置组装一份查找目录列表func getSourceDirs(repo *git.Repo, cfg *config.Config) []string { sourceDirs : []string{ filepath.Join(repo.RootPath, cfg.SourceDir), filepath.Join(repo.RootPath, cfg.SourceDirLocal), // Additional source dirs to support .config/ filepath.Join(repo.RootPath, .config, lefthook), filepath.Join(repo.RootPath, .config, lefthook-local), } for _, remote : range cfg.Remotes { if remote.Configured() { // Append only source_dir, because source_dir_local doesnt make sense sourceDirs append( sourceDirs, filepath.Join(repo.RootPath, .., remote.SourceDir), ) } } return sourceDirs }从源码结构看脚本查找存在优先级与回退机制首先是自定义或默认的source_dir与source_dir_local其次兼容.config/lefthook与.config/lefthook-local对应 XDG 风格目录若配置了remotes远程共享配置还会追加远程配置声明的 source 目录远程场景下只追加source_dir因为source_dir_local对远程共享无意义。3. 脚本路径拼接与执行真正拼接脚本路径的逻辑在 internal/run/controller/command/build_script.go。buildScript会遍历上述SourceDirs对每个目录按filepath.Join(sourceDir, hookName, scriptName)拼出候选路径并逐一探测for _, sourceDir : range b.opts.SourceDirs { scriptPath : filepath.Join(sourceDir, b.opts.HookName, params.Script) fileInfo, err : b.git.Fs.Stat(scriptPath) if os.IsNotExist(err) { b.logger.Debugf([lefthook] script doesnt exist: %s, scriptPath) continue } ... }同时该函数还做了几件关键工作校验文件类型非普通文件如目录会被跳过并返回SkipError自动赋予执行权限若脚本缺少可执行位会以0o751权限自动Chmod保证脚本可直接运行拼接运行命令若声明了runner如bash则按runner scriptPath组织命令未声明 runner 时直接执行脚本本身并追加 Git 传入的参数若所有目录都找不到该脚本返回scriptNotExistsErrorscript does not exist: ...来中断该 job。这也解释了为什么脚本路径必须遵循source_dir/hook-name/script-name的约定——这个拼接是源码层面写死的。4. 配置转储时的省略规则在lefthook dump输出配置时internal/config/config.go 会做一项优化当SourceDir仍为默认值.lefthook时直接从输出中删除该字段避免冗余if c.SourceDir DefaultSourceDir { delete(res, source_dir) } if c.SourceDirLocal DefaultSourceDirLocal { delete(res, source_dir_local) }因此 dump 结果中只有显式自定义过source_dir的配置才会出现该键。五、source_dirvssource_dir_local两者同属脚本目录类配置但定位不同配置项默认值用途是否入库source_dir.lefthook/项目共享脚本目录通常随项目提交VCSsource_dir_local.lefthook-local/本地私有脚本目录不入 VCS通常由.gitignore排除典型场景团队共享的检查脚本放入.lefthook/随仓库分发而个人偏好如本地专用格式化脚本放入.lefthook-local/配合lefthook-local.yml使用互不干扰。运行期两者都会被并入SourceDirs查找列表因此同一 hook 下共享脚本与本地脚本可以同时生效。六、常见实践建议保持默认目录减少心智负担lefthook add、lefthook install、lefthook dump等命令均默认感知.lefthook/非必要不建议改动。自定义时注意相对路径source_dir是相对于项目根目录解析的见 internal/command/run.go 中filepath.Join(repo.RootPath, ...)请勿写成绝对路径或带../的越级路径。脚本命名与配置键名保持一致配置中scripts下的键必须与source_dir/hook/下的实际文件名完全一致否则会得到 script does not exist 错误。脚本需要可执行权限虽然 lefthook 会自动补权限0o751但建议在提交前就chmod x并确认 shebang 正确以保证在未触发自动修复的情况下也能稳定运行。远程共享配置的场景当通过remotes引入共享配置时脚本查找会额外追加远程声明的source_dir此时需保证该目录在共享仓库中真实存在。七、总结source_dir虽只是一个顶层配置键但它定义了 lefthook 脚本体系的目录约定source_dir/hook-name/script-file。从 internal/config/loader.go 的默认值注入到 internal/command/run.go 的多目录查找列表组装再到 internal/run/controller/command/build_script.go 的路径拼接与权限兜底整条链路共同保证了声明式配置 约定式目录这一简洁模型的稳定运行。理解它你就能灵活地组织项目脚本也能更好地掌握 Scripts、source_dir_local 以及 remotes 等关联配置。【免费下载链接】lefthookFast and powerful Git hooks manager for any type of projects.项目地址: https://gitcode.com/GitHub_Trending/le/lefthook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表