<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="/css/feed.css"?>
<feed xmlns="http://www.w3.org/2005/Atom">

<title>Saito</title>
<subtitle>worstest coder ever.</subtitle>

<link href="http://saito.im/feed/" rel="self" />
<link href="http://saito.im/" />

<id>http://saito.im/feed/</id>

<updated>2013-05-18T10:23:12-07:00</updated>
<rights>Copyright © 2011, Saito Wu</rights>

<author>
	<name>Saito Wu</name>
	<email>saitowu@gmail.com</email>
</author>


<entry>
	<title>Github Open Source Contributions Calendar</title>
	<link href="http://saito.im/note/Github-Open-Source-Contributions-Calendar/" />
	<id>tag:saito.im,2013:/note/Github-Open-Source-Contributions-Calendar/</id>
	<updated>2013-05-19T00:00:00-07:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>Github OSS Graph</summary>
	<content type="html">
	
	&lt;p&gt;Github OSS Graph&lt;/p&gt;
	
	&lt;p&gt;&lt;h3&gt;A Nice Calendar&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/saitowu&quot;&gt;Made&lt;/a&gt; by &lt;a href=&quot;https://gist.github.com/SaitoWu/5599617&quot;&gt;a little ruby script&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/SA1T0&quot;&gt;Preview&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://d.pr/i/HHp2+&quot; alt=&quot;Github OSS Calendar&quot;&gt;&lt;/p&gt;
&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>Middle-Scale F2E Application</title>
	<link href="http://saito.im/work/Middle-Scale-F2E-Application/" />
	<id>tag:saito.im,2013:/work/Middle-Scale-F2E-Application/</id>
	<updated>2013-05-13T00:00:00-07:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>share some F2E basic knowledge</summary>
	<content type="html">
	
	  &lt;img src=&quot;http://f.cl.ly/items/2D0E12022N3S1P0K0u46/thumb_slide_0.jpg&quot; alt=&quot;Middle-Scale F2E Application&quot;&gt;
	
	&lt;p&gt;share some F2E basic knowledge&lt;/p&gt;
	
	&lt;p&gt;&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>How Gitlab Works</title>
	<link href="http://saito.im/work/How-Gitlab-Works/" />
	<id>tag:saito.im,2012:/work/How-Gitlab-Works/</id>
	<updated>2012-11-18T00:00:00-08:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>share some git and gitlab basic knowledge</summary>
	<content type="html">
	
	  &lt;img src=&quot;http://f.cl.ly/items/3P0x0P2w3n1v0K223w2c/Screen%20Shot%202012-12-01%20at%204.42.52%20PM.png&quot; alt=&quot;How Gitlab Works&quot;&gt;
	
	&lt;p&gt;share some git and gitlab basic knowledge&lt;/p&gt;
	
	&lt;p&gt;&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>Git Internals</title>
	<link href="http://saito.im/note/Git-Internals/" />
	<id>tag:saito.im,2012:/note/Git-Internals/</id>
	<updated>2012-09-14T00:00:00-07:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>Git Tag Commit Tree Blob</summary>
	<content type="html">
	
	&lt;p&gt;Git Tag Commit Tree Blob&lt;/p&gt;
	
	&lt;p&gt;&lt;p&gt;Git 一共有 4 种 SHA1. tag, commit, tree, blob. 每一种 SHA1 其实也代表了 Git 内部的一个基本对象.&lt;/p&gt;

&lt;p&gt;稍微解释一下就知道了.&lt;/p&gt;

&lt;h3&gt;如果做下面的简单操作:&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash language-bash&quot; data-lang=&quot;bash&quot;&gt;mkdir helloworld
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;helloworld
git init
&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;hello world &amp;gt; readme.md
git add .
git commit -am&lt;span class=&quot;s2&quot;&gt;&amp;quot;add readme.md&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;在这里看来? 哪一步会创建哪些对象?&lt;/h3&gt;

&lt;p&gt;答案很简单.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;在这里操作中会添加一个 blob 对象, 代表readme 文件本身. 这也是为什么你需要在 add 过一个对象之后, 撤销需要执行 rm 与 cache 相关命令的原因.&lt;/p&gt;

&lt;h3&gt;blob&lt;/h3&gt;

&lt;p&gt;而文件的内容则如下所示.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash language-bash&quot; data-lang=&quot;bash&quot;&gt;helloworld git:master ❯ git ls-files -s readme.md
100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0 readme.md
helloworld git:master ❯ git show 3b18e512dba79
hello world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;tree&lt;/h3&gt;

&lt;p&gt;当执行下面这句的时候:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git commit -am&amp;quot;add readme.md&amp;quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这一步中将创建两个对象, 一个是当前work tree 的映射 tree 对象, 还有一个就是 commit 对象.&lt;/p&gt;

&lt;p&gt;tree 对象是可以包含另外的 tree 以及 blob 的.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash language-bash&quot; data-lang=&quot;bash&quot;&gt;helloworld git:master ❯ git show 7394b8cc9ca
tree 7394b8cc9ca

readme.md
helloworld git:master ❯ git cat-file -p 7394b8cc9ca
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad  readme.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;上面是一个 tree 对象的具体内容.  tree 里面实际上就是描述了当前 tree 的内容以及 blob 的引用.&lt;/p&gt;

&lt;h3&gt;commit&lt;/h3&gt;

