TortoiseSVN 客户端 hooks 实现提交时修改项目版本号

2,224 阅读2分钟

一些老项目通过手动维护版本号,来在每次更新发布新版本的时候刷新缓存。但是手动操作很容易忘记,特别是很少维护的项目,经常忘记更新版本号。

这次就踩了这么一个坑,没有更新版本号,用户访问的还是浏览器缓存的资源,需要等到强缓存到期,进行协商缓存的时候才能从服务器获取到最新的资源。

这个老项目是用 SVN 做版本管理工具的。于是,我就想,Git 有 hooks,SVN 是不是也有?事实上还真的有。但是缺少 husky 之类的工具让这个 hook 在团队之间共享,SVN 的资料太少了,因此现在还没解决这个问题,不过问题不大吧。

现在一般都用 TortoiseSVN 作为 SVN 的客户端,设置 hooks 的相关文档在官网上可以找到:Client Side Hook Scripts

通过下面这个操作就可以添加一个 hook:

TortoiseSVN -> setting -> Hook Scripts -> Add

image.png

这里 Hook Type 选择 Start Commit Hook。这个 hook 会在点击 SVN Commit 之后,弹窗打开之前触发。

Command Line To Execute 选择 hook 脚本的地址,但是要加上执行命令。这里跟 Git Hooks 一样,支持多种脚本语言。如果用批处理脚本,则直接填入 url\hooks\start-commit.bat 格式。我这里用前端熟悉的 node.js,所以这一行应该填入 node url\hooks\start-commit.js。注意这个地址是绝对路径。

接下来就是编写这个脚本。这里我用正则表达式匹配,用当前时间戳作为版本号。可能有些提交不会发布版本,但修改总不会出错。按这个逻辑,版本号就是最新一次提交的时间戳。这个脚本也很简单:

const path = require('path')
const fs = require('fs')

const verPath = path.resolve(__dirname, '../version.jsp')
const verCtn = getFileCtn(verPath)
const nVerCtn = verCtn.replace(/version="\d+";/, `version="${new Date().getTime()}";`)
fs.writeFileSync(verPath, nVerCtn)
process.exit(0)

function getFileCtn(filePath) {
  try {
    var buffer = fs.readFileSync(filePath)
    var hasToString = buffer && typeof buffer.toString === 'function'

    return hasToString && buffer.toString()
  } catch (err) {
    if (err && err.code !== 'ENOENT' && err.code !== 'ENAMETOOLONG') {
      throw err
    }
  }
}

process.exit(0) 可以让脚本正常退出,其他的 code 都会返回一个错误,中断提交。但这里其实的调试没必要中断,下一步是打开弹窗,并不会真正提交。如果使用其他 hook,就可以使用这个技巧了。

还有一个难点,就是在写脚本的时候怎么调试。console.log 是不起作用的,这里其实是打开一个子进程,让脚本在里面运行。如果不勾选 Hide the script while running,你会看到一个 CMD 窗口一闪而过。但即使我让子进程进入等待,也不能打印信息,不知道为啥,我对这块不太了解,希望有大佬解答一下。

但是我最终还是发现一个打印信息的方法。脚本抛出的错误还是会被处理的。所以可以通过 throw new Error() 打印信息,调试脚本。

以上。