Uninote
Uninote

任务详情

任务链接

收集相关文档

  1. 搜索了解git钩子相关内容 git钩子-官方文档
  2. pre-receive钩子配置参考钩子配置

整理与需求相关的钩子配置

  • 说明pre-receive: 是服务端保存push内容前,执行的脚本或程序,当程序中返回的推出码非0,服务端将不接受客户端的推送。
  • 两种配置钩子方式:
    • 通过git config设置init.templateDir
      • 使用的是每个仓库.git/hooks目录下的钩子
      • 在仓库初始化的时候,从init.templateDir去拷贝hook到当前初始化的仓库(更详细的文档可以查看)
    • 通过git config设置core.hooksPath(服务端配置pre-receive推荐使用这个)
      • 所有仓库使用的是core.hooksPath全局设定钩子的路径
      • 当单独仓库使用本地或其他的hooks可以设置loacl级别的core.hooksPath路径来替代全局的设置
  • 配置内容(控制提交的内容不超过100M)
    • 在pre-receive.sample中添加
totalSize=$(du -sm|awk '{print $1}')
[ $totalSize -gt 100 ] && echo "can not push exceed 100M file to this depository" && exit 2
  • 重命名pre-receive.sample为pre-receive,并确保文件的权限为0755即可

http://t4.uninote.com.cn gogs上实现

优化实现

上面的方式虽然能实现对仓库总大小的限制,但是显得比较繁琐,因为要对每个仓库的钩子设定相同的pre-receive内容。 分析源码,看看能不能所有仓库实现统一git钩子。

  • clone gogs源码分析
// 同步钩子接口部分内容
// /admin组接口
m.Group("/admin", func() {
	m.Combo("").Get(admin.Dashboard).Post(admin.Operation)
...
}
// handler函数
func Operation(c *context.Context) {
switch AdminOperation(c.QueryInt("op")){
...
	// 同步githooks case
	case SyncRepositoryHooks:
		success = c.Tr("admin.dashboard.resync_all_hooks_success")
		// 同步hooks函数
		err = db.SyncRepositoryHooks()
...
}
}

func SyncRepositoryHooks() error {
	// 从repository中查询id>0的所有仓库
	return x.Where("id > 0").Iterate(new(Repository),
	// 对每个仓库的操作
		func(idx int, bean interface{}) error {
			repo := bean.(*Repository)
			// 0. 1~3步骤都是在拼凑hookPath
			// 1. 获取仓库的拥有者
			// 2. conf.Repository.Root,username+repoName+“.git”组成RepoPath
			// 3. 遍历git.ServerSideHooks的三个git服务端钩子,组成hookPath=RepoPath+hookName
			// 4. 向hookPath中写入内容,这里的内容是写死的,意思是调用接口钩子的时候手动执行gogs hook --config=/app.ini pre-receive
			/*
				"pre-receive":  "#!/usr/bin/env %s\n\"%s\" hook --config='%s' pre-receive\n",
				"update":       "#!/usr/bin/env %s\n\"%s\" hook --config='%s' update $1 $2 $3\n",
				"post-receive": "#!/usr/bin/env %s\n\"%s\" hook --config='%s' post-receive\n",
			*/
			// 同步的hook只是执行了用户设定的customPath路径下的hook
			if err := createDelegateHooks(repo.RepoPath()); err != nil {
				return err
			}
			...
			return nil
		})
}

// gogs命令与钩子相关的源码分析
	if !com.IsFile(customHooksPath) {
		return nil
	}
		var hookCmd *exec.Cmd
	if conf.IsWindowsRuntime() {
		hookCmd = exec.Command("bash.exe", "custom_hooks/pre-receive")
	} else {
	// 最终执行的也是customHooksPath下的钩子。。。。
		hookCmd = exec.Command(customHooksPath)
	}
	hookCmd.Dir = db.RepoPath(os.Getenv(db.ENV_REPO_OWNER_NAME), os.Getenv(db.ENV_REPO_NAME))
	hookCmd.Stdout = os.Stdout
	hookCmd.Stdin = buf
	hookCmd.Stderr = os.Stderr
	if err := hookCmd.Run(); err != nil {
		fail("Internal error", "Failed to execute custom pre-receive hook: %v", err)
	}
  • 按源码分析,不能实现统一hook的配置(hookPath下的钩子内容是写死的,如果统一实现得改源码写死的那部分代码,再打包才行

  • gogs githook源码分析简单总结三点

customPath下的githook是手动指定的
hookPath路径下的hook是管理员账号通过http请求同步的
gogs的githook存放在customPath和hookPath这两个路径下,hookPath通过命令调用了customPath路径下的git hook执行

front-t4自动发布

gogs分支保护

点赞(0) 阅读(104) 举报
目录
标题