在SVN中生成ChangeLog

在CVS中可以利用WinCVS中的Python和Tcl教本生成ChangeLog,但SVN的客户端TortoiseSVN却只能看,不能导出来,其实只需要动动手,也是很简单的。

首先准备工具:

首先,导出LOG到XML文件

svn log http://localhost/svn/svntest -v –limit 100 –xml > changelog.xml

-v可以生成稍微相信的LOG信息,–limit 100是只取最新的100条记录,–xml指定生成XML格式。

然后,转换XML文件,生成最终文件

xsltproc -o ChangeLog svn2cl.xsl changelog.xml

就这么简单哦。

另外,如果LOG中有中文,这样转换出来的文件中,中文会是&# 23232;这种格式,只需要把svn2cl.xsl中

<xsl:output
method="text"
encoding="iso-8859-15"
media-type="text/plain"
omit-xml-declaration="yes"
standalone="yes"
indent="no" />

里的iso-8859-15更改为utf-8,就可以了。对转换出来的ChangeLog格式不满意,调整XSL即可。

7.19

CVS的$Id$自动替换在Subversion中的实现

以前CVS用习惯了,换到Subversion中以后,$Id$不会自动替换感觉很不爽,后来一查文档,原来SVN用另外一个别扭的方式解决了这个问题。

1、打开 C:\Documents and Settings\QuietLife\Application Data\Subversion 文件夹(QuietLife 是我的用户名,换成自己的就行了);
2、找到 config 文件,用记事本打开;
3、加入下面的内容:

[miscellany]
enable-auto-props = yes

[auto-props]
*.c = svn:keywords=Id
*.cpp = svn:keywords=Id
*.h = svn:keywords=Id
*.hpp = svn:keywords=Id
*.cxx = svn:keywords=Id
*.cs = svn:keywords=Id
*.php = svn:keywords=Id
*.html = svn:keywords=Id
*.tpl = svn:keywords=Id
*.txt = svn:keywords=Id
*.vbs = svn:keywords=Id
*.js = svn:keywords=Id
*.asp = svn:keywords=Id

OK,现在试试看加入一个文件到 SVN 中,然后再提交。就会发现文件中的 $Id$ 已经被自动替换了,而且文件也自动加上了 keyword:Id 属性。

以上引自http://www.dualface.com/blog/2005/01/subversion.html,这样是使用了SVN的一个“自动属性”的功能,可以自动为文件设置属性,因为文件的性质定义全部都是用属性来实现的(项目也是)。并且不光有svn:keywords,还有其它的属性:

[auto-props]
### The format of the entries is:
### file-name-pattern = propname[=value][;propname[=value]…]
### The file-name-pattern can contain wildcards (such as ‘*’ and
### ‘?’). All entries which match will be applied to the file.
### Note that auto-props functionality must be enabled, which
### is typically done by setting the ‘enable-auto-props’ option.
# *.c = svn:eol-style=native
# *.cpp = svn:eol-style=native
# *.h = svn:eol-style=native
# *.dsp = svn:eol-style=CRLF
# *.dsw = svn:eol-style=CRLF
# *.sh = svn:eol-style=native;svn:executable
# *.txt = svn:eol-style=native
# *.png = svn:mime-type=image/png
# *.jpg = svn:mime-type=image/jpeg
# Makefile = svn:eol-style=native

顺便再引一些对这些属性的说明:

特殊性质