&lt;p&gt;同理 commit 也可以用相同的方式查看:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash language-bash&quot; data-lang=&quot;bash&quot;&gt;helloworld git:master ❯ git show 84073a0
commit 84073a0bffd4c80598dbc4941a5f84d78cc2adcd
Author: Saito &amp;lt;saitowu@gmail.com&amp;gt;
Date:   Fri Sep 14 01:12:07 2012 +0800

    add readme

diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..3b18e51
--- /dev/null
+++ b/readme.md
@@ -0,0 +1 @@
+hello world
helloworld git:master ❯ git cat-file -p 84073a0
tree 7394b8cc9ca916312a79ce8078c34b49b1617718
author Saito &amp;lt;saitowu@gmail.com&amp;gt; 1347556327 +0800
committer Saito &amp;lt;saitowu@gmail.com&amp;gt; 1347556327 +0800

add readme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以看到, commit 里面实际上保存的实际上是一个 tree 的 SHA1 以及 commit 的 author commiter 以及最终的 commit message.&lt;/p&gt;

&lt;h3&gt;tag&lt;/h3&gt;

&lt;p&gt;最后我们给当前状态打一个 1.0 版本的tag.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;helloworld git:master ❯ git tag 1.0 -m&amp;quot;create a tag&amp;quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;再来看看 tag 的 SHA1 内容.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash language-bash&quot; data-lang=&quot;bash&quot;&gt;helloworld git:master ❯ git show 1518c0a02530b3
tag 1.0
Tagger: Saito &amp;lt;saitowu@gmail.com&amp;gt;
Date:   Fri Sep 14 01:24:39 2012 +0800

creat a tag

commit 84073a0bffd4c80598dbc4941a5f84d78cc2adcd
Author: Saito &amp;lt;saitowu@gmail.com&amp;gt;
Date:   Fri Sep 14 01:12:07 2012 +0800

    add readme

diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..3b18e51
--- /dev/null
+++ b/readme.md
@@ -0,0 +1 @@
+hello world
helloworld git:master ❯ git cat-file -p 1518c0a02530b3
object 84073a0bffd4c80598dbc4941a5f84d78cc2adcd
&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;commit
tag 1.0
tagger Saito &amp;lt;saitowu@gmail.com&amp;gt; Fri Sep 14 01:24:39 2012 +0800

create a tag
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以看到, tag 里面主要存储的是 commit 的 SHA1 值, tag name 以及 tagger, 还有, 如果有 -m 参数的话会有 tag message.&lt;/p&gt;

&lt;h3&gt;为什么没有 branch&lt;/h3&gt;

&lt;p&gt;因为 branch 不在这套体系内. 是体系外的.&lt;/p&gt;

&lt;p&gt;跟基本对象相关的东西都存在 &lt;code&gt;.git/objects&lt;/code&gt; 里面.&lt;/p&gt;

&lt;p&gt;而 branch 是在同级的 &lt;code&gt;.git/refs&lt;/code&gt; 目录里面的. 而 refs 目录里面, 每条 ref 记录, 实际上也是只记录了一个 commit SHA1 而已.&lt;/p&gt;

&lt;h3&gt;结论&lt;/h3&gt;

&lt;p&gt;四种对象创建完毕.. 回头再来看, 什么时候会有什么 SHA1 已经很清楚的.&lt;/p&gt;
&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>New Workbench</title>
	<link href="http://saito.im/note/New-Workbench/" />
	<id>tag:saito.im,2012:/note/New-Workbench/</id>
	<updated>2012-08-06T00:00:00-07:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>Macbook Pro SSD Desk Chair</summary>
	<content type="html">
	
	&lt;p&gt;Macbook Pro SSD Desk Chair&lt;/p&gt;
	
	&lt;p&gt;&lt;h3&gt;Notebook:&lt;/h3&gt;

&lt;p&gt;Macbook Pro MC700&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/1N0O0h0J1k2A091Y1y1w/Screen%20Shot%202012-08-06%20at%2011.17.14%20AM.png&quot; alt=&quot;Macbook Pro&quot;&gt;&lt;/p&gt;

&lt;h3&gt;Memory:&lt;/h3&gt;

&lt;p&gt;Samsung DDR3 1333 4G * 2&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/3j1x2r3i430p1Q2Q0E2D/Screen%20Shot%202012-08-06%20at%2011.13.30%20AM.png&quot; alt=&quot;Samsung 4G * 2&quot;&gt;&lt;/p&gt;

&lt;h3&gt;SSD:&lt;/h3&gt;

&lt;p&gt;Samsung PM830 256G&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/1m2n0N3D1c281D143900/Screen%20Shot%202012-08-06%20at%2010.29.24%20AM.png&quot; alt=&quot;Samsung PM830 256G&quot;&gt;&lt;/p&gt;

&lt;h3&gt;Monitor:&lt;/h3&gt;

&lt;p&gt;Dell U2312HM&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/23010W201Q3U2e2H3k1n/Screen%20Shot%202012-08-06%20at%2010.25.39%20AM.png&quot; alt=&quot;Dell U2312HM&quot;&gt;&lt;/p&gt;

&lt;h3&gt;Desk:&lt;/h3&gt;

&lt;p&gt;IS IH-011&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/1f2L2k351F080P0f3S0l/Screen%20Shot%202012-08-06%20at%2010.39.13%20AM.png&quot; alt=&quot;IS Design&quot;&gt;&lt;/p&gt;

