koding一个在线开发环境



Koding一个挺有意思的站点,它提供了在线的开发环境。每个人都可以使用免费的虚拟主机,采用Ubuntu,Python, PHP, java, Ruby各种开发环境,还有一个基于web的集成开发环境,同时采用社区模式,直接交流开发问题。

“Say goodbye to localhost.”你基本上可以直接在Koding做web开发,并马上能在线访问。当然唯一的限制是在你退出登录20分钟后,虚拟机会被关闭。因为它目标是提供开发环境,而不是做生产应用的托管主机。详细可以参见介绍

不过个人认为还是挺不过的一个产品,毕竟你有了一个真实的可以在互联网上访问的开发环境,免费,效率也不错。有兴趣的可以点击我的推荐注册。

学习一下git(四)



之前有关git的学习都是基于本地,除了版本的管理和控制外,和别人的协作一般还是需要远程服务器。你可以自己架设服务器,也可以用git托管服务,比如github,其他的可以参见git官方wiki上的托管服务列表

可以从git clone 开始,

$ git clone https://github.com/xbin999/gittest.git
</pre> git clone除了建立自己的本地分支master和远程分支origin/master外,并且会将他们都指向orgin上的master分支,这自动就是一个跟踪分支(从远程分支checkout出来)。 <pre>
$ git remote -v
origin https://github.com/xbin999/gittest.git (fetch)
origin https://github.com/xbin999/gittest.git (push)

git remote add 可以添加远程仓库地址,指定别名。 git remote show 显示远程仓库信息。
git fetch 从远程仓库抓取信息。注意fetch出来只是更新remote索引。要在本地编辑需要merge到本地分支中或者checkout出一个新的分支。 git push 推送数据到远程仓库。

而和远程服务器最简单的协作方式之一:先在自己的特性分支中工作一段时间,完成后合并到自己的 master 分支;然后下载合并 origin/master 上的更新(如果有的话),再推回远程服务器。一般的协作流程如图所示:



对于自己拥有的项目,可以用git push推送。但如果要给公开项目作贡献,往往你并没有直接更新主仓库分支的权限,需要把工作成果交给项目维护人。

一种方式使用 git 托管服务商提供的仓库复制功能,一般称作 fork,比如GitHub 都支持这样的操作,而且许多项目管理员都希望大家使用这样的方式。 另一种方式是通过电子邮件寄送文件补丁。

学习一下git(三)



任何的版本管理控制系统都会有分支的管理,不过git的分支管理要简单地多,确实比较牛。这源于前面所说的设计,版本间的差异保存的不是文件差异或者变化量,而是一系列文件的快照。

看一个例子,git仓库中三个文件,git add加入暂存区域后,会把当前版本的文件快照保存到git仓库中,并将校验和(也就是SHA-1哈希串)加入暂存区域;git commit提交时,会计算每个目录的校验和,作为树(tree)对象保存,结果如图(这几个图真是太棒了,想不夸都不行):



每一次修改后,再提交,就有不同的commit对象指向不同的快照。



而对于git的分支,本质就是个指向commit对象的指针,默认是master分支,每次提交后移动master即可。



使用git branch testing创建一个新的分支testing,这时新分支也是一个指针,指向同一快照。至于你工作在哪个分支,则有HEAD的特别指针来标识。



可以使用git checkout testing来切换到新建分支。



有了分支后,你可以在不同的分支上分别进行版本的演进。而gi很t有意思的是可以很在同一个目录中,不同分支间进行随意地切换,切换到新的分支后,目录中的文件就都会自动更新到新版本,不象其他版本工具,你可能需要多个目录分别保存不同的版本。git的版本切换开销非常之低,可以几毫秒完成分支的创建和切换。所以Git鼓励开发者频繁使用分支。

在分支的使用中,除了branch,checkout创建和切换分支外,另外需要的就是分支代码的合并。

合并分支有两种方法:

一是采用merge,如果遇到冲突,需要手工修改冲突的文件,再运行git add把它标记为已解决状态。

