本文档仍在编写中,内容可能随时更改,并且可能无法准确描述任何已发布的 Apache™ Subversion® 软件版本。将此页面加入书签或以其他方式向他人推荐此页面可能不是明智之举。请访问 https://svnbook.subversion.org.cn/ 获取本书的稳定版本。

关键字替换

Subversion 能够将 关键字(版本化文件中一些有用、动态的信息片段)替换到文件内容本身中。关键字通常提供有关对文件进行的最后修改的信息。由于此信息会在每次文件更改时改变,更重要的是,只有在文件 更改后 才会改变,因此除了版本控制系统以外的任何进程都很难保持数据的完全最新。如果交给人工作者来维护,信息不可避免地会变得陈旧。

例如,假设您有一个文档,您希望在其中显示上次修改该文档的日期。您可以要求每个文档作者在提交更改之前,也调整描述上次更改时间的那部分文档。但迟早会有人忘记这样做。相反,只需要求 Subversion 对 LastChangedDate 关键字执行关键字替换。您可以通过在文件中的所需位置放置一个 关键字锚点来控制关键字插入的位置。此锚点只是一串格式为 $KeywordName$ 的文本。

仅将关键字锚点文本添加到您的文件中并不会产生任何特殊效果。除非明确要求,否则 Subversion 永远不会尝试对您的文件内容执行文本替换。毕竟,您可能正在编写一个关于如何使用关键字的文档[26],而您不希望 Subversion 替换您精心设计的未替换关键字锚点示例!

要告诉 Subversion 是否对特定文件执行关键字替换,我们再次使用与属性相关的子命令。当 svn:keywords 属性在版本化文件中设置时,它将控制在该文件上将替换哪些关键字。该值是关键字名称或别名的空格分隔列表。

例如,假设您有一个名为 weather.txt 的版本化文件,其内容如下

Here is the latest report from the front lines.
$LastChangedDate$
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.

如果没有在该文件中设置 svn:keywords 属性,Subversion 将不会执行任何特殊操作。现在,让我们启用对 LastChangedDate 关键字的替换。

$ svn propset svn:keywords "Date Author" weather.txt
property 'svn:keywords' set on 'weather.txt'
$

现在,您已经对 weather.txt 文件进行了本地属性修改。您将不会看到文件内容的任何更改(除非您在设置属性之前自己进行了一些更改)。请注意,该文件包含 Rev 关键字的关键字锚点,但我们在设置的属性值中没有包含该关键字。Subversion 将愉快地忽略对文件中不存在的关键字的替换请求,并且不会替换 svn:keywords 属性值中不存在的关键字。

在您提交此属性更改后,Subversion 将使用新的替换文本更新您的工作文件。您将不再看到关键字锚点 $LastChangedDate$,而是看到其替换结果。该结果还包含关键字的名称,并继续以美元符号 ($) 字符分隔。正如我们所预测的,Rev 关键字没有被替换,因为我们没有要求替换它。

另请注意,我们为 svn:keywords 属性设置了 Date Author,但关键字锚点使用了别名 $LastChangedDate$ 并且仍然正确扩展了

Here is the latest report from the front lines.
$LastChangedDate: 2006-07-22 21:42:37 -0700 (Sat, 22 Jul 2006) $
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.

如果现在其他人提交了对 weather.txt 的更改,您对该文件的副本将继续显示与之前相同的替换关键字值,直到您更新工作副本。此时,您 weather.txt 文件中的关键字将使用反映对该文件进行的最新已知提交的信息重新替换。

所有关键字在文件中的锚点位置都是区分大小写的:您必须使用正确的关键字大小写才能扩展。您应该将 svn:keywords 属性的值也视为区分大小写,为了向后兼容性,某些关键字名称将被识别,无论大小写如何,但此行为已过时。

Subversion 定义了可供替换的关键字列表。该列表包含以下关键字,其中一些关键字有别名,您也可以使用这些别名

Date

此关键字描述上次已知更改存储库中文件的日期,格式为 $Date: 2006-07-22 21:42:37 -0700 (Sat, 22 Jul 2006) $。它也可以指定为 LastChangedDate。与使用 UTC 的 Id 关键字不同,Date 关键字使用本地时区显示日期。

Revision

此关键字描述上次已知更改存储库中此文件的修订版本,格式类似于 $Revision: 144 $。它也可以指定为 LastChangedRevisionRev

Author

此关键字描述上次已知更改存储库中此文件的用户,格式类似于 $Author: harry $。它也可以指定为 LastChangedBy

HeadURL

此关键字描述存储库中文件最新版本的完整 URL,格式类似于 $HeadURL: http://svn.example.com/repos/trunk/calc.c $。它可以缩写为 URL

Id

此关键字是其他关键字的压缩组合。其替换格式类似于 $Id: calc.c 148 2006-07-28 21:30:43Z sally $,这意味着文件 calc.c 最后一次更改是在 2006 年 7 月 28 日晚上,由用户 sally 进行的,修订版本为 148。此关键字显示的日期为 UTC,与 Date 关键字(使用本地时区)不同。

Header

此关键字类似于 Id 关键字,但包含项目的最新修订版本的完整 URL,与 HeadURL 相同。其替换格式类似于 $Header: http://svn.example.com/repos/trunk/calc.c 148 2006-07-28 21:30:43Z sally $

前面的几个描述使用了 上次已知 或类似的措辞。请记住,关键字扩展是客户端操作,您的客户端 知道 的只是您更新工作副本以包含这些更改时,存储库中发生的更改。如果您从不更新工作副本,即使这些版本化文件在存储库中定期更改,您的关键字也永远不会扩展为不同的值。

