本手册的写作是为了描述 Subversion 1.4。如果您正在运行更新版本的 Subversion,我们强烈建议您访问 https://svnbook.subversion.org.cn/ 并查阅适合您 Subversion 版本的书籍版本。
存在 --diff-cmd
和 --diff3-cmd
选项,以及类似命名的运行时配置参数(参见 名为“Config”的部分),可能导致人们错误地认为使用外部差异(或“diff”)和合并工具与 Subversion 很容易。虽然 Subversion 可以使用大多数流行的此类工具,但设置这些工具所需的努力通常并不 trivial。
Subversion 和外部 diff 和合并工具之间的接口可以追溯到 Subversion 唯一的上下文差异功能围绕 GNU diffutils 工具链的调用构建的时候,特别是 diff 和 diff3 实用程序。为了获得 Subversion 所需的行为,它调用这些实用程序,并使用超过几个选项和参数,其中大多数非常特定于这些实用程序。一段时间后,Subversion 开发了自己的内部差异库,并且作为故障转移机制,[51] --diff-cmd
和 --diff3-cmd
选项被添加到 Subversion 命令行客户端,以便用户更容易地表明他们更喜欢使用 GNU diff 和 diff3 实用程序,而不是新的内部 diff 库。如果使用这些选项,Subversion 将简单地忽略内部 diff 库,并回退到运行这些外部程序,包括冗长的参数列表。这就是目前的情况。
人们很快就意识到,拥有如此容易的配置机制来指定 Subversion 应该使用系统特定位置的外部 GNU diff 和 diff3 实用程序,也可以应用于其他 diff 和合并工具。毕竟,Subversion 实际上并没有验证它被告知要运行的东西是否是 GNU diffutils 工具链的成员。但是,使用这些外部工具的唯一可配置方面是它们在系统中的位置,而不是选项集、参数顺序等。Subversion 继续将所有这些 GNU 实用程序选项抛给您的外部 diff 工具,无论该程序是否能够理解这些选项。这就是对大多数用户来说不太直观的地方。
使用外部 diff 和合并工具(当然,除了 GNU diff 和 diff3 之外)与 Subversion 的关键是使用包装脚本,将来自 Subversion 的输入转换为您的差异工具可以理解的东西,然后将您的工具的输出转换回 Subversion 预期的方式,即 GNU 工具将使用的格式。以下部分涵盖了这些期望的细节。
关于何时在更大的 Subversion 操作中触发上下文 diff 或合并的决定完全由 Subversion 决定,并受多种因素的影响,包括文件是否可读,这由它们的 svn:mime-type
属性决定。这意味着,例如,即使您拥有宇宙中最棒的 Microsoft Word 识别差异或合并工具,只要您版本化的 Word 文档具有配置为不可读的 MIME 类型(例如 application/msword
),Subversion 永远不会调用它。有关 MIME 类型设置的更多信息,请参见 名为“File Content Type”的部分
Subversion 使用适合 GNU diff 实用程序的参数调用外部 diff 程序,并且只期望外部程序返回一个成功的错误代码。对于大多数替代 diff 程序,只有第六个和第七个参数,即代表 diff 左侧和右侧文件的路径,才是有意义的。请注意,Subversion 针对 Subversion 操作涵盖的每个修改过的文件运行 diff 程序一次,因此如果您的程序以异步方式(或“后台”)运行,那么您可能会有几个实例同时运行。最后,Subversion 期望您的程序在检测到差异时返回错误代码 1,如果没有检测到差异则返回错误代码 0,任何其他错误代码都将被视为致命错误。[52]
示例 7.2,“diffwrap.sh” 和 示例 7.3,“diffwrap.bat” 分别是 Bourne shell 和 Windows 批处理脚本语言中外部 diff 工具包装器的模板。
示例 7.2。diffwrap.sh
#!/bin/sh # Configure your favorite diff program here. DIFF="/usr/local/bin/my-diff-tool" # Subversion provides the paths we need as the sixth and seventh # parameters. LEFT=${6} RIGHT=${7} # Call the diff command (change the following line to make sense for # your merge program). $DIFF --left $LEFT --right $RIGHT # Return an errorcode of 0 if no differences were detected, 1 if some were. # Any other errorcode will be treated as fatal.
示例 7.3。diffwrap.bat
@ECHO OFF REM Configure your favorite diff program here. SET DIFF="C:\Program Files\Funky Stuff\My Diff Tool.exe" REM Subversion provides the paths we need as the sixth and seventh REM parameters. SET LEFT=%6 SET RIGHT=%7 REM Call the diff command (change the following line to make sense for REM your merge program). %DIFF% --left %LEFT% --right %RIGHT% REM Return an errorcode of 0 if no differences were detected, 1 if some were. REM Any other errorcode will be treated as fatal.
Subversion 使用适合 GNU diff3 实用程序的参数调用外部合并程序,期望外部程序返回一个成功的错误代码,并且完成的合并操作所产生的完整文件内容打印在标准输出流上(以便 Subversion 可以将它们重定向到适当的版本控制文件)。对于大多数替代合并程序,只有第九、第十和第十一个参数,代表“我的”、“旧的”和“你的”输入文件的路径,才是有意义的。请注意,由于 Subversion 依赖于您的合并程序的输出,因此您的包装脚本必须在将输出传递给 Subversion 之前不退出。当它最终退出时,它应该在合并成功时返回错误代码 0,如果输出中存在未解决的冲突则返回错误代码 1,任何其他错误代码都将被视为致命错误。
示例 7.4,“diff3wrap.sh” 和 示例 7.5,“diff3wrap.bat” 分别是 Bourne shell 和 Windows 批处理脚本语言中外部合并工具包装器的模板。
示例 7.4。diff3wrap.sh
#!/bin/sh # Configure your favorite diff3/merge program here. DIFF3="/usr/local/bin/my-merge-tool" # Subversion provides the paths we need as the ninth, tenth, and eleventh # parameters. MINE=${9} OLDER=${10} YOURS=${11} # Call the merge command (change the following line to make sense for # your merge program). $DIFF3 --older $OLDER --mine $MINE --yours $YOURS # After performing the merge, this script needs to print the contents # of the merged file to stdout. Do that in whatever way you see fit. # Return an errorcode of 0 on successful merge, 1 if unresolved conflicts # remain in the result. Any other errorcode will be treated as fatal.
示例 7.5。diff3wrap.bat
@ECHO OFF REM Configure your favorite diff3/merge program here. SET DIFF3="C:\Program Files\Funky Stuff\My Merge Tool.exe" REM Subversion provides the paths we need as the ninth, tenth, and eleventh REM parameters. But we only have access to nine parameters at a time, so we REM shift our nine-parameter window twice to let us get to what we need. SHIFT SHIFT SET MINE=%7 SET OLDER=%8 SET YOURS=%9 REM Call the merge command (change the following line to make sense for REM your merge program). %DIFF3% --older %OLDER% --mine %MINE% --yours %YOURS% REM After performing the merge, this script needs to print the contents REM of the merged file to stdout. Do that in whatever way you see fit. REM Return an errorcode of 0 on successful merge, 1 if unresolved conflicts REM remain in the result. Any other errorcode will be treated as fatal.