像我儿子一样永远保持好奇和梦想

[z]从shell 到 git repo

上一篇 / 下一篇  2014-07-05 10:43:27 / 个人分类:linux

Android使用Git作为代码管理工具,开发了Gerrit进行代码审核以便更好的对代码进行集中式管理,龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台`-m2pFO9}H%|F$r U
还开发了Repo命令行工具,对Git部分命令封装,将百多个Git库有效的进行组织。
Eng3s+sSa!k0要想克隆和管理这百多个Git库,还真不是一件简单的事情。

龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台QJ&Xb c2L

如果了解了Repo的实现,

$l*VV{XX5c&e0

参考《Using Repo and Git》,

3bd3Y$ZH m f7~0 建立一个本地的 android 版本库镜像还是不难的:龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台'fk#Ak4l&r K
    下载 repo bootstrap 脚本龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台jsZg[T
    $ curl htttp://android.git.kernel.org/repo >~/bin/repo
7e[m*c{$O-i;g8D0    $ chmod a+x ~/bin/repo
zjg1]*K3lo%z5l"{0    $ export PATH=$PATH:~/bin龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台0^u'W8K,i1JjY
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Q8o6lY |\,[
提供--mirror参数调用repo init,建立 git 版本库克隆

}O8q\&Jxv J&i4y0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台e%OY8C_-r

龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台:^9f4^5d2i(}@3`

\~ h7g4U7L Vw0

-A&OC [ v+r r0$ repo init -u git://android.git.kernel.org/platform/manifest.git --mirror龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台P&B0a g.zsDO'P
使用--morror则下一步和源同步的时候,本地按照源的版本库组织方式进行组织,否则会按照龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台I7C*t&[#bw
manifest.xml指定的方式重新组织并检出到本地
4r5k/p7}&v+}s4eo kV0
$quO9]O(eS0开始和源同步龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台[sd,IL$S Q~
$ repo sync
5NCDlTd0    修改manifest,修改git库地址,指向本地的git服务器
L8` _8[ r| n0    修改platform/manifest.git库中现有的xml文件,或者创建一个新的xml文件龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 w*vpaLqM
    将 git 的地址改为本地地址,提交并 push龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台8\(}F#Uf,N
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台;B;gQ1r#sES
本地rep 镜像建立完毕之后,就可以在执行repo init时,使用本地更改后的manifest库,之后执行
!g\,p:_ G^g1zJ0repo sync就是基于本地版本库进行同步了。
U?Y,kzs:d0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台k @'\)A4Qkm |y
也可以改造repo, 使得不必为repo工具初始化龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台%\:|3EY)Qd*oU
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台gxZ*I@O:Xo
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台.zru%@ Qu+T

Repo init 干了些什么?

实际上,得到客户使用repo的信息后,首先下载repo执行脚本开始研究。
7t;x&s [~S$A|:u8~l0curl htttp://android.git.kernel.org/repo >~/bin/repo龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台x(ed$|r?$P
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台!RmE y$Uxb;UK
难道只有600行的python代码么?要是这样应该很简单的呀。可以看下来,却发现远非如此。
/~h@KBG*W0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台\*K(BQ }#F(zN
Shell script. or python?
q_&Z$@,F d{0首先repo脚本使用了一个魔法:从脚本第一行来看应该是shell脚本,但是满眼却都是python语法,怎么回事?
B*K7Oc"qSNLh Ip0
~{!Yt.i1S1l$? U0 1 #!/bin/sh
-[8]F-U6B:j0 2
i*{ |b;DA9N0 3 ## repo default configuration龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台"T})d(j f y
 4 ##
1D/N/@W:a V J[N0 5 REPO_URL='git://android.git.kernel.org/tools/repo.git'龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台;d#^+^7Xl._D
 6 REPO_REV='stable'
D wm.VNS4Q2]Hn0 7
2zm/z nU;A g0 8 # Copyright (C) 2008 Google Inc.
tS/oZKt0......   ... 龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台r;OJY-Bk

o[IcY_+X X022 magic='--calling-python-from-/bin/sh--'龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台],c"[^ D
 23 """exec" python -E "$0" "$@" """#$magic"龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台*e"^*A+wF)Z _4zW&A
 24 if __name__ == '__main__':
yZ)~w,T,g0 25   import sys_tem
3U NE\`} n4E0 26   if sys_tem.argv[-1] == '#%s' % magic:
2x0`z0V*h7MHP%d0 27     del sys_tem.argv[-1]龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台5ZC*g k%a}(j R
 28 del magic龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台xzFy2dQ
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台$PV:@7dr_
魔法就在第 23 行,巧妙的通过python三引号字串写出了一个能被python和shell script都能理解的代码,以此为界,代码由 Shell 脚本进入了 Python 的世界。
)\gv#?w?ts5M0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台`T[AA0Ou%f

-Zpd&f)w w6J _!Hx;l0

Bootstrap 和真正的 repo

龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台B-_[|A Ok|{
通过curl下载的的repo并非完整的repo脚本,只是一个bootstrap。当repo执行时,会负责下载完整的repo代码,并将控制权转移给真正的repo。龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台%l@#F"OvWi
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台koJw _Z2iq
通过main函数,可以看到repo运行的开始,就试图发现本地真正的完整的repo代码,以便移交控制权:龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台nz _ p0w3~cA
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台q]"\*\ n;[
544 def main(orig_args):
9pQ0{z7|0545   main, dir = _FindRepo()
\uxkE w$|a'm"a/X0...
4r il!N\ S5\nS0586   try:龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台"sEk)Vu/GL$W
587     os.execv(main, me)
`H)NJe4VM0其中 545 行的 _FindRepo() 会在当前目录开始向上递归查找 “.repo/repo/main.py”,如果找到则龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台,O+n`] \r
移交控制权(587行)。
k#{Qs g:_G_ m-N} e`0
ed~E@a0Repo bootstrap 脚本调用 init 只完成第一阶段的初始化龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台UtA*S;o;_
Repo的bootstrap脚本只支持两个命令help和init,而init也只完成repo版本库克隆龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台m{sK+|!y|
(即安装 repo 完整工具),之后就转移控制权。
QEQ ~TYs&z W0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台6H@Dp _\
在Repo bootstrap执行init可以提供很多参数,但实际上第一阶段初始化,只用到两个参数龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台~tN0kJ ]+Lb `L9Te
参数:--repo-url=URL repo 工具本身的 git 库地址。缺省为:git://android.git.kernel.org/tools/repo.git龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台!| M0N ]#yU(c4J ~k.]O
参数:--repo-branch=REVISION
8i(B a N5B]5Z2J l:ET{0使用repo的版本库,即repo git库的分支或者里程碑名称。缺省为 stable
[:P5^I Zn P*m0
S \b5eY1R Qrz0

第二阶段的 repo init

执行第二阶段的repo init,控制权已经移交给刚刚克隆出来的 repo git 库的脚本。
/_+S6CHT%AC0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台+|5i[cdmq r
Repo git库被克隆/检出到执行repo init命令当前目录下的 .repo/repo 子目录中,主要的执行脚本
O!@,?7j:JU0为 .repo/repo/main.py。main.py 接着执行 repo init 命令。龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Z M'c6`:s&Y k
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台(k)mP,hz

(O;t.ER#J@3D0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台N+~c+vQX[1o VG
Repo的代码组织的非常好,龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Wq IJGJ7D su$X
在.repo/repo/su bcmds/子目录下,
W:\4w8| f&h0是各个 repo 命令的处理脚本。repoinit的第二阶段脚本正是由 .repo/repo/su bcmds/init.py 负责执行的。第二阶段主要完成:
aV*V)o]t(b;O _0    克隆由 -u 参数提供的 manifest Git 库,如克隆 android 库时:龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台M/AK/F&f2y0I'P#xn
        $ repo init -u git://android.git.kernel.org/platform/manifest.git
l0b@&a*A-s;ZuR0    如果不提供 -b REVISION 或者 –manifest-branch=REVISION参数,则检出 manifest Git 库的 master 分支
cV0HU ZmIu:n'P0    如果不提供 -m NAME.xml 或者 –manifest-name=NAME.xml 参数,则使用缺省值 default.xml龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台&Av`~2o*ry
    如果提供 –mirror 参数,则后续同步操作会有相应的体现龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台i,k2x|3t#r
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台._J8kk^u ^
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台-~;E-nc-G-P_J$g
Repo start 干了些什么?
p,J&{1W[cC"ZO0Android 源码网站在介绍repo的使用模型中,有一个图片:龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台i"J:MOx6{|S
---htttp://source.android.com/images/git-repo-1.png ,
Cl/H J0K0
|O7D1VIu @^K@0介绍了 repo 的使用流程。龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台)mV)A^|%{+nR0K,ul
其中“repo start”是紧接着“repo sync”后的第一个动作。那么这个动作是干什么的呢?
ro6s(r%T#JC0
)]fs{H0s/Q3g1p-K-l0得益于 repo 对 git 操作的封装,”repo start” 命令的处理代码只有区区 68 行。
+iisZ*jv0 37   def Execute(self, opt, args):龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台1xLk4aK7H|Q
...龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台0~ ^6] L ?;x@!H
 41     nb = args[0]龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台?f6`x.X5k6t:Er
...
fO? I6I+L7t0 47     projects = []龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Ce&r0OkF#Q k g%q6t3{
 48     if not opt.all:龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台B`#xnY.Y
 49       projects = args[1:]龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台1r.eb6pa:c8h ONk
...
1_k S;J SWe0 54     all = self.GetProjects(projects)
1U-{_-B0fCc(m)y0...
o@S,\&X5a SRBc7vP0 57     for project in all:
,J(U+X?q0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台GY.rl2M-e&A
 59       if not project.StartBranch(nb):龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台3Fa&m2F"Hj4Ss
 60         err.append(project)龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Fj {g4O|
看到第 59 行了么,就是对 repo 同步下来的项目的多个 Git 版本库,逐一执行 project.StartBranch龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台0?7c2q7~Y&T y
操作。 nb 是 repo start 的第一个参数,即分支名称。
cah#s3Xa0
6[b2V9[4`T0Q0关于 StartBranch 的代码,在 project.py 中:龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台z&Y.s'O g[XU\3D,G
 857   def StartBranch(self, name):
G{ T z.Vxzld0 858     """Create a new branch off the manifest's revision.
8|%Gv3oP0 859     """龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台%m9Qp1y HOY
...
`"xnk)T i5Q-]^0 894     if GitCommand(self,
L0yX#B"C#A0 895                   ['checkout', '-b', branch.name, revid],龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台"Q!Ag'E2W9sS
 896                   capture_stdout = True,龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台R&f3f&\ dW |
 897                   capture_stderr = True).Wait() == 0:
pJI[)]{ z#on0 898       branch.Save()龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台#TjO&XY
 899       return True龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 F4X7T mEf n
龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Asfz4uy:r w&@

2]s9o,GW0NY0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台-Z2o `:eB0B6AX[

$t*|0b0jWhrvE0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台w3ge+T.Z&N

\ A,G,D!Z%_z2p#S0
d[ ?9F7Xf.eEP0
6M2aFh'V)kO0龙8国际_龙8国际下载_龙8国际娱乐官方网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台2yhOF0R:I;aH4?!U

TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar