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

[z]从shell 到 git repo

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

Android使用Git作为代码管理工具,开发了Gerrit进行代码审核以便更好的对代码进行集中式管理,ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台euNQ+H"? D-A^f6ep
还开发了Repo命令行工具,对Git部分命令封装,将百多个Git库有效的进行组织。ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台+O$MV:n*sn3jB1h
要想克隆和管理这百多个Git库,还真不是一件简单的事情。

\%puF2lfAl"}n0RP0如果了解了Repo的实现,

tJ.HZ.NL0

参考《Using Repo and Git》,

m_)lexg2e_ Rj0 建立一个本地的 android 版本库镜像还是不难的:
{,Y0N_U0    下载 repo bootstrap 脚本ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台&W]J `0B%^^3m#VH
    $ curl htttp://android.git.kernel.org/repo >~/bin/repoET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台;O9C C T3RC4H
    $ chmod a+x ~/bin/repo
2u3PY5jw C7X l%e0    $ export PATH=$PATH:~/binET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台V u_v f"q5Jp
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台H!R { y&IS7m
提供--mirror参数调用repo init,建立 git 版本库克隆ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台s2V3^ O h(]

ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台!mcT:B5Zx0|S

ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台2]3n:TKF3u ]
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台,YxAC]v

ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台isM;a9dRe^M&H

$ repo init -u git://android.git.kernel.org/platform/manifest.git --mirror
MU9wq1e:F8D)sQ w$E R9N0使用--morror则下一步和源同步的时候,本地按照源的版本库组织方式进行组织,否则会按照ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台*av)~.f X@&{
manifest.xml指定的方式重新组织并检出到本地
0V&k f-~n H`v7Yu0ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台`(gH'k%x0C7j x
开始和源同步ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台3_1G'@)h"I @b|e
$ repo sync
'h:[tb/u0    修改manifest,修改git库地址,指向本地的git服务器
6I$Fa [;EY.Hd1[3y&P0    修改platform/manifest.git库中现有的xml文件,或者创建一个新的xml文件ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台yH_:BH%K+\4w1{D0b#?
    将 git 的地址改为本地地址,提交并 pushET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台r,p0J.Hgf$~'DM

%Z|}5iDr&k0本地rep 镜像建立完毕之后,就可以在执行repo init时,使用本地更改后的manifest库,之后执行ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台&u+y8~ Y \t$z
repo sync就是基于本地版本库进行同步了。ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台sZ%yZG]
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台g#hm-Jt%d7[I`sD
也可以改造repo, 使得不必为repo工具初始化
0l|dh"{0
cX[&I ^+W3YCT;B0ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台,_m,W {r4|c*e

Repo init 干了些什么?

实际上,得到客户使用repo的信息后,首先下载repo执行脚本开始研究。
mQ`]0_ Rk1I)y0curl htttp://android.git.kernel.org/repo >~/bin/repoET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台X},u^2WQ+`
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台A#H l(Q4p'Y2r
难道只有600行的python代码么?要是这样应该很简单的呀。可以看下来,却发现远非如此。ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台+`N8ZNq+kamvs/j
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 KB^5z y_o_e
Shell script. or python?ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台/Hw1Vb/J(l4x
首先repo脚本使用了一个魔法:从脚本第一行来看应该是shell脚本,但是满眼却都是python语法,怎么回事?ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台R9g0uj uY

2[z{[u{0{0 1 #!/bin/sh
'm?n@k@s y0 2ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台1?1NT2\X&z JfC
 3 ## repo default configurationET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台%a |5d xtI2~\
 4 ##ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台4} A;ogE |KWd
 5 REPO_URL='git://android.git.kernel.org/tools/repo.git'
h4Y'ph/KA#y1@y1Qd0 6 REPO_REV='stable'ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台PO{u;k*j-l
 7ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台3kda"}2AEN.j1C/b
 8 # Copyright (C) 2008 Google Inc.ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台_7ko0}4p#`O9n
......   ...
b0zo,~Fr0
TmztWZ"A}7rV fM022 magic='--calling-python-from-/bin/sh--'ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台z'^o5p3D0i_,V
 23 """exec" python -E "$0" "$@" """#$magic"ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 m;Ue%p|I!M[
 24 if __name__ == '__main__':
Y^ Q/^&H0 25   import sys_temET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台c!Q WoI k2Gr^ O
 26   if sys_tem.argv[-1] == '#%s' % magic:
F7n0X.T\0 27     del sys_tem.argv[-1]
SR6A Z {7XIR0 28 del magic
%]RK6O@v1ZVk0
neF(|4H1k6G0魔法就在第 23 行,巧妙的通过python三引号字串写出了一个能被python和shell script都能理解的代码,以此为界,代码由 Shell 脚本进入了 Python 的世界。
'U@X9dI0
aPlTd7t#BZI#h0ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 uS1Dav ~%FG p

Bootstrap 和真正的 repo

ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 eV$z&[ l V"} cW2V&U
通过curl下载的的repo并非完整的repo脚本,只是一个bootstrap。当repo执行时,会负责下载完整的repo代码,并将控制权转移给真正的repo。
*t8Ub8e(E$nb@Y0`$~0
v V7JC-pvr?%[l)K0通过main函数,可以看到repo运行的开始,就试图发现本地真正的完整的repo代码,以便移交控制权:ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台c.VCFkM

}+AM@Sd0544 def main(orig_args):ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台;|cJ^z)F7D
545   main, dir = _FindRepo()ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台;W*z`"v[(eoi [i
...ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台)u;\7noy:a)zM
586   try:
e0Y9XM-X/x|[b0587     os.execv(main, me)
O ^/ko y3kU c0其中 545 行的 _FindRepo() 会在当前目录开始向上递归查找 “.repo/repo/main.py”,如果找到则ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 q*V|$J9n5eii
移交控制权(587行)。ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台`i8fC%q8{/F a~ S

QwD-w2IECex0Repo bootstrap 脚本调用 init 只完成第一阶段的初始化
kt3Krj#T0Repo的bootstrap脚本只支持两个命令help和init,而init也只完成repo版本库克隆
x5fU7h,y0(即安装 repo 完整工具),之后就转移控制权。
s l P(xO&y y0
)?@;K h'x$p)hf1i0在Repo bootstrap执行init可以提供很多参数,但实际上第一阶段初始化,只用到两个参数ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台!Z%gCiM&SU_*Ek
参数:--repo-url=URL repo 工具本身的 git 库地址。缺省为:git://android.git.kernel.org/tools/repo.git
S ~LT ln0参数:--repo-branch=REVISIONET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 fw)LS*g@!Gu2C
使用repo的版本库,即repo git库的分支或者里程碑名称。缺省为 stable
:f u0f%RRSm$N0
*T Hb H4w0

第二阶段的 repo init

执行第二阶段的repo init,控制权已经移交给刚刚克隆出来的 repo git 库的脚本。ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台3npy@f7?]
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 gaYzP7o
Repo git库被克隆/检出到执行repo init命令当前目录下的 .repo/repo 子目录中,主要的执行脚本
^X8xN$Fo [:adP:jOx0为 .repo/repo/main.py。main.py 接着执行 repo init 命令。
MJ.Yfs0
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台v+D1f}.oml

{ zPU/i7}?d{h:kz0
WO6OnNih0L0Repo的代码组织的非常好,
Cc2x']+AJ0在.repo/repo/su bcmds/子目录下,
tf N}c YN} `ZL0是各个 repo 命令的处理脚本。repoinit的第二阶段脚本正是由 .repo/repo/su bcmds/init.py 负责执行的。第二阶段主要完成:ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台`-V&S4r3B5u
    克隆由 -u 参数提供的 manifest Git 库,如克隆 android 库时:ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台e9N%e8vY p
        $ repo init -u git://android.git.kernel.org/platform/manifest.gitET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台.n4z+oY-B4[L
    如果不提供 -b REVISION 或者 –manifest-branch=REVISION参数,则检出 manifest Git 库的 master 分支ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台-st$T ER1C^
    如果不提供 -m NAME.xml 或者 –manifest-name=NAME.xml 参数,则使用缺省值 default.xmlET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台cZ `Ar |F
    如果提供 –mirror 参数,则后续同步操作会有相应的体现
@3^/X/k;R.I+W iYn"o0
,PLllF'Y2g0
~|1~y$F"M0D$L3\0Repo start 干了些什么?ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台9I6g(G3Ns+d1L"|,^
Android 源码网站在介绍repo的使用模型中,有一个图片:
IEL2PQ-qF zt0---htttp://source.android.com/images/git-repo-1.png ,
Z-Xe.l vP is3SV)c0
4a8U O"hA0介绍了 repo 的使用流程。ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台v;r%EYBPD
其中“repo start”是紧接着“repo sync”后的第一个动作。那么这个动作是干什么的呢?
;mvtt-O)X0
!mt}hLQ0得益于 repo 对 git 操作的封装,”repo start” 命令的处理代码只有区区 68 行。ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台EV`5k?P `@,O
 37   def Execute(self, opt, args):ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台S5`&u;S M'Q
...ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 J~ Ec'I2AQL$EC
 41     nb = args[0]
My^.G:j+\Gp j0...
4}"xb `A(] IfX0 47     projects = []
4~%v;sO6FPV0 48     if not opt.all:ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 T#[#B e{^(S4}g
 49       projects = args[1:]ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台|X[ R'UP
...ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台(Q/k"}-yy]` D
 54     all = self.GetProjects(projects)ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Y}wa Y0E0u(N
...ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台qK8U+[[ S(hqRy$D
 57     for project in all:ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台G7ou8w"^K%\
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 R.VNF8}$m9oR.r
 59       if not project.StartBranch(nb):ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台xu6e!m1m2Jn
 60         err.append(project)ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台/wvIwU+] BzM0x
看到第 59 行了么,就是对 repo 同步下来的项目的多个 Git 版本库,逐一执行 project.StartBranch
5o? sX { ab(AP0操作。 nb 是 repo start 的第一个参数,即分支名称。ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台,fpBS d;|%Ez

l^ Z dNXI.L0关于 StartBranch 的代码,在 project.py 中:
5hv1I]j\0 857   def StartBranch(self, name):ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台n'f`7F ]O
 858     """Create a new branch off the manifest's revision.ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 T'Du ZXd%C5N(q
 859     """
(pAuv X0...ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台%AoiVfc){w
 894     if GitCommand(self,
[1e:| K&J#f0 895                   ['checkout', '-b', branch.name, revid],ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台~jA3j4F
 896                   capture_stdout = True,
6~U)p#H-w0 897                   capture_stderr = True).Wait() == 0:ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台sZ8s OM0@REd
 898       branch.Save()
X{yx.k6e]M0 899       return True
%Z'~)X$V0L0ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Idy1|mr(G7z

.BMQU*t2F&mR"{!~0
-X:Q3dL4ih2h0ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台Wz*rFz.I%w

4lbro$\0^ v0
qa8oE}c0ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台x+U3DG;f c&A
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台*z2AZ;G[k6{6F
ET创芯网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台;a$W+A2Ov i+H?B

TAG:

 

评分:0

我来说两句

显示全部

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

Open Toolbar