Earlier, in “版本库开发策略”一节, we looked at some of the important decisions that should be made before creating and configuring your Subversion repository. Now, we finally get to get our hands dirty! In this section, we'll see how to actually create a Subversion repository and configure it to perform custom actions when special repository events occur.
Subversion repository creation is an incredibly simple task. The svnadmin utility that comes with Subversion provides a subcommand (svnadmin create) for doing just that.
$ # Create a repository $ svnadmin create /var/svn/repos $
This creates a new repository in the directory
/var/svn/repos, and with the default
filesystem data store. Prior to Subversion 1.2, the default
was to use Berkeley DB; the default is now FSFS. You can
explicitly choose the filesystem type using the
--fs-type argument, which accepts as a
$ # Create an FSFS-backed repository $ svnadmin create --fs-type fsfs /var/svn/repos $
# Create a Berkeley-DB-backed repository $ svnadmin create --fs-type bdb /var/svn/repos $
While some parts of a Subversion repository—such as the configuration files and hook scripts—are meant to be examined and modified manually, you shouldn't (and shouldn't need to) tamper with the other parts of the repository “by hand.” The svnadmin tool should be sufficient for any changes necessary to your repository, or you can look to third-party tools (such as Berkeley DB's tool suite) for tweaking relevant subsections of the repository. Do not attempt manual manipulation of your version control history by poking and prodding around in your repository's data store files!
A hook is a program triggered by some repository event, such as the creation of a new revision or the modification of an unversioned property. Some hooks (the so-called “pre hooks”) run in advance of a repository operation and provide a means by which to both report what is about to happen and to prevent it from happening at all. Other hooks (the “post hooks”) run after the completion of a repository event and are useful for performing tasks that examine—but don't modify—the repository. Each hook is handed enough information to tell what that event is (or was), the specific repository changes proposed (or completed), and the username of the person who triggered the event.
hooks subdirectory is, by
default, filled with templates for various repository
$ ls repos/hooks/ post-commit.tmpl post-unlock.tmpl pre-revprop-change.tmpl post-lock.tmpl pre-commit.tmpl pre-unlock.tmpl post-revprop-change.tmpl pre-lock.tmpl start-commit.tmpl $
There is one template for each hook that the Subversion
repository supports; by examining the contents of those
template scripts, you can see what triggers each script
to run and what data is passed to that script. Also present
in many of these templates are examples of how one might use
that script, in conjunction with other Subversion-supplied
programs, to perform common useful tasks. To actually install
a working hook, you need only place some executable program or
script into the
which can be executed as the name (such as
post-commit) of the hook.
On Unix platforms, this means supplying a script or
program (which could be a shell script, a Python program, a
compiled C binary, or any number of other things) named
exactly like the name of the hook. Of course, the template
files are present for more than just informational
purposes—the easiest way to install a hook on Unix
platforms is to simply copy the appropriate template file to a
new file that lacks the
customize the hook's contents, and ensure that the script is
executable. Windows, however, uses file extensions to
determine whether a program is executable, so you would
need to supply a program whose basename is the name of the
hook and whose extension is one of the special extensions
recognized by Windows for executable programs, such as
.exe for programs and
.bat for batch files.
Subversion executes hooks as the same user who owns the process that is accessing the Subversion repository. In most cases, the repository is being accessed via a Subversion server, so this user is the same user as whom the server runs on the system. The hooks themselves will need to be configured with OS-level permissions that allow that user to execute them. Also, this means that any programs or files (including the Subversion repository) accessed directly or indirectly by the hook will be accessed as the same user. In other words, be alert to potential permission-related problems that could prevent the hook from performing the tasks it is designed to perform.
There are nine hooks implemented by the Subversion repository, and you can get details about each of them in “版本库钩子”一节. As a repository administrator, you'll need to decide which hooks you wish to implement (by way of providing an appropriately named and permissioned hook program), and how. When you make this decision, keep in mind the big picture of how your repository is deployed. For example, if you are using server configuration to determine which users are permitted to commit changes to your repository, then you don't need to do this sort of access control via the hook system.
There is no shortage of Subversion hook programs and scripts freely available either from the Subversion community itself or elsewhere. These scripts cover a wide range of utility—basic access control, policy adherence checking, issue tracker integration, email- or syndication-based commit notification, and beyond. Or, if you wish to write your own, see 第 8 章 嵌入Subversion.
While hook scripts can do almost
anything, there is one dimension in which hook script
authors should show restraint: do not
modify a commit transaction using hook scripts. While it
might be tempting to use hook scripts to automatically
correct errors, shortcomings, or policy violations present
in the files being committed, doing so can cause problems.
Subversion keeps client-side caches of certain bits of
repository data, and if you change a commit transaction in
this way, those caches become indetectably stale. This
inconsistency can lead to surprising and unexpected
behavior. Instead of modifying the transaction, you should
simply validate the transaction in the
pre-commit hook and reject the commit
if it does not meet the desired requirements. As a
bonus, your users will learn the value of careful,
compliance-minded work habits.
A Berkeley DB environment is an encapsulation of one or more databases, logfiles, region files and configuration files. The Berkeley DB environment has its own set of default configuration values for things such as the number of database locks allowed to be taken out at any given time, the maximum size of the journaling logfiles, etc. Subversion's filesystem logic additionally chooses default values for some of the Berkeley DB configuration options. However, sometimes your particular repository, with its unique collection of data and access patterns, might require a different set of configuration option values.
The producers of Berkeley DB understand that different
applications and database environments have different
requirements, so they have provided a mechanism for overriding
at runtime many of the configuration values for the Berkeley
DB environment. BDB checks for the presence of a file named
DB_CONFIG in the environment directory
(namely, the repository's
subdirectory), and parses the options found in that file.
Subversion itself creates this file when it creates the rest
of the repository. The file initially contains some default
options, as well as pointers to the Berkeley DB online
documentation so you can read about what those options do. Of
course, you are free to add any of the supported Berkeley DB
options to your
DB_CONFIG file. Just be
aware that while Subversion never attempts to read or
interpret the contents of the file and makes no direct use of
the option settings in it, you'll want to avoid any
configuration changes that may cause Berkeley DB to behave in
a fashion that is at odds with what Subversion might expect.
Also, changes made to
take effect until you recover the database environment (using