移动端设计研发ios学习交流工程效率配置&Shell&打包等

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

2018-02-28  本文已影响173人  Kirn

前言

对于日渐庞大的工程项目,保持代码的整洁规范风格一致并不是一件很容易的事情。每个人都有自己的编码规范和习惯用法,通过简单的书面规范限定和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,在代码提交之前完成我们的代码格式化,然后提交格式化后的代码

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

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

上一篇 下一篇

猜你喜欢

热点阅读