关键字替换

Subversion具备添加关键字的能力—一些有用的,关于版本化的文件动态信息的片断—不必直接添加到文件本身。关键字通常会用来描述文件最后一次修改的一些信息,因为这些信息每次都有改变,更重要的一点,这是在文件修改之后,除了版本控制系统,对于任何企图保持数据最新的过程都是一场混乱,作为人类作者,信息变得陈旧是不可避免的。

举个例子,你有一个文档希望显示最后修改的日期,你需要麻烦每个作者提交之前做这件事情,也要修改文档的一部分来描述何时作的修改,但是迟早会有人忘记做这件事,不选择简单的告诉Subversion来执行替换LastChangedDate关键字的操作,你通过在目标位置放置一个keyword anchor来控制关键字插入的位置,这个anchor只是一个格式为$KeywordName$字符串。

所有作为anchor出现在文件里的关键字是大小写敏感的:为了关键字的扩展,你必须使用正确的大写,你必须考虑svn:keywords的属性值也是大小写敏感—特定的关键字名会忽略大小写,但是这个特性已经被废弃了。

Subversion定义了用来替换的关键字列表,这个列表保存了如下五个关键字,有一些也包括了可用的别名:

Date

This keyword describes the last time the file was known to have been changed in the repository, and is of the form $Date: 2006-07-22 21:42:37 -0700 (Sat, 22 Jul 2006) $. It may also be specified as LastChangedDate. Unlike the Id keyword, which uses UTC, the Date keyword displays dates using the local time zone.

Revision

这个关键字描述了这个文件最后一次修改的修订版本,看起来像$Revision: 144 $,也可以通过LastChangedRevision或者Rev引用。

Author

这个关键字描述了最后一个修改这个文件的用户,看起来类似$Author: harry $,也可以用LastChangedBy来指定。

HeadURL

这个关键字描述了这个文件在版本库最新版本的完全URL,看起来类似$HeadURL: http://svn.collab.net/repos/trunk/README $,可以缩写为URL

Id

This keyword is a compressed combination of the other keywords. Its substitution looks something like $Id: calc.c 148 2006-07-28 21:30:43Z sally $, and is interpreted to mean that the file calc.c was last changed in revision 148 on the evening of July 28, 2006 by the user sally. The date displayed by this keyword is in UTC, unlike that of the Date keyword (which uses the local time zone).

Several of the previous descriptions use the phrase “last known” or similar wording. Keep in mind that keyword expansion is a client-side operation, and your client “knows” only about changes that have occurred in the repository when you update your working copy to include those changes. If you never update your working copy, your keywords will never expand to different values even if those versioned files are being changed regularly in the repository.

Simply adding keyword anchor text to your file does nothing special. Subversion will never attempt to perform textual substitutions on your file contents unless explicitly asked to do so. After all, you might be writing a document [13] about how to use keywords, and you don't want Subversion to substitute your beautiful examples of unsubstituted keyword anchors!

To tell Subversion whether to substitute keywords on a particular file, we again turn to the property-related subcommands. The svn:keywords property, when set on a versioned file, controls which keywords will be substituted on that file. The value is a space-delimited list of the keyword names or aliases found in the previous table.

举个例子,假定你有一个版本化的文件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'
$

Now you have made a local property modification on the weather.txt file. You will see no changes to the file's contents (unless you made some of your own prior to setting the property). Notice that the file contained a keyword anchor for the Rev keyword, yet we did not include that keyword in the property value we set. Subversion will happily ignore requests to substitute keywords that are not present in the file and will not substitute keywords that are not present in the svn:keywords property value.

Immediately after you commit this property change, Subversion will update your working file with the new substitute text. Instead of seeing your keyword anchor $LastChangedDate$, you'll see its substituted result. That result also contains the name of the keyword and continues to be bounded by the dollar sign ($) characters. And as we predicted, the Rev keyword was not substituted because we didn't ask for it to be.

Note also that we set the svn:keywords property to Date Author, yet the keyword anchor used the alias $LastChangedDate$ and still expanded correctly:

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.

If someone else now commits a change to weather.txt, your copy of that file will continue to display the same substituted keyword value as before—until you update your working copy. At that time, the keywords in your weather.txt file will be resubstituted with information that reflects the most recent known commit to that file.

Subversion 1.2 introduced a new variant of the keyword syntax, which brought additional, useful—though perhaps atypical—functionality. You can now tell Subversion to maintain a fixed length (in terms of the number of bytes consumed) for the substituted keyword. By using a double colon (::) after the keyword name, followed by a number of space characters, you define that fixed width. When Subversion goes to substitute your keyword for the keyword and its value, it will essentially replace only those space characters, leaving the overall width of the keyword field unchanged. If the substituted value is shorter than the defined field width, there will be extra padding characters (spaces) at the end of the substituted field; if it is too long, it is truncated with a special hash (#) character just before the final dollar sign terminator.

例如,你有一篇文档,其中一段是一些反映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

The result is not so beautiful. And you might be tempted to then adjust the file after the substitution so that it again looks tabular. But that holds only as long as the keyword values are the same width. If the last committed revision rolls into a new place value (say, from 99 to 100), or if another person with a longer username commits the file, stuff gets all crooked again. However, if you are using Subversion 1.2 or better, you can use the new fixed-length keyword syntax and define some field widths that seem sane so your file might look like this:

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

You commit this change to your file. This time, Subversion notices the new fixed-length keyword syntax and maintains the width of the fields as defined by the padding you placed between the double colon and the trailing dollar sign. After substitution, the width of the fields is completely unchanged—the short values for Rev and Author are padded with spaces, and the long Date field is truncated by a hash character:

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

固定长度关键字在执行复杂文件格式的替换中非常易用,也可以处理那些很难通过其他程序(例如Microsoft Office文档)进行修改的文件。

警告

Be aware that because the width of a keyword field is measured in bytes, the potential for corruption of multibyte values exists. For example, a username that contains some multibyte UTF-8 characters might suffer truncation in the middle of the string of bytes that make up one of those characters. The result will be a mere truncation when viewed at the byte level, but will likely appear as a string with an incorrect or garbled final character when viewed as UTF-8 text. It is conceivable that certain applications, when asked to load the file, would notice the broken UTF-8 text and deem the entire file corrupt, refusing to operate on the file altogether. So, when limiting keywords to a fixed size, choose a size that allows for this type of byte-wise expansion.



[13] … 或者可能是一本书的一个小节 …