git repo manifest.xml

 

 

转载请注明出处: http://blog.csdn.net/sy373466062 作者: TonyHo https://blog.csdn.net/sy373466062/article/details/55190634

源起

现在很多企业的网络一般都比较快, 但是有的企业却会限速, 如果需要从github和google code上面git clone大的仓库的话, 那么需要耗费的时间是很客观的,  例如从github或者google code, 或者其他托管服务站点获取Android中需要的多个Kernel仓库, 一般一个kernel仓库都有几GB, 如果是100KB/S的话, 那么将需要很长的时间.

与此同时, 不同的Android 版本(AOSP)代码, 他们一般都会依赖许多相同的组件, 甚至获取相同的仓库代码, 仅仅只是branch或者tag不同而已, 例如对于Nexus 7 flo平板而言, 不管是AOSP 4.4 Kitkat还是 5.X Lolipop, 都会去下载flo-kernel这个内核, 他们都remote都是一样的, 唯一不同的是tag使用的不同, 因此如果我们已经获取过Kitkat的代码,那么就可以复用其中的bare repo, 从而达到快速clone.

要了解如何做, 我们需要对AOSP的代码结构非常熟悉, 一般而言, 如果是系统工程师,那么几乎对AOSP的每一个目录都会很熟悉, 对自己需要编译的target的依赖的每一个repo都几乎会心中有数(例如external中的哪些, vendor, device都会用到哪些), 这种情况下, 就可以删除某些仓库的下载, 从而节省时间.

总结起来, 要节省git clone的时间就是从两个方面入手:

 

  • 1. 复用已经clone的bare repo
  • 2. 不要clone不需要的repo

 

 

repo分析

在实现前面的两点之前, 除了对AOSP的编译, 以及Target的依赖很熟悉外, 我们还需要对google 的 repo工具以及其流程有个基本的熟悉和了解.

repo的执行过程

 

  1. 解析传入的args
  2. checkout下来最新的repo
  3. 找到manifest的目录
  4. 解析manifest.xml
  5. 根据manifest或者其他xml文件调用git clone --bare-repo获取xml中定义的clone repo
  6. 从.repo/projects中的bare repo根据manifest xml中的projects信息checkout到当前目录

 

具体查看repo这个python脚本的源码.

下面使用具体例子来讲解.

repo init

 

repo init -u https://github.com/bluez-android/aosp_platform_manifest.git -b lollipop


这个init调用传入的-u这个用于指定需要下载的manifest的仓库地址: 

 

 
  1. def _Checkout(cwd, branch, rev, quiet):

  2. """Checkout an upstream branch into the repository and track it.

  3. """

  4. cmd = [GIT, 'update-ref', 'refs/heads/default', rev]

  5. if subprocess.Popen(cmd, cwd=cwd).wait() != 0:

  6. raise CloneFailure()

  7.  
  8. _SetConfig(cwd, 'branch.default.remote', 'origin')

  9. _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch)

  10.  
  11. cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default']

  12. if subprocess.Popen(cmd, cwd=cwd).wait() != 0:

  13. raise CloneFailure()

  14.  
  15. cmd = [GIT, 'read-tree', '--reset', '-u']

  16. if not quiet:

  17. cmd.append('-v')

  18. cmd.append('HEAD')

  19. if subprocess.Popen(cmd, cwd=cwd).wait() != 0:

  20. raise CloneFailure()

  21.  

 

例如前面的 init 执行完成后, 我们可以看到在.repo目录下有一个manifest.git目录:

 

 
  1. $ cd .repo/manifests.git/

  2.  
  3. $ git remote -v

  4. origin https://github.com/bluez-android/aosp_platform_manifest.git (fetch)

  5. origin https://github.com/bluez-android/aosp_platform_manifest.git (push)


注意这个manifest.git属于bare repo , 然后repo会checkout一份出来manifest working tree到manifest目录, 且使用的就是前面repo init中的-b指定的branch:

 

 
  1. .repo/manifests

  2.  
  3. $ git status

  4. On branch default

  5. Your branch is up-to-date with 'origin/lollipop'. // branch -b指定后在这里


