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中直接完成代码格式化。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容