hsy75的个人空间 https://blog.eetop.cn/vivilife [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

[z]从shell 到 git repo

已有 2053 次阅读| 2014-7-5 10:43 |个人分类:linux

Android使用Git作为代码管理工具,开发了Gerrit进行代码审核以便更好的对代码进行集中式管理,
还开发了Repo命令行工具,对Git部分命令封装,将百多个Git库有效的进行组织。
要想克隆和管理这百多个Git库,还真不是一件简单的事情。

如果了解了Repo的实现,

参考《Using Repo and Git》,

建立一个本地的 android 版本库镜像还是不难的:
    下载 repo bootstrap 脚本
    $ curl htttp://android.git.kernel.org/repo >~/bin/repo
    $ chmod a+x ~/bin/repo
    $ export PATH=$PATH:~/bin

提供--mirror参数调用repo init,建立 git 版本库克隆


$ repo init -u git://android.git.kernel.org/platform/manifest.git --mirror
使用--morror则下一步和源同步的时候,本地按照源的版本库组织方式进行组织,否则会按照
manifest.xml指定的方式重新组织并检出到本地

开始和源同步
$ repo sync
    修改manifest,修改git库地址,指向本地的git服务器
    修改platform/manifest.git库中现有的xml文件,或者创建一个新的xml文件
    将 git 的地址改为本地地址,提交并 push

本地rep 镜像建立完毕之后,就可以在执行repo init时,使用本地更改后的manifest库,之后执行
repo sync就是基于本地版本库进行同步了。

也可以改造repo, 使得不必为repo工具初始化

Repo init 干了些什么?

实际上,得到客户使用repo的信息后,首先下载repo执行脚本开始研究。
curl htttp://android.git.kernel.org/repo >~/bin/repo

难道只有600行的python代码么?要是这样应该很简单的呀。可以看下来,却发现远非如此。

Shell script. or python?
首先repo脚本使用了一个魔法:从脚本第一行来看应该是shell脚本,但是满眼却都是python语法,怎么回事?

 1 #!/bin/sh
 2
 3 ## repo default configuration
 4 ##
 5 REPO_URL='git://android.git.kernel.org/tools/repo.git'
 6 REPO_REV='stable'
 7
 8 # Copyright (C) 2008 Google Inc.
......   ...

22 magic='--calling-python-from-/bin/sh--'
 23 """exec" python -E "$0" "$@" """#$magic"
 24 if __name__ == '__main__':
 25   import sys_tem
 26   if sys_tem.argv[-1] == '#%s' % magic:
 27     del sys_tem.argv[-1]
 28 del magic

魔法就在第 23 行,巧妙的通过python三引号字串写出了一个能被python和shell script都能理解的代码,以此为界,代码由 Shell 脚本进入了 Python 的世界。


Bootstrap 和真正的 repo


通过curl下载的的repo并非完整的repo脚本,只是一个bootstrap。当repo执行时,会负责下载完整的repo代码,并将控制权转移给真正的repo。

通过main函数,可以看到repo运行的开始,就试图发现本地真正的完整的repo代码,以便移交控制权:

544 def main(orig_args):
545   main, dir = _FindRepo()
...
586   try:
587     os.execv(main, me)
其中 545 行的 _FindRepo() 会在当前目录开始向上递归查找 “.repo/repo/main.py”,如果找到则
移交控制权(587行)。

Repo bootstrap 脚本调用 init 只完成第一阶段的初始化
Repo的bootstrap脚本只支持两个命令help和init,而init也只完成repo版本库克隆
(即安装 repo 完整工具),之后就转移控制权。

在Repo bootstrap执行init可以提供很多参数,但实际上第一阶段初始化,只用到两个参数
参数:--repo-url=URL repo 工具本身的 git 库地址。缺省为:git://android.git.kernel.org/tools/repo.git
参数:--repo-branch=REVISION
使用repo的版本库,即repo git库的分支或者里程碑名称。缺省为 stable

第二阶段的 repo init

执行第二阶段的repo init,控制权已经移交给刚刚克隆出来的 repo git 库的脚本。

Repo git库被克隆/检出到执行repo init命令当前目录下的 .repo/repo 子目录中,主要的执行脚本
为 .repo/repo/main.py。main.py 接着执行 repo init 命令。



Repo的代码组织的非常好,
在.repo/repo/su bcmds/子目录下,
是各个 repo 命令的处理脚本。repoinit的第二阶段脚本正是由 .repo/repo/su bcmds/init.py 负责执行的。第二阶段主要完成:
    克隆由 -u 参数提供的 manifest Git 库,如克隆 android 库时:
        $ repo init -u git://android.git.kernel.org/platform/manifest.git
    如果不提供 -b REVISION 或者 –manifest-branch=REVISION参数,则检出 manifest Git 库的 master 分支
    如果不提供 -m NAME.xml 或者 –manifest-name=NAME.xml 参数,则使用缺省值 default.xml
    如果提供 –mirror 参数,则后续同步操作会有相应的体现


Repo start 干了些什么?
Android 源码网站在介绍repo的使用模型中,有一个图片:
---htttp://source.android.com/images/git-repo-1.png ,

介绍了 repo 的使用流程。
其中“repo start”是紧接着“repo sync”后的第一个动作。那么这个动作是干什么的呢?

得益于 repo 对 git 操作的封装,”repo start” 命令的处理代码只有区区 68 行。
 37   def Execute(self, opt, args):
...
 41     nb = args[0]
...
 47     projects = []
 48     if not opt.all:
 49       projects = args[1:]
...
 54     all = self.GetProjects(projects)
...
 57     for project in all:

 59       if not project.StartBranch(nb):
 60         err.append(project)
看到第 59 行了么,就是对 repo 同步下来的项目的多个 Git 版本库,逐一执行 project.StartBranch
操作。 nb 是 repo start 的第一个参数,即分支名称。

关于 StartBranch 的代码,在 project.py 中:
 857   def StartBranch(self, name):
 858     """Create a new branch off the manifest's revision.
 859     """
...
 894     if GitCommand(self,
 895                   ['checkout', '-b', branch.name, revid],
 896                   capture_stdout = True,
 897                   capture_stderr = True).Wait() == 0:
 898       branch.Save()
 899       return True










点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 2

    粉丝
  • 1

    好友
  • 2

    获赞
  • 14

    评论
  • 3241

    访问数
关闭

站长推荐 上一条 /2 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-24 13:24 , Processed in 0.030803 second(s), 14 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部