Subversion Version Control. Using The Subversion Version Control System in Development Projects

6.3. Built-in Properties

Subversion provides a number of built-in properties that have special meaning to a Subversion repository or client. The built-in properties are split into two categories: the file properties and the revision properties. The file properties are assigned to specific files or directories and are generally only assigned explicitly by a userwith the exception of the svn:mime-type property, and the svn:executable property, which can be set automatically when a file is added. The revision properties, on the other hand, are all set automatically when a revision is committed to the repository, but can be changed later if the need arises. All of the built-in Subversion properties are named with a naming scheme that starts with svn:.

6.3.1. File Properties

Subversion provides several file properties that you can set for individual files or directories. Internally, these properties are handled the same as every other property, but each has added meaning and is used by Subversion clients to add functionality to the files.

svn:eol-style

Subversion uses the svn:eol-style property to determine how it should handle line-ending characters when a file is checked out or committed. By default, Subversion doesn't do any processing of line-endings and instead just leaves them in the same form as when they were committed. If your repository is being used by users on Windows and UNIX, though, line endings can become a problem. Because Windows uses both a carriage return (CR) and a line feed (LF) character to denote a line ending, whereas UNIX uses just the line feed, dealing with files on both platforms can be difficultespecially if the tools being used on the different platforms don't understand how to deal with files from another system. If you need to change this behavior, you can use the svn:eol-style property to tell the Subversion client how it should handle files.

The most common case is a user wanting files to include the line-ending character that is appropriate for his own system. In other words, Windows users will want text files that they check out to use CR/LF to end lines, whereas UNIX users will want just an LF. To ensure that this is exactly what each user sees, you can set svn:eol-style for a file to native. Then, when clients check out a file they will check to see if the svn:eol-style property is set, and if it is native they will transform all of the line-ending characters in the file to match the platform on which the client resides.

Transforming characters on checkout is not always desirable though. If the svn:eol-style property is set to a specific line-ending type, instead of the word native, the Subversion client will explicitly transform each line ending in all text files that are checked out to the supplied type. The supported line-ending types are CRLF, CR, and LF.

svn:executable

On UNIX-based systems, executable files are defined by the "executable" permission bit. It would be nice if files that were checked out of a repository retained information about whether that executable bit should be set. Not all platforms that Subversion runs on use the same format for storing permissions though, so it doesn't make sense for Subversion to directly store those permission bits when they are committed. To work around this limitation, Subversion uses the svn:executable property. Files that have the executable property set (to any value) will be automatically set to executable when checked out on any platform that supports the UNIX-style executable permissions. Files that are set to be executable will automatically have the svn:executable property set when they are added to a repository (via svn add or svn import). On filesystems that don't have an executable permission bit (e.g., Win32 with NTFS or FAT32), this property will have no effect.

svn:externals

The svn:externals property allows you to attach a property to a directory, which will tell the Subversion client to check out another part of the repository, or even another repository altogether, and place it in a subdirectory. This can be handy if you have multiple projects that have complex interdependencies, or even if you have a dependency on an external project that is also available from a Subversion repository.

As an example, let's say you have two repositories. One contains a code library, and the other contains a project that uses the library. When developers check out the project, they need to have access to the library in order to compile it. To further complicate things, the project expects the library to be located in a particular subdirectory relative to the base of the project.

One option, of course, would be to instruct each developer in the need to check out both repositories, as well as where the second repository needs to be checked out in relation to the first. At best, this is unwieldy. However, by using the svn:externals property, you can direct the Subversion client to perform the second checkout automatically.

