25.6 建立Android代码库本地镜像
Android为企业提供一个新的市场,无论企业大小都处于同一个起跑线上。研究Android尤其是Android系统核心或驱动的开发,首先要做的就是通过本地克隆建立一套Android版本库管理机制。因为Android的代码库是那么庞杂,如果一个开发团队每个人都去执行repo init-u,再执行repo sync从Android服务器克隆版本库的话,多大的网络带宽恐怕都不够用。唯一的办法是在本地建立一个Android版本库的镜像。
建立本地镜像非常简单,就是在执行repo init-u初始化的时候,附带上—mirror参数。
$mkdir android-mirror-dir
$cd android-mirror-dir
$repo init—mirror-u git://android.git.kernel.org/platform/manifest.git
之后执行repo sync就可以从安装Android的Git服务器方式来组织版本库,创建一个Android版本库镜像了。
实际上附带了—mirror参数执行repo init-u命令,会在克隆的.repo/manifests.git下的config中记录配置信息:
[repo]
mirror=true
1.从Android的工作区到代码库镜像
在初始化repo工作区时,使用不带—mirror参数的repo init-u,并完成代码同步后,如果再次执行repo init并附带了—mirror参数,repo会报错退出:"fatal:—mirror not supported on existing client"。实际上—mirror参数只能对尚未初始化的repo工作区执行。
那么如果之前没有用镜像的方法同步Android版本库,难道要为创建代码库镜像再重新执行一次repo同步吗?要知道重新同步一份Android版本库是非常慢的。我就遇到了这个问题。
不过既然有manifest.xml文件,完全可以对工作区进行反向操作,将工作区转换为镜像服务器的结构。下面就是一个示例脚本,可以从本书在Github上的相关版本库[1]下载。这个脚本利用了已有的repo代码进行实现,所以看着很简洁。8-)
脚本work2mirror.py如下:
!/usr/bin/python
--coding:utf-8--
import os,sys,shutil
cwd=os.path.abspath(os.path.dirname(file))
repodir=os.path.join(cwd,'.repo')
S_repo='repo'
TRASHDIR='old_work_tree'
if not os.path.exists(os.path.join(repodir,S_repo)):
print>>sys.stderr,"Must run under repo work_dir root."
sys.exit(1)
sys.path.insert(0,os.path.join(repodir,S_repo))
from manifest_xml import XmlManifest
manifest=XmlManifest(repodir)
if manifest.IsMirror:
print>>sys.stderr,"Already mirror,exit."
sys.exit(1)
trash=os.path.join(cwd,TRASHDIR)
for project in manifest.projects.itervalues():
将旧的版本库路径移动到镜像模式下新的版本库路径
newgitdir=os.path.join(cwd,'%s.git' %project.name)
if os.path.exists(project.gitdir)and project.gitdir!=newgitdir:
if not os.path.exists(os.path.dirname(newgitdir)):
os.makedirs(os.path.dirname(newgitdir))
print "Rename%s to%s." %(project.gitdir,newgitdir)
os.rename(project.gitdir,newgitdir)
将工作区移动到待删除目录
if project.worktree and os.path.exists(project.worktree):
newworktree=os.path.join(trash,project.relpath)
if not os.path.exists(os.path.dirname(newworktree)):
os.makedirs(os.path.dirname(newworktree))
print "Move old worktree%s to%s." %(project.worktree,newworktree)
os.rename(project.worktree,newworktree)
if os.path.exists(os.path.join(newgitdir,'config')):
修改版本库的配置
os.chdir(newgitdir)
os.system("git config core.bare true")
os.system("git config remote.korg.fetch '+refs/heads/:refs/heads/' ")
删除remotes分支,因为作为版本库镜像不需要remote分支
if os.path.exists(os.path.join(newgitdir,'refs','remotes')):
print "Delete" +os.path.join(newgitdir,'refs','remotes')
shutil.rmtree(os.path.join(newgitdir,'refs','remotes'))
设置menifest为镜像
mp=manifest.manifestProject
mp.config.SetString('repo.mirror','true')
使用方法很简单,只要将脚本放在Android工作区下执行就可以了。执行完毕会将原有工作区的目录移动到old_work_tree子目录下,在确认原有工作区没有未提交的数据后,直接删除old_work_tree即可。
$python work2mirror.py
2.创建新的清单库,或者修改原有清单库
建立了Android代码库的本地镜像后,如果不对manifest清单版本库进行定制,在使用repo sync同步代码的时候,仍然使用Android官方的代码库同步代码,就会使得本地的镜像版本库形同虚设。解决办法是创建一个自己的manifest库,或者在原有清单库中建立一个分支加以修改。如果创建新的清单库,参考Android上游的manifest清单库进行创建。
[1]https://github.com/ossxp-com/gotgit/raw/master/download/ch25/work2mirror.py