代码特点
本文所指大型三方源代码是指如手机厂商所接收到的来自各大芯片厂商的Android系统代码(非app)。这类代码的特点:
- 代码量大。代码量通常为数十G。
- 原厂的代码输出形式各异。传统的芯片厂商(相对于互联网企业)所使用的代码管理工具和管理方式五花八门,由他们交付的代码形式可能为:
- Android官方结构的多git库repo管理的代码,带历史版本信息(通常见于深度合作方式)
- Android官方结构的多git库repo管理的代码,不带历史版本信息
- SVN或其它代码管理工具所管理的代码,单库或多库形式
- 干净的源代码
不论代码以什么形式输入,仅从代码量巨大的角度上来看,如果我们只是简单接收并通过单库来管理的话,后期或多或少会遇到一些无从下手的问题,例如:
- 下载上传频繁中断
- 查询缓慢
要解决这类问题,拆库处理是比较简单易行且有效的处理方式。推荐转换成Android官方结构形式,通过repo来批量管理。以下转换及同步方法都是基于此来说明的。
另,本文虽然着眼于Android系统代码,但笔者认为,其它非Android系统代码,如果代码量很大的话,也可以考虑拆库处理。
拆库方法
根据Android官方代码库结构,整理出manifest.xml文件。这里根据不同厂商的管理方式不同,会有部分差异,但因为都是基于Android的,所以结构上的差异会非常小,很容易就能整理出来。
如果厂商本身就是使用标准Android方式管理的,那只需从厂商处获取原生的manifest.xml文件,稍加修改,变成结合我们自己的gerrit服务器地址和我们定义的分支就行。
如果厂商并没有这样的xml文件,我们则需要自己根据Android官方的xml文件以及厂商提供的代码路径结构来构造这个xml文件。这个构造过程并不会很复杂,上面已说,不同厂商基于Android的代码结构上的差异会非常小,一般都是因自身芯片而单独添加了部分库,用脚本查询、比较、处理之后,一般就能自动生成95%以上的结构,差异部分提取出来再单独处理即可。
根据内部的管理需求不同,可根据厂商的不同加一层顶级目录区分来自不同厂商的代码库;也可以只添加差异库,其它共库并以分支区分。像笔者这种强迫症加完美主义精神,就比较喜欢后者。
分支模型
- upstream分支。使用独立分支同步第三方代码,该分支仅用于获取并存放第三方代码,每同步一次最好打一个tag标记基线,为方便后面说明,我们称之为upstream分支;
- dev分支。我方开发将以upstream分支为base,我们的开发分支定义为dev分支;
- sync分支。为减少第三方代码实际同步到我们的内部开发分支期间对正常开发进度的影响,可以考虑在upstream分支和dev分支之间加一个sync分支,该分支专门用于解决同步冲突问题,经测试后正式合入dev分支。
关于这些分支之间应该采用merge还是rebase的方式,可自行考虑,此处不展开细说。此处关于分支模型的说明也仅是一个建议。
同步方法
此处仅说明第三方提供的代码如何完整地进入到我们的upstream分支。
根据代码输入形式的不同,我们可以选择是否保留第三方的完整提交记录。例如厂商交付的代码是“Android官方结构的多git库repo管理的且带历史版本信息的代码”时,我们可以选择按照厂商的管理方式来管理,并可选择保留他们的历史提交记录(提示:git fetch && git merge);其它形式交付的代码一般都不会有历史提交记录,只需要把代码完整拷贝并提交到upstream分支即可。
不过就笔者曾经趟过的坑,提醒一下,拷贝时需格外注意软链接问题,确保在完成同步后下载下来的代码软链接也是正常展示的。另可能会有一些管理比较混乱的芯片厂商,输出的代码可能是他们某次编译之后的不干净的代码,这种时候还得我们编译验证之后才能确定同步是否正确,并在下次同步之前与对方沟通好如何提供满足我们需求的代码。这期间可能还会有其它五花八门的情况发生,需要SCM甄别处理。