Subversion has the ability to substitute keywords—pieces of useful, dynamic information about a versioned file—into the contents of the file itself. Keywords generally provide information about the last modification made to the file. Because this information changes each time the file changes, and more importantly, just after the file changes, it is a hassle for any process except the version control system to keep the data completely up to date. Left to human authors, the information would inevitably grow stale.
For example, say you have a document in which you would like to display the
last date on which it was modified. You could burden every author of that
document to, just before committing their changes, also tweak the part of
the document that describes when it was last changed. But sooner or later,
someone would forget to do that. Instead, simply ask Subversion to perform
keyword substitution on the LastChangedDate
keyword. You
control where the keyword is inserted into your document by placing a
keyword anchor at the desired location in the file.
This anchor is just a string of text formatted as
$
KeywordName
$
.
All keywords are case-sensitive where they appear as anchors in files: you
must use the correct capitalization for the keyword to be expanded. You
should consider the value of the svn:keywords
property to
be case-sensitive, too—certain keyword names will be recognized
regardless of case, but this behavior is deprecated.
Subversion defines the list of keywords available for substitution. That list contains the following keywords, some of which have aliases that you can also use:
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
This keyword describes the last known revision in which this file changed in
the repository, and looks something like $Revision: 144
$
. It may also be specified as
LastChangedRevision
or Rev
.
Author
This keyword describes the last known user to change this file in the
repository, and looks something like $Author: harry $
.
It may also be specified as LastChangedBy
.
HeadURL
This keyword describes the full URL to the latest version of the file in the
repository, and looks something like $HeadURL:
http://svn.example.com/repos/trunk/calc.c $
. It may be
abbreviated as 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).
Header
This keyword is similar to the Id
keyword but contains
the full URL of the latest revision of the item, identical to
HeadURL
. Its substitution looks something like
$Header: http://svn.example.com/repos/trunk/calc.c 148 2006-07-28
21:30:43Z sally $
.
Several of the preceding 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[17] 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 keyword names or aliases.
举个例子,假定你有一个版本化的文件weather.txt
,内容如下:
Here is the latest report from the front lines. $LastChangedDate$ $Rev$ Cumulus clouds are appearing more frequently as summer approaches.
With no svn:keywords
property set on that file,
Subversion will do nothing special. Now, let's enable substitution of the
LastChangedDate
keyword.
$ 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 delimited 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.
You can also instruct 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.
For example, say you have a document in which you have some section of tabular data reflecting the document's Subversion keywords. Using the original Subversion keyword substitution syntax, your file might look something like:
$Rev$: Revision of last commit $Author$: Author of last commit $Date$: Date of last commit
Now, that looks nice and tabular at the start of things. But when you then commit that file (with keyword substitution enabled, of course), you see:
$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 later, 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
The use of fixed-length keywords is especially handy when performing substitutions into complex file formats that themselves use fixed-length fields for data, or for which the stored size of a given data field is overbearingly difficult to modify from outside the format's native application. Of course, where binary file formats are concerned, you must always take great care that any keyword substitution you introduce—fixed-length or otherwise—does not violate the integrity of that format. While it might sound easy enough, this can be an astonishingly difficult task for most of the popular binary file formats in use today, and not something to be undertaken by the faint of heart!
警告 | |
---|---|
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. |