<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dongsheng&#039;s thoughts &#187; Programming</title>
	<atom:link href="http://log.dongsheng.org/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://log.dongsheng.org</link>
	<description></description>
	<lastBuildDate>Thu, 19 Jan 2012 08:40:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>iOS工程文件里的的Localizable.strings</title>
		<link>http://log.dongsheng.org/2012/01/19/localizable-strings/</link>
		<comments>http://log.dongsheng.org/2012/01/19/localizable-strings/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 08:39:25 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=131</guid>
		<description><![CDATA[要写个自动化生成iOS语言文件的PHP脚本，用vim打开Localizable.strings发现全是乱码，还怀疑是苹果搞出来的特殊二进制文件，没想到用TextWrangler打开完全没有问题，这个文件是小头的UTF-16文件，带BOM头。这样问题就好解决了，用PHP生成文件内容，然后用mbstring转换成UTF-16加上个BOM头就成，但实验了一上午，生出来的文件总是乱码，怀疑是mbstring的问题，然后换成用iconv转码竟然就没问题了，上一小段代码： $bom = chr(255) . chr(254); $string = "\"" . $key . "\"" . " = \"" . $value . "\";\n"; $text = iconv('UTF-8', 'UTF-16', $string); file_put_contents('Localizable.strings', $text);]]></description>
			<content:encoded><![CDATA[<p>要写个自动化生成iOS语言文件的PHP脚本，用vim打开Localizable.strings发现全是乱码，还怀疑是苹果搞出来的特殊二进制文件，没想到用TextWrangler打开完全没有问题，这个文件是小头的UTF-16文件，带BOM头。这样问题就好解决了，用PHP生成文件内容，然后用mbstring转换成UTF-16加上个BOM头就成，但实验了一上午，生出来的文件总是乱码，怀疑是mbstring的问题，然后换成用iconv转码竟然就没问题了，上一小段代码：</p>
<pre>
    $bom = chr(255) . chr(254);
    $string = "\"" . $key . "\"" . " = \"" . $value . "\";\n";
    $text = iconv('UTF-8', 'UTF-16', $string);
    file_put_contents('Localizable.strings', $text);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2012/01/19/localizable-strings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tomcat6的PermGen space错误</title>
		<link>http://log.dongsheng.org/2011/07/22/tomcat6-outofmemoryerror-permgen-space/</link>
		<comments>http://log.dongsheng.org/2011/07/22/tomcat6-outofmemoryerror-permgen-space/#comments</comments>
		<pubDate>Fri, 22 Jul 2011 07:59:39 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[alfresco]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[tomcat]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=123</guid>
		<description><![CDATA[最近又要折腾Alfresco，我真服了这一坨坨Java软件了，一个安装包400M，核心包也100M，里面引用的jar就有将近200个，Java就是全球变暖的罪魁祸首。 每次安装Java软件必然要碰到各种各样麻烦问题，这次是4G内存也装不了Alfresco，反复报错：java.lang.OutOfMemoryError: PermGen space，我在终端翻了四五页才看到这个关键错误，前面报的全是反人类的不相关内容。解决办法是给tomcat传个参数进去，我得记下来，下次它肯定还得给我脸色看。 我的tomcat是用jsvc启动的加如下参数： -Xmx1024m \ -Xms1024m \ -XX:MaxPermSize=128M \ 感谢Java，你又浪费了我一个下午。]]></description>
			<content:encoded><![CDATA[<p>最近又要折腾Alfresco，我真服了这一坨坨Java软件了，一个安装包400M，核心包也100M，里面引用的jar就有将近200个，Java就是全球变暖的罪魁祸首。</p>
<p>每次安装Java软件必然要碰到各种各样麻烦问题，这次是4G内存也装不了Alfresco，反复报错：java.lang.OutOfMemoryError: PermGen space，我在终端翻了四五页才看到这个关键错误，前面报的全是反人类的不相关内容。解决办法是给tomcat传个参数进去，我得记下来，下次它肯定还得给我脸色看。</p>
<p>我的tomcat是用jsvc启动的加如下参数：</p>
<pre>
-Xmx1024m \
-Xms1024m \
-XX:MaxPermSize=128M \
</pre>
<p>感谢Java，你又浪费了我一个下午。</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2011/07/22/tomcat6-outofmemoryerror-permgen-space/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moodle Moot 2011</title>
		<link>http://log.dongsheng.org/2011/07/19/mootau11/</link>
		<comments>http://log.dongsheng.org/2011/07/19/mootau11/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 04:56:49 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[moodle]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=96</guid>
		<description><![CDATA[这个博克存在很久了，但很少涉及跟我工作相关的东西：我为一个叫Moodle的开源课程管理软件工作，可能很多人不知道Moodle是干什么的，跟我两年前参加布里斯班Moodle moot时的反应类似，当看到几百号人从世界各地赶到布里斯班参加会议，我非常惊讶，也挺自豪：我写的代码竟然有这么多人在使用，还是世界各地的。 两年后的今天再来悉尼Convention Center参加会议，发现使用Moodle的学校又大大壮大了，澳洲八大名校已有一半迁移到了Moodle（澳洲国立大学，新南威尔士大学，西澳大学和莫纳什大学），使用Moodle的TAFE和中小学更是不计其数，大约40%的学校是Moodle用户，还有个好消息是有更多的学校已经升级到2.0。比较有意思的是在会场还看到一个BlackBoard的展台，不过看上去不是很受欢迎 我来的一个目的是介绍正在开发中的Moodle for iPhone，这一个多月写的我死去活来的程序基本成型了，这个版本的功能不多，主要是Moodle端需要提供更多WebService，这个会在Moodle2.2发布的时候获得改善，做完Presentaion以后反响很热烈，有几个机构询问能否给大学提供定制版本，这对推销学校形象很有力。还有几家关心android版本的开发，可哥近期内可能不会碰android开发，cocoa touch够我喝一壶了。 还有件有意思的事，昨天参加一个session时presenter在facebook里搜索moodle，找到一本书讲解我去年写的一个核心组件 Moodle 2 The File Picker]]></description>
			<content:encoded><![CDATA[<p>这个博克存在很久了，但很少涉及跟我工作相关的东西：我为一个叫Moodle的开源课程管理软件工作，可能很多人不知道Moodle是干什么的，跟我两年前参加布里斯班Moodle moot时的反应类似，当看到几百号人从世界各地赶到布里斯班参加会议，我非常惊讶，也挺自豪：我写的代码竟然有这么多人在使用，还是世界各地的。</p>
<p>两年后的今天再来悉尼Convention Center参加会议，发现使用Moodle的学校又大大壮大了，澳洲八大名校已有一半迁移到了Moodle（澳洲国立大学，新南威尔士大学，西澳大学和莫纳什大学），使用Moodle的TAFE和中小学更是不计其数，大约40%的学校是Moodle用户，还有个好消息是有更多的学校已经升级到2.0。比较有意思的是在会场还看到一个BlackBoard的展台，不过看上去<a href="https://twitter.com/#!/dcai/status/92514578046533632" target="_blank">不是很受欢迎</a> <img src='http://log.dongsheng.org/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  </p>
<p>我来的一个目的是介绍正在开发中的Moodle for iPhone，这一个多月写的我死去活来的程序基本成型了，这个版本的功能不多，主要是Moodle端需要提供更多WebService，这个会在Moodle2.2发布的时候获得改善，做完Presentaion以后反响很热烈，有几个机构询问能否给大学提供定制版本，这对推销学校形象很有力。还有几家关心android版本的开发，可哥近期内可能不会碰android开发，cocoa touch够我喝一壶了。</p>
<p>还有件有意思的事，昨天参加一个session时presenter在facebook里搜索moodle，找到一本书讲解我去年写的一个核心组件 <img src='http://log.dongsheng.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  <a href="http://www.lulu.com/product/paperback/moodle-2-the-file-picker/16060624" target="_blank">Moodle 2 The File Picker</a></p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2011/07/19/mootau11/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>tig真好用</title>
		<link>http://log.dongsheng.org/2011/05/02/tig%e7%9c%9f%e5%a5%bd%e7%94%a8/</link>
		<comments>http://log.dongsheng.org/2011/05/02/tig%e7%9c%9f%e5%a5%bd%e7%94%a8/#comments</comments>
		<pubDate>Mon, 02 May 2011 07:20:47 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[tig]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=120</guid>
		<description><![CDATA[tig是git的浏览器，我一直用来看代码库的commits历史，今天仔细看了下manual发现很多有意思的功能， 视图切换： 在主界面按大写S可以察看当前分支的状态，按t打开文件树，在文件树上按B可以察看blame界面，按H显示本地分支，按l显示log summery，在commit上按d显示commit内容。 显示选项： 在察看commit的界面里按.可以切换行号。 在主界面按大写D可以调整commit日期显示。 主界面按A选择显示committer的方式 其他： 方便的cherry-pick，用H切换到别的分支，选中commit然后按大写C就能完成cherry-pick了！]]></description>
			<content:encoded><![CDATA[<p><a href="http://jonas.nitro.dk/tig/">tig</a>是git的浏览器，我一直用来看代码库的commits历史，今天仔细看了下manual发现很多有意思的功能，</p>
<p>视图切换：<br />
在主界面按大写S可以察看当前分支的状态，按t打开文件树，在文件树上按B可以察看blame界面，按H显示本地分支，按l显示log summery，在commit上按d显示commit内容。</p>
<p>显示选项：<br />
在察看commit的界面里按.可以切换行号。<br />
在主界面按大写D可以调整commit日期显示。<br />
主界面按A选择显示committer的方式</p>
<p>其他：<br />
方便的cherry-pick，用H切换到别的分支，选中commit然后按大写C就能完成cherry-pick了！</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2011/05/02/tig%e7%9c%9f%e5%a5%bd%e7%94%a8/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>修改Ｗordpress的Permalinks</title>
		<link>http://log.dongsheng.org/2010/11/25/change-wordpress-permalinks/</link>
		<comments>http://log.dongsheng.org/2010/11/25/change-wordpress-permalinks/#comments</comments>
		<pubDate>Thu, 25 Nov 2010 04:06:54 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Permalinks]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/archives/103</guid>
		<description><![CDATA[不知道有多少人跟我一样讨厌Wordpress的Revision和auto-save，这两个功能在Wordpress的posts表里创建大量垃圾记录，即使我在wp-config.php里设置了： define('WP_POST_REVISIONS', false); define('AUTOSAVE_INTERVAL', 60000); 还是无法彻底消灭垃圾记录。其实这对性能啥的没什么影响，主要是种程序员的洁癖，本来我的posts表是整整齐齐按ID排序的，但Wordpress这么整以后，本来连续的ID全打乱了，我的Permalinks就是依赖ID的。 所以我决定把Permalinks改成年月日+postname的形式，这样看起来就没那么乱了。在这么做之前最好设置301转向，不然apache的记录里就全是404了。这个可以用.htaccess来实现，在Wordpress目录的.htaccess里加上： RewriteEngine On RewriteBase / RewriteRule ^archives/([0-9]+)$ \?p=$1 [R] 这样原来http://log.dongsheng.org/archives/2重定向到http://log.dongsheng.org/?p=2，然后wordpress会把这个地址换成新的年月日形式。 更新：29/11/2010 还要再加一条规则重定向trackback： RewriteRule ^archives/([0-9]+)/trackback$ wp_trackback.php\?p=$1 [R]]]></description>
			<content:encoded><![CDATA[<p>不知道有多少人跟我一样讨厌Wordpress的Revision和auto-save，这两个功能在Wordpress的posts表里创建大量垃圾记录，即使我在wp-config.php里设置了：</p>
<pre>define('WP_POST_REVISIONS', false);
define('AUTOSAVE_INTERVAL', 60000);</pre>
<p>还是无法彻底消灭垃圾记录。其实这对性能啥的没什么影响，主要是种程序员的洁癖，本来我的posts表是整整齐齐按ID排序的，但Wordpress这么整以后，本来连续的ID全打乱了，我的Permalinks就是依赖ID的。</p>
<p>所以我决定把Permalinks改成年月日+postname的形式，这样看起来就没那么乱了。在这么做之前最好设置301转向，不然apache的记录里就全是404了。这个可以用.htaccess来实现，在Wordpress目录的.htaccess里加上：</p>
<pre>RewriteEngine On
RewriteBase /
RewriteRule ^archives/([0-9]+)$ \?p=$1 [R]</pre>
<p>这样原来http://log.dongsheng.org/archives/2重定向到http://log.dongsheng.org/?p=2，然后wordpress会把这个地址换成新的年月日形式。</p>
<h4>更新：29/11/2010</h4>
<p>还要再加一条规则重定向trackback：</p>
<pre>RewriteRule ^archives/([0-9]+)/trackback$ wp_trackback.php\?p=$1 [R]</pre>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2010/11/25/change-wordpress-permalinks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Moving to Git</title>
		<link>http://log.dongsheng.org/2010/11/23/moving-to-git/</link>
		<comments>http://log.dongsheng.org/2010/11/23/moving-to-git/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 11:00:31 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[moodle]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/archives/86</guid>
		<description><![CDATA[如果一切顺利的话，Moodle会在这周把主代码库从cvs换到git，之前已经有几个子项目在用git协作了，这次迁移之后，标志着核心开发团队彻底抛弃了cvs。换版本管理工具绝对不是闲的蛋疼才干的事，工作将近三年实在是吃够了cvs的苦，缓慢的diff，古怪的$id:$，作为协作工具却没有解决团队开发的协作问题。 今天我们团队花了一整天研究git，发现迁移到git最大的难度是图形化工具的匮乏，Netbeans和Eclipse还没有正式发布的git插件，SmartGit算是最好的图形化工具的，但竟然不支持添加远程代码库（git remote），最后还是不得不通过命令行完成。对于初学者来说git那一大坨命令有点吓人，所以当我说用命令行做更快时，被人狠狠鄙视了，然后我用git命令，另一个同事用netbeans+smartgit比了下，任务是创建原始项目的clone，添加远程代码库，合并并推送。结果在他研究Netbeans测试版蹦出的那一坨Java异常的时候，命令行就搞定了，超级简单。虽然命令行的学习曲线比较陡，但利于开发人员彻底理解Git的工作方式，且不会被锁定到某个特定的GUI工具。]]></description>
			<content:encoded><![CDATA[<p>如果一切顺利的话，Moodle会在这周把主代码库从cvs换到git，<a href="http://log.dongsheng.org/archives/92">之前已经有几个子项目在用git协作了</a>，这次迁移之后，标志着核心开发团队彻底抛弃了cvs。换版本管理工具绝对不是闲的蛋疼才干的事，工作将近三年实在是吃够了cvs的苦，缓慢的diff，古怪的$id:$，作为协作工具却没有解决团队开发的协作问题。</p>
<p>今天我们团队花了一整天研究git，发现迁移到git最大的难度是图形化工具的匮乏，Netbeans和Eclipse还没有正式发布的git插件，SmartGit算是最好的图形化工具的，但竟然不支持添加远程代码库（git remote），最后还是不得不通过命令行完成。对于初学者来说git那一大坨命令有点吓人，所以当我说用命令行做更快时，被人狠狠鄙视了，然后我用git命令，另一个同事用netbeans+smartgit比了下，任务是创建原始项目的clone，添加远程代码库，合并并推送。结果在他研究Netbeans测试版蹦出的那一坨Java异常的时候，命令行就搞定了，超级简单。虽然命令行的学习曲线比较陡，但利于开发人员彻底理解Git的工作方式，且不会被锁定到某个特定的GUI工具。</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2010/11/23/moving-to-git/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>简单总结一下 Git 的使用</title>
		<link>http://log.dongsheng.org/2010/08/25/git-in-actoin/</link>
		<comments>http://log.dongsheng.org/2010/08/25/git-in-actoin/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 15:14:44 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=92</guid>
		<description><![CDATA[前段时间折腾Moodle的Quesion/Quiz模块，最大的难点不是开发，而是怎么跟另一个维护该模块的同事讨论，这哥们远在大不列颠，每次在tracker上留言都不得不等到第二天起床才能看到他的回复，更烦的是要review一个个patch，小点还好说，这动辄一万多行的大patch真不好一行行的解释。 然后决定把战线延伸到GitHub。对小项目来说Git相对CVS的优势不明显，徒增学习曲线，但对于Moodle这种庞大的开源软件，Git却是大大降低复杂程度，最重要的一点是创建分支的成本为零，我可以单独创建新分支以开发某特性，开发过程中可以方便的与上游代码合并，之前的cvs是无法享受这种便利的，我们不得不checkout多份拷贝进行测试。另一个很重要的特点是Git在本地保存全部改动历史，这样可以极其快捷的进行diff和blame 再说说GitHub，对于项目管理来说，GitHub肯定是不如Jira，但细化到编码这个层次，GitHub比Jira好很多，首先Jira没有官方的Git支持，无法追踪相关的Git提交，然后Jira不便于Code review（可能有好的插件会支持，说错了请指正）。GitHub在这方面做的很好，可以在git commit做inline note，代码浏览比viewvc强出一个世纪。 转到GitHub后，工作效率提高了很多，我白天把改动push到我的在GitHub的分支上，然后同事做Code review，提交改动，第二天我把他的改动合并到我的分支上，然后继续昨天的工作…… Git实际上是个新的开发模型，从编码到项目管理都不同于cvs时代。 简单总结一下Git的使用以 Moodle在GitHub的mirror为例。 打开 http://github.com/moodle/moodle，然后Fork，这个并不是必须的，之后可以通过git remote添加新的上游代码库 git clone 我自己的代码库 我不喜欢origin这个默认远程代码库名，所以重命名一下：git remote rename origin github，运行一下 git branch -r 发现远程名字变了 我之前fork的Moodle并不是官方的，换成官方的git源：git remote add upstream git://git.moodle.org/moodle.git，然后：git fetch upstream 我要创建一个我自己的分支newfeature：git branch newfeature，切换到这个分支需运行：git checkout newfeature 这个时候newfeature是个本地分支，在github上是不存在的，我得把这个分支push到github上，同事才能看到我的改动，运行：git push github，打开.git/config [branch "newfeature"] remote = github merge = refs/heads/newfeature 如果没有就加上这段，有了这段，就可以git pull直接获取并合并，有个命令可以设置git checkout &#8211;track github/newfeature，但我觉的用配置文件更直观 如果上游更新了，我就需要合并：git [...]]]></description>
			<content:encoded><![CDATA[<p>前段时间折腾Moodle的Quesion/Quiz模块，最大的难点不是开发，而是怎么跟另一个维护该模块的同事讨论，这哥们远在大不列颠，每次在tracker上留言都不得不等到第二天起床才能看到他的回复，更烦的是要review一个个patch，小点还好说，这动辄一万多行的大patch真不好一行行的解释。</p>
<p>然后决定把战线延伸到GitHub。对小项目来说Git相对CVS的优势不明显，徒增学习曲线，但对于Moodle这种庞大的开源软件，Git却是大大降低复杂程度，最重要的一点是创建分支的成本为零，我可以单独创建新分支以开发某特性，开发过程中可以方便的与上游代码合并，之前的cvs是无法享受这种便利的，我们不得不checkout多份拷贝进行测试。另一个很重要的特点是Git在本地保存全部改动历史，这样可以极其快捷的进行diff和blame <img src='http://log.dongsheng.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>再说说GitHub，对于项目管理来说，GitHub肯定是不如<a href="http://www.atlassian.com/software/jira/">Jira</a>，但细化到编码这个层次，GitHub比Jira好很多，首先Jira没有官方的Git支持，无法追踪相关的Git提交，然后Jira不便于Code review（可能有好的插件会支持，说错了请指正）。GitHub在这方面做的很好，可以在git commit做inline note，代码浏览比<a href="http://www.viewvc.org/">viewvc</a>强出一个世纪。</p>
<p>转到GitHub后，工作效率提高了很多，我白天把改动push到我的在GitHub的分支上，然后同事做Code review，提交改动，第二天我把他的改动合并到我的分支上，然后继续昨天的工作……</p>
<p>Git实际上是个新的开发模型，从编码到项目管理都不同于cvs时代。</p>
<p>简单总结一下Git的使用以 Moodle在GitHub的mirror为例。</p>
<ol>
<li> 打开 http://github.com/moodle/moodle，然后Fork，这个并不是必须的，之后可以通过git remote添加新的上游代码库</li>
<li> git clone 我自己的代码库</li>
<li> 我不喜欢origin这个默认远程代码库名，所以重命名一下：git remote rename origin github，运行一下 git branch -r 发现远程名字变了</li>
<li> 我之前fork的Moodle并不是官方的，换成官方的git源：git remote add upstream git://git.moodle.org/moodle.git，然后：git fetch upstream</li>
<li>  我要创建一个我自己的分支newfeature：git branch newfeature，切换到这个分支需运行：git checkout newfeature</li>
<li>这个时候newfeature是个本地分支，在github上是不存在的，我得把这个分支push到github上，同事才能看到我的改动，运行：git push github，打开.git/config
<pre>
[branch "newfeature"]
remote = github
merge = refs/heads/newfeature
</pre>
<p>如果没有就加上这段，有了这段，就可以git pull直接获取并合并，有个命令可以设置git checkout &#8211;track github/newfeature，但我觉的用配置文件更直观</p>
</li>
<li>如果上游更新了，我就需要合并：git merge upstream/cvshead</li>
<li>删除本地分支：git branch -d newfeature，删除远程分支：git push :newfeature</li>
<li>一般的提交就不多说了，跟cvs之流一样，不同的是提交完了要git push才能把你的改动推送到远程服务器上</li>
<li>git可以比较分支，这样你可以比较你的当前分支和主干，生成一个patch提交到cvs里</li>
</ol>
<p>在 ~/.gitconfig 上下点功夫，能提高工作效率，Stack overflow上有个讨论不错：<a href="http://stackoverflow.com/questions/267761/what-does-your-gitconfig-contain">What does your ~/.gitconfig contain?</a></p>
<p>最后推荐两个软件，GitX和tig，两个都是Git浏览器，前者是Mac的，后者是终端上的，对于常用ssh的人，后者有用，有效率的多。</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2010/08/25/git-in-actoin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WordPress 3</title>
		<link>http://log.dongsheng.org/2010/06/18/wordpress3/</link>
		<comments>http://log.dongsheng.org/2010/06/18/wordpress3/#comments</comments>
		<pubDate>Fri, 18 Jun 2010 09:00:30 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/archives/73</guid>
		<description><![CDATA[WordPress的SVN更新够快的，3.0刚刚发布，TRUNK的版本号就变成了3.1-ALPHA]]></description>
			<content:encoded><![CDATA[<p>WordPress的SVN更新够快的，3.0刚刚发布，TRUNK的版本号就变成了3.1-ALPHA</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2010/06/18/wordpress3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP成员函数中竟然也能用static声明变量</title>
		<link>http://log.dongsheng.org/2010/04/07/using-static-variable-in-class-method/</link>
		<comments>http://log.dongsheng.org/2010/04/07/using-static-variable-in-class-method/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 02:08:57 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=84</guid>
		<description><![CDATA[又发现一个PHP Feature，PHP成员函数中竟然也能用static声明变量。怎么想怎么奇怪，你都创建新实例了，怎么static还是有效？不过有时候还蛮有用的。 class static_var { function __construct($name) { $this->name = $name; } function output() { static $counter; $counter++; echo $counter.'&#124;'.$this->name.'&#124;'; } } $t1 = new static_var('take 1'); $t1->output(); $t2 = new static_var('take 2'); $t2->output();]]></description>
			<content:encoded><![CDATA[<p>又发现一个PHP Feature，PHP成员函数中竟然也能用static声明变量。怎么想怎么奇怪，你都创建新实例了，怎么static还是有效？不过有时候还蛮有用的。</p>
<pre>
class static_var {
    function __construct($name) {
        $this->name = $name;
    }
    function output() {
        static $counter;
        $counter++;
        echo $counter.'|'.$this->name.'|';
    }
}
$t1 = new static_var('take 1');
$t1->output();
$t2 = new static_var('take 2');
$t2->output();
</pre>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2010/04/07/using-static-variable-in-class-method/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mercurial for Google Code 的几个小技巧</title>
		<link>http://log.dongsheng.org/2009/07/24/mercurial-for-google-code-tips/</link>
		<comments>http://log.dongsheng.org/2009/07/24/mercurial-for-google-code-tips/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 14:31:22 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[Mercurial]]></category>
		<category><![CDATA[scm]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/archives/64</guid>
		<description><![CDATA[为了方便改本站主题，我把代码放在了 Google Code 上，一冲动把代码管理工具选成了 Mercurial 而不是熟悉的 SVN，Mercurial 操作起来跟 Git 差不多，但配置碰到一些小问题。 1. 无法象 SVN 一样记住登录密码 解决办法：打开 .hg/hgrc ，默认是这样的： [paths] default = https://projectname.googlecode.com/hg 把密码和用户名填到 URL 里就行啦 [paths] default = https://accountname:password@projectname.googlecode.com/hg 2. 提示没有设置用户名 解决办法：在 .hg/hgrc 中添加 [ui] username = Dongsheng Cai]]></description>
			<content:encoded><![CDATA[<p>为了方便改本站主题，我把代码放在了 Google Code 上，一冲动把代码管理工具选成了 Mercurial 而不是熟悉的 SVN，Mercurial 操作起来跟 Git 差不多，但配置碰到一些小问题。<br />
1. 无法象 SVN 一样记住登录密码<br />
解决办法：打开 .hg/hgrc ，默认是这样的：</p>
<pre>
[paths]
default = https://projectname.googlecode.com/hg
</pre>
<p>把密码和用户名填到 URL 里就行啦</p>
<pre>
[paths]
default = https://accountname:password@projectname.googlecode.com/hg
</pre>
<p>2. 提示没有设置用户名<br />
解决办法：在 .hg/hgrc 中添加</p>
<pre>
[ui]
username = Dongsheng Cai
</pre>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2009/07/24/mercurial-for-google-code-tips/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>在 Patch 中添加新文件</title>
		<link>http://log.dongsheng.org/2009/07/06/including-new-files-in-a-patch/</link>
		<comments>http://log.dongsheng.org/2009/07/06/including-new-files-in-a-patch/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 08:10:39 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cvs]]></category>
		<category><![CDATA[cvsdo]]></category>
		<category><![CDATA[patch]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/archives/49</guid>
		<description><![CDATA[我们的项目使用 CVS 托管代码，在把提交代码前，我们通常会创建一个 Patch，然后放到 Tracker 上做质量检查。 作为一个不会用 IDE 的程序员，Patch 一般是这样创建的： cvs diff file1.php > file1.patch 问题是，这个命令无法处理 CVS 中不存在的文件，即新文件，诸如 Netbeans 和 Eclipse 等 IDE 都有办法为新建文件创建 Patch（因为我看到同事发的 Patch 里有 Eclipse 的标示），其实用命令行也是能实现这个功能的。 首先要下载一个叫 cvsdo 的工具，这是个 Perl 文件，下载到 /usr/bin/ 下，然后加上可执行权限就完事了。回到代码目录，执行 cvsdo add newfile.php，然后 cvs diff -uN newfile.php > newfile.patch，这样就能可以对新文件做 cvs diff 了。这个脚本的原理就是修改了 CVS/Entries，让 cvs 以为这个文件已经在 cvs 仓库里了。注意，要给 cvs diff [...]]]></description>
			<content:encoded><![CDATA[<p>我们的项目使用 CVS 托管代码，在把提交代码前，我们通常会创建一个 Patch，然后放到 Tracker 上做质量检查。<br />
作为一个不会用 IDE 的程序员，Patch 一般是这样创建的：</p>
<pre>cvs diff file1.php > file1.patch</pre>
<p>问题是，这个命令无法处理 CVS 中不存在的文件，即新文件，诸如 Netbeans 和 Eclipse 等 IDE 都有办法为新建文件创建 Patch（因为我看到同事发的 Patch 里有 Eclipse 的标示），其实用命令行也是能实现这个功能的。</p>
<p>首先要下载一个叫 <a href="http://viper.haque.net/~timeless/redbean/cvsdo">cvsdo</a> 的工具，这是个 Perl 文件，下载到 /usr/bin/ 下，然后加上可执行权限就完事了。回到代码目录，执行 cvsdo add newfile.php，然后 cvs diff -uN newfile.php > newfile.patch，这样就能可以对新文件做 cvs diff 了。这个脚本的原理就是修改了 CVS/Entries，让 cvs 以为这个文件已经在 cvs 仓库里了。注意，要给 cvs diff 使用 -N 参数，这样才能输出新文件。如果嫌 cvs diff 后面跟参数麻烦，可以创建 ~/.cvsrc</p>
<pre>
cvs -q
update -dPA
diff -uN
</pre>
<p>这样每次执行 cvs diff 就会默认加上这些参数的。</p>
<p>参考：</p>
<ol>
<li><a href="http://http://viper.haque.net/~timeless/redbean/">CVSdo</a></li>
<li><a href="https://developer.mozilla.org/En/Creating_a_patch">Creating a patch</a></li>
</ol>
<p>Updated on 7th, July, 2009<br />
补充在 Netbeans 中创建 Patch 的方法，在左边的文件树中选中修改了的文件，然后 Team -> CVS -> Export Diff Patch</p>
<p>Updated on 16th, July, 2009<br />
做了一个 Archlinux 上的 PKGBUILD，名字 cvsutils，直接装上就都有啦</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2009/07/06/including-new-files-in-a-patch/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>在提交源码前检测调试代码</title>
		<link>http://log.dongsheng.org/2009/04/29/code-review-before-commit/</link>
		<comments>http://log.dongsheng.org/2009/04/29/code-review-before-commit/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 08:37:01 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[cvs]]></category>
		<category><![CDATA[firephp]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/archives/57</guid>
		<description><![CDATA[做 Ajax 开发最大的痛苦就是调试不易，尤其是 PHP 脚本跟远程服务器交互中的调试更是不易，还好有 FirePHP，有热心人做了 FirePHP 的 Moodle 绑定，目前这个补丁还没有提交到 CVS，所以一不小心我就把调式代码放在源码里忘了去掉，然后别的开发者 update 以后就会得到一个未定义函数错误，必须想办法避免这个错误了。 首先在 vim 配置文件中加入 match ErrorMsg /echo_fb/ 这将 echo_fb 函数标记为错误，警醒我提交前要去掉。这招显然不够狠，我要是连看都不看就把 vim 关了怎么办？最有效的办法还是在提交前用 grep 搜索文件，所有有了这个 shell 脚本： ci (){ if [ $# -eq 0 ]; then echo "CVS CHECKIN: No arguments entered."; return 1 else echo "Checking in file(s): ${@:2}"; echo "Working ..."; if [...]]]></description>
			<content:encoded><![CDATA[<p>做 Ajax 开发最大的痛苦就是调试不易，尤其是 PHP 脚本跟远程服务器交互中的调试更是不易，还好有 <a href="http://www.firephp.org/">FirePHP</a>，有热心人做了 FirePHP 的<a href="http://tracker.moodle.org/browse/MDL-16371"> Moodle 绑定</a>，目前这个补丁还没有提交到 CVS，所以一不小心我就把调式代码放在源码里忘了去掉，然后别的开发者 update 以后就会得到一个未定义函数错误，必须想办法避免这个错误了。</p>
<p>首先在 vim 配置文件中加入</p>
<pre>
match ErrorMsg /echo_fb/
</pre>
<p>这将 echo_fb 函数标记为错误，警醒我提交前要去掉。这招显然不够狠，我要是连看都不看就把 vim 关了怎么办？最有效的办法还是在提交前用 grep 搜索文件，所有有了这个 shell 脚本：</p>
<pre>
ci (){
    if [ $# -eq 0 ]; then
        echo "CVS CHECKIN: No arguments entered.";
        return 1
    else
        echo "Checking in file(s): ${@:2}";
        echo "Working ...";
        if [ "$(grep "echo_fb" ${@:2})" ]; then
            echo 'Remove debug code firstly';
        else
            cvs ci -m "\"$1\"" ${@:2}
        fi

    fi
}
</pre>
<p>这样基本就没问题了。</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2009/04/29/code-review-before-commit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Movable Type 4 installation notes</title>
		<link>http://log.dongsheng.org/2009/03/17/movable-type-4-installation-notes/</link>
		<comments>http://log.dongsheng.org/2009/03/17/movable-type-4-installation-notes/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 00:55:30 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[movabletype]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=37</guid>
		<description><![CDATA[Installation 1. Uncompress movable type package, move mt-static folder to htdocs/ 2. Modify mt-config.cgi, choose your prefered DBI and remove the other chunk of code, add MailEncoding UTF-8 to mt-config.pl 3. Move all the other files to cgi-bin/mt/, assign executive right to cgi scripts 4. Access http://localhost/cgi-bin/mt/mt.cgi Theming 1. Modify the css file which can [...]]]></description>
			<content:encoded><![CDATA[<p>Installation<br />
1. Uncompress movable type package, move mt-static folder to htdocs/<br />
2. Modify mt-config.cgi, choose your prefered DBI and remove the other chunk of code, add</p>
<pre>MailEncoding UTF-8</pre>
<p> to mt-config.pl<br />
3. Move all the other files to cgi-bin/mt/, assign executive right to cgi scripts<br />
4. Access http://localhost/cgi-bin/mt/mt.cgi</p>
<p>Theming<br />
1. Modify the css file which can be located at static/themes-base/blog.css<br />
2. Remove &#8220;powered by&#8221; widget<br />
3. Modify template in admin page<br />
4. To backup templates, every template should be linked with a local file, then you can modify the files on disk to customize looking.</p>
<p>Plugins<br />
Comming soon</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2009/03/17/movable-type-4-installation-notes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac OS X 上构建 PHP5</title>
		<link>http://log.dongsheng.org/2009/02/28/build-php5-on-mac/</link>
		<comments>http://log.dongsheng.org/2009/02/28/build-php5-on-mac/#comments</comments>
		<pubDate>Sat, 28 Feb 2009 04:47:44 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=36</guid>
		<description><![CDATA[在安装 PHP 前先安装 Mysql，Apache2 我用的是 Mac 内置的那个。下载 PHP 5.2.9 源码，然后执行： ./configure &#8211;prefix=/usr/local &#8211;with-iconv &#8211;with-gd &#8211;with-xmlrpc &#8211;enable-zip &#8211;with-openssl=/usr &#8211;enable-ftp &#8211;enable-sockets &#8211;enable-mbstring &#8211;enable-bcmath &#8211;with-curl &#8211;with-zlib-dir=/usr &#8211;with-mysqli=/usr/local/mysql/bin/mysql_config &#8211;with-mysql=/usr/local/mysql &#8211;with-config-file-path=/etc/php.ini &#8211;with-apxs2=/usr/sbin/apxs 配置过程中会因为缺少某些开发包而出错，用 Mac port 安装一下就可以了 make &#038;&#038; sudo make install 这样创建的 libphp5.so 是无法被 Apache 载入的，需要用 lipo 处理一下 Apache 的二进制程序 /usr/sbin$ sudo cp httpd httpd-fat /usr/sbin$ sudo lipo httpd -thin [...]]]></description>
			<content:encoded><![CDATA[<p>在安装 PHP 前先安装 Mysql，Apache2 我用的是 Mac 内置的那个。下载 PHP 5.2.9 源码，然后执行：<br />
./configure &#8211;prefix=/usr/local &#8211;with-iconv &#8211;with-gd<br />
&#8211;with-xmlrpc &#8211;enable-zip &#8211;with-openssl=/usr &#8211;enable-ftp &#8211;enable-sockets<br />
&#8211;enable-mbstring &#8211;enable-bcmath &#8211;with-curl &#8211;with-zlib-dir=/usr<br />
&#8211;with-mysqli=/usr/local/mysql/bin/mysql_config<br />
&#8211;with-mysql=/usr/local/mysql<br />
&#8211;with-config-file-path=/etc/php.ini &#8211;with-apxs2=/usr/sbin/apxs<br />
配置过程中会因为缺少某些开发包而出错，用 Mac port 安装一下就可以了</p>
<p>make &#038;&#038; sudo make install</p>
<p>这样创建的 libphp5.so 是无法被 Apache 载入的，需要用 lipo 处理一下 Apache 的二进制程序</p>
<p>/usr/sbin$ sudo cp httpd httpd-fat<br />
/usr/sbin$ sudo lipo httpd -thin i386 -output httpd</p>
<p>完了重启 Apache 就可以使用了：<br />
sudo apachectl restart</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2009/02/28/build-php5-on-mac/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>原来 Mac 自带了 PHP</title>
		<link>http://log.dongsheng.org/2009/01/11/buildin-php-on-mac/</link>
		<comments>http://log.dongsheng.org/2009/01/11/buildin-php-on-mac/#comments</comments>
		<pubDate>Sun, 11 Jan 2009 09:30:47 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=31</guid>
		<description><![CDATA[1. 启用 Apache，System Preferences -> Sharing -> Web Sharing 2. 编辑 /etc/apache2/httpd.conf，把启用 php5 的那一行，反注释掉，然后修改 DirectoryIndex，加上 index.php，然后创建 php 配置文件： mv /etc/php.ini.default /etc/php.ini 重启 apache： apachectl restart 3. 文档根目录在 /Library/WebServer/Documents，看了看 phpninfo 发现支持的扩展还不算太少]]></description>
			<content:encoded><![CDATA[<p>1. 启用 Apache，System Preferences -> Sharing -> Web Sharing<br />
2. 编辑 /etc/apache2/httpd.conf，把启用 php5 的那一行，反注释掉，然后修改 DirectoryIndex，加上 index.php，然后创建 php 配置文件：</p>
<pre>
mv /etc/php.ini.default /etc/php.ini
</pre>
<p>重启 apache：</p>
<pre>
apachectl restart
</pre>
<p>3. 文档根目录在 /Library/WebServer/Documents，看了看 phpninfo 发现支持的扩展还不算太少 <img src='http://log.dongsheng.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2009/01/11/buildin-php-on-mac/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DSpace 安装笔记</title>
		<link>http://log.dongsheng.org/2008/12/10/dspace-installation-notes/</link>
		<comments>http://log.dongsheng.org/2008/12/10/dspace-installation-notes/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 09:18:08 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[dspace]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=26</guid>
		<description><![CDATA[DSpace 是被学术，非盈利，商业组织广泛应用的数字仓库管理软件，它可以管理包括文本，图片，动画，视频等各种数据文件，它是 BSD 协议下的开源软件。 DSpace 可以从源码或二进制包安装，我选择下载了一个 1.9 M 的二进制包，心里挺高兴，心想 Java 软件怎么做的这么小了？ 但一解压就看到一个 pom.xml，心里一凉，说完了，这个包是想用 maven 下载第三方库啊！进到根目录下的 [dspace] 目录，然后运行 mvn install，这会自动下载运行 dspace 所需要的所有包，下载了半天，这个只有 1.9M 的安装包变成了近 400M 的庞然大物。在上面的步骤里 maven 只负责包依赖关系，然后要用 ant 把 dspace 安装到适当的位置，进入 [dspace]/target/dspace-{$version}-build.dir/，编辑 config/dspace.cfg，把 dspace.dir 设置成 /usr/share/dspace，其他选项都很简单，看看就明白了。 运行 ant fresh_install 把 dspace 安装到目标位置，在我的例子里 /usr/share/dspace/webapps 是相关 web 文件。 最后设置 [tomcat]/conf/server.xml 在 host 段中加入： &#60;Context path="/jspui" docBase="/usr/share/dspace/webapps/jspui" debug="1" [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.dspace.org/index.php/Introducing-DSpace/">DSpace</a> 是被学术，非盈利，商业组织广泛应用的数字仓库管理软件，它可以管理包括文本，图片，动画，视频等各种数据文件，它是 BSD 协议下的开源软件。</p>
<p>DSpace 可以从源码或二进制包安装，我选择下载了一个 1.9 M 的二进制包，心里挺高兴，心想 Java 软件怎么做的这么小了？<br />
但一解压就看到一个 pom.xml，心里一凉，说完了，这个包是想用 <a href="http://maven.apache.org/">maven</a> 下载第三方库啊！进到根目录下的 [dspace] 目录，然后运行 mvn install，这会自动下载运行 dspace 所需要的所有包，下载了半天，这个只有 1.9M 的安装包变成了近 400M 的庞然大物。在上面的步骤里 maven 只负责包依赖关系，然后要用 ant 把 dspace 安装到适当的位置，进入 [dspace]/target/dspace-{$version}-build.dir/，编辑 config/dspace.cfg，把 dspace.dir 设置成 /usr/share/dspace，其他选项都很简单，看看就明白了。<br />
运行 ant fresh_install 把 dspace 安装到目标位置，在我的例子里 /usr/share/dspace/webapps 是相关 web 文件。<br />
最后设置 [tomcat]/conf/server.xml 在 host 段中加入：</p>
<pre>
      &lt;Context path="/jspui" docBase="/usr/share/dspace/webapps/jspui" debug="1"
          reloadable="true" cachingAllowed="false"
          allowLinking="true"/&gt;
      &lt;!-- DEFINE A CONTEXT PATH FOR DSpace OAI User Interface --&gt;
      &lt;Context path="/oai" docBase="/usr/share/dspace/webapps/oai" debug="1"
          reloadable="true" cachingAllowed="false"
          allowLinking="true"/&gt;
</pre>
<p>启动 tomcat，然后浏览 http://localhost:8080/jspui。</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2008/12/10/dspace-installation-notes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>编写 Nginx 启动脚本</title>
		<link>http://log.dongsheng.org/2008/12/07/nginx-boot-script/</link>
		<comments>http://log.dongsheng.org/2008/12/07/nginx-boot-script/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 09:10:45 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=25</guid>
		<description><![CDATA[今天试了一下直接使用 php-cgi 启用 fastcgi 的脚本竟然又可以使用了，真奇怪。 写了一个自动启动脚本，放到这里做个备份： #!/sbin/runscript # Copyright 1999-2004 Gentoo Foundation # Distributed under the terms of the GNU General Public License, v2 or # later # $Header:$ NGINX_EXEC=/usr/sbin/nginx PHP_EXEC=/usr/bin/php-cgi depend() { need logger net } start () { ebegin "Starting FCGI Service" spawn-fcgi -a 127.0.0.1 -p 9000 -C 5 -f /usr/bin/php-cgi eend $? [...]]]></description>
			<content:encoded><![CDATA[<p>今天试了一下直接使用 php-cgi 启用 fastcgi 的脚本竟然又可以使用了，真奇怪。<br />
写了一个自动启动脚本，放到这里做个备份：</p>
<pre>
#!/sbin/runscript
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License, v2 or
# later
# $Header:$

NGINX_EXEC=/usr/sbin/nginx
PHP_EXEC=/usr/bin/php-cgi

depend() {
need logger net
}

start () {
ebegin "Starting FCGI Service"
spawn-fcgi -a 127.0.0.1 -p 9000 -C 5 -f /usr/bin/php-cgi
eend $?
ebegin "Starting Nginx"
start-stop-daemon --start --exec ${NGINX_EXEC}
eend $?
}

stop() {
ebegin "Stopping FCGI Service"
killall php-cgi
eend $?
ebegin "Stopping Nginx"
killall nginx
start-stop-daemon --stop --quiet --pidfile /var/run/nginx.pid
--exec $NGINX_EXEC
eend $?
}
</pre>
<p>然后把这个文件保存为 /etc/init.d/httpd 并加上执行权限。<br />
然后运行 rc-config add httpd default</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2008/12/07/nginx-boot-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在 Gentoo 上安装 Nginx + php</title>
		<link>http://log.dongsheng.org/2008/12/06/nginx-php-gentoo/</link>
		<comments>http://log.dongsheng.org/2008/12/06/nginx-php-gentoo/#comments</comments>
		<pubDate>Sat, 06 Dec 2008 09:06:29 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[fastcgi]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=23</guid>
		<description><![CDATA[从源码安装 Nginx ./configure --prefix=/usr --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx_error.log --http-log-path=/var/log/nginx_access.log --pid-path=/var/run/nginx.pid --http-client-body-temp-path=/var/tmp/nginx_client_body.tmp --http-proxy-temp-path=/var/tmp/nginx_proxy.tmp --http-fastcgi-temp-path=/var/tmp/nginx_fastcgi.tmp --with-http_stub_status_module --with-http_ssl_module --with-openssl=/usr/src/openssl （启用了监控和ssl模块，重新设置文件路径） make make install 注意，&#8211;with-openssl 指向的是 openssl 的完整源码树。 Nginx 的配置 在 server 段中加入 root 指令，指向网站根目录，然后把 location / 段改为： location / { stub_status on; access_log off; } 这样就能在首页显示状态信息了，在这里用作测试。 从源码安装 PHP 5.2.7 ./configure --prefix=/usr --with-config-file-path=/etc/php --with-curl=shared --with-curlwrappers --enable-fastcgi --enable-force-cgi-redirect --with-openssl=shared --with-mysql=shared --with-mysqli=shared --enable-zip=shared [...]]]></description>
			<content:encoded><![CDATA[<h4>从源码安装 Nginx</h4>
<pre>./configure --prefix=/usr --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx_error.log --http-log-path=/var/log/nginx_access.log --pid-path=/var/run/nginx.pid --http-client-body-temp-path=/var/tmp/nginx_client_body.tmp --http-proxy-temp-path=/var/tmp/nginx_proxy.tmp  --http-fastcgi-temp-path=/var/tmp/nginx_fastcgi.tmp --with-http_stub_status_module --with-http_ssl_module --with-openssl=/usr/src/openssl</pre>
<p>（启用了监控和ssl模块，重新设置文件路径）<br />
<code>make<br />
make install</code><br />
注意，&#8211;with-openssl 指向的是 openssl 的完整源码树。</p>
<h4>Nginx 的配置</h4>
<p>在 server 段中加入 root 指令，指向网站根目录，然后把 location / 段改为：</p>
<pre>location / {
  stub_status on;
  access_log off;
}</pre>
<p>这样就能在首页显示状态信息了，在这里用作测试。</p>
<h4>从源码安装 PHP 5.2.7</h4>
<pre>./configure --prefix=/usr --with-config-file-path=/etc/php --with-curl=shared --with-curlwrappers --enable-fastcgi --enable-force-cgi-redirect --with-openssl=shared --with-mysql=shared --with-mysqli=shared --enable-zip=shared --with-xmlrpc=shared --enable-mbstring --enable-pdo=shared --with-pdo-sqlite=shared --with-sqlite=shared --with-gd=shared --with-zlib
make
make install
cp php.ini-dist /etc/php/php.ini</pre>
<p>在这种情况下，模块会编译进 PHP 而不是作为模块动态加载，如果想要创建模块需要设置 shared 选项，比如我要把 PDO 作为模块加载：</p>
<pre>./configure --enable-pdo=shared --with-pdo-sqlite=shared --with-sqlite=shared</pre>
<p>如果是 apache 的话要加上  &#8211;with-apxs2 项以创建模块。</p>
<h4>设置 FASTCGI</h4>
<p>我尝试用 <a href="http://blog.kovyrin.net/2006/05/30/nginx-php-fastcgi-howto/">php-cgi 直接创建 FCGI 服务</a>，但无法成功，只好使用 lighttpd 的 spawn-fcgi 程序创建 FCGI 服务（这里偷懒用 emerge 装的 lighttpd）：</p>
<pre>spawn-fcgi -a 127.0.0.1 -p 9000 -C 5 -f /usr/bin/php-cgi</pre>
<p>最后修改 nginx 的配置文件使之调用 php FCGI 服务：</p>
<pre>location / {
 index index.php index.htm index.html;
}
location ~ .php$ {
 fastcgi_pass 127.0.0.1:9000;
 fastcgi_index index.php;
 include fastcgi_params;
 fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
}</pre>
<p>创建一个 phpinfo 页面测试一下吧！</p>
<h4>参考</h4>
<p><a href="http://wiki.codemongers.com/NginxInstallOptions">Nginx 编译参数说明</a><br />
<a href="http://php.mirrors.ilisys.com.au/manual/en/configure.php">PHP 编译参数说明</a><br />
<a href="http://blog.s135.com/post/366.htm">Nginx 0.7.x + PHP 5.2.6（FastCGI）搭建胜过Apache十倍的Web服务器（第4版）</a><br />
<a href="http://blog.kovyrin.net/2006/05/30/nginx-php-fastcgi-howto/">Nginx With PHP As FastCGI Howto</a></p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2008/12/06/nginx-php-gentoo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP 的 OpenSSL 库</title>
		<link>http://log.dongsheng.org/2008/09/27/php-openssl/</link>
		<comments>http://log.dongsheng.org/2008/09/27/php-openssl/#comments</comments>
		<pubDate>Sat, 27 Sep 2008 03:23:02 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[cryptography]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=17</guid>
		<description><![CDATA[书接上回，在研究 XML 签名之前先研究一下 OpenSSL 库。 签名和原理 PHP 签名的函数原型是： bool openssl_sign ( string $data , string &#038;$signature , mixed $priv_key_id [, int $signature_alg ] ) 大四时学的密码学全忘光了，用 Google CodeSearch 搜了一气 OpenSSL 的源代码才搞明白了签名的原理。 生成签名： 对 $data 按照 $signature_alg 设置的算法（默认是OPENSSL_ALGO_SHA1）进行 hash 运算 用私钥加密（$priv_key_id） $signature 就是产生的签名数据，连同 $data 发送给接收方 可用的 hash 算法包括： OPENSSL_ALGO_SHA1 OPENSSL_ALGO_MD5 OPENSSL_ALGO_MD4 OPENSSL_ALGO_MD2 验证： 用公钥解密签名数据 解密后的结果是 $data 的 [...]]]></description>
			<content:encoded><![CDATA[<p>书接<a href="http://log.dongsheng.org/archives/16">上回</a>，在研究 XML 签名之前先研究一下 OpenSSL 库。</p>
<h3>签名和原理</h3>
<p>PHP 签名的函数原型是：</p>
<pre>
bool openssl_sign ( string $data , string &#038;$signature , mixed $priv_key_id [, int $signature_alg ] )
</pre>
<p>大四时学的密码学全忘光了，用 Google CodeSearch 搜了一气 OpenSSL 的源代码才搞明白了签名的原理。</p>
<p>生成签名：</p>
<ol>
<li>对 $data 按照 $signature_alg 设置的算法（默认是OPENSSL_ALGO_SHA1）进行 hash 运算</li>
<li>用私钥加密（$priv_key_id）</li>
<li>$signature 就是产生的签名数据，连同 $data 发送给接收方</li>
</ol>
<p>可用的 hash 算法包括：</p>
<ul>
<li>OPENSSL_ALGO_SHA1</li>
<li>OPENSSL_ALGO_MD5</li>
<li>OPENSSL_ALGO_MD4</li>
<li>OPENSSL_ALGO_MD2</li>
</ul>
<p>验证：</p>
<ol>
<li>用公钥解密签名数据</li>
<li>解密后的结果是 $data 的 hash 值，接受方再生成 $data 的 hash 值与之对比</li>
</ol>
<h3>签名验证算法</h3>
<p>最常见的有两种：基于大数因子分解问题的数字签名（RSA），基于离散对数问题的数字签名（DSA），公私钥分别对应 ~/.ssh/id_rsa &#038; ~/.ssh/id_rsa.pub 和 ~/.ssh/id_dsa &#038; ~/.ssh/id_dsa.pub<br />
二者区别在于 RSA 还可以用于加密，而 DSA 只能用于签名验证，二者签名效率相近，但 RSA 的验证要远快于 DSA。</p>
<p>所以 PHP 中使用 RSA，公私钥可以用 OpenSSL 工具包生成：</p>
<pre>
openssl genrsa 512 >id_rsa
openssl rsa -pubout <id_rsa >id_rsa.pub
</pre>
<p>我在 .ssh 目录下的 RSA 公私钥是用 ssh-keygen 生成的，但在在这里做试验失败，可能于密钥长度有关系。</p>
<p>验证函数原型：</p>
<pre>
int openssl_verify  (  string $data  ,  string $signature  ,  mixed $pub_key_id  [,  int $signature_alg = OPENSSL_ALGO_SHA1  ] )
</pre>
<p>很好理解，$data 是接受方获取的数据，$signature 是一起发过来的签名，$pub_key_id 是校验用的公钥，$signature_alg 就是前面制定的 hash 算法了。</p>
<h3>加密</h3>
<p>函数原型：</p>
<pre>
int openssl_seal  ( string $data  , string &#038;$sealed_data  , array &#038;$env_keys  , array $pub_key_ids  )
</pre>
<ol>
<li>用随机字符串加密 data （ <a href="http://www.rsa.com/rsalabs/node.asp?id=2250">RC4</a> 加密算法）</li>
<li>用 pub_key_ids 里的公钥对共享密钥进行加密，将结果保存在 env_keys</li>
<li>将 env_keys 和 sealed_data 发送给接收方</li>
</ol>
<h3>解密</h3>
<p>函数原型：</p>
<pre>
bool openssl_open  ( string $sealed_data  , string &#038;$open_data  , string $env_key  , mixed $priv_key_id  )
</pre>
<ol>
<li>私钥揭开 env_key</li>
<li>用 env_key 打开加密消息</li>
</ol>
<h3>用 PHP 创建公私钥</h3>
<pre>
function get_key_pair() {
    $ret = array();
    $res = openssl_pkey_new();
    openssl_pkey_export($res, $ret['private_key']);
    $pub_key = openssl_pkey_get_details($res);
    $ret['public_key'] = $pub_key['key'];
    return $ret;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2008/09/27/php-openssl/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>在 PHP 中使用 XMLRPC</title>
		<link>http://log.dongsheng.org/2008/09/25/xmlrpc-php/</link>
		<comments>http://log.dongsheng.org/2008/09/25/xmlrpc-php/#comments</comments>
		<pubDate>Thu, 25 Sep 2008 13:22:03 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[xmlrpc]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=16</guid>
		<description><![CDATA[这几天在研究 Moodle Network 组件，通过这个模块，各个孤立的系统被连接到了一起，实现了单点登录和资源共享（对于 e-learning 有很大的意义），通信协议是 XML-RPC，信息安全不是依赖 SSL 的方案，而是在采用了 XML 签名（不对称加密算法），想法非常好，但实现的不太完整，因为这个模块的原作者离开了在新西兰的公司，整得像个半完成作品。 今天看了一下代码，打算在这上面解决多 Moodle 系统的资源共享问题（包含点对点和 HUB 模式），之前没用过 XMLRPC，所以现在开始学一下，我用的是 PHP 的 XMLRPC 模块（比纯 PHP 实现快了不少）。 首先实现一个 XMLRPC 服务，我封装了一个简单的类： class xmlrpc_server { private $server; public function __construct() { $this->server = xmlrpc_server_create(); } public function add($name, $func) { xmlrpc_server_register_method($this->server, $name, $func); } public function run() { $req = file_get_contents('php://input'); [...]]]></description>
			<content:encoded><![CDATA[<p>这几天在研究 Moodle Network 组件，通过这个模块，各个孤立的系统被连接到了一起，实现了单点登录和资源共享（对于 e-learning 有很大的意义），通信协议是 XML-RPC，信息安全不是依赖 SSL 的方案，而是在采用了 XML 签名（不对称加密算法），想法非常好，但实现的不太完整，因为这个模块的原作者离开了在新西兰的公司，整得像个半完成作品。</p>
<p>今天看了一下代码，打算在这上面解决多 Moodle 系统的资源共享问题（包含点对点和 HUB 模式），之前没用过 XMLRPC，所以现在开始学一下，我用的是 PHP 的 XMLRPC 模块（比纯 PHP 实现快了不少）。</p>
<p>首先实现一个 XMLRPC 服务，我封装了一个简单的类：</p>
<pre>
class xmlrpc_server {
    private $server;
    public function __construct() {
        $this->server = xmlrpc_server_create();
    }
    public function add($name, $func) {
        xmlrpc_server_register_method($this->server, $name, $func);
    }
    public function run() {
        $req = file_get_contents('php://input');
        $response = xmlrpc_server_call_method($this->server, $req, null);
        echo $response;
        xmlrpc_server_destroy($this->server);
    }
}
</pre>
<p>调用这个类创建一个服务：</p>
<pre>
header('Content-Type: text/xml');
function func_add($method, $params) {
    return $params[0]+$params[1];
}
$xmlrpc = new xmlrpc_server;
$xmlrpc->add('add', 'func_add');
$xmlrpc->run();
</pre>
<p>PHP 客户端的调用是通过 HTTP 的 POST 方法，我用的是 <a href="http://code.anbutu.com/n-342">cURL</a> 扩展：</p>
<pre>
require_once('curl.class.php');
class xmlrpc_client {
    public function __construct($url, $autoload = false) {
        $this->connection = null;
        $this->url = $url;
        $this->connection = new curl;
        $this->methods = array();
        if ($autoload) {
            $resp = $this->call('system.listMethods', null);
            $this->methods = $resp;
        }
    }
    public function call($method, $params = null) {
        $post = xmlrpc_encode_request($method, $params);
        return xmlrpc_decode($this->connection->post($this->url, $post));
    }
}
header('Content-Type: text/plain');
$rpc = "http://10.0.0.10/api.php";
$client = new xmlrpc_client($rpc, true);
print_r($client->call('add', array(199,2)));
</pre>
<p>待续，下一步优化代码并实现 XML 签名技术。</p>
<p>资料：</p>
<p><a href="http://www.w3.org/TR/xmldsig-core/">XML Signature Syntax and Processing</a><br />
<a href="http://au2.php.net/manual/en/book.openssl.php">OpenSSH</a><br />
<a href="http://www.w3.org/TR/xmlenc-core/">XML Encryption Syntax and Processing</a></p>
<p>== TO BE CONTINUED ==</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2008/09/25/xmlrpc-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Gentoo 上的 Python 没有 sqlite 支持</title>
		<link>http://log.dongsheng.org/2008/09/24/gentoo-python-sqlite/</link>
		<comments>http://log.dongsheng.org/2008/09/24/gentoo-python-sqlite/#comments</comments>
		<pubDate>Wed, 24 Sep 2008 12:20:00 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[gentoo]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=15</guid>
		<description><![CDATA[Sqlite 从 Python 2.5 以后就是标准模块了，但 Gentoo 上的 Python 竟然没有这个模块，开始以为需要一个额外的包，但安装 pysqlite 以后问题依旧（过后才想起来是没进入标准前的一个模块），于是使用 USE 标签重新编译 Python： USE="sqlite" emerge python 问题解决]]></description>
			<content:encoded><![CDATA[<p>Sqlite 从 Python 2.5 以后就是标准模块了，但 Gentoo 上的 Python 竟然没有这个模块，开始以为需要一个额外的包，但安装 pysqlite 以后问题依旧（过后才想起来是没进入标准前的一个模块），于是使用 USE 标签重新编译 Python：</p>
<pre>
USE="sqlite" emerge python
</pre>
<p>问题解决</p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2008/09/24/gentoo-python-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cURL 并发访问</title>
		<link>http://log.dongsheng.org/2008/07/16/curl-multiple-handlers/</link>
		<comments>http://log.dongsheng.org/2008/07/16/curl-multiple-handlers/#comments</comments>
		<pubDate>Wed, 16 Jul 2008 03:10:23 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=8</guid>
		<description><![CDATA[通常情况下 PHP 中的 cURL 是阻塞运行的，就是说创建一个 cURL 请求以后必须等它执行成功或者超时才会执行下一个请求，curl_multi_* 系列函数使并发访问成功可能，PHP 文档对这个函数的介绍不太详细，用法如下： $requests = array('http://zz.dongsheng.org', 'http://www.google.com'); $main = curl_multi_init(); $results = array(); $errors = array(); $info = array(); $count = count($requests); for($i = 0; $i < $count; $i++) { $handles[$i] = curl_init($requests[$i]); var_dump($requests[$i]); curl_setopt($handles[$i], CURLOPT_URL, $requests[$i]); curl_setopt($handles[$i], CURLOPT_RETURNTRANSFER, 1); curl_multi_add_handle($main, $handles[$i]); } $running = 0; do { curl_multi_exec($main, [...]]]></description>
			<content:encoded><![CDATA[<p>通常情况下 PHP 中的 cURL 是阻塞运行的，就是说创建一个 cURL 请求以后必须等它执行成功或者超时才会执行下一个请求，curl_multi_* 系列函数使并发访问成功可能，PHP 文档对这个函数的介绍不太详细，用法如下：</p>
<pre>$requests = array('http://zz.dongsheng.org', 'http://www.google.com');
$main    = curl_multi_init();
$results = array();
$errors  = array();
$info    = array();
$count   = count($requests);
for($i = 0; $i < $count; $i++) {
  $handles[$i] = curl_init($requests[$i]);
  var_dump($requests[$i]);
  curl_setopt($handles[$i], CURLOPT_URL, $requests[$i]);
  curl_setopt($handles[$i], CURLOPT_RETURNTRANSFER, 1);
  curl_multi_add_handle($main, $handles[$i]);
}
$running = 0;

do {
  curl_multi_exec($main, $running);
} while($running > 0);

for($i = 0; $i < $count; $i++)
{
  $results[] = curl_multi_getcontent($handles[$i]);
  $errors[]  = curl_error($handles[$i]);
  $info[]    = curl_getinfo($handles[$i]);
  curl_multi_remove_handle($main, $handles[$i]);
}
curl_multi_close($main);
var_dump($results);
var_dump($errors);
var_dump($info);
</pre>
<p>通过这种方式就可以实现多任务并发执行，更详细的用法看我写的这个类：<a href="http://code.anbutu.com/n-342">curl class</a></p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2008/07/16/curl-multiple-handlers/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>CVS Cheat Sheet</title>
		<link>http://log.dongsheng.org/2008/07/15/cvs-cheat-sheet/</link>
		<comments>http://log.dongsheng.org/2008/07/15/cvs-cheat-sheet/#comments</comments>
		<pubDate>Tue, 15 Jul 2008 11:07:08 +0000</pubDate>
		<dc:creator>Dongsheng Cai</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cvs]]></category>

		<guid isPermaLink="false">http://log.dongsheng.org/?p=7</guid>
		<description><![CDATA[记住：cvs 的操作可以通过 cvs -H 来查看，比如： cvs -H diff CVS CHECKOUT d 输出目录 A 重设所有 sticky tags r 指定一个 tag CVS UPDATE d 参数 CVS DIFF b 忽略行尾空格 c 输出上下文 p 显示所改变的函数名（或类名） u 使用 unified 输出格式 r 标识 tag CVS UPDATE p 重定向到标准输出 r 标识tag CVS 操作的默认参数可以写在 ~/.cvsrc 里，如 diff -bc update -dP USE CASE： 1. [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-weight:bold;">记住</span>：cvs 的操作可以通过 cvs -H 来查看，比如：<br />
<code>cvs -H diff</code><br />
CVS CHECKOUT<br />
d 输出目录<br />
A 重设所有 sticky tags<br />
r 指定一个 tag<br />
CVS UPDATE<br />
d 参数</p>
<p>CVS DIFF<br />
b 忽略行尾空格<br />
c 输出上下文<br />
p 显示所改变的函数名（或类名）<br />
u 使用 unified 输出格式<br />
r 标识 tag</p>
<p>CVS UPDATE<br />
p 重定向到标准输出<br />
r 标识tag</p>
<p>CVS 操作的默认参数可以写在 ~/.cvsrc 里，如<br />
<code>diff -bc<br />
update -dP</code><br />
USE CASE：<br />
1. 查看历史<br />
<code>cvs log xx.php<br />
cvs log -r1.5 xx.php</code><br />
2. 添加文件<br />
<code>cvs add xx.php<br />
cvs ci xx.php<br />
# 添加图片<br />
cvs add -kb xx.jpg<br />
cvs ci xx.jpg<br />
# 添加目录<br />
cvs add folder1<br />
# 不需要提交</code><br />
3. 删除<br />
<code>rm xx.php<br />
cvs remove xx.php<br />
cvs commit xx.php<br />
# cvs 无法彻底删除空目录，只能到服务端彻底删除</code><br />
4. 版本恢复<br />
<code>cvs update -p -r 1.6 xx.php > xx.php</code><br />
5. 代码更新<br />
<code>cvs update<br />
cvs update -dPA<br />
# 创建新目录（如果必要），清理空目录，重置锁定点</code><br />
6. diff<br />
<code>cvs diff -upc xx.php<br />
# 生成 patch<br />
cvs diff -up xx.php > xx.patch<br />
# 应用 patch<br />
patch -p0 < xx.patch<br />
# 测试 patch<br />
patch --dry-run -p0 < xx.path<br />
</code><br />
更多 CVS 操作：<a href="http://code.anbutu.com/n-462">.bashrc</a></p>
]]></content:encoded>
			<wfw:commentRss>http://log.dongsheng.org/2008/07/15/cvs-cheat-sheet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

