北京时间2008年6月20日凌晨,令人期待的Subversion1.5发布,Subversion1.5包含了超过所有以前版本的改进。Subversion中文站第一时间为大家提供了中文版的发布说明,另外我们还为大家准备了Subversion1.5专题,给许多特性提供了更深入的讨论。还有我们翻译的《使用Subversion进行版本控制》也已经发布1.4版本,最新的1.5版本也正在翻译中。
译者: http://rocksun.cn 原始出处: http://www.subversion.org.cn/?action-viewnews-itemid-42Subversion 1.5的新东西
- 合并跟踪(基础)
- 稀疏检出(通过新的–depth选项)
- 交互式的冲突解决
- 变更列表支持
- svn:externals的相对URL和peg修订版本
- 对于ra_svn和svnserve的Cyrus SASL支持
- 通过sharding对于FSFS的大规模开发的支持
- FSFS优化,通过不变的文件隔离
- WebDAV的透明通过代理写
- copy 和move的改进
- 速度改进,取消响应改进
- 更简单的使用试验ra_serf DAV访问模块
- API改变、改进以及语言绑定
- 超过150的bug修正,改进
Subversion 1.5是以前Subversion发布版本的超集,可以认为是当前“最好的”版本。包含所有1.0.x到1.4.x的,以及以前版本没有的修正和特性。所有的新特性将会写入Subversion book,见svnbook.red-bean.com。
兼容性问题
以前的客户端和服务器可以直接与1.5的服务器和客户端交互,然而,如果服务器和客户端不全是1.5时,一些新的1.5特性(例如合并跟踪)将会不可用,而另外一些特性如稀疏检出,在服务器是旧的,客户端是新的时,可以运行但是效率比较低。
没有必要转储并重新加载版本库,subversion1.5可以读取以前创建的版本,升级只需用最新的库和二进制程序覆盖原来的程序。
Subversion会维护与先前版本API/ABI的兼容,只会增加新的特性,而不会删除旧的特性。根据1.0, 1.1, 1.2, 1.3或1.4 的API编写的程序,可以使用1.5的库编译,为1.5编写的程序不必为旧库编译或运行。
新特性的兼容性表格
新特性 | Minimum Client | Minimum Server | Minimum Repository | Notes |
---|---|---|---|---|
1.5 | 1.5 | 1.5 | ||
1.5 | any | any | ||
1.5 | any | any | ||
1.5 | any | any | ||
1.5 | any | any | ||
any*, 1.5 | any*, 1.5 | any | *受限,见 SASL 和svn:// 兼容性 | |
any*, 1.5 | 1.5 | 1.5 | *1.5 file:// 兼容性需要 | |
any*, 1.5 | 1.5 | 1.5 | *1.5 file:// 兼容性需要 | |
any | 1.5* | any | *需要Apache 2.2服务器 | |
1.5 | any*, 1.5 | any | *受限,见copy 和move的改进 | |
1.5 | any | any | ||
1.5 | any | any |
工作拷贝和版本库格式更改
工作拷贝格式已经升级,这意味着1.4和更老的Subversion客户端不能与Subversion1.5的工作拷贝上工作,工作拷贝是自动升级的。
类似的,版本库格式也已经改变,意味着直接访问库的1.4以及旧的版本的程序如svnserve,mod_dav_svn,svnadmin等不能读取Subversion1.5的版本库,但是版本库是不能自动升级的。
工作拷贝升级
警告:如果一个Subversion1.5客户端遇到了一个1.5以前的工作拷贝,它会在接触到工作拷贝时自动升级工作拷贝格式,并使旧的Subversion客户端不能再读这些工作拷贝了。如果你在机器上使用多个版本的Subversion,请确认你对工作拷贝是用的subversion版本,防止意外升级工作拷贝。(但是这种自动升级行为不会发生在版本库上,只发生在工作拷贝。)
如果你意外的将工作拷贝从1.4升级到1.5,并希望降级到1.4,可以使用change-svn-wc-format.py ,详情看这篇文章,也可以以–help运行来查看使用指导。
版本库升级
Subversion 1.5服务器可以与1.4和以前的版本库工作,如果不使用svnadmin upgrade命令,版本库不会自动升级到1.5。这意味仅仅升级服务器不能直接得到某些特性,你也需要升级版本库。(我们决定不使用自动升级版本库是因为我们不希望subversion1.5偷偷的升级成1.4不可用的版本库。)
在运行svnadmin upgrade
之后,你或许希望对版本库运行svn-populate-node-origins-index 程序。Subversion1.5为每个版本库维护了一个节点起源的索引,为了得到一些信息,偶尔构建这个索引。但是对于包含许多修订的老版本库,最好一次创建这个索引,使用前面说道的工具,而不会因为自己构建这个索引而影响查询的性能,更多细节见issue #3024。
命令行输出的变更
尽管我们希望尽可能让命令行程序的的输出与以前版本保持兼容,但是还是要添加一些信息,这会破坏一些精确依赖输出的脚本。不幸的是,我们不能列出1.5输出的所有改变,但有一条可以确定的是冲突标记的行结束符号会和文件的eol-style匹配。
SASL和svn://
的兼容性
所有1.x的客户端,包含或不包含Cyrus SASL支持的,都可以通过在Cyrus SASL没有开启时认证正常。注意CRAM-MD5和ANONYMOUS机制是Subversion内置的,所以即使Cyrus SASL插件不在,我们也可以使用。
没有Cyrus SASL支持的1.x客户端不能通过开启Cyrus SASL,允许CRAM-MD5 和ANONYMOUS机制的1.5+的subversion服务器认证,
包含Cyrus SASL支持的1.5+客户端可以通过开启SASL功能的1.5+服务器认证,只要保证服务器支持的某个机制客户端也支持。
关于Cyrus SASL的更多信息可以看这个部分。
自定义revprops现在需要通过pre-commit钩子的检验
Subversion每个修订版本都有一组关联的修订版本属性;除了标准的日志信息,作者和日志,可以设置任意的用户定义的属性。这些属性本身不是版本化的,所以不能恢复修改的内容。因此,如果我们没有设置pre-revprop-change,我们就不能修改提交修订版本的revprops。在Subversion1.5之前,我们只能在提交时提供这三个标准的revprops;管理员使用钩子来控制这三个标准修订版本属性的内容,需要在pre-commit和pre-revprop-change检查,但是对于自定义的属性,只有pre-revprop-change是相关的。
Subversion1.5添加了svn commit包含–with-revprop选项,允许用户在提交时为修订版本指定属性,因此在Subversion 1.5允许在没有pre-revprop-change钩子时设置修订版本属性,pre-commit可以在提交之前检查事务修订版本属性(就像许多服务器已经使用pre-commit来检查正确格式化的log)。
这意味着如果你以前依赖pre-revprop-change to 钩子控制对于修订版本属性的修改(不仅仅你是跟踪它们的历史),那你先现在也需要在pre-commit添加类似的控制。
新特性
合并跟踪(基础)(客户端和服务器)
合并跟踪的意思是Subversion保持哪些变更从哪里合并过来,这减轻了维护分支的负担,也给了用户一个方式来查询合并的变更—或需要合并的内容—在不同的开发线上。
Subversion1.5支持的合并跟踪是“基础的”:最重要的部分已经实现,但是在我们最初的规格中还有一部分需要去实现(特别是对于reflective merges的正确支持,更好的change-availability reporting和更好的tracking of renamed files),虽然在1.5还要加入一些主要的特性,但我们不希望为等待某个特性延迟我们的发布。更多的合并跟踪改进希望在Subversion1.6或以后的版本出现。
概述
Subversion的合并跟踪设计为:
- 减少分支维护的记录负担
- 防止常见的“重复合并”问题
- 允许对于变更的cherry-picking
每个变更集都可以通过修订版本号识别,通过新的svn:mergeinfo
属性在合并的目标存放在合并变更集的信息(通俗来说就是“合并信息(mergeinfo)”),Subversion会自动保持合并信息的为最新,但是也有办法手工记录/消除合并信息,这是因为总会有些时候人们知道一些Subversion不知道的事情。
用户界面
从主干合并分支不再需要指明修订版本范围,每当你希望与trunk同步,你可以这样做:
$ cd BRANCH_WORKING_COPY $ svn merge URL_TO_TRUNK
Subversion能够计算出从URL_TO_TRUNK有哪些变更没有合并,并只处理这些变更,当将分支合并回主干,我们只需要:
$ cd TRUNK_WORKING_COPY $ svn merge --reintegrate URL_TO_BRANCH
下面是所有合并跟踪相关接口变更的正式描述。
svn merge
命令使用两个新的选项:--record-only
和--reintegrate。
–record-only选项至于-r结合工作,并且和你所想的一样:它只是用来将修订版本标记为已合并(或未合并的,使用“-”作为否定语法),而实际上除了合并信息(mergeinfo),什么也没有做。例如,当因为效率某个人手工修改了这个文件而合并了这个其他地方修改的变更时,这非常有效,与其让让变更在下次合并时加入进来,从而引起文本冲突,我们不如记录这个变更已经合并。(细节见Subversion书的merge-tracking requirements, and Blocking Changes 。)
–reintegrate选项在将分支合并回主干时使用;它会检查一些防护措施条件并快速有效的进行合并,更多内容见Subversion book的Keeping a branch in sync。
新的svn mergeinfo
命令可以显示一个目录已经接收的变更集,以及哪些变更集还适合接收,Subversion手册的Mergeinfo and Previews有更多信息。
svn log
和svn blame
命令有了新的-g
(--use-merge-history
) 选项,使之将mergeinfo纳入考虑,如果没有提供这个选项,它们就会参考合并信息。
使用-g选项的原因是有时候忽略合并历史会更好,在blame输出中,有时候你希望看到合并变更的人物B,而有些时候你希望看到最初作出这些修改人物A;使用-g可以得到后者的信息。在日志输出中,你有时候希望看到某一行提交的修订版本,而有时你希望看到最初的修改做合并修订版本转移走了;再次,-g显示后者的信息(使用”Merged via: “标识,后面是合并发生的修订版本号码),见Subversion手册的Merge-Sensitive Logs and Annotations。
合并跟踪和兼容性
前面已经说了,在随server升级版本库以前不支持合并跟踪。
如果你正在使用svnmerge包裹程序来进行合并,而现在希望使用Subversion1.5本身的合并跟踪功能功能,你一定要使用svnmerge-migrate-history.py 脚本来转化svnmerge的自定义属性为Subversion使用的svn:mergeinfo属性。
已知问题
1.5.0的合并跟踪还有许多已知的问题,我们首先解决了最重要的,下面是:
- issue #3128:
merge --reintegrate
应该更好的处理重命名 - issue #2897: 对反向合并的更好支持
- issue #3126: 更好已知变更报告(
svn mergeinfo
显示了太少或太多的合适修订版本) - issue #2837: 当执行循环合并时合并跟踪能起效果
- issue #3056: 防止以智能方式重复合并
- issue #2898: 当删除/添加子时无需处理合并信息
- issue #3067: 在合并范围内不存在的树不应该破坏合并
- issue #3157: 从路径的自然历史合并变更会创建引用自己的合并信息
- issue #3174: 合并算法需要对重命名的子树特别关注
(可以看list of all merge-related open issues,尽管很多不是关于合并跟踪)
Issue #3157可能是会很容易遇到的,所以下面是如何解决这个问题的详细描述:
合并跟踪信息现在可以保存在路径的“本身历史”中,当从trunk的特定修订版本x创建了一个分支,然后将分支的所有变更合并回trunk时,如果没有明确的限制合并范围并且没有使用--reintegrate
选项时,后果是,trunk的合并跟踪信息将会列出x之前的信息。这对以后的合并操作没有坏处,但是对于trunk上的svn log -g
会使用以前修订版本的合并跟踪信息(而不只是HEAD)。
注意,这一定不会是一个发布分支(也叫做“维护分支”)的问题,因为一个人通常不会将其合并回主干,相反,推荐的时间是对于进入trunk的新变更使用特性分支,可以在分支的生命周期结尾一次合并到主干。
一个办法是在提交合并修订之前修正合并跟踪信息,通过恢复“本身历史”信息:svn merge --record-only -rX:1
。另一个方案是完全防止这种情形,通过在第一次就明确的指定合并范围,例如-rX:HEAD,更多信息可以看这个邮件 。
当合并一个特性分支,最佳方案是使用--reintegrate选项
深入阅读
Subversion 1.5合并跟踪的更多内容可以看:
- Chapter 4: Branching and Merging in the Subversion book
- Subversion 1.5 merge-tracking in a nutshell (blog post by Ben Collins-Sussman)
- The merge tracking design documents (requirements, use cases, functional spec, design)
稀疏检出(Sparse checkouts)(客户端和服务器)
许多用户都有很大的目录树,但他们只希望检出特定的部分。在Subversion以前的版本,checkout -N没有真的完成这个任务。Subversion 1.5引入了checkout、
switch
和update子命令的–depth选项,这个选项替代了-N,允许用户构建只包含他们需要内容的工作拷贝,而不管其他的东西。
Depth概述
每个目录现在理解了depth的概念,可以有四种值:empty、files、immediates、infinity,值的定义如下:
- –depth=empty: 更新不会拉出任何不存在的文件或目录
- –depth=files: 更新会拉出所有的文件,但不包括子目录
- –depth=immediates: 更新会拉入所有不存在的文件或子目录;但子目录的设置为depth=empty。
- –depth=infinity: 更新会拉入所有不存在的文件和目录,子目录的设置为depth=infinity,与目前的缺省更新行为方式相同。
--depth
选项设置depth的值在更新工作拷贝时按照上面说的方式更新
用户界面
影响的命令:
checkout
switch
update
status
info
-N选项开始成为这些子命令的--depth=files选项
的一个别名,这改变了现存的-N行为方式,但是以一种很琐碎的方式(见下面)。
现在对于不使用--depth
或-N
的checkout来说和以前一样。没有--depth或
-N
的switch和update命令现在只和工作拷贝完全的depth-infinity相同,没有--depth或
-N
的switch或update不会改变depth值(例外:在命令行中指定的不存在的目录会拉入)。
结果是,checkout与checkout --depth=infinity相同,但是
switch和
update
与switch --depth=infinity和
update --depth=infinity不同,前者根据现存的depth值更新,而后者获取所有的内容。
作为开始,可以使用--depth=empty
或--depth=files选项checkout文件,如果需要额外的文件或目录,可以使用合适的
--depth选项的update命令来获取。除了其他的状态信息,svn status必须列出目录周围的depths。当调用的目录的depth不是缺省值(depth-infinity)时svn info命令也会列出其depth。
注意: 当前对于稀疏检出没有反选的接口—也就是说,在引入到工作拷贝后(尽管有一些相对简单的方法可以获取此目标),没有命令可以取消选择或“折叠”子目录,详细信息见issue #2843。
与以前服务器的兼容性
–depth特性显然需要客户端是1.5以上的,也需要1.5以上的服务器才能最有效的工作,然而,客户端仍然需要在1.4.x服务器时工作正常;只是有较差的效率。
这是因为以前的服务器不会理解—因而会忽略—不会清楚客户端说的“depth”的含义。所以当客户端请求比depth-infinity更浅的depth,以前的服务器会返回比客户端需要更多的数据,然而Subversion1.5+的客户端知道是与旧的服务器通话,并会过滤这些多余的数据,因此,操作会更长一些,因为服务器发送了许多客户端忽略的数据,但是最终在客户端产生的数据相同。(注意旧的服务器理解网络协议的recurse,而1.5+客户端根据depth发送标记;这减轻了额外的网络惩罚。)
进一步阅读
- The Sparse Directories section in the Subversion book.
- The design/implementation document in the repository.
交互式冲突解决(客户端)
在update
/switch
/merge
子命令的操作中,现在冲突解决是使用交互式的命令行客户端完成,客户端库提供了一个callback函数,所以其他客户端也能以同样的方式工作。
下面是使用命令行客户端例子:
$ svn up U contrib/client-side/svnmerge/svnmerge_test.py Conflict discovered in 'contrib/client-side/svnmerge/svnmerge.py'. Select: (p) postpone, (df) diff-full, (e) edit, (s) show all options: s (p) postpone - mark the conflict to be resolved later (df) diff-full - show all changes made to merged file (e) edit - change merged file in an editor (r) resolved - accept merged version of file (mf) mine-full - accept my version of entire file (ignore their changes) (tf) theirs-full - accept their version of entire file (lose my changes) (l) launch - launch external tool to resolve conflict (s) show all - show this list Select: (p) postpone, (df) diff-full, (e) edit, (s) show all options: tf G contrib/client-side/svnmerge/svnmerge.py Updated to revision 25685. $
这个特性可以使用–non-interactive选择关闭,或者通过设置运行配置文件中的“[miscellany] interactive-conflicts = no”永久关闭。
交互式冲突解决的API通过一个callback函数公开,并有如下数据类型:
svn_wc_conflict_resolver_func_t
, callback API本身svn_wc_conflict_description_t
, 传递给callback的冲突描述svn_wc_conflict_action_t
, 冲突描述中尝试工作内容的部分svn_wc_conflict_reason_t
, 冲突描述中冲突类型部分svn_wc_conflict_result_t
, 返回的冲突解决尝试结果svn_wc_conflict_choice_t
, 用户选择动作的列表
客户端通过设置他们的svn_client_ctx_t
的conflict_func
字段提供了他们的callback函数,并可以通过对应的conflict_baton
字段提供额外的callback状态。
变更列表支持(changelist)(客户端)
Subversion客户端现在包含了变更列表(changelist)的改变,一组与选定名称关联的文件,当工作在同一个工作拷贝的不同集合的文件时这样非常有效,Subversion1.5允许你为每组文件关联一个变更列表,大多数可以将一组文件作为目标的命令现在也接受–changelist选项,会根据changelist的成员过滤目标,变更列表的成员可以使用
changelist子命令编辑。
变更列表完全是客户端控制的。他们不会发送到服务器,对同一个版本库其他用户都不可见。另外,--changelist
选项不是添加剂;如果一个文件在没有--changelist
的时候加入到目标的列表,它也不会加入进去,它不会管changelist的成员。当前,一个文件一次只能属于一个变更列表,目录不能作为变更列表的成员。
下面的子命令支持--changelist选项:
changelist
commit
diff
(only wc-wc and wc-repos cases)info
propget
proplist
propset
propdel
revert
status
update
进一步阅读
- The Changelists section in the Subversion book.
- The design/implementation document in the repository.
svn:externals中的相对URL,peg revisions(客户端)
对svn:externals 特性的两个增强
对于URL的Peg revision语法
兼容性和新的语法:由于兼容性原因,1.5以前的svn:externals语法继续不理解peg revisions,引入了一种支持URL中peg revisions的新语法。
以前的格式是:
foo http://example.com/repos/zig foo/bar -r 1234 http://example.com/repos/zag
不支持peg revisions,如下的外部定义不能工作(除非目录名就是zig@HEAD and zag@HEAD):
foo http://example.com/repos/zig@HEAD foo/bar -r 1234 http://example.com/repos/zag@HEAD
新格式将跟在外部定义后面的路径URL移动到第一位;如果有一个操作(-r)修订版本,则在URL之前,下面是四个外部定义行:
http://example.com/repos/zig foo1 -r 1234 http://example.com/repos/zag foo/bar1 http://example.com/repos/zig@HEAD foo2 -r 1234 http://example.com/repos/zag@HEAD foo/bar2
换句话说,操作(“r”)和peg(“@”)都是允许,但都不是必须的。
对相对URL的支持
在Subversion1.5之前,svn:externals中的URL必须是绝对路径,现在他们可以是相对的。现在支持四种相对外部引用。(在下面的例子里,假设我们有两种版本库:一个是在http://example.com/svn/repos-1 ,另一个在http://example.com/svn/repos-2,我们检出http://example.com/svn/repos-1/project1/trunk,而svn:externals 设置为trunk。)
-
../
-
svn:externals属性设置目录的相对路径,则URL是以../开始,例如:
-
../../project2/trunk common/project2/trunk
这就是将http://example.com/svn/repos-1/project2/trunk 加入到common/project2/trunk。外部URL相对于设置svn:externals属性的目录的URL,而不是写到磁盘的外部的目录。
^/
-
相对于库的根。
-
^/project2/trunk common/project2/trunk
这就是将http://example.com/svn/repos-1/project2/trunk加入到common/project2/trunk。
-
你可以容易使用相对URL来引用其他的版本库:
-
^/../repos-2/foo/trunk common/foo/trunk
就是http://example.com/svn/repos-2/foo/trunk加入到common/foo/trunk。
//
-
相对于模式,这就是拷贝了检出或导出URL的模式到svn:externals,当同一个主机必须依赖于网络位置按照不同的模式访问;例如局域网的客户端使用http://,而外部客户使用svn+ssh://。
-
//example.com/svn/repos-1/project2/trunk common/project2/trunk
这将会把http://example.com/svn/repos-1/project2/trunk提取到common/project2/trunk,如果工作拷贝是通过svn+ssh://example.com/svn/repos-1/project1/trunk 检出的,那么URL将会是svn+ssh://example.com/svn/repos-1/project1/trunk。
/
-
服务器root的相对URL,这是检出或导出的模式和主机名的URL拷贝到svn:externals。
-
/svn/repos-1/project2/trunk common/project2/trunk
这会提取http://example.com/svn/repos-1/project2/trunk到common/project2/trunk。如果工作拷贝是从svn+ssh://example.com/svn/repos-1/project1/trunk 检出,那么URL将会是svn+ssh://example.com/svn/repos-1/project1/trunk。
旧的svn:externals格式依然支持相对URL(不会支持peg revisions)。
当Subversion见到不使用绝对URL的externals ,会将第一个参数作为相对URL,第二个作为目标目录。
进一步阅读
See The svn:externals section of the Subversion Book.
ra_svn和svnserve的Cyrus SASL支持(服务器和客户端)
来自Wikipedia:“SASL是网络协议的认证和数据安全框架,它将认证机制与应用协议解耦,从理论上讲,允许任何SASL支持的认证机制应用到使用SASL的应用协议上”
在实践中,服务器发送会发送一组它支持的认证机制,客户端会根据客户端的支持选择一种认证机制,并通知服务器这个决定。之后,会有一些信息交换,直到成功或者失败发生,在后一种情况,允许客户端重新认证。
svn:// 协议会一直支持这种类型的协商,然而只是实现了CRAM-MD5和ANONYMOUS。Cyrus SASL支持所有这些,此外,提供了其它如DIGEST-MD5, OTP (One-Time Passwords), GSSAPI (used for Kerberos authentication), NTLM (NT LAN Manager), SRP (Secure Remote Password)以及其他机制的支持。支持机制的准确列表依赖于SASL是如何编译的,有一些还有外置依赖,或不是缺省编译。另外,因为每种机制实际上是一个共享库,会在运行中加载,有许多分布的包位于核心库外单独存放。
关于使用1.5并开启SASL与1.5前的客户端工作的更多信息请看兼容性部分,关于Subversion的SASL支持可以看sasl.txt。
对于FSFS大规模开发的改进支持,通过sharding (服务器)
FSFS文件系统后端在各自的文件存放每个修订版本,在Subversion1.5之前,所有的文件都存放在版本库一个普通的目录里,现在新创建的FSFS库会使用二级的目录树,每个目录最多1000个文件。这种版本库只能与Subversion1.5客户端兼容,但是当然,Subversion1.5仍然可以使用以前格式的版本库,而没有问题。
这样做的主要原因是允许修订数量能够超越文件系统的目录树的限制,当现代文件系统能够成支持每个目录有百万条目,它会变得很慢,而且管理工具会变得笨拙或失败。
关于FSFS sharding的更多信息可以看这个blog entry。
svnadmin create
创建后,使用版本库之前,shard大小可以通过编辑“db/format”中的“layout sharded
”来调整。
改进的FSFS优化,通过不可变的文件隔离(服务器)
FSFS版本库永远不会在写入修订版本后进行修改,尽管最好让操作系统永远缓存所有的文件,某些文件系统(例如NFS)缺省可以通过这种缓存获益,现在FSFS版本库为此将不变的文件存放在子目录“db/revs”和“db/txn-protorevs”,这允许这些目录加载到开启缓存(在Linux可以看nfs部分的“nocto”)的挂接点上。
因为提交事务存放在db/txn-protorevs” 而不是”db/transactions”,后者的目录不必在同一个挂接点,如果版本库存放在较慢的文件系统(例如NFS),提交效率可以通过将目录移动到本地磁盘(使用符号链)改进。如果你在一个网络负载平衡器之后使用多个svn服务器,你必须配置负载平衡器在一个事务中转向到同一个服务器,这通常叫做“客户端喜好”。
WebDAV透明通过代理写(服务器)
Subversion1.5引入了svnsync — 一提供从一个版本库复制内容到另一个版本库的工具。尽管很有用,但svnsync只能从一个版本库拖入修订版本,但是不能将额外的提交返回给master。Subversion1.5为mod_dav_svn添加了WebDAV代理支持,有效的使用mod_dav_svn允许双向的修订版本历史复制。
所有的客户端与slave服务器交互,但是slave会透明的将所有的写活动传递给master(根据需要重写数据),slave实质上是只读的,但是它们本地都有一个完整的版本库,服务器分流master服务器的读压力,某些情况下非常可观。
如果使用支持HTTP DAV的缓存代理,这个模型非常有好处,在这个情况下,每个slave可以对应所有对应的只读请求,而无需传递给master后端。
要求
- Subversion 1.5或更新的。
- Apache HTTP Server 2.2.0或更高,并开启mod_proxy (许多mod_proxy 修正的bug没有回到httpd的2.0版本)
实例配置
参与者:
- Slave → slave.example.com (可以很多)
- Master → master.example.com (可能只有一个)
- A WebDAV client (ra_neon, ra_serf其他WebDAV客户端)
客户端做:
% svn co http://slave.example.com/repos/slave/
...
% svn ci
% ...etc...
(客户端可以操作如常)
每个slave配置:
<Location /repos/slave>
DAV svn
SVNPath /my/local/copy/of/repos
SVNMasterURI http://master.example.com/repos/master/
</Location>
master必须有一个post-commit钩子可以更新所有的slave,一个例子使用svnadmin dump
/svnadmin load
,ssh作为支持。svnsync可以完成同样的事情。
此外,如果master版本库支持锁定,锁定数据库需要通过post-lock和post-unlock保持同步,将master状态传递到slave。(用户名保留作为读者的练习),如果不传递锁定信息,用户需要能够精确的检测是否有一个锁定-但是锁定会一直工作。
一个实例的同步脚本可能如下:
#!/bin/sh
REPOS="$1"
REV="$2"
SLAVE_HOST=slave.example.com
SLAVE_PATH=/my/local/copy/of/repos
# Ensure svnadmin is in $PATH on both this machine and the remote server!
svnadmin dump --incremental -r$2 $1 > /tmp/$2.dump
scp /tmp/$2.dump $SLAVE_HOST:$SLAVE_PATH
ssh $SLAVE_HOST "svnadmin load $SLAVE_PATH < $SLAVE_PATH/$2.dump"
ssh $SLAVE_HOST "rm $SLAVE_PATH/$2.dump"
rm /tmp/$2.dump
进一步阅读
关于WebDAV代理的更多信息可以看in the repository。
改进和bug修正
Copy/move-related improvements (client and server)
The abilities and behavior of copy
and move
operations are significantly improved in 1.5+.
Improved copy-handling during updates (client and server)
A common problem in older versions of Subversion was the way in which svn update
handled incoming copies and moves.
Consider this scenario: Harry runs svn move foo bar; svn commit
, and meanwhile Sally makes local changes to ‘foo’, and then runs svn update
. In earlier versions of Subversion, the server would send down a completely new file ‘bar’, and unversion the file ‘foo’ (if it had no uncommitted changes, Subversion would remove it entirely.) From Sally’s point of view, her changes seem to be lost; the newly added ‘bar’ file has the older content, and the file ‘foo’ has been taken out of version control.
In Subversion 1.5, the client and server both attempt to be smarter about this. The server doesn’t send a whole new file during the update, but rather instructions to copy something that likely already exists in the working copy. So Sally’s ‘foo’ file is copied to ‘bar’ (with local edits intact!).
In theory, this is the best-case scenario. There are a few caveats: this “proper copying” of existing working-copy resources only works on files, not (yet) on directories. Also, if an incoming move-operation deletes ‘foo’ before it attempts to copy it to ‘bar’, then the copy will fail, and the client reverts to the old behavior of fetching a pristine copy of the file from the repository. We hope to address this in svn 1.6.
See issue #503 for more.
Peg revisions (client)
Copy and move operations now accept sources with peg (”@”) revisions.
See issue #2546 for more.
Multiple working copy copy/move operations (client)
Clients may now perform chained copy/move operations locally on a single object in a working copy:
svn mv path1 path2 svn mv path2 path3
See issue #756 for more.
Improved handling multiple copy/move sources (client)
Clients now accept multiple sources for copy and move operations, with the ability to copy/move each of the sources to the specified directory. This mirrors the behavior of standard command-line copy and move tools, such as cp
and mv
. For example:
svn mkdir new_subdir svn mv foo.txt bar.txt baz.txt new_subdir
In practice, this means users can take advantage of shell globbing when doing a local copy or move:
svn cp *.c dir
Multiple source copy/move also works for all previously defined copy/move working copy and repository combinations.
See issue #747 for more.
Copy takes -rBASE (client)
Copy now understands the special revision “BASE” in a working copy (as in: “-rBASE“).
See issue #1643 for more.
Creation of intermediate directories with copy/move (client and server)
See the section on the new –parents option for more about this.
Cancellation improvements (client)
Clients operations are now significantly more responsive to cancellation (e.g. via control-c). In pre-1.5 releases, after directing an operation to stop, one sometimes had to wait for some time (e.g. while I/O occurred) before the operation would actually stop.
Command-line client improvements (client)
There are far too many enhancements and new options to the command-line client to list them all here. Aside from all the ones mentioned already in these release notes, below are a few more that we consider important, but please see the 1.5.0 section in the CHANGES file for a complete list.
New “resolve” subcommand replaces “resolved”
A new resolve subcommand replaces the “resolved” subcommand (the latter is deprecated, but still present for compatibility). The new subcommand takes a –accept=orig|mine|repo option to select which version of a file to retain (which means Subversion now supports batch-style conflict resolution).
See issue #2784 for more.
Create intermediate directories if asked
Add, mkdir, copy, and move take a new –parents option, which makes intermediate directories as necessary to create the destination path.
See issue #1776 for more
New –keep-local option retains path after delete.
Delete (remove) now takes a --keep-local
option to retain its targets locally, so paths will not be removed even if unmodified.
Commit now takes a –with-revprop option.
Commit now takes a –with-revprop option allowing one to set revision properties
See issue #1976 for more.
Easier to try out experimental ra_serf DAV access module (client)
Subversion 1.4 introduced the experimental ra_serf repository access module for accessing HTTP[S] DAV Subversion servers. This uses the serf library instead of the Neon library which the original DAV support uses. serf supports pipelined requests which may lead to better performance. However, Subversion 1.4 required you to choose which module to use for accessing DAV servers at build time, which made it difficult to find out which module performs better for your usage patterns.
Subversion 1.5 allows you to build both modules at the same time; you can choose which library to use on a global or host-by-host basis by setting the http-library variable in your run-time server configuration file (~/.subversion/servers). In recognition of the fact that both libraries are DAV clients, we have renamed ra_dav to ra_neon.
API changes, improvements and language bindings (client and server)
There are too many new and revised APIs in Subversion 1.5.0 to even begin to list them all here. See the Subversion API Documentation page for general API information. If you develop a 3rd-party client application that uses Subversion APIs, you should probably look at the header files for the interfaces you use and see what’s changed.
One general change is that most APIs that formerly took a recurse parameter have been upgraded to accept a depth parameter instead, to enable the new sparse checkouts feature.
Language bindings have mostly been updated for the new APIs, though some may lag more than others.
Bug fixes (client and server)
A great many bugs have been fixed. See the 1.5.0 section in the CHANGES file for details.
Subversion 1.3.x series no longer supported
The Subversion 1.3.x line is no longer supported. This doesn’t mean that your 1.3 installation is doomed; if it works well and is all you need, that’s fine. “No longer supported” just means we’ve stopped accepting bug reports against 1.3.x versions, and will not make any more 1.3.x bugfix releases, except perhaps for absolutely critical security or data-loss bugs.
Subversion Dependencies Distribution: Binary Compatibility Issues
Background
APR 0.9.x and 1.x are binary-incompatible. This means if you are already using Subversion with APR 0.9.x, and then upgrade your libapr to 1.X without rebuilding Subversion, things will break. Things will also break if your Subversion server libraries are linked to one version of APR but your Apache HTTPD server is linked to a different version.
For a long time, Subversion’s main source distribution included APR 0.9.x, which was the latest available at the time, along with a few other things (e.g., Neon, zlib) that weren’t yet widespread on installation systems.
Subversion 1.5.0 Dependencies Distribution
Today, these dependencies are no longer exotic, so our source distribution contains just Subversion itself. Those building Subversion are expected to have the necessary libraries already installed, or to be able to fetch them easily. But for convenience, we still offer a “deps” distribution: it doesn’t contain Subversion, it just has source code for those third-party libraries.
Until Subversion 1.5.0, the deps distribution contained APR 0.9.x, but as of 1.5.0, we’re finally upgrading it to APR 1.x. This is because by now there are very few systems that will have binary compatibility issues, and of those, few are likely to build using the “deps” dist.
If you already have a Subversion installation using APR 0.9.x, it’s still possible to move to APR 1.x safely (although you are not required to, unless you use the deps dist). Just be sure to recompile Subversion, and Apache httpd if necessary, after upgrading APR.
Note that it’s perfectly safe to use APR 1.x from the beginning. In fact, we recommend it. If you’re building Subversion for the first time, there’s no compatibility issue to worry about, so just grab the latest version of APR (or use our deps dist).