Objective-C 项目的自动代码格式化

前言

对于日渐庞大的工程项目,保持代码的整洁规范风格一致并不是一件很容易的事情。每个人都有自己的编码规范和习惯用法,通过简单的书面规范限定和code review是解决不了根本问题的。在Xcode还能使用插件的时候,ClangFormat-Xcode是一个不错的选择。但是Xcode 8之后就已经不支持第三方插件了,当然也有一些办法可以绕开这种限制,但是会降低Xcode的安全性。因此只能另寻思路来解决问题。

思路

代码格式化的工具我们选用clangformat,非常成熟的工具,不赘述。接下来就是寻找一个格式化的切入点,由于代码本身是托管在公司的gitlab上,因此首先想到的思路就是通过gitlab本身的机制来实现代码的自动格式化。gitlab本身有两种hook机制,客户端的和服务端的,客户端的先被触发,服务端的后触发。客户端hook由诸如提交和合并这样的操作所调用,而服务器端hook作用于诸如接收被推送的提交这样的联网操作,显然客户端的hook上更容易来完成我们想做的事情。

GitLab hooks

hook都被存储在git目录下的hooks子目录中。git本地项目的.git/hooks。git初始化的时候会在该目录下创建一些实例脚本来告诉你如何修改,这些脚本都是以.sample结尾,如果你想启用它,直接移除后缀名即可。

  • pre-commit 在键入提交信息前运行
  • prepare-commit-msg 在启动提交信息编辑器之前,默认信息被创建之后运行
  • commit-msg 接收一个参数,此参数即上文提到的,存有当前提交信息的临时文件的路径
  • post-commit 在整个提交过程完成后运行
  • applypatch-msg 它接收单个参数:包含请求合并信息的临时文件的名字
  • pre-applypatch 它正好运行于应用补丁 之后,产生提交之前,所以你可以用它在提交前检查快照
  • post-applypatch 运行于提交产生之后
  • pre-rebase 运行于变基之前,以非零值退出可以中止变基的过程
  • post-rewrite 被那些会替换提交记录的命令调用,比如 git commit --amend 和 git rebase(不过不包括 git filter-branch)
  • post-checkout 在 git checkout 成功运行后会被调用
  • post-merge 在 git merge 成功运行后,会被调用
  • pre-push 在 git push 运行期间, 更新了远程引用但尚未传送对象时被调用
  • pre-auto-gc 在垃圾回收开始之前被调用,可以用它来提醒你现在要回收垃圾了,或者依情形判断是否要中断回收

我们需要用的是pre-commit,在代码提交之前完成我们的代码格式化,然后提交格式化后的代码

参考:https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks

流程

1.jpg

流程并不复杂,代码发生变更之后在git commit的时候通过gitlab的hook机制在pre-commit拦截提交,通过我们熟悉的clang-format来完成代码的格式化,成功之后回写源文件,提交。

方案

在github上发现一个开源的解决方案spacecommander可以完成上面的流程

我们看一下它的文件结构

2.jpg

其中有一个setup-repo脚本,它做了几个事情:

  • 在工程目录下创建.git/hooks/pre-commit,并写入执行脚本
  • 在工程目录下创建.clang-format的符号链接

这样就可以在git commit 的时候完成整个代码格式化的流程

为了尽量减少其他开发人员的安装和使用成本,对spacecommander做了一下改造,通过Cocoapods的方式完成部署:

platform :ios, '8.0'
target 'XXXXX' do
    # 代码自动格式化
    pod 'CodeFormatter', :git => 'http://xx.xx.xxx.xxx/ios-team/CodeFormatter.git'
end

post_install do |installer|
    `./Pods/CodeFormatter/setup-repo.sh`
end

post_install会在pod update之后执行,pod update之后就完成了spacecommander的部署,修改setup-repo.sh文件中的

function ensure_hook_is_installed() {
  # check if this repo is referenced in the precommit hook already
  repo_path=$(git rev-parse --show-toplevel)
  if ! grep -q "$repo_path" "$pre_commit_file"; then
    echo "#!/usr/bin/env bash" >> $pre_commit_file
    echo "current_repo_path=\$(git rev-parse --show-toplevel)" >> $pre_commit_file
    echo "repo_to_format=\"$repo_path\"" >> $pre_commit_file
    echo 'if [ "$current_repo_path" == "$repo_to_format" ]'" && [ -e \"$DIR\"/format-objc-hook ]; then \"$DIR\"/format-objc-hook || exit 1; fi" >> $pre_commit_file
  fi
}

为:

function ensure_hook_is_installed() {
  # check if this repo is referenced in the precommit hook already
  repo_path=$(git rev-parse --show-toplevel)
  if ! grep -q "$repo_path" "$pre_commit_file"; then
    echo "#!/usr/bin/env bash" >> $pre_commit_file
    echo "current_repo_path=\$(git rev-parse --show-toplevel)" >> $pre_commit_file
    echo "repo_to_format=\"$repo_path\"" >> $pre_commit_file
    echo 'if [ "$current_repo_path" == "$repo_to_format" ]'" && [ -e $DIR/format-objc-files.sh ]; then $DIR/format-objc-files.sh -s || exit 1; fi" >> $pre_commit_file
  fi
}

format-objc-hook只会检测当前代码是否已经完成代码格式化,format-objc-files可以直接格式化代码。我们这里换成了format-objc-files,可以保证在pre-commit中直接完成代码格式化。

简单的小方案可以解决我们的大问题



作者:Kirn
链接:https://www.jianshu.com/p/93157f03ad96
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值