Mac/Linux svn 命令行批量处理及自动化部署

服务器

浏览数:164

2019-8-22

Windows 系统下,通常我们使用 TortoiseSVN 来处理 svn 客户端工作流,而 Mac 下第三方 svn GUI 工具一般都需要收费,这里我给大家友情链接一个破解版的 Cornerstone(声称 Mac 上最好用的 svn 客户端),当然更欢迎大家支持正版。

Mac OS 自带了 svn 的服务端和客户端环境,我们完全可以使用 svn 命令行快狠准地解决客户端工作流。

简单粗暴版

假设需要把项目的生产目录文件 distDir/* 转移到 svn 目录 svnDir 并提交到目标服务器,我们可以执行命令:

cd svnDir
svn update
svn delete *
cp -rf distDir/* svnDir
svn add *
svn commit -m "commit info"

这样粗暴覆盖上一个 version,基本能避免冲突,另外不建议用 svn 来处理开发过程中的代码冲突问题。

批量处理

实际上,我们经常会遇到 svn 目录下存在各种不同状态的文件或文件夹,譬如:

$ svn status

M       index.html
!       static/js/0.c1af89c249789814f99b.js
?       static/js/0.cbb2833152f342a96f84.js
!       static/js/1.62e25d5cba0e0b90bbe7.js
?       static/js/1.ae9f8f72ced58a1b92eb.js
?       static/js/2.5b9ab989656feaabcc44.js
!       static/js/2.f852e8b7f0bebe09723e.js
!       static/js/3.1f1f9a6192673180de94.js

PS: 常见的 svnstatus 及其含义

status 含义
M 目标被修改
! 目标遗失或不完整
? 目标未纳入版本控制
A 目标添加
D 目标删除
C 目标冲突

这个时候如果我们执行 svn add * 会失败

$ svn add *

svn: warning: W150002: 'index.html' is already under version control
svn: warning: W150002: 'static' is already under version control
svn: E200009: Could not add all targets because some targets are already versioned
svn: E200009: Illegal target for the requested operation

由于 index.html 已经在版本控制内,是无法被 add 的,所以我们需要把未纳入版本控制的项目筛选出来再添加:

# 筛选出未纳入版本控制的记录
# grep "^?" -- 匹配以`?`开始的行并输出
$ svn st | grep "^?"

?       static/js/0.cbb2833152f342a96f84.js
?       static/js/1.ae9f8f72ced58a1b92eb.js
?       static/js/2.5b9ab989656feaabcc44.js

# 过滤出文件名
# awk '{print $2}' -- 行匹配语句,输出每行第二个字段
$ svn st | grep "^?"| awk '{print $2}'

static/js/0.cbb2833152f342a96f84.js
static/js/1.ae9f8f72ced58a1b92eb.js
static/js/2.5b9ab989656feaabcc44.js

# 把上条命令的输出插入到`svn add`命令的后面即可
$ svn add `svn st | grep "^?"| awk '{print $2}'`

A         static/js/0.cbb2833152f342a96f84.js
A         static/js/1.ae9f8f72ced58a1b92eb.js
A         static/js/2.5b9ab989656feaabcc44.js

PS:awk 是 linux 系统下用于文本和数据处理的一种编程语言,有兴趣的可以看看教程文档

批量添加

svn add `svn st | grep "^?"| awk '{print $2}'`

批量删除

批量删除和批量添加的流程类似,只需要把遗失状态(status == !)的文件名筛选出来并插入到 svn delete 后面即可。

svn delete `svn st | grep ^! | awk '{print $2}'`

自动化

不妨把 svn 客户端工作流编成自动化脚本,实现一键部署。这里我设计了一个简单的脚本程序 demo,接受以下参数配置:

option required param desc
-s PATH true 源目录,通常为项目生产代码所在目录
-d PATH true svn目录
-m INFO false svn的提交信息
# svn-deploy.sh
#!/bin/bash

# 使用`getopts`解析命令行参数
while getopts :s:d:m: opt
do
  case "$opt" in
    s) SRC_DIR=$OPTARG ;; 
    d) SVN_DIR=$OPTARG ;;
    m) COMMIT_INFO=$OPTARG ;;
    *) 
      echo "ERROR: unknown option" 
      exit 0 ;;
  esac
done

# 设置-s,-d参数必填
if [ -z $SRC_DIR ] || [ -z $SVN_DIR ]
  then
  echo "ERROR: options -s, -d is null";
  exit 0;
fi

cd $SVN_DIR
svn update
svn delete *
cp -rf $SRC_DIR/* $SVN_DIR
svn add *
svn commit -m "$COMMIT_INFO"

# # 批量增删版本
# cd $SVN_DIR
# svn update
# rm -rf *
# cp -rf $SRC_DIR/* $SVN_DIR
# svn add `svn st | grep "^?"| awk '{print $2}'`
# svn delete `svn st | grep "^!" | awk '{print $2}'`
# svn commit -m $COMMIT_INFO
# 运行脚本
$ sh ./svn-deploy.sh -s ~/Documents/demo/dist -d ~/Documents/demo/svn -m "提交信息"

我们可以把脚本制作成可执行文件,并放到环境变量中支持全局调用:

$ cat svn-deploy.sh > svn-deploy

# 授予可执行权限
$ chmod +x svn-deploy

# 获取svn-deploy脚本所在目录
$ pwd
/path/to/svn-deploy

# 添加环境变量,往`.bash_profile`文件中添加:
# export PATH=/path/to/svn-deploy:$PATH
$ vim ~/.bash_profile
$ source ~/.bash_profile

接下来就可以全局使用 svn-deploy 命令了

svn-deploy -s ~/Documents/demo/dist -d ~/Documents/demo/svn

其他

如果在 svn commit 时遇到冲突或者其他异常,建议直接回滚取消当前修改:

svn revert . -R

本文中的 demo 已放在 github 上,欢迎大家一起交流。

作者:西山以南