.
版本: v0.3
作者:河东西望
日期:2022-7-5
.
如果你的开发是基于AOSP源码来建仓,那么搭建repo服务器和部署自己的repo仓库就是非常必要的工作了。
现实中很多公司都是直接把AOSP源代码放在一个git仓库中来管理,这样做没什么毛病。但是如果开发团队人数较多,会存在一些明显的弊端:
AOSP源代码结构复杂庞大,除了本身的代码模块之外,还集成了五六百个第三方仓库,这些仓库也会在不停的更新迭代。AOSP维护整个代码仓库框架就需要保持足够的灵活性,于是就引进了repo脚本来批量管理git仓库。AOSP的源代码切分的git仓库数量多达六七百多个。
如果我们想要跟上游平台仓库保持一致的仓库结构,很方便快捷的同步代码,而我们自己也能灵活的管理本地的扩展仓库,就需要搭建部署自己的repo仓库了。
在实际的团队开发实践中,代码管理框架一般是gerrit+repo的组合形式。gerrit的安装部署和权限管理等不是本文档的内容,请读者搜索网络材料来安装部署。本文档的主要内容包括:
本文档的服务器操作系统是ubuntu18.04。
新的操作系统安装包中已经包含了repo命令程序,可以直接通过下面的命令安装:
sudo apt-get install repo
# 查看repo版本
repo --version
repo launcher version 2.17
(from /usr/local/bin/repo)
git 2.34.1
Python 3.10.4 (main, Apr 2 2022, 09:04:19) [GCC 11.2.0]
OS Linux 5.15.0-39-generic (#42-Ubuntu SMP Thu Jun 9 23:42:32 UTC 2022)
CPU x86_64 (x86_64)
Bug reports: https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue
安装完毕,我们可以看到安装的实际上是一个repo的引导器。它还不是完整的管理工具。
通过cat命令查看一下repo文件,实际上是一个python3脚本.
which repo
/usr/local/bin/repo
cat /usr/local/bin/repo
........
客户端在同步仓库时一般用到的几个命令序列:
# 初始化仓库
repo init -u ....
# 检出代码
repo sync -j16
# 建立本地分支
repo start --all
# 批量执行git命令
repo forall -c `GIT COMMAND`
我们以清华大学官网的AOSP代码为例,操作一下repo的仓库同步。
# 设置一下REPO_URL。
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'
mkdir -p ~/aosp
cd aosp
# 初始化仓库
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest
Downloading Repo source from https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/
remote: Enumerating objects: 7372, done.
remote: Counting objects: 100% (7372/7372), done.
remote: Compressing objects: 100% (3935/3935), done.
remote: Total 7372 (delta 4765), reused 5577 (delta 3363)
接收对象中: 100% (7372/7372), 3.27 MiB | 3.58 MiB/s, 完成.
处理 delta 中: 100% (4765/4765), 完成.
... A new version of repo (2.21) is available.
... You should upgrade soon:
cp /home/xxx/Documents/aosp/.repo/repo/repo /usr/local/bin/repo
Downloading manifest from https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest
remote: Enumerating objects: 98793, done.
remote: Counting objects: 100% (98793/98793), done.
remote: Compressing objects: 100% (39423/39423), done.
remote: Total 98793 (delta 38918), reused 98123 (delta 38532)
接收对象中: 100% (98793/98793), 25.23 MiB | 2.40 MiB/s, 完成.
处理 delta 中: 100% (38918/38918), 完成.
Your identity is: xxx
If you want to change this, please re-run 'repo init' with --config-name
Testing colorized output (for 'repo diff', 'repo status'):
black red green yellow blue magenta cyan white
bold dim ul reverse
Enable color display in this user account (y/N)? y
repo has been initialized in /home/xxx/Documents/aosp/
If this is not the directory in which you want to initialize repo, please run:
rm -r /home/yl/Documents/aosp//.repo
and try again.
repo init命令执行完毕,实际上就是下载了一个.repo目录下(repo命令版本过时,可以根据提示更新一下,也可以不用更新)。
我们看一下repo目录内容:
repo
├── manifests // 清单仓库
│ ├── .git -> ../manifests.git/
│ ├── default.xml // 真正的仓库清单文件
│ ├── GLOBAL-PREUPLOAD.cfg
│ └── OWNERS
├── manifests.git // 清单仓库git配置信息
│ ├── branches
│ ├── config
│ ├── description
│ ├── FETCH_HEAD
│ ├── HEAD
│ ├── hooks
│ ├── index
│ ├── info
│ ├── logs
│ ├── objects
│ ├── packed-refs
│ └── refs
├── manifest.xml // 清单文件,内容包含default.xml文件
└── repo // repo工具脚本
├── color.py
├── command.py
├── git_trace2_event_log.py
├── hooks
├── hooks.py
├── repo
├── .........
└── wrapper.py
repo init干了这几件事情:
repo批量管理仓库的内容就在default.xml中。我们看一下文件内容:
......
这个XML文件的语法,不是本文档的内容。简单说明一下几个关键的:
remote: 远程服务端repo仓库名称
project: 每个项目的git仓库
path: 客户端git仓库路径
name: 服务端git仓库名称
revision: 分支名称或者commit id
linkfile: 软链接文件,src和dest表示源和目的。
copyfile: 文件拷贝,src和dest表示源和目的。
groups: 分组。
概括一下repo批量管理仓库的方式:
所以,repo仓库的管理核心就在manifest.git,而起关键作用的配置文件就是仓库清单文件xxx.xml,有多少个项目仓库,就有对应的xml清单文件。
接着就是关键问题:搭建repo服务器我们要做哪些事情?
简而言之:
实际上,如果你的网络链接可以链接到外网的话,工具仓库git-repo.git是不需要搭建部署的。
只需要通过REPO_URL这个环境变量来指定URL就可以自动拉取git-repo.git仓库。
export REPO_URL=https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/
常用的URL有这些:
## google地址,需要梯子。
https://gerrit.googlesource.com/git-repo
## 清华大学开源软件镜像站
https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/
## 其他可以自己网上搜索...
但是现实中,很多公司的外网是受限的,无法访问。这个时候就需要考虑搭建自己的工具仓库git-repo.git了。
这个仓库的搭建很简单,就是一个普通的git仓库,但是涉及到GPG签名的问题就比较复杂。这个过程不是本文档的内容,可以搜索互联网上的文档资料。
部署清单仓库的方式,跟普通的git仓库没有什么差别。关键问题在:
从服务器的角度来看,你的服务器上肯定会管理多个项目仓库(例如qcom8953,qcom8916,mtk6219,mtk2226,rk3399,rk3358等等),那我们管理这些仓库的方式可能有:
这两种方式都可以,取决于你的代码管理策略。我一般在整个服务器上使用一个manifests.git仓库,通过不同的xml文件来管理所有的项目仓库。服务器端项目仓库的目录结构设计如下:
aosp
├── manifests.git // 清单仓库
│ ├── qcom8953.xml
│ ├── rk3399.xml
│ ├── rk3358.xml
│ └── mtk6226.xml
├── qcom/qcom8953 // 项目仓库
├── rockchip/rk3399 // 项目仓库
├── rockchip/rk3358 // 项目仓库
└── mtk/mtk6226 // 项目仓库
清单仓库本身就是一个普通的git仓库,他也是有分支的。同一个配置文件,例如qcom8953.xml,他也可以切分出不同的分支,来管理不同的项目仓库版本。
清单仓库的分支,跟项目仓库的分支没有直接的关联关系。但是在实践操作中,我们一般会在清单仓库中建立项目仓库对应的分支,方便管理映射。例如qcom8953项目仓库,它有4个分支master、develop、test和release,那么我们的manifests.git也可以建立四个分支,跟项目仓库对应起来。
我这里建立两个分支:master和release。后面会按照这两个分支来操作。
我们先看一下repo init命令的常用参数:
repo init --help
Usage: repo init [options] [-u] url
Options:
Manifest options:
-u URL, --manifest-url=URL
manifest repository location
-b REVISION, --manifest-branch=REVISION
manifest branch or revision (use HEAD for default)
-m NAME.xml, --manifest-name=NAME.xml
initial manifest file
repo Version options:
--repo-url=URL repo repository location ($REPO_URL)
--repo-rev=REV repo branch or revision ($REPO_REV)
--no-repo-verify do not verify repo source code
Other options:
--config-name Always prompt for name/e-mail
一般来说,-b的默认值是master,-m的默认值是manifests.xml。如果我们想要使用不同的默认的清单文件,就需要在编写服务端清单文件和repo init参数时需要配合使用。
我这里全部使用默认值。在aosp源码的mannifests.xml中则体现在这几个项上:
编写清单文件,肯定不可能全部手写,需要拿到一份原始的manifests.xml文件。这份文件需要你从你的源头代码repo仓库中获取是最好的。
我这里就以qcom的AOSP源码为例,修改出我自己的仓库qcom8953.xml。
创建清单仓库可以有两种方式:
第一种方式比较简单,在WEB页面上操作就可以,没有什么特别的。
重点介绍第二种命令行方式。
ssh -p 29418 @ gerrit create-project aosp/manifests.git
创建完毕,在gerrit页面上也可以看到这个manifests.git仓库。管理员可以在页面上创建两个分支:master,release。
客户端按照正常的git操作操作:
## 克隆代码
git clone .../manifests.git
## 提交清单文件qcom8953.xml
git add qcom8953.xml
git commit -m "add qcom8953.xml"
git push
这样我们就建立了一个manifests.git仓库,并上传了一个清单文件qcom8953.xml。
下一步就是如何创建项目仓库了。
初始工程仓库的源代码,最好来自平台厂商提供的带了.repo和.git的完整repo仓库,然后我们看看如何将这个仓库移植到我们自己的内部仓库。
一般的操作步骤:
批量创建子仓库只能通过gerrit命令行来进行。
ssh -p 29418 @ gerrit create-project aosp/qcom8953/xxx.git
这里我们需要知道的qcom8953仓库的所有仓库名字,然后通过脚本来批量创建,有两种方式:
我们最终需要一个仓库列表文件:project.list。文件内容如下:
qcom/qcom8953/art
qcom/qcom8953/bionic
qcom/qcom8953/bootable/bootloader/edk2
qcom/qcom8953/bootable/recovery
qcom/qcom8953/build/blueprint
qcom/qcom8953/build/kati
qcom/qcom8953/build
qcom/qcom8953/build/soong
qcom/qcom8953/cts
qcom/qcom8953/dalvik
qcom/qcom8953/developers/build
qcom/qcom8953/developers/demos/JustForUs
qcom/qcom8953/developers/samples/android
qcom/qcom8953/development
qcom/qcom8953/device/common
qcom/qcom8953/device/generic/arm64
qcom/qcom8953/device/generic/armv7-a-neon
......
接下来我们可以使用下列命令来批量创建服务端空仓库:
# 参数说明
# --empty-commit: 强制参数, 必须添加;
# -p YOUR-projects: 你的gerrit权限仓库。根据你的gerrit权限名称来确定。
# 其他参数就不要再添加了,画蛇添足以后,多出很多问题。
# 注意远程仓库名称前需要带path前缀(qcom/qcom8953),防止服务器端仓库路径混乱。
cat project.list | xargs -I {} ssh -p 29418 root@192.168.1.1 gerrit create-project "{}" --empty-commit -p YOUR-projects
创建完毕,在gerrit页面上就看到了几百个git仓库。
在上传本地repo仓库之前,需要做几个预处理动作:
git remote set-url origin ssh://root@192.168.1.1:29418/xxx
仓库预处理完毕,你需要一一上传各仓库的指定的分支和代码到服务器仓库。
这里是通用的操作, 你也需要自己编写脚本进行上传同步:
git checkout master
git push origin master:master
git push -- tags
当然,上传之后,你最好在第三方测试验证一下,是不是有些.gitignore或者某些嵌套仓库存在问题,需要手工进行修复。
repo仓库搭建完毕,对客户端来说,使用操作并不麻烦,使用常用的repo命令和git命令即可完成代码提交。
# 初始化仓库
repo init -u -n -m
# 检出代码
repo sync -j16
# 建立本地分支
repo start --all
# 批量执行git命令
repo forall -c `GIT COMMAND`
单个仓库的代码提交合并:
git add xxx
git commit -m "xxxx"
git push HEAD:refs/for/BRANCH
初次提交时可能会报告no change id的小错误,百度搜索一下,很容易修复的。
参与评论
手机查看
返回顶部