URL布局
Subversion服务器通过自定义的URL公开仓库。例如,foo仓库可能位于http://www.example.com/repos/foo/。但是,服务器还需要一组其他公开资源来保证正常操作。这些附加资源会与主仓库URL下的某位置下的所有仓库关联。默认,此位置为$svn,也可以通过SVNSpecialURI指令来设置: <Location /repos/foo>
DAV svn
SVNPath /home/svn-projects/foo
SVNSpecialURI .special
</Location>
在SVNSpecialURI指定的位置下,我们需要公开一些集合(collections)。假设我们使用默认的$svn,这些集合为: $svn/act/ 此区域是活动创建的位置。客户端需要选择在此集合内唯一的名字,然后向该URL发送一个MKACTIVITY。然后,客户端就可以使用该活动做进一步交互。 $svn/act/内的资源不能使用方法. 提示: 实际上我们可以使用带Depth:1头的PROPFIND来允许客户端遍历当前所有活动。
只有一个方法子集可以操作该集合下的活动。它们是:PROPFIND, MERGE (提交活动), and DELETE (终止活动). 根据Delta-V规范,所有的活动资源在DAV:activity下都有DAV:resourcetype属性。 $svn/his/ 本节需要改进;事实上,我们没有使用版本历史资源,将来,它们可能被设计成类似下面的模型: 此集合包含一个项目下的文件和目录的版本历史资源。其内部布局完全由服务器定义。客户端将通过多个响应获取此集合及其子集合的URL。 $svn/his/内的资源不能使用方法。 URL的命名空间被设计成如下的URL形式: $svn/his/node-id
node-id是Subversion用来引用单独文件和目录的内部值,是由Subversion仓库定义的单个整数值。注意此node-id是非点状节点ID(undotted node id ?),仓库中给定节点的全部历史的基础。 node-id的DAV:resourcetype的集合是DAV:version-history. 提示: 上文信息可能不太准确。链接一个版本历史到其他版本历史的问题仍然存。进一步,我认为node 73 和 node 73.4.1是各自的版本历史(后者链接到了前者)。73.x 和73.4.1.x 是版本历史内的版本。
$svn/ver/ 这个集合包含项目的版本资源。 $svn/ver/内的资源不能使用方法。 这个集合的布局由服务器定义。为了引用(以及描述实现)的需要,它被设计为: $svn/ver/node-id/path
只有只读的方法才能用在这些资源上,如 GET, PROPFIND, REPORT;其他方法都是不合法的。 版本资源的DAV:resourcetype是检入时资源的值。(如 <D:resourcetype/> 或 <D:resourcetype><D:collection/></D:resourcetype>). $svn/wrk/ 此集合包含所有通过CHECKOUT方法被检出的资源的当前工作资源。集合的形式和结构也由服务器定义,也是明确定义的,这样客户端才可以与被检出的集合资源进行适当交互。 $svn/wrk/内的资源不能使用方法。 为了引用目的,当前工作资源的URL被设计成: $svn/wrk/activity/path
所有方法都能用在当前工作资源上,但是不能用在其父资源上。 当前工作资源的DAV:resourcetype遵循一般资源命名方式:<D:resourcetype/>代表经常性的当前工作资源,<D:resourcetype><D:collection/></D:resourcetype>代表当前工作集。 $svn/vcc/ 本节还不完整。 版本控制的配置(version-controlled configuration)... $svn/vcc/root是个单例(singleton) $svn/bln/ 本节还不完整。 基线(baselines)... $svn/bln/rev/ $svn/wbl/ 本节还不完整。 当前工作基线(working baseline)... $svn/bc/ 本节还不完整。. 基线集合(baseline collection)...
属性管理(以及历史/日志报告)
本节需要修订。属性发生在FS修订版中(通过基线公开)。 之前也提到过,Subversion的属性会映射到WebDAV的属性。对历史/日志报告,下面的WebDAV属性适用于每个基线(Subversion修订版)和每一个修订版创建的版本资源。由于这些资源都是版本资源,因此下面的属性都是只读的。 DAV:comment 用于指定检入评论的标准的(过期的)属性 DAV:creator-displayname Subversion的“用户”一次特定修改后生成的(已过期的)属性 DAV:creationdate 提交时服务器生成的只读(未过期的)属性
一个特定文件的历史将会通过REPORT方法和DAV:property-report报告生成。一个典型的历史将会获取每个文件或目录版本的以上三个属性。
基于客户端的设计,指定关于版本信息的其他只读属性可能很重要。例如,一个文件检入时,有多少行增加/删除?生成这些属性将会相当直接,并会随着时间由客户端的设计推动。 提示: 如果我们这样做,我们将会把客户端捆绑于服务器。如果客户端与其他不报告这些属性的Delta服务器交互,我们简单地在UI中不显示它们就可以了(如优雅的功能退化,graceful degradation of functionality)。
获取状态和更新 初始检出后,客户端就可以请求状态报告(客户端的变更,会挂起提交,服务器的变更,会挂起更新)。更新过程是类似的,但还会获取服务器上的变更。
本地的变更将全部由客户端处理。当前工作拷贝(the Working Copy)库会很容易地检测和报告这些变更。我们只需要关心,如何高效地检测服务器上的变更。
虽然可以遍历仓库,获取当前状态,然后与客户端状态进行比较,但是这样做不是高效的。Subvesion的设计允许服务器在获知客户端状态的情况下,轻松地计算出变更(相对于客户端)。
status和update命令的核心是基于自定义的、Subversion特定的WebDAV报告。这份自定义的报告将会通知服务器当前工作拷贝的状态,服务器的响应将会指定哪些资源需要被更新。
这种请求是个包含自定义XML结构的标准REPORT请求。这个结构体,将利用Subversion报告顶层修订版号的方法,只报告修订版不同的子节点。报告的响应也会使用相同的方式报告有变更的资源。如果有变更,服务器将会提供一个供获取已变更资源的URL。服务器也会报告当前修订版号。 请求和响应的XML DTD都是TBD。
自定义报告将只适用于支持此报告的服务器,但是将来的软件版本可能包含一个回退的代码路径(优雅的退化)来支持其他DeltaV服务器。
更新时,客户端将会获取(使用GET请求)每个服务器响应提供的URL。
可能的话,GET(和PUT)操作将会使用diff格式传递内容。该机制遵循名为HTTP的Delta编码的因特网草案。
实体标签 (etags) etag需要在一个资源的所有版本中保持唯一。幸好,对版本管理系统来说,这很容易。每个etag可以简单地为资源所在的仓库节点ID(node-id)
etag通常用于生成diff(差异),可以参考上文提及的草案 HTTP中的Delta编码。现在问题是如果获取存储在客户端的每个文件(不需要文件夹的etag,因为我们从不读取)的etag。在检出或更新过程中,很简单:etag包含在所获取的每个文件的HTTP响应头里。
问题的另一个方面是如何获取一次提交后的etag。版本资源是在活动检入时创建的,而MERGE响应头提供了一种获取版本资源属性的方法,etag以及其他属性可以通过此机制获取。
标签和分支 在Subversion中标签和分支被复制从一个区域到另一个区域被执行。例如: [.../src/my-project]$ svn cp trunk tags/1.0.3-rc4
[.../src/my-project]$ svn commit
在上面的例子中,tags/1.0.3-RC4 现在应该考虑只读并时刻反映trunk的状态。 这些副本就像一个普通的提交处理。 activity 用MKACTIVITY创建,工作资源通过CHECKOUT 创建(例如上面在我们的例子中 目标目录;tags/),然后执行复制操作。该activity然后合并到有MERGE要求的信息库。
服务器需求警告: 本节已过期。DeltaV草案已经历了多个修订版,我们使用的版本变更了一部分。 DAV方法为了能正常操作,服务器需要实现以下WebDAV方法: OPTIONS GET DELETE COPY PROPPATCH PROPFIND MKACTIVITY CHECKOUT MERGE REPORT
当前Subversion需要下面的方法: CHECKIN UNCHECKOUT UPDATE LABEL VERSION-CONTROL BASELINE-CONTROL MKWORKSPACE
DAV属性以下DeltaV属性需要被实现: DAV:comment DAV:creator-displayname DAV:supported-method-set DAV:supported-live-property-set DAV:supported-report-set DAV:version-controlled-configuration DAV:checked-in DAV:auto-version,是个只读的空元素(不支持自动版本化/auto-versioning) DAV:checked-out DAV:predecessor-set 提示:在多个前驱版本如何合并生成单个新修订版机制上,Subversion的设计文档表述不是很清楚。搞明白之后发现,DAV:predecessors可能最终包含多余零个或一个前驱URL DAV:version-name, (全局)修订版本号 DAV:checkout-fork DAV:checkin-fork DAV:auto-update DAV:subbaseline-set,只读空属性(不支持子基线/sub-baselines) DAV:unreserved,被设成F DAV:baseline-controlled-collection DAV:baseline-collection DAV:subactivity-set,只读空属性(不支持子活动/sub-activities) DAV:eclipsed-set,总是空(内部成员不能被隐藏)
与DeltaV规范相反,下面的必须属性没有被实现: DAV:successor-set,获取该值计算量很大 DAV:checkout-set,事实上我们没有被检出的记录,而是使用工作资源URL来提供必要的信息;因此我们没有记录数据来填充该属性 DAV:merge-set, MERGE只支持一次提交。并不支持规范里定义的任意合并 DAV:auto-merge-set ,等同DAV:merge-set. DAV:activity-version-set,仅用于工作资源的活动,这样版本不能是活动的一部分 也许应该被定义为空集? DAV:activity-checkout-set,仅用于工作资源的活动,我们也不记录哪些工作资源存在 DAV:activity-set,仅用于工作资源的活动,这样版本不能是活动的一部分 也许应该被定义为空集? DAV:version-controlled-binding-set,我们没有版本历史资源赋给此属性
OPTIONSOPTIONS请求表示支持下文的DAV特性: 报告(reports)DAV:supported-report-set属性表示支持以下报告: svn:update-report svn:log-report
这些报告仅可用在公共资源(版本控制资源, VCRs)上。$svn/内的资源不可用。
注意事项,提醒讨论超时和自动清洗的活动(以及相关工作资源)。 讨论通过的mod_dav_svn维护热数据库。 讨论ra_dav和mod_dav_svn的其他实施细则。 附录A:基本原理有好几次,人问,“为什么选择HTTP/ WebDAV/ DeltaV系统?这似乎是非常臃肿,不适合。你为什么不设计一个定制的,精心调校的协议?或者,使用cvs协议?”下面列出的是一些我们选择WebDAV作为我们的网络协议的原因。 虽然这个名单当然可以有更多的理由去扩展(为了公平,列出为何WebDAV的是一个糟糕的选择的原因),但同时那肯定证明了我们的选择它的基本原因。
注:此表来自电子邮件,所以语气和观点可能有点过。而且文字推敲也这样。
内置网页浏览的资料库
例如,一起来看看:http://svn.apache.org/repos/asf/subversion/trunk/README(这是概述,我们还对以前版本每个文件的网址)
基于DAV浏览使用Web文件夹或WebDrive或类似在Windows中(适用于Windows XP的原生DAV坐骑)浏览SVN仓库与Windows资源管理器。 Mac OS X中有内置的DAV服务器的安装。Nautilus 拥有DAV功能。然后,你有你的开源工具,如cadaver,Goliath等
人们可以利用现有的库我甚至不能开始计算的HTTP工具和可用的库的数量。如果我们设计我们自己的协议,那么我们将得不到任何好处。两个HTTP库的实现(Joe Orton of Neon, and Daniel Stenberg of CURL)都是这样。我用Python的httplib的(和我自己的davlib)做了很多我们的服务器的测试。没有必要去和推出新的协议库。
现有的工具
一个字:虚: - )当我们捕获网络跟踪,粗略的了解HTTP。这是相当不错的,但我知道有更棒的。不过我们也有其他的工具,比如squid 和其他(高速缓存)代理(见下一条)。
缓存代理Subversion与缓存代理一起会工作得更有效。没有必要再使用特殊的工具如cvsup。只要访问缓存代理,你就拥有了一个分布式的只读仓库。那个欧洲开发小组只要访问他们与美国服务器间的缓存,他们的检出和更新就会被缓存下来,以方便小组内的其他成员。而提交将会流经缓存,发回美国服务器。
复杂和多选认证我们没必要为新协议重新实现一个认证模式,因为已经可以使用为HTTP定义的一簇模式。看过CVS协议吗?见过“我爱你”或者“我恨你”吧(表示重新实现协议过程中,程序员的爱恨情绪)?:-) 这就是创建新的认证模式的全部。但是只要我们愿意,我们就可以使用SSL和基于证书的认证。还有Kerberos, NTLM, 甚至是简单的Basic或者摘要(Digest)。我们的用户可以来自文本文件,数据库,LDAP, 或PAM。我们不必重新发明轮子,因为这些Apache都可以用。
超棒的网络服务器
我们不必担心如何设置可移植TCP_CORK以提供最佳的网络数据包。我们不必担心何时使用sendfile()是有道理的,或者何时它是可用的。我们不必担心断开的客户端连接,如何充分利用线程和进程如何缩放,请求管理,监视,日志记录等。Apache给了我们这些所有或者更多。我"真的"不希望通过xinetd这样做。我的意思是...在标准输出上设置TCP_CORK?怪异:-)
明确定义在线压缩我们已经使用了在线压缩,类似于CVS的“-z#”开关。而其他我们什么也没做。客户端库和服务器,对于我们来说只是根据 RFC2616 使用了自动支持。
未来互操作性在未来,我们将能够实现与众多IDE和其他WebDAV/ DeltaV客户端互操作。由于DeltaV的日益流行,集成开发环境可以很好地使用它的源代码管理,而不需要写一些MS/ SCC库接口的工具。
|