二是采用rebase,参见示例,rebase是把分支experiment的C3版本在master分支上C4版本上重新打一遍,rebase比merge看起来主干线会更清晰,本质是把合并的工作责任交给主干线的提交了。



需要遵守一条准则:“一旦分支中的提交对象发布到公共仓库,就不要对该分支进行rebase操作。”

看来rebase还是少用为妙。以上的分支操作并不设计远程,下次整理一下有关远程仓库的操作和分支的管理。

学习一下git(二)



两种途径开始git,一是init初始化新仓库,再添加文件;二是从现有仓库clone。

git init git clone> 为什么是clone,而不是checkout,就是因为git和其他VCS不同的是git收取项目历史所有的数据,而不仅仅是某一个版本。

在有了git仓库后,常用的操作就是add, commit, log, status, diff, rm, mv,而这些操作还是需要理解三个区域,以及在区域间文件的状态变化周期。

文件的状态变化周期

git diff 比较工作目录中当前文件和暂存区域快照之间的差异。 git diff –cached 比较暂存区域和上次提交的快照之间的差异。
git diff –staged 同上。git diff采用合并格式diff的变体,带上下文,有关diff的格式详细参考阮一峰的读懂diff。> diff –git a/yun.txt b/yun.txt
>
> index de629e5..67ca091 100755
>
> — a/yun.txt
>
> +++ b/yun.txt
>
> @@ -13,3 +13,4 @@ pc-jfjwapp11 10.70.217.70
>
> pc-jfjwapp12 10.70.217.71
>
> $ test
>
> second line
>
> +add 8-21
>
> 1. 第一行,a版本是变动前的,b版本是变动后的。
> 2. 第二行,de629e5是a版本的哈希值,67ca091是b版本的哈希值,755表示文件权限。
> 3. 第三、四行表示比较的两个文件,—是a版本,+++是b版本。
> 4. 第五行@@和@@之间是两个文件的变化,-13,3 是a版本的第13行开始,一共3行,+13,4是表示b版本的第13行开始,一共4行。
> 5. 之后是变化的文件内容,带有+号的是表示b版本内容,带有-号的是表示a版本的内容。
git commit git commit -a 跳过使用暂存区域,也就是不要git add了。 git rm 移除文件
git rm –cached 从暂存区域移除,当前工作目录保留,比如编译中间文件。 git log -p -2 其中-p选项展开显示每次提交的内容差异,-2则仅显示最近的两次更新。
* gitk 是随git一同发布,基于Tcl/Tk的,git log的图形化工具。

如果和常规的版本控制管理系统相比较,多人协同开发,还是需要一个代码托管的地方。github 就提供了免费软件项目git仓库托管服务,国内也有gitcafe。所以完整的git使用还涉及和托管服务之间的交互,和远程仓库的协作下次继续。

学习一下git(一)



看ruby和写代码的时候,很难离得开git )和github,所以让自己也系统地看一下。

git )是一个分布式的版本控制和源代码管理系统,最开始是由Linus Torvalds为linux内核开发而设计实现的。

传统的版本控制管理,象CVS,SVN一般都会有一个中心服务器,本地check out代码,然后修改,提交合并代码,但这样的问题是依赖于中心服务器。而对于分布式版本控制系统则在本地都有完整的代码仓库,任何一台服务器发生故障,都可以使用镜像的本地仓库恢复。

git很大的一个特点是对于文件保存完整的数据,而非文件的增量差异,在不同版本时对于没有变化的文件不再保存,而仅做一个链接。

Git保存更新时的文件快照

由于其分布式的特点,每台机器上都是一个仓库,所以基本上操作都在本地,包括往库里提交修改、版本差异比较、查看更新日志等等。

对于git来说,任何一个文件流转过程中都存在三种状态:

已提交(committed),表明文件已经提交到本地仓库中。 已修改(modified),表明文件已经修改,但未提交。
已暂存(staged),表明已修改的文件放在下次提交时要保存的清单中。

所以对于本地工作时,git有三个工作区域:git的工作目录,git本地仓库和暂存区域,一般在工作目录中会有一个.git目录,其中就保存了元数据和对象数据库,而暂存区域文件(index索引文件)也放在.git目录中。对于理解暂存区的作用,worldhello上有一篇很好的文章和一个图,引用一下:
git work area

如果我修改一个文件,增加一行”in stage”,然后使用git add 保存到暂存区,之后再增加一行”in work directory”,git status查看状态:

➜ /Users/yangbin/tmp/gittest git:(master) >git status -s
➜ /Users/yangbin/tmp/gittest git:(master) >git add yun.txt
➜ /Users/yangbin/tmp/gittest git:(master) ✗ >echo “in stage” >> yun.txt
➜ /Users/yangbin/tmp/gittest git:(master) ✗ >git status -s
M yun.txt
➜ /Users/yangbin/tmp/gittest git:(master) ✗ >echo “in work directory” >> yun.txt
➜ /Users/yangbin/tmp/gittest git:(master) ✗ >git status -s
MM yun.txt

此时工作区、暂存区和本地仓库yun.txt文件的内容各不相同,可以使用:
git commit yun.txt 提交暂存区的内容到本地仓库,也就是增加“in stage”;
git rm – cached yun.txt 直接从暂存区删除内容,工作区不变; git checkout . yun.txt 使用暂存区文件更新工作区文件;
* git chekcout HEAD yun.txt 使用本地仓库文件更新工作区和暂存区文件。

当然我们要使用git一般都是从git init 和git clone开始的,这个下次再说。

brew,gem,rvm and bundler



brew,gem,rvm 和 bundler都是软件包的管理工具,搞过来搞过去,有点晕,需要理理。

brew是OS X上提供软件包的管理。Homebrew将软件包安装到单独的目录,然后符号链接到/usr/local 中,完全基于git和ruby。使用gem来安装你的gems,用brew来搞定他们的依赖包。brew的安装:

