Files
android_development/tools/repo_diff/repo_diff_android.py
Diego Wilson 190a725b60 repo_diff: sync tip of branches of no tag is given
Not all Android source trees support build IDs and tags.
When no build tag is requested, rather than try to match
the build IDs just sync the branch tips of the upstream
and downstream source trees.

Also select two Android Oreo release candidates
as the default branches. The fact that there are frozen
branches and that the diff is small serve as a good showcase
of the tool.

Change-Id: Ifdefd79fb6b32c6b83e0aee390dd5a435b6a61fc
2017-09-14 15:56:54 -07:00

173 lines
5.3 KiB
Python

#!/usr/bin/python
"""Diff a repo (downstream) and its upstream.
This script:
1. Downloads a repo source tree with specified manifest URL, branch
and release tag.
2. Retrieves the BUILD_ID from $downstream/build/core/build_id.mk.
3. Downloads the upstream using the BUILD_ID.
4. Diffs each project in these two repos.
"""
import argparse
import os
import subprocess
import repo_diff_downstream
HELP_MSG = "Diff a repo (downstream) and its upstream"
DOWNSTREAM_WORKSPACE = "downstream"
UPSTREAM_WORKSPACE = "upstream"
DEFAULT_MANIFEST_URL = "https://android.googlesource.com/platform/manifest"
DEFAULT_MANIFEST_BRANCH = "android-8.0.0_r10"
DEFAULT_UPSTREAM_MANIFEST_URL = "https://android.googlesource.com/platform/manifest"
DEFAULT_UPSTREAM_MANIFEST_BRANCH = "android-8.0.0_r1"
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
DEFAULT_EXCLUSIONS_FILE = os.path.join(SCRIPT_DIR, "exclusions.txt")
def parse_args():
"""Parse args."""
parser = argparse.ArgumentParser(description=HELP_MSG)
parser.add_argument("-u", "--manifest-url",
help="manifest url",
default=DEFAULT_MANIFEST_URL)
parser.add_argument("-b", "--manifest-branch",
help="manifest branch",
default=DEFAULT_MANIFEST_BRANCH)
parser.add_argument("-r", "--upstream-manifest-url",
help="upstream manifest url",
default=DEFAULT_UPSTREAM_MANIFEST_URL)
parser.add_argument("-a", "--upstream-manifest-branch",
help="upstream manifest branch",
default=DEFAULT_UPSTREAM_MANIFEST_BRANCH)
parser.add_argument("-e", "--exclusions-file",
help="exclusions file",
default=DEFAULT_EXCLUSIONS_FILE)
parser.add_argument("-t", "--tag",
help="release tag (optional). If not set then will"
"sync the latest in the branch.")
return parser.parse_args()
def repo_init(url, rev, workspace):
"""Repo init with specific url and rev.
Args:
url: manifest url
rev: manifest branch, or rev
workspace: the folder to init and sync code
"""
print("repo init:\n url: %s\n rev: %s\n workspace: %s" %
(url, rev, workspace))
subprocess.check_output("repo init --manifest-url=%s --manifest-branch=%s" %
(url, rev), cwd=workspace, shell=True)
def repo_sync(workspace, retry=5):
"""Repo sync."""
count = 0
while count < retry:
count += 1
print("repo sync (retry=%d/%d):\n workspace: %s" %
(count, retry, workspace))
try:
subprocess.check_output(("repo sync --jobs=24 --current-branch --quiet "
"--no-tags --no-clone-bundle"),
cwd=workspace, shell=True)
except subprocess.CalledProcessError as e:
print "Error: %s" % e.output
# Stop retrying if the repo sync was successful
else:
break
def get_commit_with_keyword(project_path, keyword):
"""Get the latest commit in $project_path with the specific keyword."""
return subprocess.check_output(("git -C %s "
"rev-list --max-count=1 --grep=\"%s\" "
"HEAD") %
(project_path, keyword), shell=True).rstrip()
def get_build_id(workspace):
"""Get BUILD_ID defined in $workspace/build/core/build_id.mk."""
path = os.path.join(workspace, "build", "core", "build_id.mk")
return subprocess.check_output("source %s && echo $BUILD_ID" % path,
shell=True).rstrip()
def repo_sync_specific_release(url, branch, tag, workspace):
"""Repo sync source with the specific release tag."""
if not os.path.exists(workspace):
os.makedirs(workspace)
manifest_path = os.path.join(workspace, ".repo", "manifests")
repo_init(url, branch, workspace)
if tag:
rev = get_commit_with_keyword(manifest_path, tag)
if not rev:
raise(ValueError("could not find a manifest revision for tag " + tag))
repo_init(url, rev, workspace)
repo_sync(workspace)
def diff(manifest_url, manifest_branch, tag, upstream_manifest_url,
upstream_manifest_branch, exclusions_file):
"""Syncs and diffs an Android workspace against an upstream workspace."""
workspace = os.path.abspath(DOWNSTREAM_WORKSPACE)
upstream_workspace = os.path.abspath(UPSTREAM_WORKSPACE)
# repo sync downstream source tree
repo_sync_specific_release(
manifest_url,
manifest_branch,
tag,
workspace)
build_id = None
if tag:
# get the build_id so that we know which rev of upstream we need
build_id = get_build_id(workspace)
if not build_id:
raise(ValueError("Error: could not find the Build ID of " + workspace))
# repo sync upstream source tree
repo_sync_specific_release(
upstream_manifest_url,
upstream_manifest_branch,
build_id,
upstream_workspace)
# do the comparison
repo_diff_downstream.diff(
upstream_workspace,
workspace,
os.path.abspath("project.csv"),
os.path.abspath("commit.csv"),
os.path.abspath(exclusions_file),
)
def main():
args = parse_args()
diff(args.manifest_url, args.manifest_branch, args.tag,
args.upstream_manifest_url, args.upstream_manifest_branch,
args.exclusions_file)
if __name__ == "__main__":
main()