How does the repo of android source code work ?
.repo
通常情况下, Android 的 .repo 里面有如下内容:
| 12
 
 | $ ls .repomanifests  manifests.git  manifest.xml  project.list  project-objects  projects  repo
 
 | 
manifests
manifests 路径是项目 manifest 仓的 git checkout,其中的 .git 是 manifest.git 的软链接,追踪 repo init --manifest-branch 指定的分支。
| 12
 3
 4
 5
 6
 7
 
 | .repo$ ls manifests/.git/config       HEAD   index  logs     ORIG_HEAD    refs      shallow
 description  hooks  info   objects  packed-refs  rr-cache  svn
 
 .repo$ ls manifests.git/
 branches  description  HEAD   info  objects      refs      svn
 config    FETCH_HEAD   hooks  logs  packed-refs  rr-cache
 
 | 
不管远程分支名字是什么,manifests 的本地分支命名为 default。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | .repo$ cat manifests/.git/HEAD ref: refs/heads/default
 
 .repo$ cat manifests.git/config
 
 [core]
 repositoryformatversion = 0
 filemode = true
 [filter "lfs"]
 smudge = git-lfs smudge --skip -- %f
 [remote "origin"]
 url = https://<url>/platform/manifest.git
 fetch = +refs/heads/*:refs/remotes/origin/*
 [branch "default"]
 remote = origin
 merge = refs/heads/<remote_branch_name>
 
 | 
manifests.git
manifests.git 是当前项目 manifest 仓的一个没有工作空间的 checkout,即只 checkout .git ,追踪repo init --manifest-url 指定的 Git 仓。不能手动修改这部分,如果需要修改的话,可重新运行 repo init 来更新设置。
.repo_config.json
缓存 manifests.git/config,用来提升 repo 的速度。
manifest.xml
repo 使用的 manifest , 此文件由 repo init --manifest-name 指定链接到 manifests 中的哪一个文件,如下:  
| 1
 | manifest.xml -> manifests/<manifest-name>.xml 
 | 
以 default.xml in Android 为例简单介绍下 manifest 的格式。 
详细格式介绍见 repo Manifest Format 。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 
 | <?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" />
 
 
 
 
 
 
 
 
 
 <project path="build/make" name="platform/build" groups="pdk" >
 <copyfile src="core/root.mk" dest="Makefile" />
 <linkfile src="CleanSpec.mk" dest="build/CleanSpec.mk" />
 <linkfile src="buildspec.mk.default" dest="build/buildspec.mk.default" />
 <linkfile src="core" dest="build/core" />
 <linkfile src="envsetup.sh" dest="build/envsetup.sh" />
 <linkfile src="target" dest="build/target" />
 <linkfile src="tools" dest="build/tools" />
 </project>
 <project path="build/bazel" name="platform/build/bazel" groups="pdk" >
 <linkfile src="bazel.WORKSPACE" dest="WORKSPACE" />
 </project>
 <project path="build/blueprint" name="platform/build/blueprint" groups="pdk,tradefed" />
 <project path="build/soong" name="platform/build/soong" groups="pdk,tradefed" >
 <linkfile src="root.bp" dest="Android.bp" />
 <linkfile src="bootstrap.bash" dest="bootstrap.bash" />
 </project>
 <project path="art" name="platform/art" groups="pdk" />
 <project path="bionic" name="platform/bionic" groups="pdk" />
 ...
 <project path="tools/treble" name="platform/tools/treble" groups="tools,pdk" />
 <project path="tools/trebuchet" name="platform/tools/trebuchet" groups="tools,cts,pdk,pdk-cw-fs,pdk-fs" />
 <repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload" />
 </manifest>
 ```
 
 ## repo hook
 
 [hook](https://android.googlesource.com/platform/tools/repohooks) 主要在允许执行步骤之前(例如在将提交上载到Gerrit之前),运行 linters,检查格式和运行单元测试。
 
 > linter 的维基百科解释是:a tool that analyzes source code to flag programming errors, bugs, stylistic errors, and suspicious constructs.<br/>简单来说就是分析源码,查找问题。
 
 如下是一个 Android 中的使用范例,在战’pre-upload'(即,`repo upload`) 阶段运行名为 ’platform/tools/repohooks‘ 的 hook 。
 ```xml
 <project path="tools/repohooks" name="platform/tools/repohooks" />
 <repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload" />
 
 | 
project.list
repo sync 基于此文件内容增删 projects ,并更新对应的 checkout 工作路径。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | .repo$ more project.list art
 bionic
 bootable/bootloader/edk2
 bootable/recovery
 build/blueprint
 build/kati
 build/make
 build/soong
 cts
 dalvik
 developers/build
 ...
 device/qcom/common
 device/qcom/sepolicy
 ...
 
 | 
projects
存放 repo 克隆的 manifest 中指定的所有 project 的 git 仓库,repo 将基于此 git 仓库链接 .git 并创建工作路径,然后 checkout 对应分支,并更新 .repo/project.list。一些 git 将进一步拆分到如下的 project-objects。
| 12
 3
 4
 5
 6
 
 | .repo$ ls projectsart.git     dalvik.git       frameworks           packages              shortcut-fe.git  vendor
 bionic.git  developers       hardware             pdk.git               system
 bootable    development.git  kernel               platform_testing.git  test
 build       device           libcore.git          prebuilts             toolchain
 cts.git     external         libnativehelper.git  sdk.git               tools
 
 | 
project-objects
可以在多个 git chekcout 中安全共享的 Git 对象,例如,可以将 foo/bar.git 的不同分支 checkout 到 foo/bar-master,foo/bar-release 等, 在 projects 下将为每一个分支创建路径,而  project-objects 下面将会只有一个路径。
| 12
 
 | .repo$ ls project-objects/abl  device  kernel  platform  toolchain
 
 | 
repo
完整的 Repo 工具,接收并处理 Repo-Launcher 转发的命令。
| 12
 3
 4
 
 | $ ls .repo/repo/color.py    command.pyc  editor.py   error.pyc        git_config.py   gitc_utils.pyc  git_ssh  manifest_xml.py   pager.pyc     project.py    pyversion.pyc  repoc                  tests      wrapper.py
 color.pyc   COPYING      editor.pyc  git_command.py   git_config.pyc  git_refs.py     hooks    manifest_xml.pyc  progress.py   project.pyc   README.md      subcmds                trace.py   wrapper.pyc
 command.py  docs         error.py    git_command.pyc  gitc_utils.py   git_refs.pyc    main.py  pager.py          progress.pyc  pyversion.py  repo           SUBMITTING_PATCHES.md  trace.pyc
 
 |