diff options
author | Vince Harron <vharron@google.com> | 2016-05-01 04:42:59 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2016-05-01 04:42:59 +0000 |
commit | 65404466e5bec13ee304b3efbb617a940b12278a (patch) | |
tree | 659e17ed3831c7d682feb24fda62df1018cbf24b | |
parent | c427e5d5227ba9413307670a5d758d9ced394a7e (diff) | |
parent | 62e3795e341341d69452cd7e69ab3cfb74918544 (diff) | |
download | emulator-65404466e5bec13ee304b3efbb617a940b12278a.tar.gz |
Merge "Added script that shows all repo commits between two builds" into emu-master-dev
-rwxr-xr-x | build_diff.py | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/build_diff.py b/build_diff.py new file mode 100755 index 0000000..87b0399 --- /dev/null +++ b/build_diff.py @@ -0,0 +1,167 @@ +#!/usr/bin/python +# Creates a combined git log of all changes between to repo manifests +# +# Usage: +# cd <path-to-emu-master-dev-repository> +# ./build_diff.py <build-id-a> <build-id-b> + +import apiclient +import httplib2 +import io +import oauth2client +import os +import sys +import xml.etree.ElementTree + +from apiclient.discovery import build as googleapi +from oauth2client import client +from oauth2client import tools + +def get_credentials(): + """Gets valid user credentials from storage. + + If nothing has been stored, or if the stored credentials are invalid, + the OAuth2 flow is completed to obtain the new credentials. + + Create your own client_secret.json + https://pantheon.corp.google.com/apis/credentials + Create credential > OAuth client id > Other > Download JSON + + Returns: + Credentials, the obtained credential. + """ + + CLIENT_SECRET_FILE = 'client_secret.json' + APPLICATION_NAME = 'Android Emulator GmsCore Updater' + SCOPES = 'https://www.googleapis.com/auth/androidbuild.internal' + + home_dir = os.path.expanduser('~') + credential_dir = os.path.join(home_dir, '.credentials') + if not os.path.exists(credential_dir): + os.makedirs(credential_dir) + credential_path = os.path.join(credential_dir, + 'calendar-python-quickstart.json') + + store = oauth2client.file.Storage(credential_path) + credentials = store.get() + if not credentials or credentials.invalid: + flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) + flow.user_agent = APPLICATION_NAME + credentials = tools.run_flow(flow, store, flags) + print('Storing credentials to ' + credential_path) + return credentials + +def get_branch_from_build_id(service, build_id): + response = service.build().list( + buildType='submitted', + buildId=str(build_id), + maxResults=1, + fields='builds/branch').execute() + return response.get('builds',[])[0].get('branch') + + +def download(service, buildId, branch, target, name, output_path=None): + buildType = 'submitted' + attemptId='latest' + + artifact = service.buildartifact().get( + buildType=buildType, + buildId=buildId, + target=target, + attemptId=attemptId, + resourceId=name).execute() + + if artifact is None: + raise FetchArtifactException('Unknown artifact %s/%s/%s/%s', + buildId, target, attemptId, name) + + # Lucky us, we always have the size + size = artifact['size'] + + chunksize = -1 + DEFAULT_CHUNK_SIZE = 20 * 1024 * 1024 + if size >= DEFAULT_CHUNK_SIZE: + chunksize = DEFAULT_CHUNK_SIZE + + # Just like get, except get_media + dl_req = service.buildartifact().get_media( + buildType=buildType, + buildId=buildId, + target=target, + attemptId=attemptId, + resourceId=name) + + # Make any root directories if needed + if output_path is None: + output_path = os.getcwd() + output = os.path.join(output_path, name) + + root_dir = os.path.dirname(output) + if root_dir and not os.path.isdir(root_dir): + os.makedirs(root_dir) + + with io.FileIO(output, mode='wb') as fh: + downloader = apiclient.http.MediaIoBaseDownload(fh, dl_req, + chunksize=chunksize) + done = False + while not done: + status, done = downloader.next_chunk() + +credentials = get_credentials() +http = credentials.authorize(httplib2.Http()) + +# API list +# https://developers.google.com/apis-explorer/#p/androidbuildinternal/v1/ +service = googleapi('androidbuildinternal', 'v1', http=http) + +build_lo = int(sys.argv[1]) +build_hi = int(sys.argv[2]) + +branch_lo = get_branch_from_build_id(service, build_lo) +branch_hi = get_branch_from_build_id(service, build_hi) + +print '{0}@{1}'.format(branch_lo, build_lo); +print '{0}@{1}'.format(branch_hi, build_hi); + +repo = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) + +def getManifest(branch, buildId): + manifest = 'manifest_{0}.xml'.format(buildId) + if not os.path.isfile(manifest): + download(service, buildId=buildId, branch=branch, target='sdk_tools_linux', name=manifest) + return manifest + +manifestLo = getManifest(branch_lo, build_lo) +manifestHi = getManifest(branch_hi, build_hi) + +treeLo = xml.etree.ElementTree.parse(manifestLo) +rootLo = treeLo.getroot() + +treeHi = xml.etree.ElementTree.parse(manifestHi) +rootHi = treeHi.getroot() +projectsHi = rootHi.iter('project') + +log = "/tmp/build_diff.log" +if os.path.isfile(log): + os.remove(log) + +os.system('repo sync -j8') + +command = 'bash -c "(' + +for project in projectsHi: + path = project.get('path') + shaHi = project.get('revision') + projectLo = rootLo.find("./project/[@path='{}']".format(path)) + if projectLo is None: + command += '*************** echo new project {} >> {}'.format(path, log) + else: + shaLo = projectLo.get('revision') + if shaLo != shaHi: + command += '(cd {} && git log --no-merges {}..{}) >> {} &&\n'.format(repo + '/' + path, shaLo, shaHi, log) + +command += 'true)"' + +print command +os.system(command) +os.system('less {}'.format(log)) |