除了之前的标准关键字定义和别名集之外,Subversion 1.8 允许您自由定义和使用自定义关键字。要定义自定义关键字,请将一个标记添加到 svn:keywords 属性的值中,该标记的格式为 MyKeyword=FORMAT,其中 MyKeyword 是关键字名称(您将在关键字锚点中使用它),而 FORMAT 是一个格式字符串,当您的关键字在您的文件中扩展时,将使用它来替换信息。

用于自定义关键字的格式字符串语法支持以下格式代码

%a

%r 指定的修订版本的作者。

%b

文件的 URL 的基本名称。

%d

%r 指定的修订版本的日期的简短格式。

%D

%r 指定的修订版本的日期的长格式。

%P

文件相对于存储库根目录的路径。

%r

上次已知更改存储库中此文件的修订版本。(这与将替换 Revision 关键字的修订版本相同。)

%R

存储库根目录的 URL。

%u

文件的 URL。

%_

空格字符。(关键字定义不能包含文字空格字符。)

%%

文字百分号('%')。

%H

等效于 %P%_%r%_%d%_%a

%I

等效于 %b%_%r%_%d%_%a

如您所见,许多单独的格式代码充当可用通过标准关键字获取的相同信息的占位符。但当然,自定义关键字格式允许您更灵活地将多个信息片段串联在一起。例如,您可能希望在您的文件中有一个单独的关键字,它以一种令人愉悦、易于阅读的方式报告文件的存储库相对路径和最后更改的修订版本。为此,您首先要定义您的自定义关键字

$ svn pset svn:keywords "PathRev=%P,%_r%r" calc/button.c
property 'svn:keywords' set on 'button.c'
$

接下来,您将编辑文件的内容以添加自定义关键字的关键字锚点,在本例中为 $PathRev$。提交这些更改后,检查文件内容将显示您的自定义关键字按预期进行了替换,之前文件包含 $PathRev$,现在变为 $PathRev: trunk/calc/button.c, r23 $

[Note] 注意

Subversion 会自动截断任何超过 255 字节长度的关键字扩展。此外,使用超过 255 字节的名称定义的自定义关键字将完全被忽略。

您也可以指示 Subversion 为替换的关键字维护一个固定长度(以字节数表示)。在关键字名称后使用双冒号(::),后面跟着若干个空格,即可定义该固定宽度。当 Subversion 替换关键字及其值时,它将只替换这些空格,从而保持关键字字段的总宽度不变。如果替换后的值比定义的字段宽度短,则替换后的字段末尾将有额外的填充字符(空格);如果它太长,则会在最后的美元符号终止符之前的某个特殊哈希 (#) 字符处截断。

例如,假设您有一个文档,其中包含反映文档 Subversion 关键字的表格数据部分。使用原始的 Subversion 关键字替换语法,您的文件可能看起来像这样

$Rev$:     Revision of last commit
$Author$:  Author of last commit
$Date$:    Date of last commit

现在,在开始时它看起来很漂亮,并且呈表格形式。但是,当您提交该文件(当然,启用了关键字替换)时,您会看到

$Rev: 12 $:     Revision of last commit
$Author: harry $:  Author of last commit
$Date: 2006-03-15 02:33:03 -0500 (Wed, 15 Mar 2006) $:    Date of last commit

结果并不那么美观。您可能会想在替换后调整文件,使其再次呈现表格形式。但是,这只有在关键字值宽度相同的情况下才有效。如果最后提交的版本进入新的位值(例如,从 99 到 100),或者如果另一个用户名更长的用户提交了该文件,东西就会再次变得歪斜。但是,如果您使用的是 Subversion 1.2 或更高版本,您可以使用新的固定长度关键字语法并定义一些看起来合理的字段宽度,因此您的文件可能看起来像这样

$Rev::               $:  Revision of last commit
$Author::            $:  Author of last commit
$Date::              $:  Date of last commit

您将此更改提交到您的文件。这一次,Subversion 会注意到新的固定长度关键字语法,并保持字段的宽度,如您在双冒号和尾随美元符号之间放置的填充所定义的那样。替换后,字段的宽度完全不变 - RevAuthor 的短值用空格填充,而长 Date 字段则被一个哈希字符截断

$Rev:: 13            $:  Revision of last commit
$Author:: harry      $:  Author of last commit
$Date:: 2006-03-15 0#$:  Date of last commit

当将替换应用于复杂的文件格式时,固定长度关键字的使用特别方便,这些文件格式本身使用固定长度字段来存储数据,或者对于这些格式,给定数据字段的存储大小难以从格式的本机应用程序外部修改。当然,在涉及二进制文件格式时,您必须始终小心确保您引入的任何关键字替换(固定长度或其他)都不会违反该格式的完整性。虽然听起来很简单,但这对于当今使用的大多数流行的二进制文件格式来说可能是非常困难的任务,并且 不要由胆小者来承担!

[Warning] 警告

请注意,由于关键字字段的宽度以字节为单位,因此存在损坏多字节值的可能性。例如,包含一些多字节 UTF-8 字符的用户名可能会在构成这些字符之一的字节字符串的中间被截断。结果将是在字节级别进行简单的截断,但在以 UTF-8 文本形式查看时,可能会显示为具有不正确或乱码的最终字符的字符串。可以想象,某些应用程序在被要求加载文件时,会注意到损坏的 UTF-8 文本,并认为整个文件已损坏,从而拒绝完全操作该文件。因此,在将关键字限制为固定大小时,请选择一个允许这种字节级扩展的大小。



[26] …或者可能是一本书的一部分…

TortoiseSVN 官方中文版 1.14.7 发布