本手册旨在描述 Subversion 1.1。如果您正在运行更新版本的 Subversion,我们强烈建议您访问 https://svnbooks.subversion.org.cn/ 并查阅适合您 Subversion 版本的书籍版本。
那么 Subversion 与其他 DeltaV 软件的“兼容性”如何呢?简单来说:不太好。至少在 Subversion 1.0 中还没有。
虽然 libsvn_ra_dav 向服务器发送 DeltaV 请求,但 Subversion 客户端不是一个通用的 DeltaV 客户端。事实上,它期望服务器提供一些自定义功能(尤其是在自定义的REPORT请求中)。此外,mod_dav_svn 不是一个通用的 DeltaV 服务器。它只实现了 DeltaV 规范的一个严格子集。更通用的 WebDAV 或 DeltaV 客户端可能能够与它进行交互,但前提是该客户端在服务器已实现的功能的狭窄范围内运行。Subversion 开发团队计划在 Subversion 的未来版本中解决通用 WebDAV 的互操作性问题。
以下是对各种 Subversion 客户端操作如何使用 DeltaV 的非常“高层次”的描述。在许多情况下,这些解释都是极大的简化。它们不应被视为阅读 Subversion 源代码或与开发人员交流的替代品。
执行PROPFIND深度为 1 的集合以获取直接子项的列表。执行GET(可能还会执行PROPFIND)在每个子项上。递归进入集合并重复。
使用MKACTIVITY创建活动,并对每个已更改的项目执行CHECKOUT,然后执行PUT以更新新数据。最后,一个MERGE请求会导致所有工作资源的隐式CHECKIN。
发送一个自定义的REPORT请求,描述工作副本的混合修订版(和混合 URL)状态。服务器发送一个自定义响应,描述哪些项目需要更新并包含文件内容的二进制增量。解析响应。对于更新和切换,在工作副本中安装新数据。对于 diff 和 merge 命令,将数据与工作副本进行比较,可能将更改应用为本地修改。
在撰写本文时,事实是世界上只有很少的 DeltaV 客户端;RFC 3253 仍然比较新。但是,用户确实可以访问“通用”客户端,因为几乎所有现代操作系统现在都集成了基本的 WebDAV 客户端。考虑到这一点,Subversion 开发人员意识到,如果 Subversion 1.0 要具备任何互操作性功能,那么支持 DeltaV 自动版本控制将是最佳方法。
要在 mod_dav_svn 中激活自动版本控制,请使用SVNAutoversioning指令,位于httpd.conf Location块中,如下所示
<Location /repos> DAV svn SVNPath /absolute/path/to/repository SVNAutoversioning on </Location>
通常,如果通用 WebDAV 客户端尝试对存储库位置内的路径执行PUT操作,mod_dav_svn 会直接拒绝该请求。(它通常只允许对 DeltaV“活动”内的“工作资源”执行此类操作。)但是,当SVNAutoversioning启用时,服务器将解释PUT请求为内部的MKACTIVITY, CHECKOUT, PUT操作,并CHECKIN。会自动生成一个通用的日志消息,并创建一个新的文件系统修订版。
由于许多操作系统已经集成了 WebDAV 功能,因此此功能的使用案例几乎是天方夜谭:想象一下一个办公室,里面有一般的用户使用 Microsoft Windows 或 Mac OS 运行电脑。每台电脑“挂载”Subversion 存储库,该存储库看起来像一个普通的网络共享。他们像往常一样使用服务器:从服务器打开文件、编辑文件并将文件保存回服务器。但在这种幻想中,服务器会自动对所有内容进行版本控制。之后,系统管理员可以使用 Subversion 客户端搜索和检索所有旧版本。
这种幻想是真实的嗎?不完全是。主要障碍是 Subversion 1.0 根本不支持 WebDAV 的LOCK或UNLOCK方法。大多数操作系统 DAV 客户端都会尝试LOCK直接从 DAV 挂载的网络共享中打开的资源。目前,用户可能需要将文件从 DAV 共享复制到本地磁盘,编辑文件,然后将其复制回 DAV 共享。这并不是理想的自动版本控制,但仍然可行。
mod_dav Apache 模块是一个复杂的模块:它理解和解析所有 WebDAV 和 DeltaV 方法,但它依赖于一个后端“提供者”来访问资源本身。
最简单的形式是,用户可以使用 mod_dav_fs 作为 mod_dav 的提供者。mod_dav_fs 使用普通的文件系统来存储文件和目录,并且只理解基本的 WebDAV 方法,而不是 DeltaV 方法。
另一方面,Subversion 使用 mod_dav_svn 作为 mod_dav 的提供者。mod_dav_svn 理解所有 WebDAV 方法,除了LOCK方法,并且理解 DeltaV 方法的一个相当大的子集。它访问 Subversion 存储库中的数据,而不是实际文件系统中的数据。Subversion 1.0 不支持锁定,因为实际上这将很难实现,因为 Subversion 使用的是复制-修改-合并模型。[47]
在 Apache httpd-2.0 中,mod_dav 通过在私有数据库中跟踪锁来支持LOCK方法,假设提供者愿意接受它们。然而,在 Apache httpd-2.1 或更高版本中,这种锁定支持已拆分为一个独立的模块,即 mod_dav_lock。它允许任何 mod_dav 提供者利用锁定数据库,包括 mod_dav_svn,即使 mod_dav_svn 实际上并不理解锁定。
困惑了吗?
简而言之,您可以在 Apache httpd-2.1(或更高版本)中使用 mod_dav_lock 来创建错觉,即 mod_dav_svn 正在响应LOCK请求。确保 mod_dav_lock 已编译到 httpd 中或正在您的httpd.conf中加载。然后简单地将DAVGenericLockDB指令添加到您的Location中,如下所示
<Location /repos> DAV svn SVNPath /absolute/path/to/repository SVNAutoversioning on DavGenericLockDB /path/to/store/locks </Location>
这种技术是一项冒险的业务;在某种意义上,mod_dav_svn 现在正在对 WebDAV 客户端撒谎。它声称接受LOCK请求,但实际上锁定根本没有在所有级别上执行。如果第二个 WebDAV 客户端尝试LOCK同一个资源,那么 mod_dav_lock 会注意到并正确拒绝该请求。但是,没有任何东西可以阻止普通的 Subversion 客户端通过正常的 svn commit 来更改文件!如果您使用这种技术,您就在给用户提供践踏彼此更改的机会。特别是,WebDAV 客户端可能会意外地覆盖由常规 Subversion 客户端提交的更改。
另一方面,如果您非常仔细地设置好环境,您就可以减轻风险。例如,如果您的所有用户都通过基本的 WebDAV 客户端(而不是 Subversion 客户端)工作,那么一切都应该没问题。