xxxxxxxxxx
repo一般用于安卓(Android项目)的工具,基于python开发,目的为了进行多版本库的管理,repo并不是取代git,而是用python对git进行一定的封装,简化了多版本库的管理,而对repo管理的任何一个版本库,都可以使用git命令进行操作
Anfroid的版本库管理工程repo
git://android.git.kernel/org/tools/repo.git
保存GPS配置文件的版本库
git://android.git.kernel.org/device/common.git
repo使用过程大致:
(1)运行repo init命令,克隆Android的一个清单库
(2)清单库中的manifest.xml文件,列出n多个版本库的克隆方式,包括保本库的地址和工作区地址的对应关系,以及分支关系
(3)运行repo sync命令,开始同步,分别克隆这N多个版本库到本地工作区
(4)同时对这n多个版本库执行切换分值操作,切换到某个分支
xxxxxxxxxx
1.首先下载repo的引导脚本
curl -L -k http://android.git.kernel.org/repo > ~/bin/repo
chmod a+x ~/bin/repo 或者 chmod 777 ~/bin/repo
这只是个引导脚本,不是完全的repo,因为repo的大部分的功能代码不在其中,下载的只是一个帮助完成整个repo程序继续下载和加载的工具
分析下repo引导脚本
来看看repo引导脚本的前几行。
1 #!/bin/sh
2
3 REPO_URL='git://android.git.kernel.org/tools/repo.git'
4 REPO_REV='stable'
5
6 magic='--calling-python-from-/bin/sh--'
7 """exec"python -E "$0" "$@" """#$magic"
8 if __name__ == '__main__':
9 import sys
10 if sys.argv[-1] == '#%s' % magic:
11 delsys.argv[-1]
12 del magic
从第1行可以看出,这个脚本是用Shell脚本写的。第7行既是一条合法的Shell语句,又是一条合法的Python语句。如果作为Shell语句,执行exec,用Python调用本脚本,并替换本进程。三引号在这里相当于一个空字符串和一个单独的引号。如果作为Python语句,三引号定义的是一个字符串,字符串后面是一个注释。实际上第1行到第7行,既是合法的Shell语句又是合法的Python语句。从第8行开始都是Python语句。repo引导脚本无论是用Shell执行,还是用Python执行,效果都相当于使用Python执行这个脚本。
在引导脚本repo的main函数中,首先调用_FindRepo()函数,从当前目录开始依次向上递归查找.repo/repo/main.py文件。如果找到了.repo/repo/main.py脚本,则把程序的控制权交给.repo/repo/main.py脚本。
在下载repo引导脚本后,没有repoinit之前,自然是不会存在.repo/repo/main.py脚本(手动拷贝除外),这时必须进行初始化操作。
从main主方法开始看起:
1、执行_FindRepo()函数,返回找到的.repo/repo/main.py脚本文件,以及包含repo/main.py的.repo目录
2、执行_ParseArguments()函数,分析命令行参数,分析出哪些是命令,哪些是参数。
3、执行_RunSelf()函数,判断本次执行所需的脚本和目录(main.p文件、git_config.py、project.py、.git目录和subcmds目录)是否存在,如果存在返回main.py文件和.git目录的绝对路径。
4、如果main.py不存在,则执行_Init()函数(如执行repoinit命令)。如果没有指定--repo-url或者--repo-branch,则采用脚本开始定义的REPO_URL或者REPO_REV作为默认值。repo先在本地创建一个空的repo库,然后设置注册远程库,最后调用_Clone()函数克隆repo库
5、如果main.py存在(如执行reposync命令),则移交控制权给main.py,并将参数传递给main.py。
这里完成权利交接,下面就该main.py显身手了。
在main.py中有这么一句:from subcmds import all_commands,它表示从模块包subcmds中导入所有命令。在包的每个目录中必须包含一个名为”__init__.py”(init的前后均是两条下划线)的文件。”__init__.py”可以是一个空文件,仅用来表示该目录为一个包。__init__.py是初始化模块,from-import语句导入子包时需要用到它。
“__init__.py”的主要用途是设置”__all__”变量以及包含包初始化所需的代码。在导入包内所有名字时在from中使用”*”通配符,”__all__”可以保证名字的正确导入。
__init__.py的代码如下:
1 import os
2 all_commands = {}
3
4 my_dir = os.path.dirname(__file__)
5 print __file__, 'variable --> my_dir',my_dir
6 for py in os.listdir(my_dir):
7 ifpy == '__init__.py':
8 continue
9 ifpy.endswith('.py'):
10 name = py[:-3]
11 clsn = name.capitalize()
12 while clsn.find('_') >0:
13 h =clsn.index('_')
14 clsn =clsn[0:h] + clsn[h + 1:].capitalize()
15 mod =__import__(__name__,
16 globals(),
17 locals(),
18 ['%s' % name])
19 mod = getattr(mod, name)
20 try:
21 cmd =getattr(mod, clsn)()
22 except AttributeError:
23 raiseSyntaxError, '%s/%s does not define class %s' % (
24 __name__, py, clsn)
25 name = name.replace('_','-')
26 print __file__, 'variable--> cmd_name', name
27 cmd.NAME = name
28 all_commands[name]= cmd
29 if 'help' in all_commands:
30 all_commands['help'].commands= all_commands
main.py负责具体命令的执行,包括manifests库的克隆的检出。main.py的结构和repo脚本类似。
1、从subcmds导入repo的相关命令。
2、执行init_ssh()函数(在git_confit.py中实现),完成ssh验证,包括用户名、邮箱地址等。
3、执行init_http()函数,进行网络验证。
4、解析manifest.xml,没有指定的就是默认名称。
5、通过getattr方式执行命令。_Run()函数根据命令的名称,执行subcmds下相应的文件。例如,repoinit就是执行subcmds/init.py,repo sync就是执行subcmds/sync.py。
####工作中的repo文件(软通SDK和鼎桥)
repo_SDK和repo_TD if not REPO_URL: REPO_URL = 'ssh://10.148.192.216:29418/ST/no_sync/repo'
REPO_REV = 'stable' 区别就是这一句
xxxxxxxxxx
#### repo和清单库的初始化的介绍
下载并保存了repo引导脚本后,就repo环境是OK的,
1.repo init -u http://szxgit10-rd.huawei.com:8080/HIS/HIS_STB_GIT/HiSTBLinux/manifest.git -b linux_master
2.repo init -u ssh://10.148.192.216:29418/ST/config/manifest.git -b config_JEF_10.1.1_Single_BRG_B211 -m cust.xml --no-repo-verify --repo-branch=stable
命令repo init 的过程:
1.初始化操作会从android的代码中克隆repo.git库(脚本都在这里面,例如上面的ssh://10.148.192.216:29418/ST/no_sync/repo)到当前目录下的,repo/repo目录下。完成repo.git克隆之后,repo init命令会把控制权交给工作区的,repo/repo/main.py(来自repo.git库),继续进行初始化
2.克隆的清单库位于.repo/manifest.xml(地址来自于-u参数例如http://szxgit10-rd.huawei.com:8080/HIS/HIS_STB_GIT/HiSTBLinux/manifest.git)
简单介绍下manifest.xml清单(其实就是组装git仓库)
2
REPO_REV = 'stable' 如果不想从默认URL地址中获取repo或者不想获取稳定版(stable分支)的repo,可以通过repo init的参数去覆盖默认设置,从指定源地址克隆repo代码库 --repo-url,用于设定repo的版本库地址。 --repo-branch,用于设定要检出的分支 --no-repo-verify,设定不要对repo的里程碑签名进行严格的验证。 其实,当完成repo.git版本库的克隆,repo引导脚本工作就完了,repo init都是由后续戈隆出来的.repo/repo/main.py执行 1.清单库只包含一个default.xml文件。这个XML文件定义了多个版本库和本地地址的映射关系,映射关系可以修改、也是repo工作的指引文件。所以使用repo引导脚本初始化时候需要通过-u指定清单的源地址 repo init命令初始化时,用-u参数指定清单库的位置来下载清单库 repo init -u http://szxgit10-rd.huawei.com:8080/HIS/HIS_STB_GIT/HiSTBLinux/manifest.git -b linux_master 下载清单库相关参数 -u(--manifest-url):设定清单库的git服务器地址 -b(--manifest-branch):检出清单库的特定分支 --mirror:只在repo第一次初始化的时候使用,以和android服务器同样的结构在本地建立镜像(没有工作区) -m:(--manifest-name)当有多个清单时,只可以清单库的某个清单文件为有效的清单文件,默认为defaut.xml repo初始化命令(repo init)可以执行多次: 不带参数地执行repo init,可以从上游清单库获取新的清单文件default.xml -u执行repo init(--manifest-url),和重新锌锭上游的清单库地址,并重新同步 -b(--manifest-branch)执行repoinit,会使用清单库的不同分支,一遍使用repo sync时将项目同步到不同的里程碑 不能使用--mirror命令,该命令只能在第一次初始化时执行
x