In our example, all you would need to do to set svn:externals properly would be to add a line to the property (on the project's base directory) that contains the relative path to where the library should be checked out, followed by whitespace and then the repository URL that should be checked out. So, depending on the layout, it might look something like this:

$ svn propget svn:externals trunk libraries/mylib http://svn.example.com/library_repos/trunk/mylib

If you have multiple dependencies, you can declare them using multiple lines in the svn:externals property.

$ svn propget svn:externals trunk libraries/mylib http://svn.example.com/library_repos/trunk/mylib libraries/otherlib http://svn.example.net/repos/tags/otherlib_rel_1_0

You can also set up an externals link to grab a particular revision of a repository.

$ svn propget svn:externals trunk libraries/mylib -r 1256 http://svn.example.com/repos/trunk/mylib

svn:ignore

Working copies have a tendency to get cluttered with files that you need, but don't want to be committed to the repository, such as object files, compiled executables, editor swap files, and other temporary files. Unfortunately, these unversioned files tend to get in the way of Subversion. Because Subversion shows these files in svn status with a ?, they can quickly clutter up its output, making it hard to see files with legitimate output information (for example, I tend to use Subversion commands while the Vi editor is running, and it's not uncommon for me to have twenty to thirty files open in the same directorythat leaves twenty to thirty .swp files that swamp all other svn output). It can also be easy to accidentally add files that you didn't mean to, especially if you recursively add a directory.

The svn:ignore property lets you set unversioned files that will be ignored by all Subversion commands, except svn status when it is run with the --no-ignore, or svn add and svn import when they are explicitly directed to add the ignored file. Elements to be ignored are listed in the svn:ignore property, one per line. Ignored elements can either be an exact filename match or a pattern that contains wildcards (*).

The following example shows an svn:ignore property that is directing Subversion to ignore all files that end in .o, all files that start with a dot (.), and the file named debug.out.

$ svn propget svn:ignore trunk/src *.o .* debug.out

It should be noted that svn:ignore is not recursive. It applies only to the directory that you set it for. If you want to set ignores for an entire repository, you either have to use svn propset with the --recursive option or set up a user-level ignore (which is discussed in Section 7.2.1).

svn:keywords

It's all well and good to be able to use Subversion commands to find out information like the last time a file was modified, but sometimes it's useful to actually store that information in the file itselfespecially if you are planning on distributing that file to someone via a means other than the Subversion repository. In those cases, Subversion has the capability to perform inline replacements on certain keywords, whenever a file is checked out or updated.

By default, Subversion will not perform any keyword replacements. If you want to turn keyword replacement on, you need to do it by setting the svn:keywords property, which should contain a list of the keywords that you want Subversion to perform substitution on, separated by whitespace. So, if you want Subversion to substitute the keywords HeadURL and LastChangedRevision, your svn:keywords property would look like this:

$ svn propget svn:keywords foo.c LastChangedRevision HeadURL

The set of keywords that Subversion will replace is actually fairly small, and mostly revolve around the last time the file was changed. In fact, three of the five keywords are information about the last file change. Those keywords are LastChangedBy, LastChangedDate, and LastChangedRevision. If you would like to save yourself a few keystrokes, these keywords can be abbreviated with Author, Date, and Revision (or even Rev), respectively. The content of each substitution should be fairly self-explanatory.

Subversion also provides a keyword for embedding a URL to the file in the HEAD revision of the repository, called HeadURL. It can also be abbreviated as URL.

The fifth and final keyword is Id. The Id keyword is a summary keyword that includes data from several other keywords. Its content is made up of the name of the file, the last revision number of a commit for the file, a date showing when the file was last modified, and the username of the person who committed the last modification.

Keywords are placed into a file surrounded by dollar signs ($). When a substitution is performed, Subversion will add the value of the substitution after the keyword, separated by a colon. It is important that the keyword itself be left in the file; otherwise, Subversion wouldn't know that it was substituted text when you next commit the file, and wouldn't keep the keyword.

The following example shows an (admittedly contrived) file with keywords, followed by that file after it has been checked out and the keywords have been substituted.

original file: This file was last changed on $Date$, by $Author$, in revision $Rev$. It can be found at $HeadURL$ $Id$ substituted file: This file was last changed on $Date: 2004-08-12 01:56:13 -0500 (Thur, 12 Aug 2004) $ by $Author: bill $, in revision $Rev: 1276 $. It can be found at $HeadURL: http://svn.example.com/repos/trunk/keywords.txt $ $Id keywords.txt 1276 2004-08-12 01:56:13 bill $

svn:mime-type

The de facto cross-platform standard for identifying file types is the Multipurpose Internet Mail Exchange (MIME)-type, which consists of a general type and a specific type, separated by a slash. MIME-types are used by many programs (especially Internet-based ones, like Web browsers and e-mail clients) to determine how they should handle a file. Because the MIME-type is a useful piece of information to have, Subversion provides the svn:mime-type property as a standard place to store the MIME-type for a versioned file.

