husky源码分析——这个库到底做了什么?
husky 源码分析
前⾔
在做前端⼯程化时 husky 可以说是⼀个必不可少的⼯具。husky 可以让我们在项⽬中⽅便添加 git hooks。
这个库的名字指的是 “哈⼠奇”,结合库主要⽤在提交前发现问题、规范代码的作⽤,应该是这个意思: ‘不好好规范你的代码,你就像⼀个哈⼠奇⼀样,会⽤代码拆家的’ 。这个寓意跟另⼀个经常和 husky 搭配使⽤的库 lint-staged 很像
lint-staged官⽹
Run linters against staged git files and don't let slip into your code base!(⼤概意思:不要让粑粑溜进你的代码库!)
这⼤概就是 ‘屎⼭’ ⼀词的由来吧(我猜的)有个性!同时也说明了代码规范的重要性!
今天我从源码来探究下,这个 npm 库到底做了什么!
该项⽬为 ts 项⽬,通过 tsconfig.json、package.json 可知,编译⼊⼝为 src 出⼝为 lib 。项⽬执⾏主⽂件为 lib/index.js
主要⽂件为:src/index.ts、src/bin.ts、husky.sh
主⽂件 src/index.ts
import cp = require('child_process') // ⼦进程
import fs = require('fs') // ⽂件处理
import p = require('path') // 路径⽅法
// ⽇志输出
const l = (msg: string): void => console.log(`husky - ${msg}`)
// 通过 node ⼦进程拼接 git 参数并返回执⾏结果
const git = (args: string[]): cp.SpawnSyncReturns<Buffer> =>
cp.spawnSync('git', args, { stdio: 'inherit' })
/**
* install ⽅法可以看作初始化设置,在此⽅法中实现了以下功能
* 1、辅助 Plumbing 底层命令,主要⽤于操作
* 2、判断安装⽬录是否为项⽬根⽬录并创建 .husky ⽂件夹
* 3、判断项⽬中是否存在 .git ⽂件。如果不存在则不存在 githook ⽂件,也就不存在替换 githook 的⽂件路径的可能了
* 4、
* [1] 在 .husky ⽂件下创建⽂件夹 '_'
* [2] 在 '_' ⽂件下写⼊⽂件 .gitignore, ⽂件内容为 ‘*’, 忽略该⽬录下所有⽂件的 git 提交
* [3] 复制 husky 项⽬根⽬录下的 husky.sh ⽂件到⽬标项⽬的 '_' ⽬录下,名称不变
* [4] 执⾏ git 操作,修改 githook 的执⾏路径为⽬标项⽬的 .husky ⽂件下
* [5] 执⾏成功 or 失败后的 log 提⽰
*/
export function install(dir = '.husky'): void {
// Ensure that we're inside a git repository
// If git command is not found, status is null and we should return.
// That's why status value needs to be checked explicitly.
// ----1----
if (git(['rev-parse']).status !== 0) {
return
}
// Custom dir help
const url = 'git.io/Jc3F9'
const url = 'git.io/Jc3F9'
// ----2----
// Ensure that we're not trying to install outside of cwd
if (!p.resolve(process.cwd(), dir).startsWith(process.cwd())) {
throw new Error(`.. not allowed (see ${url})`)
}
// ----3----
// Ensure that cwd is git top level
if (!fs.existsSync('.git')) {
throw new Error(`.git can't be found (see ${url})`)
}
/
/ ----4----
try {
// Create .husky/_ ----4.1----
fs.mkdirSync(p.join(dir, '_'), { recursive: true })
// Create .husky/_/.gitignore ----4.2----
fs.writeFileSync(p.join(dir, '_/.gitignore'), '*')
// Copy husky.sh to .husky/_/husky.sh ----4.3----
// Configure repo ----4.4----
const { error } = git(['config', 'core.hooksPath', dir])
if (error) {
throw error
}
// ----4.5----
} catch (e) {
l('Git hooks failed to install')
throw e
}
l('Git hooks installed')
}
/**
* set: 创建指定的 githook ⽂件,并写⼊⽂件内容
* 1、如果⽂件⽬录不存在, 中断并提⽰执⾏ husky install 初始化配置
* 2、写⼊⽂件, 指定解释器为 sh 执⾏ shell 脚本, cmd 动态参数,为开发者想要在这个 githook 阶段执⾏的操作,⼀般为脚本 * 例:npm run lint
* 3、创建成功的 log
*/
export function set(file: string, cmd: string): void {
const dir = p.dirname(file)
// ----1----
if (!fs.existsSync(dir)) {
throw new Error(
`can't create hook, ${dir} directory doesn't exist (try running husky install)`,
)
}
// ----2----
fs.writeFileSync(
file,
`#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
${cmd}
`,
{ mode: 0o0755 },
)
// ----3----
l(`created ${file}`)
}
/**
* add: 在已有的 githook ⽂件中追加命令
* 1、githook ⽂件是否存在
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论