&lt;p&gt;Buyout: &lt;a href=&quot;http://detail.tmall.com/item.htm?id=13373468566&quot;&gt;http://detail.tmall.com/item.htm?id=13373468566&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Chair:&lt;/h3&gt;

&lt;p&gt;Sihoo M25V&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/3N2F2A2B31021D2b0W3Y/Screen%20Shot%202012-08-06%20at%2010.48.09%20AM.png&quot; alt=&quot;Shihoo m25v&quot;&gt;&lt;/p&gt;

&lt;p&gt;Buyout: &lt;a href=&quot;http://detail.tmall.com/item.htm?id=14483891010&quot;&gt;http://detail.tmall.com/item.htm?id=14483891010&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;That&amp;#39;s all!&lt;/h3&gt;
&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>Smart HTTP Protocal Internals</title>
	<link href="http://saito.im/note/Smart-HTTP-Protocal-Internals/" />
	<id>tag:saito.im,2012:/note/Smart-HTTP-Protocal-Internals/</id>
	<updated>2012-06-19T00:00:00-07:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>Git HTTP Internals</summary>
	<content type="html">
	
	&lt;p&gt;Git HTTP Internals&lt;/p&gt;
	
	&lt;p&gt;&lt;h3&gt;Git&lt;/h3&gt;

&lt;h4&gt;fetch( include clone &amp;amp; pull ):&lt;/h4&gt;

&lt;p&gt;get_info_refs:&lt;/p&gt;

&lt;p&gt;request:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET: /info/refs?service=git-upload-pack&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;response:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;001e# service=git-upload-pack\n000000a3f989f58785072b3b3ba66650d53a22cc29e79b24 HEAD\u0000multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed no-done\n0041f989f58785072b3b3ba66650d53a22cc29e79b24 refs/heads/features\n003ff989f58785072b3b3ba66650d53a22cc29e79b24 refs/heads/master\n0000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;git_upload_pack:&lt;/p&gt;

