summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVince Harron <vharron@google.com>2016-05-01 04:42:59 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2016-05-01 04:42:59 +0000
commit65404466e5bec13ee304b3efbb617a940b12278a (patch)
tree659e17ed3831c7d682feb24fda62df1018cbf24b
parentc427e5d5227ba9413307670a5d758d9ced394a7e (diff)
parent62e3795e341341d69452cd7e69ab3cfb74918544 (diff)
downloademulator-65404466e5bec13ee304b3efbb617a940b12278a.tar.gz
Merge "Added script that shows all repo commits between two builds" into emu-master-dev
-rwxr-xr-xbuild_diff.py167
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))