SwiftLine安装使用---包含Git Hooks

SwiftLine的使用分为 编译期间代码提交期间

1. SwiftLine的安装使用 - 编译期间的使用

参考文章:https://blog.csdn.net/blog_t/article/details/89025230?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_default&utm_relevant_index=1

全局安装

全局安装非常简单,首先我们需要通过brew命令安装SwiftLint:

brew install swiftlint

然后添加编译脚本:


image.png

最后在黑框框中添加如下脚本:

if which swiftlint >/dev/null; then
swiftlint
#echo "skip"
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi

大功告成,就可以编译啦,之后每次安装只需要给工程添加脚本就可以了。

局部安装

除了全局安装,我们也可以通过CocoaPods进行安装。在Podfile上添加相关的依赖:

pod 'SwiftLint'

然后跟全局方法一样,在Run Script中添加命令,但是内容有些许的不同:

"${PODS_ROOT}/SwiftLint/swiftlint"
image.png

接下来就让我们来试试看SwiftLint的吧!

使用

在给项目初次接入SwiftLint的时候,你可能会被下面这样的情景给吓到


image.png

但是呢,不用慌,我们可以看一下这是什么情况。仔细观察一番之后,我们会发现,绝大多数的Warning都是这个原因:


image.png

我这一行哪里有空格符?简直就是冤枉啊!但其实是这样的,虽然看起来好像没有空格符,但是在换行符之间不应该掺杂制表符,也就是说你实际的代码是这样的:

\n \tab \n

所以呢,人家的Warning也不是没有道理的嘛。那么我们该怎么来消除这些Warning呢?

首先,我们要确保,以后我们所码的代码不再出现这样的格式,所以我们需要把Text Editing里面的Including whitespace-only lines勾选上:

image.png

这样可以保证我们今后的换行不再出现制表符的警告,然后,我们就需要处理现有的代码。现有的代码,少说也有几万行,手动改不是要累死人?这个时候就轮到SwiftLint的命令行出场了:

image.png

我们将目录切换到工程的根目录之下,然后敲击如下命令:

swiftlint autocorrect

然后我们就会发现,所有的空格符Warning都消失了。这都得益于我们刚刚所进行的命令行操作,它会将已知的能够自动修复的Error和Warning都自动修复,大大的减轻了我们的工作量。
但是又出现了一个问题,在项目的根目录之下执行自动纠正,SwiftLint会将Pods文件夹中的Swift文件也一起纠正了,第三方的框架原则上能不动就不动,那么我们该怎么办呢?
这个时候就需要.swiftlint.yml文件了。那么这是一个什么文件呢?在使用SwiftLint的时候,很多时候我们会碰到一些自定义的规则需求,这个时候就需要.swiftlint.yml来解决问题了。

.swiftlint.yml

所谓的.swiftlint.yml其实就是SwiftLint的一个配置文件,我们可以通过这个配置文件来修改约束的规则,以此达到自定义的效果。把这个文件放在代码根目录下面。

.swiftlint.yml.png

一般的配置文件大概长这个样子:

excluded: # 执行 linting 时忽略的路径。 优先级比 `included` 更高。
  - Carthage
  - Pods

line_length:
  warning: 350
  error: 450
  ignores_function_declarations: true
  ignores_comments: true

function_body_length: # 函数体长度
  warning: 300
  error: 350

identifier_name:
  min_length: # 只有最小长度
    error: 1 # 只有错误

type_body_length: # 类的长度
  warning: 800
  error: 1200

file_length: # 文件长度
  warning: 1000
  error: 1500

cyclomatic_complexity: # 代码复杂度,默认为10
  warning: 30
  error: 35

force_cast: warning # 强制转换(代码中存在一些前面通过if判断过类型,后面做的强制转换的代码)
force_try: warning # try语句判断

disabled_rules: # 执行时排除舍弃的规则
  - trailing_whitespace # 每一个空行不能有空格,会与Xcode换行后自动对齐生成的空格冲突,建议排除掉加。
  - identifier_name # 命名规则必须按照驼峰原则(可能model中的某些字段与json字段命名冲突,建议排除掉)
  - type_name # 类型命名规则限制,以大写字母开头,且长度在1到20个字符之间
  - shorthand_operator # 使用+= , -=, *=, /=  代替 a = a + 1

2. SwiftLine的使用 - 代码提交期间的使用

  1. 首先要安装swiftlint,上面文章已经写过,只需要安装上去,不用在Run Script中添加命令。.swiftlint.yml文件放在根目录下面

  2. 在代码提交期间,使用git hooks原理,对提交的代码进行规范规则判断检查 ,不符合.swiftlint.yml的规范,就会报错、报警告。 在根目录下面的hooks文件里面有commit-msg和pre-commit这个两个脚本,

C295B40C-AAB8-4FB4-B8D5-432D57671447.png
commit-msg 的脚本内容如下:
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message.  The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit.  The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".

# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

# This example catches duplicate Signed-off-by lines.

forcecommit=$(git config --type=bool hooks.forcecommit)

if [ "$forcecommit" != "true" ]
 then
if [ "$(grep '^feat:' "$1")" == "" ] &&
   [ "$(grep '^fix:' "$1")" == "" ] &&
   [ "$(grep '^lint_error:' "$1")" == "" ] &&
   [ "$(grep '^lint_warning:' "$1")" == "" ] &&
   [ "$(grep '^docs:' "$1")"  == "" ] &&
   [ "$(grep '^style:' "$1")" == "" ] &&
   [ "$(grep '^refactor:' "$1")" == "" ] &&
   [ "$(grep '^test:' "$1")" = "" ] &&
   [ "$(grep '^chore:' "$1")" == "" ]