然后我们可以看到有一个manifest.xml会指向checkout的working tree中的xml:

 

cd /Dir/Contain/.repo/../

 

 

 
  1. $ ls -l

  2. total 12

  3. drwxrwxr-x 3 hexiongjun hexiongjun 4096 Feb 15 10:57 manifests // 从下面这个bare repo checkout

  4. drwxrwxr-x 10 hexiongjun hexiongjun 4096 Feb 15 10:54 manifests.git //bare repo

  5. lrwxrwxrwx 1 hexiongjun hexiongjun 21 Feb 15 10:40 manifest.xml -> manifests/default.xml

  6. drwxrwxr-x 7 hexiongjun hexiongjun 4096 Feb 15 10:40 repo // repo本身的working tree checkout

 

repo本身的checkout

 

在repo init执行的时候会到: https://gerrit.googlesource.com/git-repo

checkout最新的repo, checkout下来后放在了.repo/repo目录

 

manifest的修改

前面的ls -l命令中列出了manifest.xml指向的是manifests/default.xml, 然后这个xml中会指明各种fetch的url, 版本revision, 以及需要checkout下来的projects, 例如:

 

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <manifest>

  3.  
  4. <remote name="aosp"

  5. fetch=".." />

  6. <default revision="refs/tags/android-5.0.0_r7"

  7. remote="aosp"

  8. sync-j="4" />

  9.  
  10. <project path="build" name="platform/build" groups="pdk,tradefed" >

  11. <copyfile src="core/root.mk" dest="Makefile" />

  12. </project>

  13. <project path="abi/cpp" name="platform/abi/cpp" groups="pdk" />

  14. <project path="art" name="platform/art" groups="pdk" />

  15. .............

  16. <include name="bluez-android.xml" />

  17.  
  18. </manifest>

 

里面的remote就是git remote获取得到的remote name, fetch指定的是从哪里checkout projects, 随后指定了revision, 以及sync的并心数.

接下来是projects的list, path指定checkout下来后放到哪里, 例如下面这行:

 

  <project path="device/htc/flounder-kernel" name="device/htc/flounder-kernel" groups="device,flounder" clone-depth="1" />

指定了从fetch/name这个位置clone, 因为repo本身会将所有的projects放到.repo/projects目录下面, 这个存放的位置就是由后面的groups来指定的, 例如上面的flounder-kernel的repo 本地bare repo位于:

.repo/projects/device/flounder-kernel.git

而这个repository的objects则位于:

.repo/project-objects/aosp_device_asus_flo-kernel.git/

这个objects目录大小为:

 

 
  1. $ du -sh ../../project-objects/aosp_device_asus_flo-kernel.git/

  2. 1.2G ../../project-objects/aosp_device_asus_flo-kernel.git/

 

然后repo在为每一个project建立了bare repository之后, 会从本地使用git clone一份出来, 且版本为前面指定的revision.

 

最后xml还可以使用include来包含, 实现"重载"

 

了解了repo的工作过程后,我们就可以想办法来重用以前的bare repository了, 也知道如何不去clone和建立不需要的project的bare repository.

 

如何重用已有的bare repo仓库来加快clone

假设我们已经有了一个AOSP 4.4 Kitkat的flo-kernel的bare repository了, 而AOSP 5.1 Lollipop也需要fetch 这个project,那么我们就可以按照下面这个方式来做.

1. 拷贝project objects到对应目录

2. 拷贝projects下的对应目录到新的需要checkout的目录, 例如从AOSP4到5

然后直接repo sync, sync完成后, 我们可以看到对应的branch被重新checkout下来了:

 

 
  1. $ git branch -a

  2. remotes/github/kitkat

  3. remotes/github/lollipop

  4. remotes/m/kitkat -> github/kitkat

  5. remotes/m/lollipop -> github/lollipop

可以看到既有kitkat也有lollipop, 这个和我们期望的一致:

 

  <project path="device/asus/flo-kernel" name="aosp_device_asus_flo-kernel" groups="device,flo" revision="lollipop" remote="github" />