&lt;p&gt;request:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;POST: /git-upload-pack&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;006fwant f989f58785072b3b3ba66650d53a22cc29e79b24 multi_ack_detailed no-done side-band-64k thin-pack ofs-delta\n0032want f989f58785072b3b3ba66650d53a22cc29e79b24\n0032want f989f58785072b3b3ba66650d53a22cc29e79b24\n00000009done\n
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;response:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;0008NAK\n0021\x02Counting objects: 27, done.\n004b\x02Compressing objects:  11% (1/9)   \rCompressing objects:  22% (2/9)   \r0028\x02Compressing objects:  33% (3/9)   \r0028\x02Compressing objects:  44% (4/9)   \r0028\x02Compressing objects:  55% (5/9)   \r0028\x02Compressing objects:  66% (6/9)   \r0028\x02Compressing objects:  77% (7/9)   \r0028\x02Compressing objects:  88% (8/9)   \r0028\x02Compressing objects: 100% (9/9)   \r002c\x02Compressing objects: 100% (9/9), done.\n002c\x02Total 27 (delta 0), reused 0 (delta 0)\n0787\x01PACK\x00\x00\x00\x02\x00\x00\x00\e\x90\rx\x9C\x95\xCB\xCD\t\x021\x10@\xE1{\xAA\xC8]\x90Iv3? b\x0FV0&amp;amp;\x13]0\xAE\xC4,\xB6\xAF\x96\xE0\xE9\xC1\aot3O\&amp;quot;9*\x152\xC6KFF\fVC\xB5\xC4Z\x959\x94\x99\xB8\x12\x8A{j\xB7\xC7\xF00%\x12 D\xCD!C\xB8\xC44\x19$`\x12\xCC4\x03\x17\xE0(1\x89\xD3m\xDC\xD6\xEE\xCF\xBA\x8C\xD5\x1F^\xBF\xBC\xB7\xD3\xB5\xE9r\xDF\xE7\xB5\x1D}\x98f\x00\&amp;quot;\x8E\xD1\xEF\x80\x01\xDCW\xDB2\x86\xFD59-\xC5w\xD3f\xEE\x03\x8F\xBB&amp;lt;n\x91\rx\x9C\x95\x8B\xDB\t\x021\x10\x00\xFFSE\xFE\x05\xD9\\\xB2y\x80\x88=X\xC1f\xB3\xD1\x80\xF1$\xE6\xB0}\xCF\x12\xFC\x18\x06\x06f\x0E\x11\xBD$\xEFw0e_\x1D\xC7d0\x16\xBB\x10p\xE4%Z2\xC5D\x9F([\xF5\xA2!\xCF\xA9\xAB\rIr\x14\t\xC2Y\x10\x01jF\x0E)Kp\x80\x95\xAB\t\x9C\x1DZE\xDB\xBC\xAFC_\xA9\xCDU\x9F\xDE?}\xB6\xCB\xADS{\x1Cy\xEDgm\xAC\x03\b\x01!\xE9\x03D\x00\xB5\xD7\xDE\xE6\x94\xBF&amp;amp;E\xA5\xE8!T\xBA\xA8/a\x11&amp;gt;A\x91\rx\x9C\x95\x8BQ\n\x021\f\x05\xFF{\x8A\xFE\v\x92\xB6i\xBA\v\&amp;quot;\xDE\xC1\x13d\x9BT\x17\xAC+\xB5\x8B\xD7\xB7\x1EAx0\xCC\xC0\xEBM\xD5\x06O\xA1\xB89;\x87\xEA\x88s*\x98\x9C\xF3\x02~\x19[b^\&amp;quot;\x11\xB2\x98\x177}v\e\t\x85f\x8A@AR\x9A$\n\xE2\x10N\x9C\xB5@\xD1\x182\xA3\&amp;quot;\x18\xDE\xFB}k\xF6\xCAk\xDF\xEC\xE9\xFD\xC3g\xBF\xDC*\xAF\x8Fc\xDE\xEA\xD9\xBA\x80\x00)\xE1\xE4\xED\x01&amp;amp;\x003j]{\xD7\xBFN\x86ElS\x96\xAA\xE6\v\x11\xCA=\xAD\x94\rx\x9C\x95\xCBQ\n\xC20\f\x80\xE1\xF7\x9E\xA2\xEF\xC2\xC8\x966\xCB\x83\x88w\xF0\x04Y\x93\xE8\xC0:\xA9\x1D^_=\x82O?|\xF0\xF7f\x16\x89@\xD2\x82y.\x93/N\xCE\xC5\x99m2)\xC5\xBD\xA8\x81\xF8l#bxJ\xB3G\x8FZ\x04\x8D\x119/\xA0\xC49q\xCAD\xC6\x19\xD9h\x1Au\xF1D@nA\xF6~\xDBZ\xBC\xC8\xDA\xB7x|\xFD\xF2\xDE\xCF\xD7*\xEB}([=\xC5\x11\x13\xC0LL\x14\x0F\xC0\x00\xE1\xABu\xED\xDD\xFE\x9A\x82\xA8\xC6f\xA2\xD5\x86\xAA\xE1\x03\xFAy@4\x91\rx\x9C\x95\x8BA\n\x021\fE\xF7=E\xF7\x82d\xD2\xA6MA\xC4;x\x82\xB4Mu\xC0q\xA4v\xF0\xFA\x8EG\x90\xBFx\xF0\x1E\x7FtU\xEB\x8B\x17&amp;amp;\xE4\xD0\x1C\xE5\xAA\x98\xA5b\xA0)y\xA6=\xB8\x06\xAC)I.\xE6%]\x9F\xC3\xB6\xC4\xA9\x11G&amp;amp;\x88\x98\xDD&amp;gt;\t!\x10Tr\x82X\n&amp;amp;\x8D)\xA37\xB2\x8D\xFB\xDA\xEDU\xE6\xB1\xDA\xD3\xFB\x87\xCFv\xB9-2?\x8Ee]\xCEvr\x1E \x06F\xB2\a`\x00\xB3\xDBe\x1EC\xFF:\x19\xA9\xD5v\x95\xBA\xA8\xF9\x021\x88=\xAE\x91\rx\x9C\x95\x8BQ\n\x02!\x10@\xFF=\x85\xFFA\xCC\xA8\xEB\x8E\x10\xD1\x1D:\xC1\xE8\xCC\xD6B\xB6a.]?;B\xF0\xE0\xC1\x83\xD7\x9B\xAA\rT\x8A,\fS \x11`\n\x8E\b\x13\xCD\x89\x10\xBC\xBAi\xC1%\xE6\x92\xD0\xBC\xB8\xE9\xB3[AI\x9C3\xB3`\x8C\x03\xF2\x1A\x02E\xF4\x91a\xA41\x86,9%\xC3{\xBFo\xCD^y\xED\x9B=\xBD\x7F\xFA\xEC\x97[\xE5\xF5q,[=[\xF4\x01`\xF6\xE8\x9C=\x00\x01\x98Q\xEB\xDA\xBB\xFE5\x19\x16\xB1MY\xAA\x9A/*-=\x8D\x91\rx\x9C\x95\xCBM\n\x021\f@\xE1}O\xD1\xBD M\xD2\x9F\x19\x10\xF1\x0E\x9E iS\x1D\xB0\xCEP;x}\xF5\b\xAE\x1E|\xF0FW\xB5a\xAE\xC4\x80$D(\x01UQ\xB3\a\xCAU$\xC9\xCC\x90\x04=\x00\x16\xB3q\xD7\xE7\xB0\xC9\v\x8AN\\9F/A\x93\x84\x90(!2\xC6\f~\x8E\x15\xA7\xAA\xCE\e\xDE\xC7}\xED\xF6\xCA\xCBX\xED\xE9\xF5\xCB{\xBF\xDC\x1A/\x8Fc^\xDB\xD9\x02y\xE7\x129\b\xF6\xE0&amp;amp;\xE7\xCCW\xDB2\x86\xFE5\x19.\xC5v\xE5\xD2\xD4|\x00i\xD9=\xF3\x96\rx\x9C\x95\x8C[\n\xC20\x10\x00\xFFs\x8A\xFD\x17d\x93\xE6U\x10\xF1\x0E\x9E`\x93\xDD\xD8\x82\xB1%M\xE9\xF5\xADG\xF0k``\xA67\x110\x85\x06\xAF}\x8C\xB9\xE8,F8\x12\xBB\x9C\x06G\x81I&amp;#39;\x8F\xEC\xB55%\xA9\x95\x9A|:dc\x8D\xC4\x88\x98\x84J@d\xB2\xC1\xB9\x92(`\xCC\xE8,\xFB1\x85\xB3R\xB4\xF7ii\xF0\xA4\xB9/p\xDB~8\xF6\xC7\xAB\xD2\xFC\xBE\xE6\xA5\xDEA\x0F\x161\x98\xD1\x8Dp\xC1s\xA8N[\xE7\xDE\xE5\xAFH\xAD\xFB6\xC1G\x0EhB\\E}\x012\xEC@\xD3\x91\nx\x9C\x95\xCBA\n\xC20\x10@\xD1}N1{\xA1$3M\x9A\x01\x11\xEF\xE0\t\xA6\xC9\xA8\x01c M\xF1\xFA\xDA#\xB8\xFA\xF0\xE0\x8F\xAE\nH\xAC\xC93\xA5 \xE8\x18u\t\xC9Z?\x93\xBF/s\\Q2\xC6U#\xA1\x91}&amp;lt;[\x87\x9B\x94\xD1\xE0\xBC\x1D\xF9\xEC\xD7G\x95\xF2\x9AR\xAB\x17pD\xCC\xCEc\fp\xB2\xD1Z\xF3\xD3Z\xC6\xD0\xBF&amp;amp;#9CWyW5_&amp;lt;\x850\x0E\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xD0\xBE\x1E\xC2\xEE\xBEf\xFA\xEDL\xF3T\xCE\x98\r\xFF&amp;amp;.\xBD\xB7\xA2\x06\x00\xE4\xF5\x0E\xCF\xB0\x01x\x9C+\xC9L\xCEN-\xE1*\x81\x02.\x006f\x069\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xB0\x9A{\xFE\xE8\x17\r&amp;#39;[\xD9\xFB\x12\x8E\x8A\xD2\x8Bu\xD2n[p\x03\x00\xE3\xC1\f\xA7?x\x9C+\xC9L\xCEN-\xE1*\x81\x00.\x00/\xC3\x05\xC5\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xF8\xBE\xE0i\x97\xA9\x97\xE6\xB20\xF1\xDB\xDFw\x84*V\xF2\xCA}\xE1\x06\x00\xF5\x1C\x0E!&amp;gt;x\x9C+\xC9L\xCEN-\xE1*\x01\x03.\x00)\x94\x05Q\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\x98\x94\x9F&amp;#39;&amp;#39;P\xAE?\xBD+\xF6K\xD2\x94\x9A\x7FIjw\xBE\xFE\x05\x00\xE3\\\x0F8=x\x9C+\xC9L\xCEN-\xE1*\x01\x01.\x00#\xD9\x04\xDD\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa0\x17\x15\xCDV\xB4\xF8\x94\xAE\xE2q\xCF\xAB\xEE\xE4\xF6\x87\x93b$e\x00\xD2v\f\xD1&amp;lt;x\x9C+\xC9L\xCEN-\xE1*\x01\x02.\x00\x1E\x92\x04i\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\x98\xB3\xFE\xDC\xA5O\xD9\x97\x16/\x8B\x8D\xDB\xDC\xE9\xE7\x14\xD8\xFB\xEA\xEF\x1E\x00\f$\x11(;x\x9C+\xC9L\xCEN-\xE1*))\xE1\x02\x00\x19\xBF\x03\xF5\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMax\x13\xB4F\xF6\x8E\xAF\xBET\xFF\x94\xED\x8F/q\x1C0\xB51\xD5h\x03\x00\xED\xFA\r\xE1:x\x9C+\xC9L\xCEN-\xE1*)\xE1\x02\x00\x15`\x03\x81\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xB0x\xAB\xF5j\x9F\x9Et\xF3\xFF\xB5\xC7\x99\xB46\xF4X\xAF\x0F\xFD\xEE\x00\x00\xF1&amp;lt;\x0E\xD17x\x9C+\xC9L\xCEN-\xE1\x02\x00\ve\x02\x8F\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMax6\xF7\xD1\xECM\x17\xAF9{wk\xAE+\x8F\xBAq\xE8IO\xF0D\x00\v`\x10\xC50x\x9C\x03\x00\x00\x00\x00\x01\x198^\x9E\x03\xAA\x8D&amp;amp;\xFDb&amp;#39;\xF1\xB4wh\x8B:\xE9y0006\x01\xFB0000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;push:&lt;/h4&gt;

&lt;p&gt;get_info_refs:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET: /info/refs?service=git-receive-pack&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;response:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;001f# service=git-receive-pack\n00000074f989f58785072b3b3ba66650d53a22cc29e79b24 refs/heads/features\u0000 report-status delete-refs side-band-64k ofs-delta\n003fdca3e83385b0d685484566e8538e621dbf4606fe refs/heads/master\n0000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;git_receive_pack:&lt;/p&gt;

&lt;p&gt;request:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;POST: /git-receive-pack&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;0084f379eb8ee7ecbe5500fb5c79be7405fcf17cb453 035790766ac1c01b253e0508796c7408d0829259 refs/heads/master\x00 report-status side-band-64k0000PACK\x00\x00\x00\x02\x00\x00\x00\x03\x91\rx\x9C\x95\x8B\xDB\t\x021\x10\x00\xFFSE\xFE\x05\xD9\\\xB2y\x80\x88=X\xC1f\xB3\xD1\x80\xF1$\xE6\xB0}\xCF\x12\xFC\x18\x06\x06f\x0E\x11\xBD$\xEFw0e_\x1D\xC7d0\x16\xBB\x10p\xE4%Z2\xC5D\x9F([\xF5\xA2!\xCF\xA9\xAB\rIr\x14\t\xC2Y\x10\x01jF\x0E)Kp\x80\x95\xAB\t\x9C\x1DZE\xDB\xBC\xAFC_\xA9\xCDU\x9F\xDE?}\xB6\xCB\xADS{\x1Cy\xEDgm\xAC\x03\b\x01!\xE9\x03D\x00\xB5\xD7\xDE\xE6\x94\xBF&amp;amp;E\xA5\xE8!T\xBA\xA8/a\x11&amp;gt;A\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xB0\x9A{\xFE\xE8\x17\r&amp;#39;[\xD9\xFB\x12\x8E\x8A\xD2\x8Bu\xD2n[p\x03\x00\xE3\xC1\f\xA7?x\x9C+\xC9L\xCEN-\xE1*\x81\x00.\x00/\xC3\x05\xC5Wu\x8E\xD6\x88\xCB\x0F\xEA\x83\xA6\x97\xB2\xA3p\xA31\x9C\xFB\xC9\x18
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;response:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;0030\x01000eunpack ok\n0019ok refs/heads/master\n00000000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>Drawbacks of Git</title>
	<link href="http://saito.im/note/Drawbacks-of-Git/" />
	<id>tag:saito.im,2012:/note/Drawbacks-of-Git/</id>
	<updated>2012-06-06T00:00:00-07:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>Git Encoding Submodule HTTP</summary>
	<content type="html">
	
	&lt;p&gt;Git Encoding Submodule HTTP&lt;/p&gt;
	
	&lt;p&gt;&lt;h1&gt;Git:&lt;/h1&gt;

&lt;h3&gt;Encoding:&lt;/h3&gt;

&lt;p&gt;Encoding 是 VCS 系统该考虑还是不该考虑的?&lt;/p&gt;

&lt;p&gt;Git 告诉我们不需要: &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/v1.5.0.2/git-log.html&quot;&gt; git commit log &lt;/a&gt; .&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At the core level, git is character encoding agnostic.&lt;/p&gt;

&lt;p&gt;The pathnames recorded in the index and in the tree objects are treated as uninterpreted sequences of non-NUL bytes. What readdir(2) returns are what are recorded and compared with the data git keeps track of, which in turn are expected to be what lstat(2) and creat(2) accepts. There is no such thing as pathname encoding translation.&lt;/p&gt;

&lt;p&gt;The contents of the blob objects are uninterpreted sequence of bytes. There is no encoding translation at the core level.&lt;/p&gt;

&lt;p&gt;The commit log messages are uninterpreted sequence of non-NUL bytes.&lt;/p&gt;

&lt;p&gt;Although we encourage that the commit log messages are encoded in UTF-8, both the core and git Porcelain are designed not to force UTF-8 on projects. If all participants of a particular project find it more convenient to use legacy encodings, git does not forbid it. However, there are a few things to keep in mind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;对比一下其他 VCS 系统, &lt;a href=&quot;http://mercurial.selenic.com/wiki/EncodingStrategy&quot;&gt;HG&lt;/a&gt; 与 &lt;a href=&quot;http://www.tigris.org/scdocs/SVNEncoding&quot;&gt;SVN&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;简单来说: 一个没有对 commit log 与 path 做 encoding 的 VCS 系统会有两方面的问题.&lt;/p&gt;

&lt;p&gt;第一, 万恶的 windows 存在各种奇葩的 encoding, 这需要不同语言之间做兼容, 不然会因为编码的原因无法 clone 成功或者无法知道 commit log 具体是什么内容.( 一个 workaround 的办法是: 大家都用 msysgit patch 过的 utf8 版本的 Git Client) .&lt;/p&gt;

&lt;p&gt;第二, 作为一个 Github Like 系统的开发人员会做的很辛苦. 因为没人知道 push 到仓库的代码是什么编码, 甚至路径与提交信息都是别种的编码. 所以几乎处处都需要 detect 编码, 以及转换, 效率很差. 因为 Git 客户端没有在最适合的时候做最应该做的处理, 所以导致越外层效率越差, 而且效果不好. &lt;a href=&quot;https://github.com/holman/feedback/issues/191&quot;&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;SubModule:&lt;/h3&gt;

&lt;p&gt;submodule 作为一个相对于 svn 的 co 子目录被开发出来. 现阶段除了在 vim 插件领域大家应用广泛之外. 在现实开发领域很少有人会使用. ( 有使用经验的可以举手. 分享一下经验. )&lt;/p&gt;

&lt;p&gt;值得欣喜的是 subtree 已经被开发出来并 merge 到了 master. 这个值得期待. 是否实用暂时不清楚.&lt;/p&gt;

&lt;h3&gt;HTTP Support:&lt;/h3&gt;

&lt;p&gt;Git 在 1.6 之后才开始支持 smart http transport 协议, 并且在最近的一个发布版里面增强了 http 协议的功能, 但是还是不够. 在最近的 1.7 发布版里面 Git 默认支持了短时效的认证信息缓存功能, 默认有15分钟. 对于 Mac 版则可以将认证信息存储在 key-chain 里面 ( 貌似需要打patch. ).&lt;/p&gt;

&lt;p&gt;现阶段大家在 workaround 的方法一般都是: 在 home 下面 新建 .netrc 文件, 利用 curl 的附带认证信息的能力, 完成默认的认证. 否则每次提交都需要重新输入密码. ( 如果觉得每次输入密码这样安全的话, 可以忽略这一条. 或者你本身 ssh-keygen 之前都是需要输入密码的, 也可以略过. )&lt;/p&gt;

&lt;h3&gt;Feature:&lt;/h3&gt;

&lt;p&gt;最后, 我最期待的是: Git 2.0 能解决 Encoding 的问题, 当然这个涉及到很多打破兼容性的问题, 虽然可能性非常小, 但是真的值得做.&lt;/p&gt;

&lt;p&gt;最后, 欢迎补充与各种批评指正.&lt;/p&gt;
&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>Sinatra Extensions</title>
	<link href="http://saito.im/note/Sinatra-Extensions/" />
	<id>tag:saito.im,2012:/note/Sinatra-Extensions/</id>
	<updated>2012-03-25T00:00:00-07:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>Sinatra extensions in Action</summary>
	<content type="html">
	
	&lt;p&gt;Sinatra extensions in Action&lt;/p&gt;
	
	&lt;p&gt;&lt;h1&gt;sinatra 扩展:&lt;/h1&gt;

&lt;h3&gt;Sinatra编程的两种风格:&lt;/h3&gt;

&lt;p&gt;经典风格:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require&amp;#39;sinatra&amp;#39;

get &amp;#39;/&amp;#39; do
  &amp;quot;hello world&amp;quot;
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;模块化风格:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require&amp;#39;sinatra/base&amp;#39;

class Hello &amp;lt; Sinatra::Base

  get &amp;quot;/&amp;quot; do
    &amp;quot;hello world&amp;quot;
  end

  run!
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;为两种风格编写扩展:&lt;/h3&gt;

&lt;p&gt;Sinatra扩展也分为两种: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;helper 型&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dsl 型&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;helper型:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require &amp;#39;sinatra/base&amp;#39;

module Sinatra
  module FormatHelper
    def escape_html(text)
      Rack::Utils.escape_html(text)
    end
  end

  # make sure classic style can use this extension
  helpers FormatHelper 
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;classic style 使用extension&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require &amp;#39;sinatra&amp;#39;

get &amp;#39;/&amp;#39; do
  escape_html(&amp;quot;x &amp;gt; y&amp;quot;)
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;modular style 使用extension&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require &amp;#39;sinatra/base&amp;#39;

class Hello &amp;lt; Sinatra::Base

  helpers Sinatra::FormatHelper

  get &amp;#39;/&amp;#39; do
    escape_html(&amp;quot;x &amp;gt; y&amp;quot;)
  end

  run!
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;dsl型:&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require &amp;#39;sinatra/base&amp;#39;

module Sinatra
  module Devise
    def authenticate!
      before {
        halt 403, &amp;quot;You Bastards!&amp;quot;
      }
    end
  end

  # make sure classic style can use this extension
  register Devise
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;classic style 使用 dsl extension&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require &amp;#39;sinatra&amp;#39;

authenticate!

get &amp;#39;/&amp;#39; do
  escape_html(&amp;quot;x &amp;gt; y&amp;quot;)
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;modular style 使用 dsl extension&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require &amp;#39;sinatra/base&amp;#39;

class Hello &amp;lt; Sinatra::Base
  register Sinatra::Devise

  authenticate!

  get &amp;#39;/&amp;#39; do
    &amp;quot;hello world&amp;quot;
  end

  run!
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;两种扩展可以为sinatra扩展很多东西.&lt;/p&gt;

&lt;p&gt;例如: &lt;/p&gt;

&lt;p&gt;actionpack的各种helpers. 可以移植到sinatra上面来.&lt;/p&gt;

&lt;p&gt;sinatra自己的devise也是很容易通过扩展机制来实现的.&lt;/p&gt;

&lt;h3&gt;Sinatra helpers 和 register 的实现机制.&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;# lib/sinatra/base.rb#1772L
# Extend the top-level DSL with the modules provided.
def self.register(*extensions, &amp;amp;block)
  Delegator.target.register(*extensions, &amp;amp;block)
end

# Include the helper modules provided in Sinatra&amp;#39;s request context.
def self.helpers(*extensions, &amp;amp;block)
  Delegator.target.helpers(*extensions, &amp;amp;block)
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果Delegator.target本身没有被覆盖.则为Application本身.&lt;/p&gt;

&lt;p&gt;而Application的register方法如下:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;# lib/sinatra/base.rb#1681L
def self.register(*extensions, &amp;amp;block) #:nodoc:
  added_methods = extensions.map {|m| m.public_instance_methods }.flatten
  Delegator.delegate(*added_methods)
  super(*extensions, &amp;amp;block)
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;将扩展的public_instace_methods全部抽出来了,然后给Delegator.然后delegator通过send动态调用该method.&lt;/p&gt;

&lt;p&gt;Sinatra的helper则是直接被include至当前module或者classic模式下面的.&lt;/p&gt;

&lt;h3&gt;MRI vs JVM&lt;/h3&gt;

&lt;p&gt;JVM:&lt;/p&gt;

&lt;p&gt;java version &amp;quot;1.6.0_29&amp;quot;&lt;/p&gt;

&lt;p&gt;Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-11D50)&lt;/p&gt;

&lt;p&gt;Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02-402, mixed mode)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;        user       system     total       real
send    0.378000   0.000000   0.378000 (  0.335000)
method  0.114000   0.000000   0.114000 (  0.114000)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;MRI:&lt;/p&gt;

&lt;p&gt;ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin11.3.0]&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;        user       system     total       real
send    0.290000   0.000000   0.290000 (  0.284137)
method  0.280000   0.000000   0.280000 (  0.281496)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;不难想象JRuby下的sinatra跑的比较慢.(暂时没有openjdk7的环境, 或许在JDK7下会跑的比较快.)&lt;/p&gt;
&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>Ruby off Rails</title>
	<link href="http://saito.im/note/Ruby-off-Rails/" />
	<id>tag:saito.im,2012:/note/Ruby-off-Rails/</id>
	<updated>2012-02-21T00:00:00-08:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>rack, sinatra, padrino, etc...</summary>
	<content type="html">
	
	&lt;p&gt;rack, sinatra, padrino, etc...&lt;/p&gt;
	
	&lt;p&gt;&lt;h1&gt;Rack&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;minimal interface for web servers&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;gem i rack&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;require&amp;#39;rack&amp;#39;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;Rack handler&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Rack::Handler.constants&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A Rack application is an Ruby object (not a class) that responds to call. It takes exactly one argument, the environment and returns an Array of exactly three values: The status, the headers, and the body.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Ruby object that responds to call&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;object&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lambda or proc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;method&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-&amp;gt;{}.call&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It takes exactly one argument, the environment and returns an Array of exactly
three values: The status, the headers, and the body.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;-&amp;gt;(env){[200, {}, [Hello Saito]]}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Rack::Handler::Thin.run -&amp;gt;(env){[200, {}, [&amp;quot;Hey Saito&amp;quot;]]}&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;Middleware&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;class Decorator
def initialize(app)
@app = app
end

def call(env)
status, headers, body = @app.call(env)
[status, headers, body]
end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Rack::Handler::Thin.run Decorator(-&amp;gt;(env){[200, {}, [&amp;quot;Hey Saito&amp;quot;]]})&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Rack middleware is also a rack application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;Sinatra&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;require&amp;#39;sinatra&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;get &amp;#39;/&amp;#39; do
    &amp;#39;Hello saito!&amp;#39;
  end&lt;/p&gt;

&lt;h3&gt;REST, &lt;a href=&quot;http://www.ietf.org/rfc/rfc2616.txt&quot;&gt;RFC-2616&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;get, post, put, patch, delete, options
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rails/rails/pull/505&quot;&gt;Rails pull request 505&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Sinatra-contrib&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;sinatra/reloader
sinatra/namespace
sinatra/respond_with
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;…&lt;/p&gt;

&lt;h1&gt;Padrino&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;the Godfather of Sinatra&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Key Features&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;Admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Helpers
  Generators
  Mountable&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Padrino is another Rails&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;Others&lt;/h1&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;h1&gt;Sponsored by yavaeye.com&lt;/h1&gt;
&lt;/p&gt;
	</content>
</entry>

<entry>
	<title>Hypertext Transfer Protocol memes</title>
	<link href="http://saito.im/note/Hypertext-Transfer-Protocol-memes/" />
	<id>tag:saito.im,2011:/note/Hypertext-Transfer-Protocol-memes/</id>
	<updated>2011-12-22T00:00:00-08:00</updated>
	<author>
		<name>Saito Wu</name>
		<uri>http://saito.im/</uri>
	</author>
	<summary>idempotent patch delete verb</summary>
	<content type="html">
	
	&lt;p&gt;idempotent patch delete verb&lt;/p&gt;
	
	&lt;p&gt;&lt;h3&gt;Idempotent&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;9.1.2 Idempotent Methods
The methods GET, HEAD,PUT and DELETE share this property.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;9.1.2小节里面表示幂等方法是这么5个.&lt;/p&gt;

&lt;h3&gt;Delete&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;9.7 DELETE
A successful response SHOULD be 200 (OK) if the response includes an entity describing 
the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content)
if the response is OK but does not include an entity.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;9.7小节, delete正确且牛逼的返回应该是: 1) 带entity返回 =&amp;gt; 200, 异步还未处理结束 =&amp;gt; 202, 不带entity返回 =&amp;gt; 204 这个有人用对过么?&lt;/p&gt;

&lt;h3&gt;Patch&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;text language-text&quot; data-lang=&quot;text&quot;&gt;19.6.1.1 PATCH
The PATCH method is similar to PUT except that the entity contains a list of differences
between the original version of the resource identified by the Request-URI and the desired
content of the resource after the PATCH action has been applied. The list of differences
is in a format defined by the media type of the entity (e.g., &amp;quot;application/diff&amp;quot;) and MUST
include sufficient information to allow the server to recreate the changes necessary to
convert the original version of the resource to the desired version.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;19.6.1.1小节给出了这么一个addtional的请求方法,跟put的区别是patch会返回diff而不是整个entity.所以put是幂等的,patch则可幂等可不幂等..所以就不是幂等的...rails 4在还在纠结该怎么映射patch跟put在actionpack的update上.纠结着呢..&lt;/p&gt;

&lt;h3&gt;thread&lt;/h3&gt;

&lt;p&gt;另: 看thread学知识: &lt;a href=&quot;https://github.com/rails/rails/pull/505&quot;&gt;github rails pull-request 505&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;
	</content>
</entry>

</feed>

