如何搭建android源代碼repo倉庫
目錄
- 如何搭建android源代碼repo倉庫
- 1 repo是如何管理倉庫的?
- 1.1 repo如何作業的?
- 1.2 搭建repo服務需要做哪些事情?
- 2 部署工具倉庫git-repo.git
- 3 部署清單倉庫manifests.git
- 3.1 如何設計清單倉庫及分支?
- 3.1.1 需要幾個倉庫?
- 3.1.2 需要幾個分支?
- 3.2 如何撰寫清單檔案?
- 3.3 創建清單倉庫manifests.git
- 3.1 如何設計清單倉庫及分支?
- 4 批量創建工程子倉庫
- 4.1 批量創建服務端空倉庫
- 4.2 預處理本地repo代碼
- 4.3 上傳分支和代碼
- 5 repo倉庫使用簡述
.
版本: v0.3
作者:河東西望
日期:2022-7-5
.
如果你的開發是基于AOSP原始碼來建倉,那么搭建repo服務器和部署自己的repo倉庫就是非常必要的作業了,
現實中很多公司都是直接把AOSP源代碼放在一個git倉庫中來管理,這樣做沒什么毛病,但是如果開發團隊人數較多,會存在一些明顯的弊端:
- AOSP源代碼一般的大小是20GB,編譯之后達到40GB以上,每次同步會很耗費時間,
- AOSP源代碼檔案數量將近70W個,單個倉庫的檔案索引會很龐大,每次檢索非常耗時,
- AOSP和芯片平臺廠商(例如qcom、mtk、rockchip等)的原始代碼倉庫,一般是以repo倉庫結構提供的,而不是單個git倉庫,改變倉庫結構之后,人工維護的作業量比較大,
AOSP源代碼結構復雜龐大,除了本身的代碼模塊之外,還集成了五六百個第三方倉庫,這些倉庫也會在不停的更新迭代,AOSP維護整個代碼倉庫框架就需要保持足夠的靈活性,于是就引進了repo腳本來批量管理git倉庫,AOSP的源代碼切分的git倉庫數量多達六七百多個,
如果我們想要跟上游平臺倉庫保持一致的倉庫結構,很方便快捷的同步代碼,而我們自己也能靈活的管理本地的擴展倉庫,就需要搭建部署自己的repo倉庫了,
在實際的團隊開發實踐中,代碼管理框架一般是gerrit+repo的組合形式,gerrit的安裝部署和權限管理等不是本檔案的內容,請讀者搜索網路材料來安裝部署,本檔案的主要內容包括:
- 說明repo倉庫的管理策略,
- 如何建立清單倉庫,
- 如何批量切分git倉庫,
- repo倉庫的操作使用,
本檔案的服務器作業系統是ubuntu18.04,
1 repo是如何管理倉庫的?
1.1 repo如何作業的?
新的作業系統安裝包中已經包含了repo命令程式,可以直接通過下面的命令安裝:
sudo apt-get install repo
# 查看repo版本
repo --version
<repo not installed>
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 <BRANCH> --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 <[email protected]>
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工具倉庫,其中包含了python腳本,在.repo/repo目錄下,
- 下載了manifests清單倉庫,在目錄.repo/manifests下,軟鏈接包含了.repo/manifests.git目錄,
- 下載了一個倉庫清單檔案manifests.xml,其中包含default.xml,
repo批量管理倉庫的內容就在default.xml中,我們看一下檔案內容:
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote name="aosp"
fetch=".."
review="https://android-review.googlesource.com/" />
<default revision="master"
remote="aosp"
sync-j="4" />
<manifest-server url="http://android-smartsync.corp.google.com/android.googlesource.com/manifestserver" />
<superproject name="platform/superproject" remote="aosp"/>
<contactinfo bugurl="go/repo-bug" />
<project path="build/make" name="platform/build" groups="pdk" >
<linkfile src="https://www.cnblogs.com/aosp/p/CleanSpec.mk" dest="build/CleanSpec.mk" />
<linkfile src="https://www.cnblogs.com/aosp/p/buildspec.mk.default" dest="build/buildspec.mk.default" />
<linkfile src="https://www.cnblogs.com/aosp/p/core" dest="build/core" />
<linkfile src="https://www.cnblogs.com/aosp/p/envsetup.sh" dest="build/envsetup.sh" />
<linkfile src="https://www.cnblogs.com/aosp/p/target" dest="build/target" />
<linkfile src="https://www.cnblogs.com/aosp/p/tools" dest="build/tools" />
</project>
<project path="build/bazel" name="platform/build/bazel" groups="pdk" >
<linkfile src="https://www.cnblogs.com/aosp/p/bazel.WORKSPACE" dest="WORKSPACE" />
<linkfile src="https://www.cnblogs.com/aosp/p/bazel.sh" dest="tools/bazel" />
<linkfile src="https://www.cnblogs.com/aosp/p/bazel.BUILD" dest="BUILD" />
</project>
<project path="build/bazel_common_rules" name="platform/build/bazel_common_rules" groups="pdk" />
<project path="build/blueprint" name="platform/build/blueprint" groups="pdk,tradefed" />
<project path="build/pesto" name="platform/build/pesto" groups="pdk" />
<project path="build/soong" name="platform/build/soong" groups="pdk,tradefed" >
<linkfile src="https://www.cnblogs.com/aosp/p/root.bp" dest="Android.bp" />
<linkfile src="https://www.cnblogs.com/aosp/p/bootstrap.bash" dest="bootstrap.bash" />
</project>
<project path="art" name="platform/art" groups="pdk" />
<project path="bionic" name="platform/bionic" groups="pdk" />
<project path="bootable/recovery" name="platform/bootable/recovery" groups="pdk" />
<project path="bootable/libbootloader" name="platform/bootable/libbootloader" groups="vts,pdk" />
<project path="device/common" name="device/common" groups="pdk-cw-fs,pdk" />
<project path="device/generic/arm64" name="device/generic/arm64" groups="pdk" />
<project path="device/generic/armv7-a-neon" name="device/generic/armv7-a-neon" groups="pdk" />
<project path="device/generic/art" name="device/generic/art" groups="pdk" />
......
<repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload" />
<!--
Merge marker to make it easier for git to merge AOSP-only manifest
changes to a custom manifest. Please keep this marker here and
refrain from making changes on or below it.
-->
</manifest>
這個XML檔案的語法,不是本檔案的內容,簡單說明一下幾個關鍵的:
remote: 遠程服務端repo倉庫名稱
project: 每個專案的git倉庫
path: 客戶端git倉庫路徑
name: 服務端git倉庫名稱
revision: 分支名稱或者commit id
linkfile: 軟鏈接檔案,src和dest表示源和目的,
copyfile: 檔案拷貝,src和dest表示源和目的,
groups: 分組,
概括一下repo批量管理倉庫的方式:
- repo init命令下載工具腳本倉庫和清單倉庫,
- repo sync命令根據清單檔案中的配置,下載遠程倉庫二進制檔案,
- repo start檢出分支,
所以,repo倉庫的管理核心就在manifest.git,而起關鍵作用的組態檔就是倉庫清單檔案xxx.xml,有多少個專案倉庫,就有對應的xml清單檔案,
1.2 搭建repo服務需要做哪些事情?
接著就是關鍵問題:搭建repo服務器我們要做哪些事情?
簡而言之:
- 部署通用的工具倉庫git-repo.git,
- 部署自己的清單倉庫manifests.git,
- 撰寫清單檔案manifests.xml
- 批量創建工程子倉庫和上傳源代碼,
2 部署工具倉庫git-repo.git
實際上,如果你的網路鏈接可以鏈接到外網的話,工具倉庫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簽名的問題就比較復雜,這個程序不是本檔案的內容,可以搜索互聯網上的檔案資料,
3 部署清單倉庫manifests.git
部署清單倉庫的方式,跟普通的git倉庫沒有什么差別,關鍵問題在:
- 清單倉庫如何管理多個專案倉庫?
- 如何撰寫清單檔案manifests.xml?
3.1 如何設計清單倉庫及分支?
3.1.1 需要幾個倉庫?
從服務器的角度來看,你的服務器上肯定會管理多個專案倉庫(例如qcom8953,qcom8916,mtk6219,mtk2226,rk3399,rk3358等等),那我們管理這些倉庫的方式可能有:
- 整個服務器只建立一份manifests.git倉庫,每個倉庫下的不同的xml檔案管理不同的專案倉庫,例如qcom8953.xml,rk3399.xml等,
- 每個專案倉庫建立一個對應的清單倉庫,例如manifests-qcom8953.git、manifests-rk3399.git等,其中放置各專案倉庫的清單檔案xml,
這兩種方式都可以,取決于你的代碼管理策略,我一般在整個服務器上使用一個manifests.git倉庫,通過不同的xml檔案來管理所有的專案倉庫,服務器端專案倉庫的目錄結構設計如下:
aosp
├── manifests.git // 清單倉庫
│ ├── qcom8953.xml
│ ├── rk3399.xml
│ ├── rk3358.xml
│ └── mtk6226.xml
├── qcom/qcom8953 // 專案倉庫
├── rockchip/rk3399 // 專案倉庫
├── rockchip/rk3358 // 專案倉庫
└── mtk/mtk6226 // 專案倉庫
3.1.2 需要幾個分支?
清單倉庫本身就是一個普通的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中則體現在這幾個項上:
<remote name="aosp"
fetch=".."
review="https://android-review.googlesource.com/" />
<default revision="master" ## 遠程默認分支
remote="aosp" ## 遠程默認倉庫,就是remote標簽中的name="aosp"
sync-j="4" />
3.2 如何撰寫清單檔案?
撰寫清單檔案,肯定不可能全部手寫,需要拿到一份原始的manifests.xml檔案,這份檔案需要你從你的源頭代碼repo倉庫中獲取是最好的,
我這里就以qcom的AOSP原始碼為例,修改出我自己的倉庫qcom8953.xml,
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<!--
remote: 服務器遠程倉庫的資訊,
name: 遠程manifest倉庫名稱,一般默認為origin
fetch: 倉庫url,如果設定為"."(注意是一個點), 就表示在repo init -u url中配置,
review: 評審系統網址,如果提交代碼,就會進入這個評審系統,
-->
<remote name="origin" fetch="." review="gerrit.your_domain.com" />
<!--
default: 這個repo倉庫的默認屬性,
revision: 默認的工程代碼倉庫分支,可以修改這里來指向不同的分支,
remote: 遠程倉庫的名稱,這里跟<remote>標簽是對應的,當然還可以指向其他倉庫的remote,
-->
<default revision="master" remote="origin"/>
<!--
project: 每個倉庫就是一個project
path: 客戶端同步到本地后的路徑名稱,
name: 服務器端git倉庫名稱,注意帶了路徑,
-->
<project path="build" name="build" />
<project path="device" name="device" />
<project path="frameworks/base" name="frameworks/base" />
<!--
重要說明:
這里的build目錄和其下的三個子目錄:blueprint, kati, soong是嵌套的git倉庫結構!
這種嵌套的git倉庫,有一個非常重要的控制檔案:.gitignore.
父級目錄那種一定存在一個.gitignore檔案,其中包含了嵌套的子級倉庫路徑,
-->
<project path="build" name="build">
<!-- copyfile: 將build/core/root.mk拷貝為Makefile,其中帶有相對路徑 -->
<copyfile src="https://www.cnblogs.com/aosp/p/core/root.mk" dst="Makefile" />
</project>
<project path="build/blueprint" name="build/blueprint" />
<project path="build/kati" name="build/kati" />
<project path="build/soong" name="build/soong">
<!-- linkfile: 建立一個軟鏈接Android.bp指向build/soong/root.bp -->
<linkfile src="https://www.cnblogs.com/aosp/p/root.bp" dest="Android.bp" />
<linkfile src="https://www.cnblogs.com/aosp/p/bootstrap.bash" dest="bootstrap.bash" />
</project>
<!-- 更多倉庫資訊 ...... -->
</manifest>
3.3 創建清單倉庫manifests.git
創建清單倉庫可以有兩種方式:
- gerrit系統的web頁面創建,這種方式適合創建少量的倉庫,簡單快捷,
- gerrit命令創建,這種方式適合批量創建大量的倉庫,特別是AOSP倉庫,
第一種方式比較簡單,在WEB頁面上操作就可以,沒有什么特別的,
重點介紹第二種命令列方式,
ssh -p 29418 <USERNAME>@<GERRIT_IP_ADDRESS> 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,
下一步就是如何創建專案倉庫了,
4 批量創建工程子倉庫
初始工程倉庫的源代碼,最好來自平臺廠商提供的帶了.repo和.git的完整repo倉庫,然后我們看看如何將這個倉庫移植到我們自己的內部倉庫,
一般的操作步驟:
- gerrit命令批量創建服務端空倉庫,
- 預處理本地repo倉庫,
- 批量上傳源代碼,
4.1 批量創建服務端空倉庫
批量創建子倉庫只能通過gerrit命令列來進行,
ssh -p 29418 <USERNAME>@<GERRIT_IP_ADDRESS> gerrit create-project aosp/qcom8953/xxx.git
這里我們需要知道的qcom8953倉庫的所有倉庫名字,然后通過腳本來批量創建,有兩種方式:
- 從xml腳本中提取倉庫名稱,
- 從原始源代碼倉庫的.repo/manifets.git中的project.list檔案中直接獲取,
不管哪種方式,都需要人工核對一下最終的倉庫數量和名稱是一致的,
我們最終需要一個倉庫串列檔案: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 [email protected] gerrit create-project "{}" --empty-commit -p YOUR-projects
創建完畢,在gerrit頁面上就看到了幾百個git倉庫,
4.2 預處理本地repo代碼
在上傳本地repo倉庫之前,需要做幾個預處理動作:
- 洗掉本地工程中的.repo目錄,
- 核對本地倉庫.repo/manifests.git/xxxx.xml清單檔案,根據檔案內容洗掉掉本地代碼中的copyfile和linkfile的源,
- 修改本地每個倉庫的git remote url路徑,這里你需要自己撰寫腳本來批量完成,
git remote set-url origin ssh://[email protected]:29418/xxx
4.3 上傳分支和代碼
倉庫預處理完畢,你需要一一上傳各倉庫的指定的分支和代碼到服務器倉庫,
這里是通用的操作, 你也需要自己撰寫腳本進行上傳同步:
git checkout master
git push origin master:master
git push -- tags
當然,上傳之后,你最好在第三方測驗驗證一下,是不是有些.gitignore或者某些嵌套倉庫存在問題,需要手工進行修復,
5 repo倉庫使用簡述
repo倉庫搭建完畢,對客戶端來說,使用操作并不麻煩,使用常用的repo命令和git命令即可完成代碼提交,
# 初始化倉庫
repo init -u <remote manifests url> -n <manifests branch> -m <manifest NAME.xml>
# 檢出代碼
repo sync -j16
# 建立本地分支
repo start <BRANCH> --all
# 批量執行git命令
repo forall -c `GIT COMMAND`
單個倉庫的代碼提交合并:
git add xxx
git commit -m "xxxx"
git push HEAD:refs/for/BRANCH
初次提交時可能會報告no change id的小錯誤,百度搜索一下,很容易修復的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/499211.html
標籤:Android