除了对你的目录与档案进行版本控制之外, Subversion 还提供了一个接口, 可用来新增, 修改, 以及移除已纳入版本控制的目录与档案的版本控制描述资料. 我们称这个描述资料为性质,在这里我主要介绍以下几个比较重要的特殊性质
svn:mime-type
svn:mime-type 性质在 Subversion 中有很多作用. 除了作为储存档案的多用途网际网络邮件延伸语法 (MIME) 分类之外, 这个性质的内容还会决定几项 Subversion 的行为特征.
举 个例子, 如果 svn:mime-type 性质设为文字的 MIME 类别 , Subversion 会假设该档的内容是二进制(也就是人类看不懂的资料). Subversion 提供的功能中, 其中一项是在从服务器收到工作档的更新中, 依文字内容与文字列进行合并. 但是对含有二进制资料的档案, 根本就没有 “文字列” 的概念. 因此, Subversion 对这些档案在更新时, 不会试着进行内文合并. 它改用另一种方式。
一般来说Subversion 在执行 svn import 与 svn add 子命令时, 会使用二进制侦测运算法的方式来协助使用者.但是如果 Subversion 猜错了, 或是你希望将 svn:mime-type 设定成更为明确的值(可能是 image/png)你都可以移除或是手动编辑这个性质.
svn:ignore
svn:ignore 性质包含了档案样式的列表, Subversion 处理时会忽略. 它可以与执行时期设定的 global-ignores 选项一起工作, 以便在类似 svn status 的命令中过滤掉未纳入版本控制的目录与档案.
我们知道新增的文件和目录必须透过 svn add 命令, 才会被纳入 Subversion 的管理. svn status 命令会将工作复本中未纳入版控制目录与档案显示出来.
$ svn status calc
M calc/button.c
? calc/calculator
? calc/data.c
? calc/debug_log
? calc/debug_log.1

在 这个范例中, 用?标注出来的文件就是未纳入版控制的档案.如果你不想每次执行 svn status 时, 都看到这些档案, 那幺svn:ignore 性质就是解决方案。你可以透过 svn propedit svn:ignore calc 对 calc 目录加上一些忽略样式. 举个例子,将以下的值作为 svn:ignore 性质的新内容:
calculator
debug_log*
加上这个性质后再执行你的 svn status 输出便会不同:
$ svn status
M calc
M calc/button.c
? calc/data.c
现在, 所有不想看到的东西都从输出中消失了!


