设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

在Subversion中使用WebDAV

2014-12-5 13:35| 发布者: joejoe0332| 查看: 4368| 评论: 0|原作者: douxingxiang, donhui, 倚天屠龙之金毛狮王, f4f|来自: oschina

摘要: 本文详叙了WebDAV怎样用于Subversion。特别是,客户端怎么用Neon生成WebDAV请求,以及服务器端怎么将WebDAV请求转变成Subversion代码仓库的操作。这里的服务器端是一个作为mod_dav功能后端的Apache 2.0模块。 ...


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,我们没有版本历史资源赋给此属性

OPTIONS

OPTIONS请求表示支持下文的DAV特性:

  • 1

  • 2

  • 版本控制/version-control

  • 检出/checkout

  • 工作资源working-resource

  • 合并/merge

  • 基线/baseline

  • 活动/activity

  • 版本控制集/version-controlled-collection

报告(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功能。然后,你有你的开源工具,如cadaverGoliath

 人们可以利用现有的库

我甚至不能开始计算的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库接口的工具。


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部