0. 前言
整个android系统源码大约有500个左右大大小小的project,其中每个project都是使用git进行管理。为了对所有的这些project进行统一的管理操作,谷歌就用python开发了repo工具。本文主要介绍如何使用repo工具来对android源码进行管理。
1. repo常用命令
repo的命令操作很简单,常用的也就几个,只要操作过很快就能够熟练使用了。下面对这些常用命令进行介绍。
1.1 init
repo init -u <URL> [<OPTIONS>]
该操作将会在当前目录创建一个.repo
目录,其中包括一个repo的源代码的git仓库和一个包含Android manifest文件的git仓库。在.repo
目录下还包含了一个manifest.xml
文件,它是一个软连接,指向.repo/manifest
目录的一个manifest文件(当前选择的manifest)。
该命令包含的选项包括:
-u
:指定一个URL用于获取manifest仓库-m
:从.repo/manifest目录选择一个manifest,如果没有指定的话,那就是default.xml-b
:指定manifest仓库的分支
如在《Android AOSP源码下载》一篇中,使用的init的命令如下:
../repo/repo init -u git://aosp.tuna.tsinghua.edu.cn/android/platform/manifest -b android-5.1.1_r6
可以看到-u指定了manifest仓库的URL,-b指定分支,-m并没有指定,所以使用的是default.xml。
1.2 sync
repo sync [<PROJECT_LIST>]
该命令将会根据之前init
中选择的manifest文件,将新的变化下载到本地环境中。如果没有指定任何参数,将会同步manifest文件中的所有project。
当执行rep sync的时候,主要做了如下操作:
如果该工程之前从未同步过,那么repo sync就等效于执行git clone操作,会将指定的project从远程仓库拷贝到本地。
如果工程之前有同步过一次,那么rep syn就等效于执行以下操作:
git remote update
git rebase origin/<BRANCH>
<BRANCH>
是当前本地的project所checked-out的分支。如果本地分支没有跟踪一个远程分支,那么该project将不会有同步发生。
当成功执行repo sync命令后,指定project的代码将会与远程仓库的代码同步。
该命令包含的选项有:
-d
: 将指定的project切换回manifest文件中指定的分支-s
: 根据当前manifest文件中manifest-server
元素所的指定,切换到一个已知好的版本-f
: 即使当前project同步失败了,也会继续处理其他的project
1.3 diff
repo diff [<PROJECT_LIST>]
该命令就是对指定的每个project用git diff
命令显示project的修改状态。
1.4 forall
repo forall [<PROJECT_LIST>] -c <COMMAND>
在每个project中执行给定shell命令,有以下附加的环境变量可以使用:
- REPO_PROJECT 是该project的唯一的名字
- REPO_PATH 是该project的与根目录的相对路径
- REPO_REMOTE 是manifest中指定的
remote
值 - REPO_LREV 是将manifest中指定的
revision
的值变换为本地跟踪的分支名 - REPO_RREV 是manifest文件中写的
revision
的值
该命令有以下选项:
-c
: 指定要执行的shel命令和参数(使用/bin/sh
执行)-p
: show project headers before output of the specified command. This is achieved by binding pipes to the command’s stdin, stdout, and sterr streams, and piping all output into a continuous stream that is displayed in a single pager session.-v
: 显示命令写到stderr的消息
1.5 start
repo start <BRANCH_NAME> [<PROJECT_LIST>]
基于manifest中指定的revision创建一个新分支用于开发。
1.6 status
repo status [<PROJECT_LIST>]
对于每个指定的project,将工作树、暂存区和当前分支最近的commit进行比较。对于有差异的文件将其用一行显示出来。其中有差异的文件的修改状态使用两个字母进行表示。
第一个字母是大写,表示该文件在暂存区与当前分支的最新commi有不同:
letter | meaning | description |
---|---|---|
- | no change | same in HEAD and index |
A | added | not in HEAD, in index |
M | modified | in HEAD, modified in index |
D | deleted | in HEAD, not in index |
R | renamed | not in HEAD, path changed in index |
C | copied | not in HEAD, copied from another in index |
T | mode changed | same content in HEAD and index, mode changed |
U | unmerged | conflict between HEAD and index; resolution required |
第二个字母是小写的,表示该文件在当前工作目录与暂存区不一致:
letter | meaning | description |
---|---|---|
- | new/unknown | not in index, in work tree |
m | modified | in index, in work tree, modified |
d | deleted | in index, not in work tree |
1.7 help
如果有不熟悉的命令就通过repo help
查看手册,其中对于每个命令,还可以通过指定–help 查看该命令的手册,如:
repo sync --help
2. manifest介绍
默认.repo/manifest.xml指向当前的sd的manifest文件,即位于.repo/manifests目录下(默认下载的aosp代码为default.xml)。repo工具就是根据这个manifest文件来管理android 500个大大小小的project,下面我们就来看一下该文件。
<manifest>
<remote name="aosp" fetch=".." />
<default revision="refs/tags/android-5.1.1_r6" remote="aosp" sync-j="4" />
<project path="build" name="platform/build" groups="pdk,tradefed">
</project>
<project path="abi/cpp" name="platform/abi/cpp" groups="pdk" />
<project path="art" name="platform/art" groups="pdk" />
<project path="bionic" name="platform/bionic" groups="pdk" />
<project path="bootable/bootloader/legacy" name="platform/bootable/bootloader/legacy" groups="pdk-cw-fs" />
<project path="bootable/recovery" name="platform/bootable/recovery" groups="pdk" />
......
<project path="tools/studio/cloud" name="platform/tools/studio/cloud" groups="notdefault,tools" />
<project path="tools/studio/translation" name="platform/tools/studio/translation" groups="notdefault,tools" />
<project path="tools/swt" name="platform/tools/swt" groups="notdefault,tools" />
<project path="tools/tradefederation" name="platform/tools/tradefederation" groups="notdefault,tradefed" />
</manifest>
可以看到该xml文件主要包括3种元素:remote
,default
和 project
。
2.1 remote
预先定义每个project中能够指定的remote,remote的功能见下面。
2.2 default
默认的remote,如果project中没有指定remote,则使用该remote。
2.3 project
指定整个Android源码的每一个project的配置,它包括以下属性值:
1) name
唯一的该project的名字。
2) remote
remote为project的远程仓库的URL字符串前面的定义,需要与name拼接成该project的远程仓库的实际的URL地址。每个project的仓库的在源码服务器中的实际路径应该为,remote中指定的路径 + project的name
属性值,即:
${remote_fetch}/${project_name}.git
如果project没有指定remote,就使用default元素中定义的remote。
如platform/abi/cpp
,该project在源码服务器中的远程仓库的实际路径为:
<URL_TO_MANIFEST>/../platform/abi/cpp.git
3) path
该project在本地源码中的路径,如果没有指定,那就使用project的name
的值,如果该project还有一个父元素,那么path会以父元素的path作为前缀。
4) revision
该project需要跟踪的远程git仓库的分支名。
5) upstream
该project的Git ref名,可以是一个sha1值。用于当以以-c模式同步一个revision的时候锁定manifest,从而避免同步全部的ref空间。
6) group
该project属于的组列表,可以用空格或者逗号分隔。所有的project都会属于all
组,并且每个project都会属于它的name
和path
组。如果将project放置于组notdefault
,那么repo将不会自动下载该project。
3 参考文献
[1] http://source.android.com/source/using-repo.html
[2] https://gerrit.googlesource.com/git-repo/+/master/docs/manifest-format.txt
[3] https://wiki.cyanogenmod.org/w/Doc:_Using_manifests