then
    cat <<\EOF
    ❌错误:提交日志格式错误; 如需强制提交,可执行以下命令(仅限于本次提交)
        git config hooks.forcecommit true
    我们有如下几种提交格式可供选择:
    
    feat: 新功能(feature)
    fix: 修补bug
    lint_error: 处理lint❎
    lint_warning: 处理lint⚠️
    docs: 文档(documentation)
    style: 格式(不影响代码运行)
    refactor: 重构(即不是新增功能,也不是修改bug的代码变动)
    test: 增加测试
    chore: 构建过程或辅助工具的变动
    
    如 "feat:新增直播间粉丝之间问候语"
    :冒号为英文格式,切记切记
EOF
    exit 1
fi
else
    git config hooks.forcecommit false
fi

# echo "提交的日志为:$1"
# test "" = "$(grep '^Signed-off-by: ' "$1" |
#    sort | uniq -c | sed -e '/^[   ]*1[    ]/d')" || {
#   echo >&2 Duplicate Signed-off-by lines.
#   exit 1
# }

pre-commit的脚本内容如下:
#!/bin/bash

# use for SourceTree And Xcode
if test -d "/opt/homebrew/bin/"; then
  PATH="/opt/homebrew/bin/:${PATH}"
fi
export PATH

# 检测swiftLint工具是否安装
if [ -z "$(which swiftlint)" ]
then
    cat <<\EOF
    设备上没有检测到SwiftLint,请使用以下命令进行下载安装:
    brew install swiftLint
EOF
    exit 1
fi

# 接收lint结果,并进行格式化处理
function dealLintResult() {
  while read -r line; do
    FILE_NAME=$(echo "$line" | cut -d : -f 1 | rev | cut -d / -f 1 | rev)
    LINE=$(echo "$line" | cut -d : -f 2)
    COLUMN=$(echo "$line" | cut -d : -f 3)
    VIOLATION_TYPE=$(echo "$line" | cut -d : -f 4 | cut -c 2-)
    VIOLATION=$(echo "$line" | cut -d : -f 5 | cut -c 2-)
    DESCRIPTION=$(echo "$line" | cut -d : -f 6 | cut -c 2-)

    if [ "$VIOLATION_TYPE" == "warning" ]; then
      echo -e "\n⚠️  $VIOLATION \n"
    else
      echo -e "\n❌ $VIOLATION \n"
    fi
    echo -e "$FILE_NAME: 第${LINE}行 第${COLUMN}列。- $DESCRIPTION \n"
    echo "---------------------------------------------------------------------"
  done <<<"$1"
  
  printf "\n♀️提交被阻止,请在提交前修复好以上问题\n"
  cat <<\EOF
  或使用终极命令 git commit -m 'xxx' --no-verify (不建议使用)
EOF
}

EXIT_CODE=0

COMMIT_SWIFT_FILES=()
# 搜集un-staged files中的swift文件
CHANGED_FILES_UNSTAGED=$(git diff --diff-filter=d --name-only -- "*.swift")
if [ "$CHANGED_FILES_UNSTAGED" ]; then
  COMMIT_SWIFT_FILES+=("$CHANGED_FILES_UNSTAGED")
fi

# 搜集staged files中的swift文件
CHANGED_FILES_STAGED=$(git diff --cached --diff-filter=d --name-only -- "*.swift")
if [ "$CHANGED_FILES_STAGED" ]; then
  COMMIT_SWIFT_FILES+=("$CHANGED_FILES_STAGED")
fi

# 遍历所有添加的swift文件,并对其逐一进行lint
while read -r swiftfile; do
  if [ -e "$swiftfile" ]; then
      LINTRESULT=$($(which swiftlint) lint --quiet --path "$swiftfile" --config ".swiftlint.yml")
      if [ -n "$LINTRESULT" ]; then
        dealLintResult "$LINTRESULT"
        EXIT_CODE=1
      fi
  fi
done <<<"${COMMIT_SWIFT_FILES[@]}"

exit $EXIT_CODE

注意 我用 sourcetree clone 到本地的代码后 .git 目录下没有发现 hooks 文件夹,但是通过终端 git clone 完的仓库里就有,我想不明白,sourcetree 只不过是个 git 客户端而已,还能给我过滤掉了文件夹吗。后来看到别人写的 hooks 的应用才明白,对于任何 Git 仓库来说钩子(hooks)都是本地的,而且它不会随着 git clone 一起复制到新的仓库。 但是在终端里的 git clone 密令是可以把它克隆下来的
参考文章:
https://blog.csdn.net/weixin_42206732/article/details/90737049

上面的脚本配置完了,接下来就是代码提交期间使用swiftlint了,在终端里面写commit命令,会报错误,我列出来两种:
git commit -m "测试swiftlint的使用代码"
错误1:

YPLetterIndexView.swift 这个文件写法不规范

错误1.png
错误2:

提交代码的时候,调教文案不规范。改成如下就OK了。

git commit -m "feat: 测试swiftlint的使用代码"
错误2.png

你可能感兴趣的:(SwiftLine安装使用---包含Git Hooks)