在 Subversion 中,获取最近更改的分支的完整 URL



简要地说 - 有没有一个简单的svn命令告诉我们">最近更改的分支"?

更深入地说,作为构建过程的一部分,我们尝试检测 Subversion 中最近更改的分支,以便对该分支执行进一步的处理。

例如,如果有人添加了文件:

http://server/svn/project/branches/Integration1/newfile.txt

我们希望能够确定字符串:

http://server/svn/project/branches/Integration1

即,最近更改的父文件夹。

我们能找到的最接近的是执行以下命令:

svn log --verbose --limit 1 http://server/svn/project/

但它随后给出了我们需要使用 batch 解析的 4 行输出。

我们有一个安装了 Subversion 插件的 Jenkins 构建服务器,它可以检测对整个 Subversion 存储库的更改,但它只为我们提供了环境变量 SVN_URL 和 SVN_REVISION,这两个变量都没有解决我们的目标。

我会使用:

svn log --verbose --quiet --limit 1 "http://server/svn/project/"

因此,您可以删除任何提交日志消息,并且只有一个修改路径的列表和一个标头。然后使用 for /F 循环来捕获路径:

rem // Capture output of `svn log`, skip header and hyphen-only lines:
for /F "skip=3 eol=- tokens=1*" %%I in ('
    svn log --verbose --quiet --limit 1 "http://server/svn/project/"
') do echo(%%J

棘手的部分是派生多个项目的公共根路径,例如,可以像以下脚本一样完成(请参阅代码中的所有解释性rem注释;提供存储库路径http://server/svn/project/作为第一个命令行参数(:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_REPOPATH=%~1" & rem // (take the first argument as the repository path)
rem // Clear buffer for common root path:
set "COMM="
rem // Clear all variables beginning with `$`:
for /F "delims=" %%K in ('set $ 2^> nul') do set "%%K="
rem // Capture output of `svn log`, skip header and hyphen-only lines:
for /F "skip=3 eol=- tokens=1*" %%I in ('
    svn log --verbose --quiet --limit 1 "%_REPOPATH%"
') do (
    rem // Store currently iterated path:
    set "ITEM=%%J"
    rem // Check whether buffer for common root path is empty:
    if not defined COMM (
        rem // Buffer is empty, hence this is the first iteration:
        set "COMM=%%J"
    ) else (
        rem // Otherwise, store each `/`-separated path element in array `$ITEM[]`:
        set /A "IDX=0"
        setlocal EnableDelayedExpansion
        for %%K in ("!ITEM:/=" "!") do (
            for %%L in (!IDX!) do (
                endlocal
                set "$ITEM[%%L]=%%~K"
                set /A "IDX+=1"
                setlocal EnableDelayedExpansion
            )
        )
        endlocal
        rem // Store each element of buffered common root path in array `$COMM[]`:
        set /A "CNT=IDX-1, IDX=0"
        setlocal EnableDelayedExpansion
        for %%K in ("!COMM:/=" "!") do (
            for %%L in (!IDX!) do (
                endlocal
                set "$COMM[%%L]=%%~K"
                set /A "IDX+=1"
                setlocal EnableDelayedExpansion
            )
        )
        rem // Determine the lower number of elements of `$ITEM[]` and `$COMM[]`:
        if !CNT! geq !IDX! set /A "CNT=IDX-1"
        rem // Loop through both arrays and write all common elements to buffer:
        set "COMM=" & set "FLAG=#"
        for /L %%L in (0,1,!CNT!) do (
            if /I "!$ITEM[%%L]!" == "!$COMM[%%L]!" (
                rem // The flag is just necessary to stop at the first difference:
                if defined FLAG set "COMM=!COMM!!$COMM[%%L]!/"
            ) else set "FLAG="
        )
        rem // Transport the built common root path buffer beyond `endlocal`:
        for /F "delims=" %%K in (""!COMM!"") do (
            endlocal & set "COMM=%%~K"
        )
    )
)
setlocal EnableDelayedExpansion
if defined COMM (
    rem // Check if there was only one path and just get get its parent in case:
    if not "!COMM:~-1!" == "/" (
        for %%K in ("!COMM:/=!") do (
            endlocal & set "COMM=%%~pK"
            setlocal EnableDelayedExpansion
            set "COMM=!COMM:=/!"
        )
    )
    rem // Return the finally retrieved common root path of all paths:
    echo(!COMM:~1,-1!
)
endlocal
endlocal
exit /B

我不知道这是否适用于您的 Jenkins 环境,但这是我在标准(例如 bash(shell 中会做的事情。我使用简洁的svn log

svn log ^/branches -l1 -q --incremental

添加一个管道来解析它,完整的命令将是:

svn log ^/branches -l1 -q --incremental | sed -n "s/.*| (.*) |.*/1/p"

将插入符号 ( ^ ( 替换为 http://server/svn/project/

EDIT:要获取分支名称,请使用-v增加svn log的详细程度以打印修改后的路径,并调整sed命令以提取分支名称。以下内容对我有用:

svn log ^/branches -l1 -q -v | sed -n '4 s|.*/branches/||p' 

或更具侵略性:

svn log ^/branches -l1 -q -v | sed -nr '4 s|.*/branches/([^/]+).*|1|p'

最新更新