svn:keywords
Subversion 具有取代关键词(有关纳入版本控制档案的有用信息)进入档案内容的功能.
举 个例子, 假设你有个文件, 想要在里面显示最近一次修改的日期. 你可以把这个负担加诸文件的作者身上, 让他们每一次送交更动之前, 顺便添加最近一次修改日期的部份. 但是迟早有人会忘记这件事. 换个方式, 只要叫 Subversion 对 LastChangedDate 关键词进行关键词取代即可.
Subversion 定义了可用来进行取代的关键词列表. 这个列表包含了以下五个关键词:
LastChangedDate
LastChangedRevision
LastChangedBy
HeadURL
Id
如果只把关键词定位锚加进档案里的话, 什幺事也不会发生.要告诉 Subversion 是否该对某一个档案进行关键词取代,得使用svn:keywords这个性质。当它被设定时, 它会控制该档案哪个关键词应该被取代.
举个例子, 假设你有一个纳入版本控制的档案, 名为 weather.txt, 看起来像这样:
Here is the latest report from the front lines.
$LastChangedDate$
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.
如果没有设定该档案的 svn:keywords 性质, Subversion 什幺事也不会作. 让我们开启关键词 LastChangedDate 的内容取代.
$ svn propset svn:keywords "LastChangedDate Author" weather.txt
property `svn:keywords’ set on ‘weather.txt’
$
在你送交了这个性质更动之后, Subversion 会显示为:
Here is the latest report from the front lines.
$LastChangedDate: 2002-07-22 21:42:37 -0700 (Mon, 22 Jul 2002) $
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.
这样不管谁提交这个文件,都会在里面显示最近一次修改的日期。
svn:eol-style
除 非另外指定版本控制档案的 svn:mime-type 性质, Subversion 会假设档案包含人类可读的资料.这对于列尾符号 (EOL) 是很不幸地, 因为不同的操作系统会使用不同的符号来表示一列的结尾. 举个例子, 一般用在 Windows 平台上的列尾符号是两个 ASCII 控制字符 :返回字符 (CR) 与换行字符 (LF). 但是 Unix 软件就只使用 LF 字符来表示一列的结尾.这样以来window客户提交的档案中的CR 字符在 linux客户端会显示成 ^M, 而linux客户提交的档案中CR 字符在 Windows 客户端会被忽略。结果将档案里的所有文字列合并成一个超长的文字列, 这是因为没有返回CRLF字符组合的存在来表示一个换行。 解决的方法是 svn:eol-style 性质. 当这个性质设定为native时, Subversion 会根据系统的类型来决定是否对该档案的结尾进行自动处理。.
svn:externals
有的时候, 一个工作复本可能包含了数个不同来源的工作复本. 举个例子, 你可能想要有数个不同的目录, 各来自不同的档案库.我们可以通过svn:externals 性质来宣告这一对对应关系。内容是子目录对应至 Subversion 档案库 URL 的多行表格.
$ svn propget svn:externals calc
third-party/sounds http://sounds.red-bean.com/repos
third-party/skins http://skins.red-bean.com/repositories/skinproj
third-party/skins/toolkit http://svn.red-bean.com/repos/skin-maker
当有人取出 calc 目录的工作复本, Subversion 还会继续取出在外部定义里的项目.
$ svn checkout http://svn.example.com/repos/calc
A calc
A calc/Makefile
A calc/integer.c
A calc/button.c
Checked out revision 148.

Fetching external item into calc/third-party/sounds
A calc/third-party/sounds/ding.ogg
A calc/third-party/sounds/dong.ogg
A calc/third-party/sounds/clang.ogg
Checked out revision 14.

Fetching external item into calc/third-party/skins
鈥?/p>

7.19

Subversion mod_dav安装方式下的权限控制

先来个最简单的认证方式--使用Apache的认证,首先建立Apache的passwd文件:

htpasswd -c -s apache_passwd Fwolf

-c为新建文件,下次添加用户的时候就不用这个参数了,-s为使用SHA算法加密密码。然后,在apache的httpd.conf中的<Location /svn>段增加如下几句:

AuthType Basic
AuthName "Fwolf’s Subversion repositories"
AuthUserFile h:/svn/svnpasswd
#AuthzSVNAccessFile h:/svn/svnaccessfile
Require valid-user

然后重启Apache。现在使用TortoiseSVN和http访问svn的Repository就都要求输入用户名密码了。

如果想把浏览权放开,只限制更新的时候进行认证,可以把Require valid-user改为

<LimitExcept GET PROPFIND OPTIONS REPORT> Require valid-user </LimitExcept>

这样匿名用户就可以浏览了。如果想要更进一步、更细致的权限控制,可以在使用上述方法验证用户身份的基础上,使用SVNAccessFile限定用户的操作范围。

首先把

#AuthzSVNAccessFile h:/svn/svnaccessfile

的注释取消,然后按照如下格式建立accessfile即可

[groups]
developers = user1,user2,user3,user4
docs = user5,user6,user7

to allow everyone read access

[/]
* = r

allow all developers complete access

@developers = rw

give the doc people write access to the docs folder

[project:/trunk/doc]
@docs = rw

在accessfile中,可以定义用户组,可以针对全局或者某个Repository甚至它的某个子目录指定权限。

原帮助中的对[/project/trunk/doc]指定权限的方式,好像在SVNParentPath模式下不可用,把名称格式改一下就可以了。

7.14

cvs2svn转换Repository时,中文更新记录乱码的问题

使用使用cvs2svn转换Repository的时候,发现转换过来的更新记录中,所有的中文都是乱码,不是显示方块,就是问号,原来是没有加上–encoding参数的缘故,原来使用的命令如下:

c:/python23/python h:/cvs2svn-1.2.1/cvs2svn -s h:/svn/repo h:/cvsroot/repo

–encoding参数的含义是“所采用的编码,默认为ascii”,但我加上这个参数“–encoding=gb2312”之后,转换却出了问题,提示

LookupError: unknown encoding: gb2312

原来cvs2svn在转换的时候使用 的是Python的字符集,而Python 2.3好像不支持gb2312字符集,因此更新到Python 2.4.1并使用如下命令进行转换

c:/python24/python h:/cvs2svn-1.2.1/cvs2svn –encoding=gb2312 -s h:/svn/repo h:/cvsroot/repo

就一切正常了,转换很顺利,更新记录中的中文也没有乱码。

这里有Python 2.4支持的所有字符集列表。

subversion起步

SVN服务器也建好了,Tortoisesvn客户端也安装好了,下面就可以开始使用SVN了。通过cvs2svn转过来的Repository可以直接用,但如果要新建一个Repository,导入现有的项目,就要稍微麻烦一些了,甚至有些绕,大致步骤如下:

  1. 在服务端的SVN parent目录下,建立一个空的repository,可以使用svnadmin create –fs-type fsfs MyNewRepository命令,也可以使用Tortoisesvn的TortoiseSVN->Create Repository Here …命令。
  2. 在客户端建立一个repo目录,并且在下面建三个空目录,分别是branches、tags、trunk,其中branches用来保存分支,tags用来保存标签(?不知道这个叫法是否正确),trunk用来保存当前工作状态的文件。这个目录结构也可以采用其它方式建立,详细的说明在TortoiseSVN的帮助的“5.2. Importing Data Into A Repository ”中有更详细的解释。
  3. 使用TortoiseSVN客户端工具,把repo目录Import(导入)到服务端,服务端地址为domain.com/svnparentpath/MyNewRepository。这样我们就建立了这个Repository的目录层次。Revision编号为0。
  4. 删除repo目录下的三个空目录,把要导入的项目文件拷贝到这个目录下,当然也可以直接使用其它的目录。
  5. 使用TortoiseSVN客户端工具,把repo目录下的内容(已有项目文件)Import(导入)到服务端,和上次导入不同的是,上次是建立目录结构,而这次是导入项目文件,因此服务端地址为domain.com/svnparentpath/MyNewRepository/trunk,注意最后多了个trunk,也就是说现在导入的内容是作为工作状态的文件存在的,以后才可以根据需要在这个基础上建立tags或branches。
  6. checkout服务端的domain.com/svnparentpath/MyNewRepository/trunk到某个目录,我们就可以开始工作了。

在这里有一个比较绕圈的概念,那就是SVN的branches和tags是用“copy”的方式建立的,给用户的感觉就是拷贝了一个副本,所以我们分别建立了三个目录来保存他们,而日常的工作都在trunk下进行。而在CVS中,branches和tags都是附加在现有文件之上的,你的文件只“保存”一份,至少感觉上是这样的。

subversion和module_rewrite的小冲突?

我的Apache上同时挂有SVN和rewrite module,SVN配置都没有问题,通过HTTP访问正常,但通过Toroisesvn客户端访问总是不行,错误信息如下:

Error: PROPFIND request failed on ‘/svn/svntest’
Error: PROPFIND of ‘/svn/svntest’: 302 Found (http://www.domain.com)

经查,如果我去掉Apache的httpd.conf中的这两句,就可以正常使用了:

RewriteRule (.+)\/(\w+[^\/])$ $1/$2/ [R]
RewriteRule \/(\w+[^\/])$ /$1/ [R]

这两句RewriteRule是为了添加URL地址末尾的斜杠的,看来这两句对SVN的调用起了影响,原因大概是访问SVN的地址,比如是“/svn/svntest”时,RewriteRule会将其改写为“/svn/svntest/”,多了一个斜杠,然后SVN就不知所综了。

原来Apache 2.0的mod-dir已经有了自动添加斜杠的功能:

A "trailing slash" redirect is issued when the server receives a request for a URL http://servername/foo/dirname where dirname is a directory. Directories require a trailing slash, so mod_dir issues a redirect to http://servername/foo/dirname/.

不用劳烦RewriteRule了。

话又说回来,不管是mod_dir也好,RewriteRule也好,使用反向代理(ProxyPass)的时候还是有些问题,比如说,domain1.com/d2地址贝配置为转向到domain2.com,那么访问地址domain1.com/d2/subdir时,如果subdir时确实存在的,而输入地址的时候最后又没有输入斜杠/,那么你将会得到一个404错误页面,并且地址栏显示的是domain1.com/subdir,这个问题遇到很久了,一直不知道如何解决。通过端口进行反向代理好像同样存在这样的问题。

所以,使用反向代理时,一是老老实实的加上斜杠,二就是最好尽量采用如下的反向代理方式:domain1.com/subdir1定向到domain2.com/subdir2,并且subdir1和subdir2同名,这样就不会出现上面说到的问题了。