Subversion有一个模块化的设计,以库的形式由C编写和实现。每个库都有一个定义良好的目的和API,而且这些接口不仅仅为了Subversion本身使用,也可以为任何希望嵌入编程方式控制Subversion的软件。此外,Subversion的API不仅仅可以为C程序使用,也可以使用如Ptyhon、Perl、Java或Ruby等高级语言调用。
本章是为那些希望编写代码或其他语言绑定与Subversion交互的人准备的。如果你围绕Subversion功能编写健壮的脚本来简化你的生活,设法开发Subversion与其他软件的复杂集成,或者只是对Subversion不同库模块提供功能感兴趣,这一章是为你准备的。然而,如果你不能预见你会以此种程度参与Subversion,你可以放心的跳过本章,略过本章不会影响你对Subversion使用的体验。
Each of Subversion's core libraries can be said to exist in
one of three main layers—the Repository Layer, the
Repository Access (RA) Layer, or the Client Layer (see 图 1 “Subversion's architecture”). We will examine
these layers shortly, but first, let's briefly summarize
Subversion's various libraries. For the sake of consistency, we
will refer to the libraries by their extensionless Unix library
names (libsvn_fs
, libsvn_wc
,
mod_dav_svn
, etc.).
客户端程序的主要接口
目录树和文本区别程序
上下文区别和合并例程
Subversion文件系统库和模块加载器
The Berkeley DB filesystem backend
The native filesystem (FSFS) backend
版本库访问通用组件和模块装载器
WebDAV版本库访问模块
本地版本库访问模块
另一个(实验性的) WebDAV 版本库访问模块
一个自定义版本库访问模块
版本库接口
各色各样的有用的子程序
工作拷贝管理库
使用WebDAV访问Subversion版本库的Apache授权模块
影射WebDAV操作为Subversion操作的Apache模块
The fact that the word “miscellaneous” appears only once in the previous list is a good sign. The Subversion development team is serious about making sure that functionality lives in the right layer and libraries. Perhaps the greatest advantage of the modular design is its lack of complexity from a developer's point of view. As a developer, you can quickly formulate that kind of “big picture” that allows you to pinpoint the location of certain pieces of functionality with relative ease.
Another benefit of modularity is the ability to replace a
given module with a whole new library that implements the same
API without affecting the rest of the code base. In some sense,
this happens within Subversion already. The
libsvn_ra_neon
,
libsvn_ra_local
,
libsvn_ra_serf
, and
libsvn_ra_svn
libraries each implement the
same interface, all working as plug-ins to
libsvn_ra
. And all four communicate with
the Repository Layer—libsvn_ra_local connects to the
repository directly; the other three do so over a network. The
libsvn_fs_base
and
libsvn_fs_fs
libraries are another pair of
libraries that implement the same functionality in different
ways—both are plug-ins to the common
libsvn_fs
library.
The client itself also highlights the benefits of modularity
in the Subversion design. Subversion's
libsvn_client
library is a one-stop shop
for most of the functionality necessary for designing a working
Subversion client (see “客户端层”一节). So while the
Subversion distribution provides only the svn
command-line client program, there are several third-party
programs that provide various forms of graphical client UIs.
These GUIs use the same APIs that the stock command-line client
does. This type of modularity has played a large role in the
proliferation of available Subversion clients and IDE
integrations and, by extension, to the tremendous adoption rate
of Subversion itself.
When referring to Subversion's Repository Layer, we're
generally talking about two basic concepts—the versioned
filesystem implementation (accessed via
libsvn_fs
, and supported by its
libsvn_fs_base
and
libsvn_fs_fs
plug-ins), and the repository
logic that wraps it (as implemented in
libsvn_repos
). These libraries provide
the storage and reporting mechanisms for the various revisions
of your version-controlled data. This layer is connected to
the Client Layer via the Repository Access Layer, and is, from
the perspective of the Subversion user, the stuff at the
“other end of the line.”
The Subversion Filesystem is not a kernel-level filesystem that one would install in an operating system (such as the Linux ext2 or NTFS), but instead is a a virtual filesystem. Rather than storing “files” and “directories” as real files and directories (the kind you can navigate through using your favorite shell program), it uses one of two available abstract storage backends—either a Berkeley DB database environment or a flat-file representation. (To learn more about the two repository backends, see “选择数据存储格式”一节.) There has even been considerable interest by the development community in giving future releases of Subversion the ability to use other backend database systems, perhaps through a mechanism such as Open Database Connectivity (ODBC). In fact, Google did something similar to this before launching the Google Code Project Hosting service: they announced in mid-2006 that members of its open source team had written a new proprietary Subversion filesystem plug-in that used their ultra-scalable Bigtable database for its storage.
The filesystem API exported by
libsvn_fs
contains the kinds of
functionality you would expect from any other filesystem
API—you can create and remove files and directories,
copy and move them around, modify file contents, and so on.
It also has features that are not quite as common, such as the
ability to add, modify, and remove metadata
(“properties”) on each file or directory.
Furthermore, the Subversion Filesystem is a versioning
filesystem, which means that as you make changes to your
directory tree, Subversion remembers what your tree looked
like before those changes. And before the previous changes.
And the previous ones. And so on, all the way back through
versioning time to (and just beyond) the moment you first
started adding things to the filesystem.
所有你对目录树的修改包含在Subversion事务的上下文中,下面描述了修改文件系统的例程:
开始 Subversion 的提交事务。
作出修改(添加、删除、属性修改等等。)。
提交事务。
一旦你提交了你的事务,你的文件系统修改就会永久的作为历史保存起来,每个这样的周期会产生一个新的树,所有的修订版本都是永远可以访问的一个不变的快照。
Most of the functionality provided by the filesystem
interface deals with actions that occur on individual
filesystem paths. That is, from outside of the filesystem, the
primary mechanism for describing and accessing the individual
revisions of files and directories comes through the use of
path strings such as /foo/bar
, just as if
you were addressing files and directories through your
favorite shell program. You add new files and directories by
passing their paths-to-be to the right API functions. You
query for information about them by the same mechanism.
Unlike most filesystems, though, a path alone is not enough information to identify a file or directory in Subversion. Think of a directory tree as a two-dimensional system, where a node's siblings represent a sort of left-and-right motion, and navigating into the node's subdirectories represents a downward motion. 图 8.1 “二维的文件和目录” shows a typical representation of a tree as exactly that.
The difference here is that the Subversion filesystem has a
nifty third dimension that most filesystems do not
have—Time!
[50]
In the filesystem interface, nearly every function that has a
path
argument also expects a
root
argument. This
svn_fs_root_t
argument describes
either a revision or a Subversion transaction (which is simply
a revision in the making) and provides that third-dimensional
context needed to understand the difference between
/foo/bar
in revision 32, and the same
path as it exists in revision 98. 图 8.2 “版本时间—第三维!” shows revision
history as an added dimension to the Subversion filesystem
universe.
As we mentioned earlier, the
libsvn_fs
API looks and feels like any
other filesystem, except that it has this wonderful versioning
capability. It was designed to be usable by any program
interested in a versioning filesystem. Not coincidentally,
Subversion itself is interested in that functionality. But
while the filesystem API should be sufficient for basic file
and directory versioning support, Subversion wants
more—and that is where libsvn_repos
comes in.
The Subversion repository library
(libsvn_repos
) sits (logically speaking)
atop the libsvn_fs
API, providing
additional functionality beyond that of the underlying
versioned filesystem logic. It does not completely wrap each
and every filesystem function—only certain major steps
in the general cycle of filesystem activity are wrapped by the
repository interface. Some of these include the creation and
commit of Subversion transactions and the modification of
revision properties. These particular events are wrapped by
the repository layer because they have hooks associated with
them. A repository hook system is not strictly related to
implementing a versioning filesystem, so it lives in the
repository wrapper library.
The hooks mechanism is but one of the reasons for the
abstraction of a separate repository library from the rest of
the filesystem code. The libsvn_repos
API provides several other important utilities to Subversion.
These include the abilities to:
Create, open, destroy, and perform recovery steps on a Subversion repository and the filesystem included in that repository.
Describe the differences between two filesystem trees.
Query for the commit log messages associated with all (or some) of the revisions in which a set of files was modified in the filesystem.
Generate a human-readable “dump” of the filesystem—a complete representation of the revisions in the filesystem.
Parse that dump format, loading the dumped revisions into a different Subversion repository.
伴随着Subversion的发展,版本库库会随着文件系统提供更多的功能和配置选项而不断成长。
If the Subversion Repository Layer is at “the other
end of the line,” the Repository Access (RA) Layer is
the line itself. Charged with marshaling data between the
client libraries and the repository, this layer includes the
libsvn_ra
module loader library, the RA
modules themselves (which currently includes
libsvn_ra_neon
,
libsvn_ra_local
,
libsvn_ra_serf
, and
libsvn_ra_svn
), and any additional
libraries needed by one or more of those RA modules (such as
the mod_dav_svn
Apache module or
libsvn_ra_svn
's server,
svnserve).
因为Subversion使用URL来识别版本库资源,URL模式的协议部分(通常是file:
、http:
、https:
或svn:
)用来监测那个RA模块用来处理通讯。每个模块注册一组它们知道如何“说话”的协议,所以RA加载器可以在运行中监测在手边的任务中使用哪个模块。通过运行svn --version,你可以监测Subversion命令行客户端所支持的RA模块和它们声明支持的协议:
$ svn --version svn, version 1.5.0 (Beta 1) compiled Mar 19 2008, 14:19:42 Copyright (C) 2000-2008 CollabNet. Subversion is open source software, see http://subversion.tigris.org/ This product includes software developed by CollabNet (http://www.Collab.Net/). The following repository access (RA) modules are available: * ra_neon : Module for accessing a repository via WebDAV protocol using Neon. - handles 'http' scheme - handles 'https' scheme * ra_svn : Module for accessing a repository using the svn network protocol. - handles 'svn' scheme * ra_local : Module for accessing a repository on local disk. - handles 'file' scheme * ra_serf : Module for accessing a repository via WebDAV protocol using serf. - handles 'http' scheme - handles 'https' scheme $
The public API exported by the RA Layer contains
functionality necessary for sending and receiving versioned
data to and from the repository. And each of the available RA
plug-ins is able to perform that task using a specific
protocol—libsvn_ra_dav
speaks
HTTP/WebDAV (optionally using SSL encryption) with an Apache
HTTP Server that is running the
mod_dav_svn
Subversion server module;
libsvn_ra_svn
speaks a custom network
protocol with the svnserve program; and so
on.
For those who wish to access a Subversion repository using still another protocol, that is precisely why the Repository Access Layer is modularized! Developers can simply write a new library that implements the RA interface on one side and communicates with the repository on the other. Your new library can use existing network protocols or you can invent your own. You could use interprocess communication (IPC) calls, or—let's get crazy, shall we?—you could even implement an email-based protocol. Subversion supplies the APIs; you supply the creativity.
On the client side, the Subversion working copy is where all the action takes place. The bulk of functionality implemented by the client-side libraries exists for the sole purpose of managing working copies—directories full of files and other subdirectories that serve as a sort of local, editable “reflection” of one or more repository locations—and propagating changes to and from the Repository Access layer.
Subversion's working copy library,
libsvn_wc
, is directly responsible for
managing the data in the working copies. To accomplish this,
the library stores administrative information about each
working copy directory within a special subdirectory. This
subdirectory, named .svn
, is present in
each working copy directory and contains various other files
and directories that record state and provide a private
workspace for administrative action. For those familiar with
CVS, this .svn
subdirectory is similar in
purpose to the CVS
administrative
directories found in CVS working copies. For more information
about the .svn
administrative area, see
“进入工作拷贝的管理区”一节 later in this
chapter.
The Subversion client library,
libsvn_client
, has the broadest
responsibility; its job is to mingle the functionality of the
working copy library with that of the Repository Access Layer,
and then to provide the highest-level API to any application
that wishes to perform general revision control actions. For
example, the function
svn_client_checkout()
takes a URL as an
argument. It passes this URL to the RA layer and opens an
authenticated session with a particular repository. It then
asks the repository for a certain tree, and sends this tree
into the working copy library, which then writes a full
working copy to disk (.svn
directories
and all).
The client library is designed to be used by any
application. While the Subversion source code includes a
standard command-line client, it should be very easy to write
any number of GUI clients on top of the client library. New
GUIs (or any new client, really) for Subversion need not be
clunky wrappers around the included command-line
client—they have full access via the
libsvn_client
API to the same functionality,
data, and callback mechanisms that the command-line client
uses. In fact, the Subversion source code tree contains a
small C program (which can be found at
tools/examples/minimal_client.c
) that
exemplifies how to wield the Subversion API to create a simple
client program.