Monday, April 8, 2013

[android help] Android source code and repo - What exactly is happening when getting code


repo init


Since you seem pretty savvy, you know repo is just a python script, right? You can read it to see exactly how it works. I haven't read through the entire thing, but, basically, it wraps git and provides support for working across multiple git repositories. The idea is there is a manifest file that specifies requirements for different versions of Android. When you do repo init with an argument it looks at which git repositories it needs to clone and which git repositories you have already synced, and which branches it needs to fetch once it has obtained the proper repositories. It then handles keeping all the repositories it is managing on the proper branches. Think of repo as adding another layer to the standard git workflow (which I'll assume you're familiar with).


The first time you use repo, to get the master branch, you need to use



repo init -u https://android.googlesource.com/platform/manifest


And afterwards you need to sync all the files from the server:



repo sync


This will update your current working directory to the exact state specified by the master version of the manifest you downloaded. To checkout a different version of the AOSP, you use:



repo init -b version_name


This updates the manifest to the one that contains information about the Android version you want (also called a branch).


Don't forget to sync.



To switch to another manifest branch, repo init -b otherbranch may be used in an existing client. However, as this only updates the manifest, a subsequent repo sync (or repo sync -d) is necessary to update the working directory files.



The behavior you are experiencing may seem weird because you're probably not used to working with a system that overwrites your local state so easily. When using git, you're not supposed to init a bunch of times in the same directory. Another option, then, is to make new directories for each project. The purpose of the .repo directory is to store all the information relevant to your current repo setup (also like the .git directory). In fact, running repo init does many things:


  1. Downloads the manifest from the specified url.

  2. Tries to open or create the .repo directory.

  3. Makes sure your GPG key is set up.

  4. Clones the specified branch (which defaults to REPO_REV if none is specified).

  5. Verifies it.

  6. Checks out the appropriate branch for each of the projects.

I would assume the clone operation writes over information in the .repo folder. The reason it takes ages after the first command you run:



repo init -u https://android.googlesource.com/platform/manifest
repo sync


Is because it has to download many gigabytes of information. Now, going from the master branch to gingerbread repo knows it simply needs to drop about 68 commits which can be done very quickly.



$ repo init -u https://android.googlesource.com/platform/manifest -b gingerbread
$ repo sync
...
.repo/manifests/: discarding 68 commits
...


Ramping back up to android_4.2.2_r1 means repo needs to not just download any information needed by those commits again, but also update the current branches on all the referenced projects. This will take a long time. We are trading disk usage for processing time (=


really?


Now, this presents a problem: what if you want to compare two repo branches at once? This is difficult because when you repo init && repo sync you lose the old information you were looking at. The answer, then, is to copy the relevant information and then repo init && repo sync again. This will get annoying really fast -- thankfully repo provides a way to speed up this process if you have the disk space.


One strategy to make things quicker is to create a local mirror in a workspace/master directory. Then, checkout your desired branch from the mirror in a new directory, e.g. workspace/gingerbread . Now you can switch between branches simply by changing to the appropriate directory.


Mirror the AOSP locally:



cd workspace
mkdir master && cd master
repo init --mirror


will cause repo to mirror the remote server on your local machine. Then, when you want to switch to a new branch, you can:



mkdir ../gingerbread && cd ../gingerbread
repo init -b version_name --reference=../master


The result is a workspace with a folder containing the mirror and a folder containing the gingerbread branch referencing the mirror where possible.


The other option is to simply initialize and sync the branch you want, then copy the folder to another location and use the copy to initialize and sync again. Repo should only download what's missing.


Other repo uses:


Beyond init, repo provides support for passing commands, such as branch, to all the different git repositories in a given manifest so that you don't have to worry about that when working with the code. It also facilitates collaboration by making it easy to submit your local changes to the gerrit code review system. I'm unsure what the official reason for partitioning the AOSP into multiple git repositories is, but I would imagine it was done in order to manage the scaling issues of version control and in order to keep the project robust and fault-tolerant (if someone brakes one git repo it doesn't destroy the entire AOSP). It is also necessary to provide a way that vendors can contribute back to the source and letting them manage their own git repositories which can simply be registered with, or entered into, a overarching manifest makes sense. I didn't answer your questions line-item, but does this give you the information you are looking for?



.

stackoverflow.comm

No comments:

Post a Comment

Google Voice on T-Mobile? [General]

Google Voice on T-Mobile? So I recently switched from a GNex on Verizon to a Moto X DE on T-Mobile. I had always used Google Voice for my v...