Subversion和DeltaV

所以Subversion与其他DeltaV的兼容性如何?两个字:不好,至少在Subversion 1.0还不好。

当libsvn_ra_dav发送DeltaV到服务器,Subversion客户端不是一个普通目的的DeltaV客户端。实际上,它希望服务器一些自定义的特性(特别是通过自定义的REPORT请求)。更进一步,mod_dav_svn不是一个普通目的的DeltaV服务器,它只实现了DeltaV的一个严格子集,一个更加普通的WebDAV或DeltaV客户端可能与之很好的交互工作,但是只有在服务器非常窄的已经实现的特性范围之内。Subversion开发团队计划会设法在以后的版本中完成普通的WebDAV交互性。

影射Subversion到DeltaV

这里是多种Subversion客户端如何使用DeltaV操作的一个非常“高级别”描述。在很多种情况下,这些解释过于粗略,这能作为阅读Subversion源代码和与开发者交谈的替代。

svn checkout/list

对集合执行一个深度为1的PROPFIND来得到直接孩子的列表,对每个孩子执行一个GET(也可能是一个PROPFIND),递归到集合并且重复。

svn commit

使用MKACTIVITY创建一个活动,然后对每个修改项目执行一个CHECKOUT,紧跟一个对新数据的PUT。最终,一个MERGE请求导致一个隐含的对所有工作资源的CHECKIN

svn update/switch/status/merge/diff

发送一个自定义的描述工作拷贝混合修订版本(和混合URL)状态的REPORT请求,服务器发送一个描述需要更新的项目和文件内容增量数据的响应。解析响应,对于update和switch,在工作拷贝安装新数据,对于diff和merge,与工作拷贝的数据比较,应用修改作为本地修改。

自动版本化支持

在写作的时候,有一个事实就是这个世界只有很少的DeltaV客户端;RFC 3253一直是相对比较新。然而用户有一些“普通的”客户端,因为几乎所有的现代操作系统现在拥有集成的基本WebDAV客户端,因为这一点,Subversion开发者认识到如果Subversion 1.0可以支持DeltaV自动版本化这一交互特性会是最好的方法。

为了激活mod_dav_svn的自动版本化,使用httpd.conf Location区块的SVNAutoversioning指示,例如:

<Location /repos>
  DAV svn
  SVNPath /absolute/path/to/repository
  SVNAutoversioning on
</Location>

通常情况下,如果一个原始的WebDAV客户端尝试PUT到你的版本库位置的一个路径,mod_dav_svn会直接拒绝这个请求。(通常只允许对于DeltaV“活动”里面的对于“工作资源”的操作。)通过打开SVNAutoversioning,无论何时,服务器会把PUT请求转化为内部的MKACTIVITYCHECKOUTPUTCHECKIN。一个普通的日志信息是自动生成的,并且创建一个新的文件系统修订版本。

因为有这样多的操作系统已经集成了WebDAV能力,这个特性的用例近似于空想:想象一个普通用户运行Microsoft Windows或Mac OS的办公室,每个电脑“装配”了一个Subversion版本库,作为一个普通的网络共享。他们向普通目录一样操作服务器:从服务器打开文件,修改并且保存回服务器。但在这个幻想中,服务器自动版本化所有的事情,之后,一个系统管理员可以使用Subversion客户端来查找和检索所有旧的版本。

这个幻想是现实吗?完全不是,主要的障碍是Subversion 1.0不支持WebDAV的LOCK方法UNLOCK,大多数操作系统的DAV客户端尝试LOCK一个直接从DAV装配的网络共享的资源,到目前为止,用户必须要把文件从DAV共享拷贝到本地磁盘,编辑文件,然后再拷贝回去。没有理想的自动版本化,但还是可行的。

选择mod_dav_lock

Apache模块mod_dav是一个复杂的野兽:它理解和解析所有的WebDAV和DeltaV方法,然而它依赖于后端“提供者”来访问资源本身。

在最简单的化身里,一个用户可以使用mod_dav_fs可以作为mod_dav的提供者,mod_dav_fs使用普通的文件系统来存放文件和目录,只理解平凡的WebDAV方法,不是DeltaV。

在另一方面,Subversion使用mod_dav_svn作为mod_dav的提供者,mod_dav_svn理解除了LOCK以外的所有WebDAV方法,并且理解相当大的DeltaV方法子集,它访问Subversion版本库的数据,而不是真实的文件系统。Subversion 1.0不支持锁定,因为这会非常难于实现,因为Subversion使用拷贝-修改-合并模型。[48]

在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中加载,然后只需要在Location简单的添加如下的DAVGenericLockDB指示:

<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客户端),然后事情变得美好了。



[48] Subversion可能有一天会开发一个保留检出的锁定模型,可以与拷贝-修改-合并和平相处,但是可能不会立刻发生。