In addition to using svn:mime-type as a standard location, Subversion also uses a file's MIME-type for its own purposes. Primarily, Subversion uses the MIME-type to determine when a file is binary and should not be textually merged. It determines which files are binary by looking at the general type of a file's MIME-type. If the general type is anything other than text (i.e., the MIME-type doesn't begin with text/[2]), Subversion will assume that the file is binary. Additionally, Subversion will send the svn:mime-type through the Apache server whenever a client requests a file's type.

[2] Subversion also treats image/x-bitmap and image/x-pixmap as text.

The svn:mime-type property can be set manually, just like any other property, using svn propset or svn propedit. However, to make life a little easier on you, Subversion will also try to guess which files are binary when they are added to the repository. If it decides that a file appears to be binary, it will automatically set the svn:mime-type property equal to application/octet-stream. If you don't like what Subversion decides, you can always change it later.

If you are using a UNIX-like system, you can use the file program to determine the type of a file. If file is run with the -i option, it will output a file's MIME-type. You can combine this with svn propset to set a file's MIME-type in a single step, as in the following example (the -b tells file not to output the name of the file it processed).

$ svn propset svn:mime-type " ` file -i -b foo.txt ` " foo.txt $ svn propget svn:mime-type foo.txt text/plain; charset=us-ascii

svn:special

This property is new in version 1.1 of Subversion, and is used to identify special types of files. It is not meant to be edited directly by a user. Instead, the Subversion client uses it internally to recognize files that it should interpret in some special way, based on the file's contents. Currently, this is only used to implement symbolic links. When a symbolic link file is checked out on a system that supports symbolic links, the file will be read to determine how the symbolic link should be created. If the operating system does not support symbolic links (e.g. Windows), the file will not be interpreted, but rather will be checked out as a normal file.

6.3.2. Revision Properties

When new revisions are committed to a repository, Subversion automatically sets three revision properties. Each of these properties can be changed if necessary, but remember that revision properties are unversioned and a change results in the loss of the property's previous value. Also, modification of revision properties is disabled by default. To allow revision properties to be modified, you must have a hook script set up to process revision property changes. Hook scripts are discussed in Section 11.1, "An Introduction to Hooks."

svn:author

The svn:author property contains the username of the user who committed the revision. Changing this can be useful if the username listed on the commit was not the actual user who logically performed the commit (if, for instance, you borrowed a colleague's computer to make a quick change).

svn:date

Subversion stores the date and time that a revision was committed in the svn:date property. In general, this is the revision property that you are least likely to need to change. Usually, the need to change it will only come about because of an incorrect clock at the time of the commit.

If you do need to change the svn:date property, Subversion stores the dates in UTC (Coordinated Universal Time), using the ISO-8601 format, which looks similar to the following.

$ svn propget --revprop -r 1262 svn:date 2004-07-30T05:28:19.312099Z

The details of the ISO-8601 format are beyond the scope of this book, but if you simply need to slightly modify a time it should be relatively easy to figure out what you need to do. Remember, though, that UTC time is time-zone independent and not likely to be the same as your time zone (unless you live near Greenwich in England). If you modify svn:date, you will need to manually compensate for the time zone. For example, if you live in the Eastern time zone of the United States, you will need to add five hours to your local time in order to get UTC.

Now that I've given you a lecture on how you can change the svn:date property, let me stress that I strongly suggest you don't change it unless you absolutely have to. The change will not be undoable, and a messed up date can really throw things off in your repository.

svn:log

The automatically generated revision property that you are most likely to need to change is the svn:log property. Subversion stores the log entry for each revision in this property. If you make a commit and then realize that you forgot to put something into the log, or realize that something you put in was incorrect, you can modify this property. Do so with caution though, as a slip could erase valuable information. As a precaution, I suggest always editing log files using the svn propedit command, which will open the log entry in an editor for you to edit. If you use svn propset, it is much easier to accidentally wipe out information that you didn't want to lose. (Imagine your horror when you realize that you just overwrote the log for revision 21 instead of revision 12.)

    Категории