ruby -e “$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
</pre> [**RubyGems**](http://rubygems.org/)是一个包管理框架,提供了ruby社区gem的托管服务,用于方便地下载、安装和使用ruby软件包。ruby软件包被称为"gem",包含了ruby应用或库。要升级到最新的RubyGems,运行: <pre>
$ gem update –system
</pre> 如果没有安装RubyGems,则需要先下载安装包,然后解压开后运行ruby setup.rb。 gem常用的命令有search, install, list, uninstall。如果要看安装的gem文档,一是可以用ri,二是可以gem server启动一个web服务。详细的帮助参见[RubyGems Guides](http://guides.rubygems.org/)。 brew和gem不同,brew用于操作系统层面上软件包的安装,而gem只是管理ruby软件。 [**RVM**](http://rvm.io/)(Ruby enVironment (Version) Manager)是一个命令行工具,提供在多个ruby环境中方便的安装、管理和工作,包括解释器和gem集合。rvm自己的安装通过curl命令执行,如:[curl -L https://get.rvm.io | bash](http://rvm.io/rvm/install)。 RVM有一个非常灵活的gem管理系统,称为Gem Sets。RVM的'gemsets'管理横跨多个Ruby版本的gems包。 采用rvm安装ruby: <pre>
$ rvm list known
$ rvm install 1.9.3
$ rvm use 1.9.3

Bundler为ruby维持一个一致性的环境,跟踪应用代码和所需要的ruby gems,这样一个应用可以有所需要的精确的gems(和版本)。

$ gem install bundler

安装的顺序,先安装rvm,之后选择安装一个ruby版本,就可以提供一个完整的ruby运行环境。之后可以安装brew(brew虽然是管理os的,但基于ruby)和gem,分别管理操作系统和ruby的软件包。之后ruby重新编译的时候所依赖的包可以使用brew安装。有了gem之后,bundler只不过就是一个gem,直接通过gem install 即可。

ruby p vs puts



代码的时候看到了 p “ 80 + “validated” ,心想这个p是啥玩意,为啥不用puts啊?

细看一下还有点讲究,p是个Kernel方法,p打印的是inspect方法,而不是to_s,更适合与调试。比如 1, “1” and “2\b1”的区别,用puts输出的全是1,而p则能输出内部结构

1.9.3p125 :055 > puts 1, “1”, “2\b1”
1
1
1
=> nil
1.9.3p125 :056 > p 1, “1”, “2\b1”
1
“1”
“2\b1”
=> [1, “1”, “2\b1”]
</pre> 在[What is “p” in Ruby?](http://stackoverflow.com/questions/1758284/what-is-p-in-ruby)还说到了一个poetry mode,写Ruby方法调用参数时不使用括号,不是很理解。 优酷上有段视频[“HASHES AND POETRY MODE ”](http://v.youku.com/v_show/id_XNTg0NDM3OTA0.html),"poetry mode"是指: * using hashes to pass "keyword-like" arguments * omit hash braces when last argument to function is hash * omitting parens around function arguments 主要的目的还是在不引起歧义的情况下,去掉hash的{}和函数参数的(),使得代码阅读更象句子。看示例就很清楚: <pre>
link_to(“Edit”, {:controller=>’students’, :action=>’edit’})
link_to ‘Edit’, :controller=>’students’, :action=>’edit
link_to ‘Edit’, controller: ‘students’, action: ‘edit

(redirect_to(login_page)) and return() unless logged_in?
redirect_to login_page and return unless logged_in?

BTW. 还可以用” 80,这个比我上次写(all-depth).times {print “ “} 就要优雅多了。

xml-rpc



XML-RPC 是互联网上的一种远程过程调用协议,采用http+xml的方式。XML-RPC消息是一个HTTP-POST请求,请求报文是XML,而服务端调用返回的报文也采用XML格式。

XML-RPC支持的数据类型有:int, string, boolean, double, dateTime.iso8601, base64, array, struct。如果不指定类型,缺省为string。

返回报文正常情况都是200 OK,比如:

HTTP/1.1 200 OK
Connection: close
Content-Length: 158
Content-Type: text/xml
Date: Fri, 17 Jul 1998 19:55:08 GMT
Server: UserLand Frontier/5.1.2-WinNT
</pre> &lt;?xml version="1.0"?&gt; &lt;methodResponse&gt; &lt;params&gt; &lt;param&gt; &lt;value&gt;&lt;string&gt;South Dakota&lt;/string&gt;&lt;/value&gt; &lt;/param&gt; &lt;/params&gt; &lt;/methodResponse&gt; &lt;/code&gt;&lt;/pre&gt; <pre>Ruby 很好地提供了对XML-RPC的支持,直接require “xmlrpc”,分别有clientserver。一个简单的例子:
</pre> server 端,new创建一个实例,并在指定端口侦听,serve在增加了处理器后启动服务,处理XML-RPC请求并响应。 <pre>
require “xmlrpc/server”

s = XMLRPC::Server.new(7777)
s.add_handler(“michael.add”) do |a,b|
a + b
end

s.serve
</pre> client 端采用call调用方法,第一个参数是方法名,之后跟着方法需要的参数。 <pre>
require “xmlrpc/client”

server = XMLRPC::Client.new(“localhost”, “/RPC2”, 7777)
begin
param = server.call(“michael.add”, 4, 5)
puts “4 + 5 = #{param}”
rescue XMLRPC::FaultException => e
puts “Error:”
puts e.faultCode
puts e.faultString
end

Wordpress提供了XML-PRC的支持,从WordPress 3.5起就默认支持XML-RPC功能,详细的API参见XML-RPC WordPress API,采用wp.接口取代了Blogger, MovableType和metaWeblog接口。

列出数据量大的文件或目录



一不小心发现机器的磁盘空间差不多用满了,空间紧张啊,虽然可以用du查看各个目录占用的情况,再进行清理,但往往需要一层层去查找占用空间最大的目录,比较累人。所以用ruby练练手,写了个递归便利目录中大的文件和目录,可以设定参数如下:

Usage: mydu [options] directory
Specific options:
-d, –depth [depth] Search directories depth
–dsize [dsize Mbyte] Directory size limit to display
–fsize [fsize Mbyte] File size limit to display
-h, –help Display this message
</pre> 代码也比较简单,有几点注意的: * %x(du -sm \'#{dir}\'/*) 执行os命令,注意dir用引号引起,防止特殊字符,而/在引号外面,否则特殊字符也会使得目录名无效。 * 把目录和大小丢进hash,直接sort.reverse即可倒序排。 * line.split(' ', 2) 也是防止带空格的目录名,保证后面的都作为第二个元素,得到完整的目录名。 [详细代码](https://gist.github.com/xbin999/6162968)如下: <pre>
require ‘optparse’

def du(dir, all, depth, dsize, fsize)
return if depth = dsize
(all-depth).times {print “ “}
puts “[d], #{k}, #{v}”
du(“#{v}”, all, depth - 1, dsize, fsize)
end
if File.file?(“#{v}”) && k >= fsize
(all-depth).times {print “ “}
puts “[f], #{k}, #{v}”
end
size += k
}
(all-depth-1).times {print “==”}
puts “#{dir} size is #{size}M.”
end

options = {}
optparse = OptionParser.new do|opts|
opts.banner = “Usage: mydu [options] directory”
opts.separator “Specific options:”
options[:depth] = 2
opts.on( ‘-d’, ‘–depth [depth]’, Integer, ‘Search directories depth’ ) do|depth|
options[:depth] = depth
end
options[:dsize] = 1024
opts.on( ‘–dsize [dsize Mbyte]’, Integer, ‘Directory size limit to display’ ) do|dsize|
options[:dsize] = dsize
end
options[:fsize] = 200
opts.on( ‘–fsize [fsize Mbyte]’, Integer, ‘File size limit to display’ ) do|fsize|
options[:fsize] = fsize
end
opts.on( ‘-h’, ‘–help’, ‘Display this message’ ) do
puts opts
exit
end
end

optparse.parse!(ARGV)
du(ARGV[0], options[:depth], options[:depth], options[:dsize], options[:fsize])

什么是RubyGem



RubyGems包管理系统(也称为Gems)已经成为Ruby代码包发布和管理的标准,在Ruby 1.9中已经打包在Ruby中提供。

每个gem有名称、版本和平台。比如rake gem版本是0.8.7,平台是ruby,可以在Ruby的任意平台上运行,其他平台还包括java(比如nokogiri)和mswin32(比如sqlite-ruby)。

Gems的结构,一般包括三部分:

代码,包括测试和支持工具。 文档
gemspec

每个gem有同样的标准代码组织结构:

% tree freewill
freewill/
├── bin/
│ └── freewill
├── lib/
│ └── freewill.rb
├── test/
│ └── test_freewill.rb
├── README
├── Rakefile
└── freewill.gemspec
`
lib包含gem的代码。
test或spec包含测试,取决于采用测试框架。 一个gem通常有一个Rakefile,用于rake程序自动化测试、生成代码和执行其他一些任务。
一般在bin目录下会有一个执行文件,gem安装后,该bin目录通常会在PATH路径中。 文档一般包含在README和代码中。当安装gem时,文档会自动生成,大多数gems包括RDoc文档,有的也用YARD
* 最后一部分是gemspec,包含有关这个gem的规格信息。包括文件、测试、平台、版本号和其他的作者邮件和姓名等等。

RubyGems修改了Ruby的装载路径,控制你的Ruby代码能被require找到。

一旦使用require请求一个gem,RubyGems

自动把lib目录加入到$LOAD_PATH中,有些gems也会增加其他目录,比如bin。这些是可选的,你可以把一个gem的多个目录加入到装载路径中。

Gemspec提供基本的信息,让你知道gem包含的内容,一个简单例子:

`
% cat freewill.gemspec
Gem::Specification.new do |s|
s.name = ‘freewill’
s.version = ‘1.0.0’
s.date = ‘2010-04-27’
s.summary = “Freewill!”
s.description = “I will choose Freewill!”
s.authors = [“Nick Quaranto”]
s.email = 'nick@quaran.to
s.homepage = ‘http://example.com'
s.files = [“lib/freewill.rb”]
end

来源What is a gem?