这个xml中的project还指定了路径, 我们到里面确定一下:

 

 
  1. cd ../device/asus/flo-kernel/

  2.  
  3. $ git branch -a

  4. * (no branch)

  5. remotes/github/kitkat

  6. remotes/github/lollipop

  7. remotes/m/kitkat -> github/kitkat

  8. remotes/m/lollipop -> github/lollipop


然后我们使用gitk看看, 可以确定是我们需要的branch中:

 

删除不需要的代码仓库

例如我们使用的Nexus 7 flo来做开发, 并不需要Nexus 9等其他的内核, 那么可以直接在xml中注释掉其他的, repo就不会去下载了:

 

如果后来又需要checkout这些仓库,那么取消注释, 然后重新repo sync即可.

也可以使用remove-project指定, 如同上图中的前面几行.

其他的例如drawn, MIPS等一些用不到的仓库也可以删除掉.

 

https://blog.csdn.net/jefbai/article/details/20304725

 在Android源码的下载和应用程序编程中,manifest.xml文件是非常重要的,是repo仓库的大管家,在里面定义着repo中可用的git项目。这里主要讲的是Android源码中的manifest.xml文件,应用程序中的manifest文件不是很了解,没有发言权。

       今天就因为一个manifest.xml文件的问题,自己纠结了一天,总是不太明白为啥没有下载合适的工程,各种google,最后自己阅读了下.repo/manifest.xml文件,才发现可能是由于网页编辑人员的失误,将项目组的名称写错了,而自己又不太会看manifest.xml文件,所以怎么也找不出来问题。

       下面以一个实际的例子来说明manifest.xml文件的结构(arndale-octa.xml),由于源文件非常大,只选取部分来进行说明:

 

 

[html] view plain copy

 

  1. <code class="language-html"><manifest>  
  2. <remote name="aosp" fetch="git://android.git.linaro.org/" review="review.android.git.linaro.org"/>  
  3. …  
  4. <default revision="refs/tags/android-4.4.2_r2" remote="aosp" sync-j="4"/>  
  5. <!--  Developer extras  -->  
  6. <project path="packages/apps/AndroidTerm" name="platform/external/AndroidTerm" revision="linaro-master" groups="devel"/>  
  7. </manifest></code>  

 

另外,google公司给出的文档manifest-format.txt中定义了XML文件的格式:

 

在<manifest>和</manifest>标记之间的是由repo脚本解释执行的一些命令。

 

Remote 定义了远程git的名称,fetch给定了该git项目的存放地址(URL)。Review定义了当使用命令’repo upload’上传更新后,审核代码的gerrit服务器的主机名。

Name:A short name uniqueto this manifest file。用来作为每个项目的.git/config的远程名称。

 

Project定义了一个新的项目

Path:定义了git仓库应该把远程源码存放到本地的位置

Name:git项目的名称

Revision:定义了在仓库中使用哪个分支或者tag,如果没有说明,则repo sync会使用由<default ../>标记的版本。

Groups:项目组的名称,有一些项目可能在被用在多个具体的实例中,所以将它们分组,通常有common,devel等组。

 

<default revision="refs/tags/android-4.4.2_r2" remote="aosp" sync-j="4"/>

在大多数情况下,可能规定一个默认的元素。它的Remote和revision属性被用于当项目没有指定自己的remote和revision属性时。

Revision属性:git分支的名称。(例如master或者refs/heads/master)。

 

当我们从google网站上下载到最新的repo脚本文件后,运行repo init来初始化一个仓库,需要添加一些额外的参数例如,-u 指定从哪个仓库下载,-b指定分支,-m指定manifest文件名称,-g指定项目组。

 

      整理完后,对于manifest.xml不再感觉那么神秘难懂了,对于可能出现的错误,也可以去检查manfiest.xml文件(一般是对.repo/manifests/default.xml的链接),找出命令中可能出现的错误,再接着repo sync即可从仓库中拉下正确的源码。很方便啊!!

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值