@@ -297,11 +297,86 @@ def init(self) -> None:
297297 self .gh_proxy_service .update_proxy_url ()
298298
299299 self .init_others ()
300+ self ._setup_git_hooks ()
300301 except Exception :
301302 log .error ('初始化出错' , exc_info = True )
302303 finally :
303304 self ._init_lock .release ()
304305
306+ def _setup_git_hooks (self ) -> None :
307+ """
308+ 自动配置本地的 git hooks 指向项目中的 .githooks 目录
309+ """
310+ try :
311+ import subprocess
312+
313+ cls_file = inspect .getfile (self .__class__ )
314+ src_dir = file_utils .find_src_dir (cls_file )
315+ if src_dir is None :
316+ return
317+ project_root = src_dir .parent
318+ git_dir = project_root / ".git"
319+ githooks_dir = project_root / ".githooks"
320+
321+ if git_dir .exists () and githooks_dir .exists ():
322+ # 检查当前的 hooksPath
323+ result = subprocess .run (
324+ ["git" , "config" , "core.hooksPath" ],
325+ capture_output = True ,
326+ text = True ,
327+ cwd = str (project_root )
328+ )
329+
330+ # 若命令返回码非 0 且 stderr 存在内容,才视为真实错误返回
331+ stderr_msg = result .stderr .strip ()
332+ if result .returncode != 0 and stderr_msg :
333+ log .warning (f"获取当前 Git hooksPath 失败: { stderr_msg } " )
334+ return
335+ current_hooks_path = result .stdout .strip ()
336+
337+ # 根据已有配置情况进行处理
338+ if not current_hooks_path :
339+ set_result = subprocess .run (
340+ ["git" , "config" , "core.hooksPath" , ".githooks" ],
341+ capture_output = True ,
342+ text = True ,
343+ cwd = str (project_root )
344+ )
345+ if set_result .returncode == 0 :
346+ log .info ("Git hooks 路径已成功配置为 .githooks" )
347+ else :
348+ log .warning (f"配置 Git hooks 失败 (返回码 { set_result .returncode } ): { set_result .stderr .strip ()} " )
349+ return
350+ elif current_hooks_path != ".githooks" :
351+ # 检测到自定义 hooksPath,尝试自动将 pre-push 注入到对方的路径中以保证两者共存
352+ import shutil
353+ custom_hooks_dir = project_root / current_hooks_path
354+ custom_pre_push = custom_hooks_dir / "pre-push"
355+
356+ if not custom_pre_push .exists ():
357+ try :
358+ custom_hooks_dir .mkdir (parents = True , exist_ok = True )
359+ source_pre_push = githooks_dir / "pre-push"
360+ if source_pre_push .exists ():
361+ shutil .copy2 (source_pre_push , custom_pre_push )
362+ custom_pre_push .chmod (0o755 )
363+ log .info (f"成功将 pre-push 保护逻辑注入到自定义路径 '{ current_hooks_path } ' 中" )
364+ except Exception as e :
365+ log .warning (f"尝试向自定义 hooksPath 注入 pre-push 失败: { e } " )
366+ else :
367+ log .warning (f"检测到自定义的 Git hooks 路径 '{ current_hooks_path } ' 且已存在 pre-push 脚本。请手动将仓库 '.githooks/pre-push' 逻辑合并进去。" )
368+
369+ # 无论 hooksPath 是否刚配置过,都确保钩子文件有执行权限
370+ pre_push_file = githooks_dir / "pre-push"
371+ if pre_push_file .exists ():
372+ try :
373+ pre_push_file .chmod (0o755 )
374+ except Exception as pe :
375+ log .warning (f"赋予 pre-push 脚本可执行权限失败: { pe } " )
376+
377+ except (subprocess .SubprocessError , OSError ) as e :
378+ log .warning (f"自动配置 Git hooks 失败: { e } " )
379+
305380 def init_controller (self ) -> None :
306381 """
307382 初始化控制器
0 commit comments