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